Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add largely untested APIs for rebasing changesets. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions-rebase |
Files: | files | file ages | folders |
SHA3-256: |
39915b683b3f8d3bf872af1dede96bf2 |
User & Date: | dan 2018-03-14 21:06:58.004 |
Context
2018-03-15
| ||
19:25 | Add simple tests for the sessions module rebase API. (check-in: cf0d1abb44 user: dan tags: sessions-rebase) | |
2018-03-14
| ||
21:06 | Add largely untested APIs for rebasing changesets. (check-in: 39915b683b user: dan tags: sessions-rebase) | |
2018-03-13
| ||
20:31 | Add sqlite3_changeset_apply_v2() and apply_v2_strm() to the sessions module. (check-in: 445bfe977d user: dan tags: sessions-rebase) | |
Changes
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
2914 2915 2916 2917 2918 2919 2920 | ** successfully advanced to the next change in the changeset, an SQLite ** error code if an error occurs, or SQLITE_DONE if there are no further ** changes in the changeset. */ static int sessionChangesetNext( sqlite3_changeset_iter *p, /* Changeset iterator */ u8 **paRec, /* If non-NULL, store record pointer here */ | | > | 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 | ** successfully advanced to the next change in the changeset, an SQLite ** error code if an error occurs, or SQLITE_DONE if there are no further ** changes in the changeset. */ static int sessionChangesetNext( sqlite3_changeset_iter *p, /* Changeset iterator */ u8 **paRec, /* If non-NULL, store record pointer here */ int *pnRec, /* If non-NULL, store size of record here */ int *pbNew /* If non-NULL, true if new table */ ){ int i; u8 op; assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); /* If the iterator is in the error-state, return immediately. */ |
︙ | ︙ | |||
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 | } sessionDiscardData(&p->in); p->in.iCurrent = p->in.iNext; op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; p->in.iCurrent = p->in.iNext; if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; op = p->in.aData[p->in.iNext++]; } | > | 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 | } sessionDiscardData(&p->in); p->in.iCurrent = p->in.iNext; op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ if( pbNew ) *pbNew = 1; p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; p->in.iCurrent = p->in.iNext; if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; op = p->in.aData[p->in.iNext++]; } |
︙ | ︙ | |||
3027 3028 3029 3030 3031 3032 3033 | ** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE ** or SQLITE_CORRUPT. ** ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ int sqlite3changeset_next(sqlite3_changeset_iter *p){ | | | 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 | ** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE ** or SQLITE_CORRUPT. ** ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ int sqlite3changeset_next(sqlite3_changeset_iter *p){ return sessionChangesetNext(p, 0, 0, 0); } /* ** The following function extracts information on the current change ** from a changeset iterator. It may only be called after changeset_next() ** has returned SQLITE_ROW. */ |
︙ | ︙ | |||
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 | /* ** This function is called to merge two changes to the same row together as ** part of an sqlite3changeset_concat() operation. A new change object is ** allocated and a pointer to it stored in *ppNew. */ static int sessionChangeMerge( SessionTable *pTab, /* Table structure */ int bPatchset, /* True for patchsets */ SessionChange *pExist, /* Existing change */ int op2, /* Second change operation */ int bIndirect, /* True if second change is indirect */ u8 *aRec, /* Second change record */ int nRec, /* Number of bytes in aRec */ SessionChange **ppNew /* OUT: Merged change */ | > | 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 | /* ** This function is called to merge two changes to the same row together as ** part of an sqlite3changeset_concat() operation. A new change object is ** allocated and a pointer to it stored in *ppNew. */ static int sessionChangeMerge( SessionTable *pTab, /* Table structure */ int bRebase, /* True for a rebase hash-table */ int bPatchset, /* True for patchsets */ SessionChange *pExist, /* Existing change */ int op2, /* Second change operation */ int bIndirect, /* True if second change is indirect */ u8 *aRec, /* Second change record */ int nRec, /* Number of bytes in aRec */ SessionChange **ppNew /* OUT: Merged change */ |
︙ | ︙ | |||
4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 | } memset(pNew, 0, sizeof(SessionChange)); pNew->op = op2; pNew->bIndirect = bIndirect; pNew->nRecord = nRec; pNew->aRecord = (u8*)&pNew[1]; memcpy(pNew->aRecord, aRec, nRec); }else{ int op1 = pExist->op; /* ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. ** op1=INSERT, op2=UPDATE -> INSERT. ** op1=INSERT, op2=DELETE -> (none) | > > | 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 | } memset(pNew, 0, sizeof(SessionChange)); pNew->op = op2; pNew->bIndirect = bIndirect; pNew->nRecord = nRec; pNew->aRecord = (u8*)&pNew[1]; memcpy(pNew->aRecord, aRec, nRec); }else if( bRebase){ assert( 0 ); }else{ int op1 = pExist->op; /* ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. ** op1=INSERT, op2=UPDATE -> INSERT. ** op1=INSERT, op2=DELETE -> (none) |
︙ | ︙ | |||
4641 4642 4643 4644 4645 4646 4647 | /* ** Add all changes in the changeset traversed by the iterator passed as ** the first argument to the changegroup hash tables. */ static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ | | > | | 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 | /* ** Add all changes in the changeset traversed by the iterator passed as ** the first argument to the changegroup hash tables. */ static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ int bRebase /* True if hash table is for rebasing */ ){ u8 *aRec; int nRec; int rc = SQLITE_OK; SessionTable *pTab = 0; while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ const char *zNew; int nCol; int op; int iHash; int bIndirect; SessionChange *pChange; SessionChange *pExist = 0; |
︙ | ︙ | |||
4729 4730 4731 4732 4733 4734 4735 | pExist = *pp; *pp = (*pp)->pNext; pTab->nEntry--; break; } } | | | 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 | pExist = *pp; *pp = (*pp)->pNext; pTab->nEntry--; break; } } rc = sessionChangeMerge(pTab, bRebase, pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); if( rc ) break; if( pChange ){ pChange->pNext = pTab->apChange[iHash]; pTab->apChange[iHash] = pChange; pTab->nEntry++; |
︙ | ︙ | |||
4837 4838 4839 4840 4841 4842 4843 | */ int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ | | | 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 | */ int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; } /* ** Obtain a buffer containing a changeset representing the concatenation |
︙ | ︙ | |||
4868 4869 4870 4871 4872 4873 4874 | void *pIn ){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ | | | 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 | void *pIn ){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; } /* ** Streaming versions of changegroup_output(). |
︙ | ︙ | |||
4952 4953 4954 4955 4956 4957 4958 4959 4960 | if( rc==SQLITE_OK ){ rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); } sqlite3changegroup_delete(pGrp); return rc; } #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 | if( rc==SQLITE_OK ){ rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); } sqlite3changegroup_delete(pGrp); return rc; } struct sqlite3_rebaser { sqlite3_changegroup grp; /* Hash table */ }; /* ** Buffers a1 and a2 must both contain a sessions module record nCol ** fields in size. This function appends an nCol sessions module ** record to buffer pBuf that is a copy of a1, except that: ** ** + If bUndefined is 0, for each field that is not "undefined" in either ** a1[] or a2[], swap in the field from a2[]. ** ** + If bUndefined is 1, for each field that is "undefined" in a1[] ** swap in the field from a2[]. */ static void sessionAppendRecordMerge( SessionBuffer *pBuf, int nCol, int bUndefined, u8 *a1, int n1, u8 *a2, int n2, int *pRc ){ sessionBufferGrow(pBuf, n1+n2, pRc); if( *pRc==SQLITE_OK ){ int i; u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; for(i=0; i<nCol; i++){ int nn1 = sessionSerialLen(a1); int nn2 = sessionSerialLen(a2); if( bUndefined==0 ){ if( *a1 && *a2 ){ memcpy(pOut, a2, nn2); pOut += nn2; }else{ memcpy(pOut, a1, nn1); pOut += nn1; } }else{ if( *a1==0 ){ memcpy(pOut, a2, nn2); pOut += nn2; }else{ memcpy(pOut, a1, nn1); pOut += nn1; } } a1 += n1; a2 += n2; } } } static int sessionRebase( sqlite3_rebaser *p, /* Rebaser hash table */ sqlite3_changeset_iter *pIter, /* Input data */ int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut, /* Context for xOutput callback */ int *pnOut, /* OUT: Number of bytes in output changeset */ void **ppOut /* OUT: Inverse of pChangeset */ ){ int rc = SQLITE_OK; u8 *aRec = 0; int nRec = 0; int bNew = 0; SessionTable *pTab = 0; SessionBuffer sOut = {0,0,0}; while( SQLITE_OK==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ SessionChange *pChange = 0; if( bNew ){ const char *zTab = pIter->zTab; for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; } bNew = 0; /* Append a table header to the output for this new table */ sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc); sessionAppendVarint(&sOut, pIter->nCol, &rc); sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc); sessionAppendBlob(&sOut, (u8*)pIter->zTab, strlen(pIter->zTab)+1, &rc); } if( pTab ){ int bPkOnly = (pIter->bPatchset && pIter->op==SQLITE_DELETE); int iHash = sessionChangeHash(pTab, bPkOnly, aRec, pTab->nChange); for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ if( sessionChangeEqual(pTab, bPkOnly, aRec, 0, pChange->aRecord) ){ break; } } } if( pChange ){ assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT ); /* If pChange is an INSERT, then rebase the change. If it is a ** DELETE, omit the change from the output altogether. */ if( pChange->op==SQLITE_INSERT ){ if( pChange->bIndirect ){ /* The change being rebased against was a DELETE. So, if the ** input is a: ** ** DELETE - omit the change altogether. ** UPDATE - change to an INSERT, ** INSERT - no change (output the record as is). */ if( pIter->op!=SQLITE_DELETE ){ sessionAppendByte(&sOut, SQLITE_INSERT, &rc); sessionAppendByte(&sOut, pIter->bIndirect, &rc); if( pIter->op==SQLITE_INSERT ){ sessionAppendBlob(&sOut, aRec, nRec, &rc); }else{ sessionAppendRecordMerge(&sOut, pIter->nCol, 1, aRec, nRec, pChange->aRecord, pChange->nRecord, &rc ); } } }else{ sessionAppendByte(&sOut, pIter->op, &rc); sessionAppendByte(&sOut, pIter->bIndirect, &rc); if( pIter->op==SQLITE_INSERT ){ sessionAppendBlob(&sOut, aRec, nRec, &rc); }else{ u8 *pCsr = aRec; sessionAppendRecordMerge(&sOut, pIter->nCol, 0, aRec, nRec, pChange->aRecord, pChange->nRecord, &rc ); if( pIter->op==SQLITE_UPDATE ){ sessionSkipRecord(&pCsr, pIter->nCol); sessionAppendBlob(&sOut, pCsr, nRec - (pCsr-aRec), &rc); } } } } }else{ sessionAppendByte(&sOut, pIter->op, &rc); sessionAppendByte(&sOut, pIter->bIndirect, &rc); sessionAppendBlob(&sOut, aRec, nRec, &rc); } if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; } if( rc ) break; } if( rc!=SQLITE_OK ){ sqlite3_free(sOut.aBuf); memset(&sOut, 0, sizeof(sOut)); } if( rc==SQLITE_OK ){ if( xOutput ){ if( sOut.nBuf>0 ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); } }else{ *ppOut = (void*)sOut.aBuf; *pnOut = sOut.nBuf; sOut.aBuf = 0; } } sqlite3_free(sOut.aBuf); return rc; } /* ** Create a new rebaser object. */ int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ int rc = SQLITE_OK; sqlite3_rebaser *pNew; pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); if( pNew==0 ){ rc = SQLITE_NOMEM; } *ppNew = pNew; return rc; } /* ** Call this one or more times to configure a rebaser. */ int sqlite3rebaser_configure( sqlite3_rebaser *p, int nRebase, const void *pRebase ){ sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, &p->grp, 1); } sqlite3changeset_finalize(pIter); return rc; } /* ** Rebase a changeset according to current rebaser configuration */ int sqlite3rebaser_rebase( sqlite3_rebaser *p, int nIn, const void *pIn, int *pnOut, void **ppOut ){ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); if( rc==SQLITE_OK ){ rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); sqlite3changeset_finalize(pIter); } return rc; } /* ** Rebase a changeset according to current rebaser configuration */ int sqlite3rebaser_rebase_strm( sqlite3_rebaser *p, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ){ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); sqlite3changeset_finalize(pIter); } return rc; } /* ** Destroy a rebaser object */ void sqlite3rebaser_destroy(sqlite3_rebaser *p){ if( p ){ sessionDeleteTable(p->grp.pList); sqlite3_free(p); } } #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 | ** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. ** </dl> */ #define SQLITE_CHANGESET_OMIT 0 #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 /* ** CAPI3REF: Streaming Versions of API functions. ** ** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** <table border=1 style="margin-left:8ex;margin-right:8ex"> | > > > > > > > > > > > > > > > > > > > > > | 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 | ** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. ** </dl> */ #define SQLITE_CHANGESET_OMIT 0 #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 typedef struct sqlite3_rebaser sqlite3_rebaser; /* Create a new rebaser object */ int sqlite3rebaser_create(sqlite3_rebaser **ppNew); /* Call this one or more times to configure a rebaser */ int sqlite3rebaser_configure( sqlite3_rebaser*, int nRebase, const void *pRebase ); /* Rebase a changeset according to current rebaser configuration */ int sqlite3rebaser_rebase( sqlite3_rebaser*, int nIn, const void *pIn, int *pnOut, void **ppOut ); /* Destroy a rebaser object */ void sqlite3rebaser_destroy(sqlite3_rebaser *p); /* ** CAPI3REF: Streaming Versions of API functions. ** ** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
︙ | ︙ | |||
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 | int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus } #endif #endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ | > > > > > > > | 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 | int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3rebaser_rebase_strm( sqlite3_rebaser *pRebaser, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus } #endif #endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ |
Changes to ext/session/test_session.c.
︙ | ︙ | |||
757 758 759 760 761 762 763 | (objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx, &pRebase, &nRebase ); } }else{ sStr.aData = (unsigned char*)pChangeset; sStr.nData = nChangeset; | > | | > | > > > > > > > | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | (objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx, &pRebase, &nRebase ); } }else{ sStr.aData = (unsigned char*)pChangeset; sStr.nData = nChangeset; if( bV2==0 ){ rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr, (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx ); }else{ rc = sqlite3changeset_apply_v2_strm(db, testStreamInput, (void*)&sStr, (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx, &pRebase, &nRebase ); } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); }else{ Tcl_ResetResult(interp); if( bV2 && pRebase ){ |
︙ | ︙ |