using System.Data.Common; using FrameworkBLL.Connection; namespace FrameworkBLL.Engine { // ConflictPolicy values mirror TDSYNCJOB.CONFLICTPOLICY tinyint: // 0 = Overwrite — DELETE target rows WHERE PK IN (chunk PKs), then INSERT all // 1 = Skip — INSERT only if PK absent in target // 2 = LastWriteWins — write only if source.ModifiedOn > target.ModifiedOn; insert if absent public enum ConflictPolicy : byte { Overwrite = 0, Skip = 1, LastWriteWins = 2 } public interface ISyncEngine { // Streams source rows in configurable-sized pages — never loads the full table. // selectSql must already contain ORDER BY and OFFSET/FETCH NEXT @ChunkSize parameters. IAsyncEnumerable>> StreamPagedAsync( DbConnection conn, string selectSql, int chunkSize, IDictionary baseParams, CancellationToken ct); // Applies one chunk to the target using the specified conflict resolution strategy. // Returns number of rows written (inserted + updated). // srcDbType is required for TypeNormalizer; tgtDbType drives identifier quoting. Task ApplyChunkToTargetAsync( DbConnection targetConn, string schemaName, string tableName, IEnumerable> chunk, string pkColumn, ConflictPolicy policy, string? modifiedDateColumn, DatabaseType srcDbType, DatabaseType tgtDbType, CancellationToken ct); // Detects deletes via CDC for SQL Server or ISDELETED propagation for other engines. // tgtDbType drives identifier quoting on the target DELETE statement. Task ApplyDeletesAsync( DbConnection sourceConn, DbConnection targetConn, string schemaName, string tableName, string pkColumn, DateTime sinceUtc, DatabaseType sourceDbType, DatabaseType tgtDbType, CancellationToken ct); } // DatabaseType mirrors MDBTYPE.DBTYPEID public enum DatabaseType : int { SqlServer = 1, PostgreSQL = 2, MySQL = 3, Oracle = 4 } }