]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the xFilter callback to the sqlite3changeset_apply() function. This callback...
authordan <dan@noemail.net>
Wed, 13 Jul 2011 15:21:02 +0000 (15:21 +0000)
committerdan <dan@noemail.net>
Wed, 13 Jul 2011 15:21:02 +0000 (15:21 +0000)
FossilOrigin-Name: 282474c42f24f0e66c69b576b72ef8ce764d49e2

ext/session/sqlite3session.c
ext/session/sqlite3session.h
ext/session/test_session.c
manifest
manifest.uuid

index 50c436b8c49da1b7106f027286d7e25c331371e1..78d2b6d86c8518ea323c151ede7f0274123942f0 100644 (file)
@@ -2756,6 +2756,10 @@ int sqlite3changeset_apply(
   sqlite3 *db,                    /* Apply change to "main" db of this handle */
   int nChangeset,                 /* Size of changeset in bytes */
   void *pChangeset,               /* Changeset blob */
+  int(*xFilter)(
+    void *pCtx,                   /* Copy of sixth arg to _apply() */
+    const char *zTab              /* Table name */
+  ),
   int(*xConflict)(
     void *pCtx,                   /* Copy of fifth arg to _apply() */
     int eConflict,                /* DATA, MISSING, CONFLICT, CONSTRAINT */
@@ -2788,7 +2792,6 @@ int sqlite3changeset_apply(
     if( zTab==0 || sqlite3_strnicmp(zNew, zTab, nTab+1) ){
       u8 *abPK;
 
-      schemaMismatch = 0;
       sqlite3_free((char*)sApply.azCol);  /* cast works around VC++ bug */
       sqlite3_finalize(sApply.pDelete);
       sqlite3_finalize(sApply.pUpdate); 
@@ -2797,40 +2800,50 @@ int sqlite3changeset_apply(
       memset(&sApply, 0, sizeof(sApply));
       sApply.db = db;
 
-      sqlite3changeset_pk(pIter, &abPK, 0);
-      rc = sessionTableInfo(
-          db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
-      );
-      if( rc!=SQLITE_OK ) break;
-
-      if( sApply.nCol==0 ){
-        schemaMismatch = 1;
-        sqlite3_log(SQLITE_SCHEMA, 
-            "sqlite3changeset_apply(): no such table: %s", zTab
-        );
-      }
-      else if( sApply.nCol!=nCol ){
-        schemaMismatch = 1;
-        sqlite3_log(SQLITE_SCHEMA, 
-            "sqlite3changeset_apply(): table %s has %d columns, expected %d", 
-            zTab, sApply.nCol, nCol
-        );
-      }
-      else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){
-        schemaMismatch = 1;
-        sqlite3_log(SQLITE_SCHEMA, 
-            "sqlite3changeset_apply(): primary key mismatch for table %s", zTab
+      /* If an xFilter() callback was specified, invoke it now. If the 
+      ** xFilter callback returns zero, skip this table. If it returns
+      ** non-zero, proceed. */
+      schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew)));
+      if( schemaMismatch ){
+        zTab = sqlite3_mprintf("%s", zNew);
+        nTab = strlen(zTab);
+        sApply.azCol = (const char **)zTab;
+      }else{
+        sqlite3changeset_pk(pIter, &abPK, 0);
+        rc = sessionTableInfo(
+            db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
         );
+        if( rc!=SQLITE_OK ) break;
+  
+        if( sApply.nCol==0 ){
+          schemaMismatch = 1;
+          sqlite3_log(SQLITE_SCHEMA, 
+              "sqlite3changeset_apply(): no such table: %s", zTab
+          );
+        }
+        else if( sApply.nCol!=nCol ){
+          schemaMismatch = 1;
+          sqlite3_log(SQLITE_SCHEMA, 
+              "sqlite3changeset_apply(): table %s has %d columns, expected %d", 
+              zTab, sApply.nCol, nCol
+          );
+        }
+        else if( memcmp(sApply.abPK, abPK, nCol)!=0 ){
+          schemaMismatch = 1;
+          sqlite3_log(SQLITE_SCHEMA, "sqlite3changeset_apply(): "
+              "primary key mismatch for table %s", zTab
+          );
+        }
+        else if( 
+            (rc = sessionSelectRow(db, zTab, &sApply))
+         || (rc = sessionUpdateRow(db, zTab, &sApply))
+         || (rc = sessionDeleteRow(db, zTab, &sApply))
+         || (rc = sessionInsertRow(db, zTab, &sApply))
+        ){
+          break;
+        }
+        nTab = sqlite3Strlen30(zTab);
       }
-      else if( 
-          (rc = sessionSelectRow(db, zTab, &sApply))
-       || (rc = sessionUpdateRow(db, zTab, &sApply))
-       || (rc = sessionDeleteRow(db, zTab, &sApply))
-       || (rc = sessionInsertRow(db, zTab, &sApply))
-      ){
-        break;
-      }
-      nTab = sqlite3Strlen30(zTab);
     }
 
     /* If there is a schema mismatch on the current table, proceed to the
index 38164401f4d13a40088bf5ea99cd44fbc5e56bc0..d8db1d6137cf20df51fd4740634d510c1ac6d8bc 100644 (file)
@@ -610,9 +610,19 @@ int sqlite3changeset_concat(
 ** "main" database attached to handle db with the changes found in the
 ** changeset passed via the second and third arguments.
 **
-** For each change in the changeset, this function tests that the target
-** database contains a compatible table. A table is considered compatible
-** if all of the following are true:
+** The fourth argument (xFilter) passed to this function is the "filter
+** callback". If it is not NULL, then for each table affected by at least one
+** change in the changeset, the filter callback is invoked with
+** the table name as the second argument, and a copy of the context pointer
+** passed as the sixth argument to this function as the first. If the "filter
+** callback" returns zero, then no attempt is made to apply any changes to 
+** the table. Otherwise, if the return value is non-zero or the xFilter
+** argument to this function is NULL, all changes related to the table are
+** attempted.
+**
+** For each table that is not excluded by the filter callback, this function 
+** tests that the target database contains a compatible table. A table is 
+** considered compatible if all of the following are true:
 **
 ** <ul>
 **   <li> The table has the same name as the name recorded in the 
@@ -623,17 +633,17 @@ int sqlite3changeset_concat(
 **        recorded in the changeset.
 ** </ul>
 **
-** If there is no compatible table, it is not an error, but the change is
-** not applied. A warning message is issued via the sqlite3_log() mechanism
-** with the error code SQLITE_SCHEMA. At most one such warning is issued for
-** each table in the changeset.
+** If there is no compatible table, it is not an error, but none of the
+** changes associated with the table are applied. A warning message is issued
+** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most
+** one such warning is issued for each table in the changeset.
 **
-** Otherwise, if there is a compatible table, an attempt is made to modify
-** the table contents according to the UPDATE, INSERT or DELETE change.
-** If a change cannot be applied cleanly, the conflict handler function
-** passed as the fourth argument to sqlite3changeset_apply() may be invoked.
-** A description of exactly when the conflict handler is invoked for each
-** type of change is below.
+** For each change for which there is a compatible table, an attempt is made 
+** to modify the table contents according to the UPDATE, INSERT or DELETE 
+** change. If a change cannot be applied cleanly, the conflict handler 
+** function passed as the fifth argument to sqlite3changeset_apply() may be 
+** invoked. A description of exactly when the conflict handler is invoked for 
+** each type of change is below.
 **
 ** Each time the conflict handler function is invoked, it must return one
 ** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or 
@@ -729,8 +739,12 @@ int sqlite3changeset_apply(
   sqlite3 *db,                    /* Apply change to "main" db of this handle */
   int nChangeset,                 /* Size of changeset in bytes */
   void *pChangeset,               /* Changeset blob */
+  int(*xFilter)(
+    void *pCtx,                   /* Copy of sixth arg to _apply() */
+    const char *zTab              /* Table name */
+  ),
   int(*xConflict)(
-    void *pCtx,                   /* Copy of fifth arg to _apply() */
+    void *pCtx,                   /* Copy of sixth arg to _apply() */
     int eConflict,                /* DATA, MISSING, CONFLICT, CONSTRAINT */
     sqlite3_changeset_iter *p     /* Handle describing change and conflict */
   ),
index 099307332892055b1af646444ab66edfd1d94840..9817b3c2f45f7874df3432e75b3afd060853c79d 100644 (file)
@@ -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);
index 31ce25fa38fc1047aaaa90032b5dfeea6e8a104a..f77afa1ffeb16f2b661a0b920f934fcb637ebee9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Modifications\sso\sthat\sthe\ssessions\sextension\sworks\swith\sblob\shandles.
-D 2011-07-11T19:45:38.954
+C Add\sthe\sxFilter\scallback\sto\sthe\ssqlite3changeset_apply()\sfunction.\sThis\scallback\sallows\sthe\sapplication\sto\saccept\sor\sreject\schanges\son\sa\sper-table\sbasis\swhen\sapplying\sa\schangeset.
+D 2011-07-13T15:21:02.741
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -110,9 +110,9 @@ F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478
 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26
 F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5
 F ext/session/sessionfault.test 401045278298a242cbc2e4bc986c102f01ff2180
-F ext/session/sqlite3session.c 26de50c3e34d89ae62e97024ad07e772e1c52db2
-F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf
-F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388
+F ext/session/sqlite3session.c c05d28332fcdd66c82de85f5459d71554e2259d7
+F ext/session/sqlite3session.h f34905c818569779ddaea1bbef43469177614c69
+F ext/session/test_session.c 209f13fa8f4a597ffcc15fd0f8a3f27ed079c5e5
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F main.mk f56d9895882f5cdd9f9f9ba8f8a679e9202288c1
@@ -961,7 +961,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00
 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d
-P 840bf9c2d92192ee3cc2aa7c0e9bdb805a066fd4
-R c823c2479e73fc426d6fab6fb150638b
+P 82ac16c4f873d3bd7c22f36ba7b974b4903a2d50
+R c22fa4ebad64b5fe1347a3f0a2dcb7e8
 U dan
-Z 6339a08530525dea9c6675e0fc9a27f5
+Z 6a509799e9e665bc4a33861bc6dba39f
index fecbc08bba671b7dadda3a9edfbaf2a0caeb7b2f..527039d08d4a04eb214a20ccb3756566ce67793f 100644 (file)
@@ -1 +1 @@
-82ac16c4f873d3bd7c22f36ba7b974b4903a2d50
\ No newline at end of file
+282474c42f24f0e66c69b576b72ef8ce764d49e2
\ No newline at end of file