]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add tests for sqlite3changegroup_add_change().
authordan <Dan Kennedy>
Mon, 6 May 2024 17:21:23 +0000 (17:21 +0000)
committerdan <Dan Kennedy>
Mon, 6 May 2024 17:21:23 +0000 (17:21 +0000)
FossilOrigin-Name: 9d67bedc20c3a59e5488f0eaea6a6611940a9cb63f7cf5e687b061cb5d510943

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

index e6081a6ce0d36a80ed016699c63e40a47bb39484..7a8132bfa6011734ede3ab5a86e69bcb729fcaa6 100644 (file)
@@ -6031,11 +6031,14 @@ int sqlite3changegroup_add_change(
   sqlite3_changegroup *pGrp,
   sqlite3_changeset_iter *pIter
 ){
-  if( pIter->in.iCurrent==pIter->in.iNext || pIter->rc!=SQLITE_OK ){
-    /* Iterator does not point to any valid entry. */
+  if( pIter->in.iCurrent==pIter->in.iNext 
+   || pIter->rc!=SQLITE_OK 
+   || pIter->bInvert
+  ){
+    /* Iterator does not point to any valid entry or is an INVERT iterator. */
     return SQLITE_ERROR;
   }
-  return sessionChangesetToHash(pIter, pGrp, 0);
+  return sessionOneChangeToHash(pGrp, pIter, 0);
 }
 
 /*
index 69c8ee588cc4fb021f127f97ef144a458fbcc2a9..ebd2cc5312ec6e250e7cb98f7df2f56ad54332d8 100644 (file)
@@ -1067,7 +1067,9 @@ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
 **
 ** The iterator must point to a valid entry when this function is called.
 ** If it does not, SQLITE_ERROR is returned and no change is added to the
-** changegroup.
+** changegroup. Additionally, the iterator must not have been opened with
+** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
+** returned.
 */
 int sqlite3changegroup_add_change(
   sqlite3_changegroup*,
index f6db38c8a2db0ed6a7327958254690eccb31619d..00c3c25068cddafd0be5599242d2b48f59806a11 100644 (file)
@@ -1038,6 +1038,64 @@ static int SQLITE_TCLAPI test_sqlite3changeset_concat(
   return rc;
 }
 
+static Tcl_Obj *testIterData(sqlite3_changeset_iter *pIter){
+  Tcl_Obj *pVar = 0;
+  int nCol;                       /* Number of columns in table */
+  int nCol2;                      /* Number of columns in table */
+  int op;                         /* SQLITE_INSERT, UPDATE or DELETE */
+  const char *zTab;               /* Name of table change applies to */
+  Tcl_Obj *pOld;                  /* Vector of old.* values */
+  Tcl_Obj *pNew;                  /* Vector of new.* values */
+  int bIndirect;
+    
+  char *zPK;
+  unsigned char *abPK;
+  int i;
+
+  sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
+  pVar = Tcl_NewObj();
+
+  Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
+        op==SQLITE_INSERT ? "INSERT" :
+        op==SQLITE_UPDATE ? "UPDATE" : 
+        "DELETE", -1
+  ));
+
+  Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
+  Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
+
+  zPK = ckalloc(nCol+1);
+  memset(zPK, 0, nCol+1);
+  sqlite3changeset_pk(pIter, &abPK, &nCol2);
+  assert( nCol==nCol2 );
+  for(i=0; i<nCol; i++){
+    zPK[i] = (abPK[i] ? 'X' : '.');
+  }
+  Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
+  ckfree(zPK);
+
+  pOld = Tcl_NewObj();
+  if( op!=SQLITE_INSERT ){
+    for(i=0; i<nCol; i++){
+      sqlite3_value *pVal;
+      sqlite3changeset_old(pIter, i, &pVal);
+      test_append_value(pOld, pVal);
+    }
+  }
+  pNew = Tcl_NewObj();
+  if( op!=SQLITE_DELETE ){
+    for(i=0; i<nCol; i++){
+      sqlite3_value *pVal;
+      sqlite3changeset_new(pIter, i, &pVal);
+      test_append_value(pNew, pVal);
+    }
+  }
+  Tcl_ListObjAppendElement(0, pVar, pOld);
+  Tcl_ListObjAppendElement(0, pVar, pNew);
+
+  return pVar;
+}
+
 /*
 ** sqlite3session_foreach VARNAME CHANGESET SCRIPT
 */
@@ -1111,67 +1169,8 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach(
   }
 
   while( SQLITE_ROW==sqlite3changeset_next(pIter) ){
-    int nCol;                     /* Number of columns in table */
-    int nCol2;                    /* Number of columns in table */
-    int op;                       /* SQLITE_INSERT, UPDATE or DELETE */
-    const char *zTab;             /* Name of table change applies to */
-    Tcl_Obj *pVar;                /* Tcl value to set $VARNAME to */
-    Tcl_Obj *pOld;                /* Vector of old.* values */
-    Tcl_Obj *pNew;                /* Vector of new.* values */
-    int bIndirect;
-
-    char *zPK;
-    unsigned char *abPK;
-    int i;
-
-    /* Test that _fk_conflicts() returns SQLITE_MISUSE if called on this
-    ** iterator. */
-    int nDummy;
-    if( SQLITE_MISUSE!=sqlite3changeset_fk_conflicts(pIter, &nDummy) ){
-      sqlite3changeset_finalize(pIter);
-      return TCL_ERROR;
-    }
-
-    sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
-    pVar = Tcl_NewObj();
-    Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
-          op==SQLITE_INSERT ? "INSERT" :
-          op==SQLITE_UPDATE ? "UPDATE" : 
-          "DELETE", -1
-    ));
-
-    Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
-    Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
-
-    zPK = ckalloc(nCol+1);
-    memset(zPK, 0, nCol+1);
-    sqlite3changeset_pk(pIter, &abPK, &nCol2);
-    assert( nCol==nCol2 );
-    for(i=0; i<nCol; i++){
-      zPK[i] = (abPK[i] ? 'X' : '.');
-    }
-    Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
-    ckfree(zPK);
-
-    pOld = Tcl_NewObj();
-    if( op!=SQLITE_INSERT ){
-      for(i=0; i<nCol; i++){
-        sqlite3_value *pVal;
-        sqlite3changeset_old(pIter, i, &pVal);
-        test_append_value(pOld, pVal);
-      }
-    }
-    pNew = Tcl_NewObj();
-    if( op!=SQLITE_DELETE ){
-      for(i=0; i<nCol; i++){
-        sqlite3_value *pVal;
-        sqlite3changeset_new(pIter, i, &pVal);
-        test_append_value(pNew, pVal);
-      }
-    }
-    Tcl_ListObjAppendElement(0, pVar, pOld);
-    Tcl_ListObjAppendElement(0, pVar, pNew);
-
+    Tcl_Obj *pVar = 0;            /* Tcl value to set $VARNAME to */
+    pVar = testIterData(pIter);
     Tcl_ObjSetVar2(interp, pVarname, 0, pVar, 0);
     rc = Tcl_EvalObjEx(interp, pScript, 0);
     if( rc!=TCL_OK && rc!=TCL_CONTINUE ){
@@ -1459,6 +1458,12 @@ struct TestChangegroup {
   sqlite3_changegroup *pGrp;
 };
 
+typedef struct TestChangeIter TestChangeIter;
+struct TestChangeIter {
+  sqlite3_changeset_iter *pIter;
+};
+
+
 /*
 ** Destructor for Tcl changegroup command object.
 */
@@ -1491,6 +1496,7 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
     { "add",          1, "CHANGESET",  }, /* 1 */
     { "output",       0, "",           }, /* 2 */
     { "delete",       0, "",           }, /* 3 */
+    { "add_change",   1, "ITERATOR",   }, /* 4 */
     { 0 }
   };
   int rc = TCL_OK;
@@ -1542,6 +1548,24 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
       break;
     };
 
+    case 4: {      /* add_change */
+      Tcl_CmdInfo cmdInfo;            /* Database Tcl command (objv[2]) info */
+      TestChangeIter *pIter = 0;
+      const char *zIter = Tcl_GetString(objv[2]);
+      if( 0==Tcl_GetCommandInfo(interp, zIter, &cmdInfo) ){
+        Tcl_AppendResult(interp, "no such iter: ", Tcl_GetString(objv[2]), 0);
+        return TCL_ERROR;
+      }
+
+      pIter = (struct TestChangeIter*)cmdInfo.objClientData;
+
+      rc = sqlite3changegroup_add_change(p->pGrp, pIter->pIter);
+      if( rc!=SQLITE_OK ){
+        rc = test_session_error(interp, rc, 0);
+      }
+      break;
+    };
+
     default: {     /* delete */
       assert( iSub==3 );
       Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
@@ -1585,10 +1609,16 @@ static int SQLITE_TCLAPI test_sqlite3changegroup(
   return TCL_OK;
 }
 
-typedef struct TestChangeIter TestChangeIter;
-struct TestChangeIter {
-  sqlite3_changeset_iter *pIter;
-};
+extern const char *sqlite3ErrName(int);
+
+/*
+** Destructor for Tcl iterator command object.
+*/
+static void test_iter_del(void *clientData){
+  TestChangeIter *p = (TestChangeIter*)clientData;
+  sqlite3changeset_finalize(p->pIter);
+  ckfree(p);
+}
 
 static int SQLITE_TCLAPI test_iter_cmd(
   void * clientData,
@@ -1596,6 +1626,44 @@ static int SQLITE_TCLAPI test_iter_cmd(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
+  static const char *aSub[] = {
+    "next",        /* 0 */
+    "data",        /* 1 */
+    "finalize",    /* 2 */
+    0
+  };
+  int iSub = 0;
+
+  TestChangeIter *p = (TestChangeIter*)clientData;
+  int rc = SQLITE_OK;
+
+  if( objc<2 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "CMD");
+    return TCL_ERROR;
+  }
+
+  if( Tcl_GetIndexFromObj(interp, objv[1], aSub, "sub-command", 0, &iSub) ){
+    return TCL_ERROR;
+  }
+  switch( iSub ){
+    case 0:
+      rc = sqlite3changeset_next(p->pIter);
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+      break;
+    case 1:
+      Tcl_SetObjResult(interp, testIterData(p->pIter));
+      break;
+    case 2:
+      rc = sqlite3changeset_finalize(p->pIter);
+      p->pIter = 0;
+      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+      break;
+    default:
+      assert( 0 );
+      break;
+  }
+
   return TCL_OK;
 }
 
@@ -1645,7 +1713,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_start(
   pNew->pIter = pIter;
 
   sprintf(zCmd, "csiter%d", iCmd++);
-  Tcl_CreateObjCommand(interp, zCmd, test_iter_cmd, (void*)pNew, 0);
+  Tcl_CreateObjCommand(interp, zCmd, test_iter_cmd, (void*)pNew, test_iter_del);
   Tcl_SetObjResult(interp, Tcl_NewStringObj(zCmd, -1));
   return TCL_OK;
 }
index e95fd9eb1b8c8f844b1538876c5602562f6be876..d8069fa67e5371aedfe7ba596537bb1d5e4090c6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\snew\ssessions\sAPI\ssqlite3changegroup_add_change().
-D 2024-05-04T21:10:24.120
+C Add\stests\sfor\ssqlite3changegroup_add_change().
+D 2024-05-06T17:21:23.939
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -582,9 +582,9 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
 F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
 F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
 F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
-F ext/session/sqlite3session.c 0cdf052460fe11fd00a5c3f83b4a7152ed6c72ff7dacd4664c30ce16579748d7
-F ext/session/sqlite3session.h e36392d1087e42f4e691caff23cb99f4e9fc3b8b88ac7504dac3ea30883dc08b
-F ext/session/test_session.c ba40d22840f3ed667448e34ab4eaa38e69f62f23af530c0f8f70a64ed92b039b
+F ext/session/sqlite3session.c c7473aafbd88f796391a8c25aa90975a8f3729ab7f4f8cf74ab9d3b014e10abe
+F ext/session/sqlite3session.h 1e9a1ab23701d85bb1a3794bae38a4c618c652ff84f744a7fd9b6339e9c8af2e
+F ext/session/test_session.c 8bcc857125372e640f75ab63b4188080f9bbab92b65f86dfd160721c574b2044
 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt ca7e9ee82ca4e1c1744295f8184dd70edfae1992865d26c64303f539eb6c084c
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
@@ -2188,11 +2188,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8c3086f9fe502dfc4a1fa610a23794fb037721df29dc5d2126cfb749a9d44a50
-R 92b682ff0cdf49829f0c1fddda225a0c
-T *branch * changegroup-add-change
-T *sym-changegroup-add-change *
-T -sym-trunk *
+P 73647db1ddfdaf40cbf18f1e47c10b4a906489f6d34d7667f0f2ff532f1eb37c
+R 57bf39cdeb4ff65bb7bb7b027bf86eec
 U dan
-Z d18fc76401ae213ec8fe7cdec8b2f0ce
+Z 43c000dbcc9bde7f8ce3b6fbffdd9a33
 # Remove this line to create a well-formed Fossil manifest.
index 6e66176619c4b907e4a174c5b87108c9beb31551..18a3d1fa2a72fc9b2ae8dd259f742f5db7b0ae2b 100644 (file)
@@ -1 +1 @@
-73647db1ddfdaf40cbf18f1e47c10b4a906489f6d34d7667f0f2ff532f1eb37c
\ No newline at end of file
+9d67bedc20c3a59e5488f0eaea6a6611940a9cb63f7cf5e687b061cb5d510943
\ No newline at end of file