diff --git a/patch/0006-Support-Binlog.patch b/patch/0006-Support-Binlog.patch index d7dd62dd47a3b8ac8f4092742f3caccec8bd19fa..a733a692516c047fc53a2a4c328fafe34620e3dc 100644 --- a/patch/0006-Support-Binlog.patch +++ b/patch/0006-Support-Binlog.patch @@ -1,14 +1,14 @@ -From 759ae762933810cd476838f4b41afc52a9317d0c Mon Sep 17 00:00:00 2001 +From 9c6a4ddfc703ef7fed8fc3a645f18ff8ba87e874 Mon Sep 17 00:00:00 2001 From: Liu Hongyang -Date: Mon, 19 May 2025 22:18:58 +0800 +Date: Mon, 26 May 2025 20:46:29 +0800 Subject: [PATCH] Support-Binlog --- - src/sqlite3.c | 1313 ++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 1304 insertions(+), 9 deletions(-) + src/sqlite3.c | 1329 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 1320 insertions(+), 9 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c -index 2a4e87f..2f26487 100644 +index e7e8b3c..6565c14 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -2938,7 +2938,9 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); @@ -249,7 +249,7 @@ index 2a4e87f..2f26487 100644 }; /* -@@ -23666,6 +23874,12 @@ struct Vdbe { +@@ -23666,6 +23874,14 @@ struct Vdbe { int startPos; int addedRows; #endif /* SQLITE_SHARED_BLOCK_OPTIMIZATION */ @@ -257,12 +257,14 @@ index 2a4e87f..2f26487 100644 +/* begin of binlog related field */ + StmtType stmtType; /* Type of binlog statement */ + BinlogDMLData *pBinlogDMLData; /* Data for binlog row-based DML statement */ ++ const char *pDataTmp; /* Temporary binlog data for op_notfound */ ++ sqlite3_uint64 nDataTmp; /* Size of pDataTmp */ +/* end of binlog related field */ +#endif }; /* -@@ -88435,7 +88649,11 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ +@@ -88435,7 +88651,11 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ rc = sqlite3BtreeCommitPhaseOne(pBt, 0); } } @@ -275,7 +277,7 @@ index 2a4e87f..2f26487 100644 /* Do the commit only if all databases successfully complete phase 1. ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an ** IO error while deleting or truncating a journal file. It is unlikely, -@@ -88583,6 +88801,9 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ +@@ -88583,6 +88803,9 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** transaction is already guaranteed, but some stray 'cold' journals ** may be lying around. Returning an error code won't help matters. */ @@ -285,7 +287,7 @@ index 2a4e87f..2f26487 100644 disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); for(i=0; inDb; i++){ -@@ -88868,6 +89089,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ +@@ -88868,6 +89091,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ }else if( eStatementOp==0 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ eStatementOp = SAVEPOINT_RELEASE; @@ -295,7 +297,7 @@ index 2a4e87f..2f26487 100644 }else if( p->errorAction==OE_Abort ){ eStatementOp = SAVEPOINT_ROLLBACK; }else{ -@@ -89090,6 +89314,9 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ +@@ -89090,6 +89316,9 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ fclose(out); } } @@ -305,7 +307,7 @@ index 2a4e87f..2f26487 100644 #endif return p->rc & db->errMask; } -@@ -89194,6 +89421,9 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ +@@ -89194,6 +89423,9 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ sqlite3DbFree(db, p->aScan); } #endif @@ -315,7 +317,7 @@ index 2a4e87f..2f26487 100644 } /* -@@ -91886,6 +92116,44 @@ SQLITE_API int sqlite3_set_droptable_handle(sqlite3 *db, void (*xFunc)(sqlite3*, +@@ -91886,6 +92118,44 @@ SQLITE_API int sqlite3_set_droptable_handle(sqlite3 *db, void (*xFunc)(sqlite3*, } #endif /* SQLITE_ENABLE_DROPTABLE_CALLBACK */ @@ -360,7 +362,20 @@ index 2a4e87f..2f26487 100644 /* ** This is the top-level implementation of sqlite3_step(). Call ** sqlite3Step() to do most of the work. If a schema error occurs, -@@ -99584,6 +99852,15 @@ case OP_Insert: { +@@ -99189,6 +99459,12 @@ case OP_Found: { /* jump, in3, ncycle */ + pC->nullRow = 1-alreadyExists; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; ++#ifdef SQLITE_ENABLE_BINLOG ++ if ( pOp->opcode==OP_NotFound && r.nField==0 && !sqlite3IsSkipWriteBinlog(p)){ ++ p->nDataTmp = r.aMem->n; ++ p->pDataTmp = r.aMem->z; ++ } ++#endif + if( pOp->opcode==OP_Found ){ + VdbeBranchTaken(alreadyExists!=0,2); + if( alreadyExists ) goto jump_to_p2; +@@ -99584,6 +99860,15 @@ case OP_Insert: { } x.pKey = 0; assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); @@ -376,7 +391,7 @@ index 2a4e87f..2f26487 100644 rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), seekResult -@@ -99699,6 +99976,21 @@ case OP_Delete: { +@@ -99699,6 +99984,27 @@ case OP_Delete: { assert( CORRUPT_DB || pC->movetoTarget==iKey ); } #endif @@ -389,8 +404,14 @@ index 2a4e87f..2f26487 100644 + } else { + Table *pBinlogTab = sqlite3BinlogFindTable(pC->uc.pCursor); + if (pBinlogTab != NULL && !HasRowid(pBinlogTab)) { -+ /* If pC is not a table, then this is a delete operation in a without rowid table */ -+ sqlite3StoreBinlogRowData(p, pC->uc.pCursor, pC->szRow, (const char *)pC->aRow, SQLITE_DELETE, -1); ++ /* If pC is not a table, then this is a delete operation in a without rowid table ++ ** pC may have no row data or invalid row data when deletion has a subquery ++ ** so we need to get row data from op_notfound, which is stored in p->pDataTmp ++ */ ++ int isUseTmpData = pOp->p4type == P4_TABLE && p->nDataTmp != 0 && p->pDataTmp != NULL; ++ sqlite3_uint64 nData = isUseTmpData ? p->nDataTmp : pC->szRow; ++ const char *pData = isUseTmpData ? p->pDataTmp : (const char *)pC->aRow; ++ sqlite3StoreBinlogRowData(p, pC->uc.pCursor, nData, pData, SQLITE_DELETE, -1); + } + } + } @@ -398,7 +419,7 @@ index 2a4e87f..2f26487 100644 /* If the update-hook or pre-update-hook will be invoked, set zDb to ** the name of the db to pass as to it. Also set local pTab to a copy -@@ -100322,6 +100614,14 @@ case OP_IdxInsert: { /* in2 */ +@@ -100322,6 +100628,14 @@ case OP_IdxInsert: { /* in2 */ x.pKey = pIn2->z; x.aMem = aMem + pOp->p3; x.nMem = (u16)pOp->p4.i; @@ -413,7 +434,7 @@ index 2a4e87f..2f26487 100644 rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) -@@ -116953,7 +117253,11 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( +@@ -116953,7 +117267,11 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); renameTestSchema(pParse, zDb, iDb==1, "after rename", 0); @@ -426,7 +447,7 @@ index 2a4e87f..2f26487 100644 exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); -@@ -117135,6 +117439,9 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ +@@ -117135,6 +117453,9 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ zTab, zDb ); } @@ -436,7 +457,7 @@ index 2a4e87f..2f26487 100644 } } -@@ -117346,7 +117653,13 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn( +@@ -117346,7 +117667,13 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn( /* Drop and reload the database schema. */ renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename); renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1); @@ -451,7 +472,7 @@ index 2a4e87f..2f26487 100644 exit_rename_column: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zOld); -@@ -118957,7 +119270,13 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T +@@ -118957,7 +119284,13 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); } @@ -466,7 +487,7 @@ index 2a4e87f..2f26487 100644 exit_drop_column: sqlite3DbFree(db, zCol); sqlite3SrcListDelete(db, pSrc); -@@ -123295,6 +123614,9 @@ SQLITE_PRIVATE void sqlite3StartTable( +@@ -123295,6 +123628,9 @@ SQLITE_PRIVATE void sqlite3StartTable( sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeAddOp0(v, OP_Close); @@ -476,7 +497,7 @@ index 2a4e87f..2f26487 100644 } /* Normal (non-error) return. */ -@@ -124963,7 +125285,13 @@ SQLITE_PRIVATE void sqlite3CreateView( +@@ -124963,7 +125299,13 @@ SQLITE_PRIVATE void sqlite3CreateView( /* Use sqlite3EndTable() to add the view to the schema table */ sqlite3EndTable(pParse, 0, &sEnd, 0, 0); @@ -491,7 +512,7 @@ index 2a4e87f..2f26487 100644 create_view_fail: sqlite3SelectDelete(db, pSelect); if( IN_RENAME_OBJECT ){ -@@ -125486,6 +125814,9 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, +@@ -125486,6 +125828,9 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, sqlite3FkDropTable(pParse, pName, pTab); } sqlite3CodeDropTable(pParse, pTab, iDb, isView); @@ -501,7 +522,7 @@ index 2a4e87f..2f26487 100644 } exit_drop_table: -@@ -126344,6 +126675,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex( +@@ -126344,6 +126689,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex( /* A named index with an explicit CREATE INDEX statement */ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", onError==OE_None ? "" : " UNIQUE", n, pName->z); @@ -511,7 +532,7 @@ index 2a4e87f..2f26487 100644 }else{ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ /* zStmt = sqlite3MPrintf(""); */ -@@ -126546,6 +126880,9 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists +@@ -126546,6 +126894,9 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists sqlite3ChangeCookie(pParse, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); @@ -521,7 +542,7 @@ index 2a4e87f..2f26487 100644 } exit_drop_index: -@@ -127070,6 +127407,9 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ +@@ -127070,6 +127421,9 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ } } sqlite3VdbeAddOp0(v, OP_AutoCommit); @@ -531,7 +552,7 @@ index 2a4e87f..2f26487 100644 } /* -@@ -127092,6 +127432,9 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse *pParse, int eType){ +@@ -127092,6 +127446,9 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse *pParse, int eType){ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, isRollback); @@ -541,7 +562,7 @@ index 2a4e87f..2f26487 100644 } } -@@ -127112,6 +127455,9 @@ SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){ +@@ -127112,6 +127469,9 @@ SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){ return; } sqlite3VdbeAddOp4(v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC); @@ -551,7 +572,7 @@ index 2a4e87f..2f26487 100644 } } -@@ -137480,6 +137826,13 @@ typedef int (*sqlite3_loadext_entry)( +@@ -137480,6 +137840,13 @@ typedef int (*sqlite3_loadext_entry)( /* handle after drop table done */ #define sqlite3_set_droptable_handle sqlite3_api->set_droptable_handle #endif /* SQLITE_ENABLE_DROPTABLE_CALLBACK */ @@ -565,7 +586,7 @@ index 2a4e87f..2f26487 100644 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) -@@ -139533,6 +139886,9 @@ SQLITE_PRIVATE void sqlite3Pragma( +@@ -139533,6 +139900,9 @@ SQLITE_PRIVATE void sqlite3Pragma( if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; @@ -575,7 +596,7 @@ index 2a4e87f..2f26487 100644 /* Interpret the [schema.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ -@@ -152286,7 +152642,13 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( +@@ -152286,7 +152656,13 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( if (tr_tm == TK_INSTEAD){ tr_tm = TK_BEFORE; } @@ -590,7 +611,7 @@ index 2a4e87f..2f26487 100644 /* Build the Trigger object */ pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; -@@ -152681,6 +153043,13 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr) +@@ -152681,6 +153057,13 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr) goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger); @@ -604,7 +625,7 @@ index 2a4e87f..2f26487 100644 drop_trigger_cleanup: sqlite3SrcListDelete(db, pName); -@@ -153427,6 +153796,15 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger( +@@ -153427,6 +153810,15 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger( assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER ); assert( (op==TK_UPDATE)==(pChanges!=0) ); @@ -620,7 +641,7 @@ index 2a4e87f..2f26487 100644 for(p=pTrigger; p; p=p->pNext){ /* Sanity checking: The schema for the trigger and for the table are -@@ -180656,6 +181034,13 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ +@@ -180656,6 +181048,13 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ break; } #endif /* SQLITE_SHARED_BLOCK_OPTIMIZATION */ @@ -634,7 +655,7 @@ index 2a4e87f..2f26487 100644 default: { static const struct { int op; /* The opcode */ -@@ -181083,6 +181468,9 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ +@@ -181083,6 +181482,9 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ sqlite3CollapseDatabaseArray(db); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); @@ -644,7 +665,7 @@ index 2a4e87f..2f26487 100644 /* Tell the code in notify.c that the connection no longer holds any ** locks and does not require any further unlock-notify callbacks. -@@ -183308,6 +183696,9 @@ opendb_out: +@@ -183308,6 +183710,9 @@ opendb_out: db->mDropSchemaName = NULL; db->xDropTableHandle = NULL; #endif /* SQLITE_ENABLE_DROPTABLE_CALLBACK */ @@ -654,7 +675,7 @@ index 2a4e87f..2f26487 100644 *ppDb = db; #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ -@@ -256913,6 +257304,898 @@ static void walLogCheckpointInfo(Wal *pWal, sqlite3 *db, sqlite3_int64 startTime +@@ -256913,6 +257318,900 @@ static void walLogCheckpointInfo(Wal *pWal, sqlite3 *db, sqlite3_int64 startTime } #endif @@ -1453,7 +1474,6 @@ index 2a4e87f..2f26487 100644 + if (rc == SQLITE_OK || rc == SQLITE_CONSTRAINT) { + return SQLITE_OK; + } -+ sqlite3BinlogErrorCallback(srcDb, rc, "exec replay sql failed"); + return rc; +} + @@ -1510,6 +1530,9 @@ index 2a4e87f..2f26487 100644 + bSql = NULL; + } + sqlite3BinlogStmtFinalize(srcDb, &bStmt); ++ if (res != SQLITE_DONE && res != SQLITE_OK) { ++ sqlite3BinlogErrorCallback(srcDb, res, "exec replay sql failed"); ++ } + if (res != SQLITE_DONE) { + break; + } @@ -1541,7 +1564,7 @@ index 2a4e87f..2f26487 100644 + } + + const char *zFile = sqlite3_db_filename(db, 0); -+ if (zFile == NULL || (db->xBinlogHandle.flags & BINLOG_FLAG_ENABLE)) { ++ if (zFile == NULL || (db->xBinlogHandle.flags & BINLOG_FLAG_ENABLE) == 0) { + sqlite3_log(SQLITE_ERROR, "binlog db has no file path"); + return; + } @@ -1553,7 +1576,7 @@ index 2a4e87f..2f26487 100644 // hw export the symbols #ifdef SQLITE_EXPORT_SYMBOLS #ifndef SQLITE_CKSUMVFS_STATIC -@@ -256942,6 +258225,9 @@ struct sqlite3_api_routines_hw { +@@ -256942,6 +258241,9 @@ struct sqlite3_api_routines_hw { int (*key_v2)(sqlite3*,const char*,const void*,int); int (*rekey)(sqlite3*,const void*,int); int (*rekey_v2)(sqlite3*,const char*,const void*,int); @@ -1563,7 +1586,7 @@ index 2a4e87f..2f26487 100644 }; typedef struct sqlite3_api_routines_hw sqlite3_api_routines_hw; -@@ -256952,13 +258238,22 @@ static const sqlite3_api_routines_hw sqlite3HwApis = { +@@ -256952,13 +258254,22 @@ static const sqlite3_api_routines_hw sqlite3HwApis = { sqlite3_key, sqlite3_key_v2, sqlite3_rekey, diff --git a/patch/0007-Bugfix-on-current-version.patch b/patch/0007-Bugfix-on-current-version.patch index 80567a18a2c5c48244699dd587f0dace116efbe1..6fd652a58cea146cedda640ab7ed97da3aaca9ef 100644 --- a/patch/0007-Bugfix-on-current-version.patch +++ b/patch/0007-Bugfix-on-current-version.patch @@ -9,10 +9,10 @@ Signed-off-by: ryne3366 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/sqlite3.c b/src/sqlite3.c -index 2f26487..fac1ec2 100644 +index 6565c14..8fa785a 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c -@@ -121506,8 +121506,8 @@ static void attachFunc( +@@ -121520,8 +121520,8 @@ static void attachFunc( if( rc==SQLITE_OK ){ extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); @@ -23,7 +23,7 @@ index 2f26487..fac1ec2 100644 int t = sqlite3_value_type(argv[2]); switch( t ){ case SQLITE_INTEGER: -@@ -121524,14 +121524,7 @@ static void attachFunc( +@@ -121538,14 +121538,7 @@ static void attachFunc( break; case SQLITE_NULL: @@ -39,7 +39,7 @@ index 2f26487..fac1ec2 100644 break; } } -@@ -204144,6 +204137,39 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ +@@ -204158,6 +204151,39 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ return rc; } @@ -79,7 +79,7 @@ index 2f26487..fac1ec2 100644 /* ** Implementation of offsets() function. */ -@@ -204180,6 +204206,12 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( +@@ -204194,6 +204220,12 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( sCtx.iDocid = pCsr->iPrevId; sCtx.pCsr = pCsr; @@ -93,5 +93,5 @@ index 2f26487..fac1ec2 100644 ** string-buffer res for each column. */ -- -2.34.1 +2.25.1