1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge all of the trunk enchancements into the bedrock branch.

FossilOrigin-Name: ba2174bdca7d1d1aadf0a4de1e01aeba3d95b6656cb9ecdff88b00cfbef8f3a9
This commit is contained in:
drh
2025-07-17 15:31:16 +00:00
66 changed files with 3879 additions and 973 deletions

View File

@@ -525,6 +525,65 @@ static int test_obj_eq_string(Tcl_Obj *p, const char *z){
return (nObj==n && (n==0 || 0==memcmp(zObj, z, n)));
}
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;
}
static int test_filter_handler(
void *pCtx, /* Pointer to TestConflictHandler structure */
const char *zTab /* Table name */
@@ -544,6 +603,29 @@ static int test_filter_handler(
Tcl_BackgroundError(interp);
}
Tcl_DecrRefCount(pEval);
return res;
}
static int test_filter_v3_handler(
void *pCtx, /* Pointer to TestConflictHandler structure */
sqlite3_changeset_iter *pIter
){
TestConflictHandler *p = (TestConflictHandler *)pCtx;
int res = 1;
Tcl_Obj *pEval = 0;
Tcl_Interp *interp = p->interp;
pEval = Tcl_DuplicateObj(p->pFilterScript);
Tcl_IncrRefCount(pEval);
Tcl_ListObjAppendElement(0, pEval, testIterData(pIter));
if( 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;
}
@@ -781,7 +863,7 @@ static int testStreamInput(
static int SQLITE_TCLAPI testSqlite3changesetApply(
int bV2,
int iVersion,
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -798,11 +880,13 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
int nRebase = 0;
int flags = 0; /* Flags for apply_v2() */
assert( iVersion==1 || iVersion==2 || iVersion==3 );
memset(&sStr, 0, sizeof(sStr));
sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
/* Check for the -nosavepoint, -invert or -ignorenoop switches */
if( bV2 ){
if( iVersion==2 || iVersion==3 ){
while( objc>1 ){
const char *z1 = Tcl_GetString(objv[1]);
int n = (int)strlen(z1);
@@ -827,7 +911,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
if( objc!=4 && objc!=5 ){
const char *zMsg;
if( bV2 ){
if( iVersion==2 || iVersion==3 ){
zMsg = "?-nosavepoint? ?-inverse? ?-ignorenoop? "
"DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
}else{
@@ -847,30 +931,49 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
ctx.interp = interp;
if( sStr.nStream==0 ){
if( bV2==0 ){
rc = sqlite3changeset_apply(db, (int)nChangeset, pChangeset,
(objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx
);
}else{
rc = sqlite3changeset_apply_v2(db, (int)nChangeset, pChangeset,
(objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx,
&pRebase, &nRebase, flags
);
switch( iVersion ){
case 1:
rc = sqlite3changeset_apply(db, (int)nChangeset, pChangeset,
(objc==5)?test_filter_handler:0, test_conflict_handler, (void*)&ctx
);
break;
case 2:
rc = sqlite3changeset_apply_v2(db, (int)nChangeset, pChangeset,
(objc==5)?test_filter_handler:0, test_conflict_handler, (void*)&ctx,
&pRebase, &nRebase, flags
);
break;
case 3:
rc = sqlite3changeset_apply_v3(db, (int)nChangeset, pChangeset,
(objc==5)?test_filter_v3_handler:0, test_conflict_handler,
(void*)&ctx, &pRebase, &nRebase, flags
);
break;
}
}else{
sStr.aData = (unsigned char*)pChangeset;
sStr.nData = (int)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, flags
);
switch( iVersion ){
case 1:
rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr,
(objc==5) ? test_filter_handler : 0,
test_conflict_handler, (void *)&ctx
);
break;
case 2:
rc = sqlite3changeset_apply_v2_strm(db, testStreamInput, (void*)&sStr,
(objc==5) ? test_filter_handler : 0,
test_conflict_handler, (void *)&ctx,
&pRebase, &nRebase, flags
);
break;
case 3:
rc = sqlite3changeset_apply_v3_strm(db, testStreamInput, (void*)&sStr,
(objc==5) ? test_filter_v3_handler : 0,
test_conflict_handler, (void *)&ctx,
&pRebase, &nRebase, flags
);
break;
}
}
@@ -878,7 +981,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
return test_session_error(interp, rc, 0);
}else{
Tcl_ResetResult(interp);
if( bV2 && pRebase ){
if( (iVersion==2 || iVersion==3) && pRebase ){
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pRebase, nRebase));
}
}
@@ -895,7 +998,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_apply(
int objc,
Tcl_Obj *CONST objv[]
){
return testSqlite3changesetApply(0, clientData, interp, objc, objv);
return testSqlite3changesetApply(1, clientData, interp, objc, objv);
}
/*
** sqlite3changeset_apply_v2 DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
@@ -906,7 +1009,18 @@ static int SQLITE_TCLAPI test_sqlite3changeset_apply_v2(
int objc,
Tcl_Obj *CONST objv[]
){
return testSqlite3changesetApply(1, clientData, interp, objc, objv);
return testSqlite3changesetApply(2, clientData, interp, objc, objv);
}
/*
** sqlite3changeset_apply_v3 DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?
*/
static int SQLITE_TCLAPI test_sqlite3changeset_apply_v3(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
return testSqlite3changesetApply(3, clientData, interp, objc, objv);
}
/*
@@ -1039,64 +1153,6 @@ 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
*/
@@ -1877,6 +1933,7 @@ int TestSession_Init(Tcl_Interp *interp){
{ "sqlite3changeset_concat", test_sqlite3changeset_concat },
{ "sqlite3changeset_apply", test_sqlite3changeset_apply },
{ "sqlite3changeset_apply_v2", test_sqlite3changeset_apply_v2 },
{ "sqlite3changeset_apply_v3", test_sqlite3changeset_apply_v3 },
{ "sqlite3changeset_apply_replace_all",
test_sqlite3changeset_apply_replace_all },
{ "sql_exec_changeset", test_sql_exec_changeset },