Add WriteMode with SQL MERGE upsert support including optional DELETE to SQL Server extension#228
Merged
markjbrown merged 8 commits intomainfrom Jan 5, 2026
Merged
Conversation
- Create SqlWriteMode enum with Insert and Upsert modes - Update SqlServerSinkSettings with WriteMode and PrimaryKeyColumns - Implement WriteInsertAsync and WriteUpsertAsync methods - Add SQL MERGE logic using staging table approach - Create comprehensive unit tests for WriteMode settings - Update README with detailed WriteMode documentation and examples Co-authored-by: philnach <19275540+philnach@users.noreply.github.com>
- Add IValidatableObject interface implementation - Add validation to ensure at least one non-key column exists for Upsert mode - Improve error handling with proper transaction rollback - Fix BuildMergeStatement to handle edge cases gracefully - Add test for all-columns-are-primary-keys validation - Fix stack overflow by removing recursive validation call Co-authored-by: philnach <19275540+philnach@users.noreply.github.com>
- Add ValidateSqlIdentifier method to validate SQL identifiers - Apply validation in both WriteInsertAsync and WriteUpsertAsync - Prevent SQL injection by ensuring identifiers only contain safe characters - Allows alphanumeric, underscores, dots, spaces, and brackets Co-authored-by: philnach <19275540+philnach@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add WriteMode option for upsert operations in SQL Server
Add WriteMode with SQL MERGE upsert support to SQL Server extension
Dec 30, 2025
philnach
reviewed
Dec 30, 2025
…upport - Add DeleteNotMatchedBySource property to SqlServerSinkSettings (defaults to false) - Update BuildMergeStatement to include WHEN NOT MATCHED BY SOURCE THEN DELETE when enabled - Add 3 new unit tests for DeleteNotMatchedBySource functionality - Update README with documentation and warning about data loss - Add full table sync example configuration with DELETE enabled Co-authored-by: philnach <19275540+philnach@users.noreply.github.com>
- Add validation to ensure DeleteNotMatchedBySource is only used with Upsert mode - Add unit test to verify the validation logic - Prevents invalid configuration that would have no effect Co-authored-by: philnach <19275540+philnach@users.noreply.github.com>
…hedBySource - Update validation to allow Upsert mode with only primary key columns when DeleteNotMatchedBySource is true - This enables valid use case of syncing which records exist without updating other columns - Add test case to verify this scenario passes validation Co-authored-by: philnach <19275540+philnach@users.noreply.github.com>
Copilot
AI
changed the title
Add WriteMode with SQL MERGE upsert support to SQL Server extension
Add WriteMode with SQL MERGE upsert support including optional DELETE to SQL Server extension
Dec 30, 2025
philnach
approved these changes
Dec 30, 2025
Collaborator
philnach
left a comment
There was a problem hiding this comment.
This looks good to me.
Collaborator
|
@bowencode / @markjbrown, this looks good to me and is ready for review. The strategy here is to perform an upsert, which provides either insert / updating existing options and then there's the optional delete operation. This provides the complete option for "merging" sink with source. It does leverage a temp table as the intermediary, but that's reasonable given the potential amount of data. Copilot updated tests and documentation. Please take a look when you get a chance. |
markjbrown
approved these changes
Jan 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements
WriteModeconfiguration parameter for SQL Server sink to support upsert operations via SQL MERGE, including optional DELETE support for full table synchronization. Addresses requirement to sync source data with destination tables using insert-or-update semantics.Changes
New Configuration Options
WriteMode: Enum withInsert(default, preserves existing behavior) andUpsert(SQL MERGE)PrimaryKeyColumns: List of columns forming the primary key, required for Upsert modeDeleteNotMatchedBySource: Boolean flag to enable DELETE operations for full table sync (defaults to false)Implementation
WriteAsyncintoWriteInsertAsync(original logic) andWriteUpsertAsync(staging table + MERGE)WHEN MATCHED UPDATEandWHEN NOT MATCHED INSERTDeleteNotMatchedBySourceis true, MERGE includesWHEN NOT MATCHED BY SOURCE THEN DELETEfor complete synchronizationExample Configuration (Upsert without DELETE)
{ "SinkSettings": { "ConnectionString": "...", "TableName": "AccountTransactions", "WriteMode": "Upsert", "PrimaryKeyColumns": ["Id"], "ColumnMappings": [ {"ColumnName": "Id"}, {"ColumnName": "Amount", "DataType": "System.Decimal"} ] } }Example Configuration (Full Sync with DELETE)
{ "SinkSettings": { "ConnectionString": "...", "TableName": "Products", "WriteMode": "Upsert", "PrimaryKeyColumns": ["ProductId"], "DeleteNotMatchedBySource": true, "ColumnMappings": [ {"ColumnName": "ProductId"}, {"ColumnName": "ProductName"}, {"ColumnName": "Price", "DataType": "System.Decimal"} ] } }Sync Modes
The implementation supports three levels of synchronization:
Important Notes
DeleteNotMatchedBySourceis opt-in (defaults to false) to prevent accidental data lossTesting
Added 14 unit tests covering validation, deserialization, composite key scenarios, and DELETE functionality. All existing tests pass (25 tests passed, 1 skipped).
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.