internal DataRow MergeRow(DataRow row, DataRow targetRow, bool preserveChanges, Index idxSearch) { if (targetRow == null) { targetRow = this.NewEmptyRow(); targetRow.oldRecord = recordManager.ImportRecord(row.Table, row.oldRecord); targetRow.newRecord = targetRow.oldRecord; if(row.oldRecord != row.newRecord) { targetRow.newRecord = recordManager.ImportRecord(row.Table, row.newRecord); } InsertRow(targetRow, -1); } else { // SQLBU 500789: Record Manager corruption during Merge when target row in edit state // the newRecord would be freed and overwrite tempRecord (which became the newRecord) // this would leave the DataRow referencing a freed record and leaking memory for the now lost record int proposedRecord = targetRow.tempRecord; // by saving off the tempRecord, EndEdit won't free newRecord targetRow.tempRecord = -1; try { DataRowState saveRowState = targetRow.RowState; int saveIdxRecord = (saveRowState == DataRowState.Added) ? targetRow.newRecord : saveIdxRecord = targetRow.oldRecord; int newRecord; int oldRecord; if (targetRow.RowState == DataRowState.Unchanged && row.RowState == DataRowState.Unchanged) { // unchanged row merging with unchanged row oldRecord = targetRow.oldRecord; newRecord = (preserveChanges) ? recordManager.CopyRecord(this, oldRecord, -1) : targetRow.newRecord; oldRecord = recordManager.CopyRecord(row.Table, row.oldRecord, targetRow.oldRecord); SetMergeRecords(targetRow, newRecord, oldRecord, DataRowAction.Change); } else if (row.newRecord == -1) { // Incoming row is deleted oldRecord = targetRow.oldRecord; if (preserveChanges) { newRecord = (targetRow.RowState == DataRowState.Unchanged)? recordManager.CopyRecord(this, oldRecord, -1) : targetRow.newRecord; } else newRecord = -1; oldRecord = recordManager.CopyRecord(row.Table, row.oldRecord, oldRecord); // Change index record, need to update index if (saveIdxRecord != ((saveRowState == DataRowState.Added) ? newRecord : oldRecord)) { SetMergeRecords(targetRow, newRecord, oldRecord, (newRecord == -1) ? DataRowAction.Delete : DataRowAction.Change); idxSearch.Reset(); saveIdxRecord = ((saveRowState == DataRowState.Added) ? newRecord : oldRecord); } else { SetMergeRecords(targetRow, newRecord, oldRecord, (newRecord == -1) ? DataRowAction.Delete : DataRowAction.Change); } } else { // incoming row is added, modified or unchanged (targetRow is not unchanged) oldRecord = targetRow.oldRecord; newRecord = targetRow.newRecord; if (targetRow.RowState == DataRowState.Unchanged) { newRecord = recordManager.CopyRecord(this, oldRecord, -1); } oldRecord = recordManager.CopyRecord(row.Table, row.oldRecord, oldRecord); if (!preserveChanges) { newRecord = recordManager.CopyRecord(row.Table, row.newRecord, newRecord); } SetMergeRecords(targetRow, newRecord, oldRecord, DataRowAction.Change); } if (saveRowState == DataRowState.Added && targetRow.oldRecord != -1) idxSearch.Reset(); Debug.Assert(saveIdxRecord == ((saveRowState == DataRowState.Added) ? targetRow.newRecord : targetRow.oldRecord), "oops, you change index record without noticing it"); } finally { targetRow.tempRecord = proposedRecord; } } // Merge all errors if (row.HasErrors) { if (targetRow.RowError.Length == 0) { targetRow.RowError = row.RowError; } else { targetRow.RowError += " ]:[ " + row.RowError; } DataColumn[] cols = row.GetColumnsInError(); for (int i = 0; i < cols.Length; i++) { DataColumn col = targetRow.Table.Columns[cols[i].ColumnName]; targetRow.SetColumnError(col, row.GetColumnError(cols[i])); } }else { if (!preserveChanges) { targetRow.ClearErrors(); } } return targetRow; }
internal DataRow MergeRow(DataRow row, DataRow targetRow, bool preserveChanges, Index idxSearch) { if (targetRow == null) { targetRow = this.NewEmptyRow(); targetRow.oldRecord = this.recordManager.ImportRecord(row.Table, row.oldRecord); targetRow.newRecord = targetRow.oldRecord; if (row.oldRecord != row.newRecord) { targetRow.newRecord = this.recordManager.ImportRecord(row.Table, row.newRecord); } this.InsertRow(targetRow, -1L); } else { int tempRecord = targetRow.tempRecord; targetRow.tempRecord = -1; try { int oldRecord; int newRecord; int num4; DataRowState rowState = targetRow.RowState; num4 = (rowState == DataRowState.Added) ? targetRow.newRecord : (num4 = targetRow.oldRecord); if ((targetRow.RowState == DataRowState.Unchanged) && (row.RowState == DataRowState.Unchanged)) { oldRecord = targetRow.oldRecord; newRecord = preserveChanges ? this.recordManager.CopyRecord(this, oldRecord, -1) : targetRow.newRecord; oldRecord = this.recordManager.CopyRecord(row.Table, row.oldRecord, targetRow.oldRecord); this.SetMergeRecords(targetRow, newRecord, oldRecord, DataRowAction.Change); } else if (row.newRecord == -1) { oldRecord = targetRow.oldRecord; if (preserveChanges) { newRecord = (targetRow.RowState == DataRowState.Unchanged) ? this.recordManager.CopyRecord(this, oldRecord, -1) : targetRow.newRecord; } else { newRecord = -1; } oldRecord = this.recordManager.CopyRecord(row.Table, row.oldRecord, oldRecord); if (num4 != ((rowState == DataRowState.Added) ? newRecord : oldRecord)) { this.SetMergeRecords(targetRow, newRecord, oldRecord, (newRecord == -1) ? DataRowAction.Delete : DataRowAction.Change); idxSearch.Reset(); num4 = (rowState == DataRowState.Added) ? newRecord : oldRecord; } else { this.SetMergeRecords(targetRow, newRecord, oldRecord, (newRecord == -1) ? DataRowAction.Delete : DataRowAction.Change); } } else { oldRecord = targetRow.oldRecord; newRecord = targetRow.newRecord; if (targetRow.RowState == DataRowState.Unchanged) { newRecord = this.recordManager.CopyRecord(this, oldRecord, -1); } oldRecord = this.recordManager.CopyRecord(row.Table, row.oldRecord, oldRecord); if (!preserveChanges) { newRecord = this.recordManager.CopyRecord(row.Table, row.newRecord, newRecord); } this.SetMergeRecords(targetRow, newRecord, oldRecord, DataRowAction.Change); } if ((rowState == DataRowState.Added) && (targetRow.oldRecord != -1)) { idxSearch.Reset(); } } finally { targetRow.tempRecord = tempRecord; } } if (row.HasErrors) { if (targetRow.RowError.Length == 0) { targetRow.RowError = row.RowError; } else { targetRow.RowError = targetRow.RowError + " ]:[ " + row.RowError; } DataColumn[] columnsInError = row.GetColumnsInError(); for (int i = 0; i < columnsInError.Length; i++) { DataColumn column = targetRow.Table.Columns[columnsInError[i].ColumnName]; targetRow.SetColumnError(column, row.GetColumnError(columnsInError[i])); } return targetRow; } if (!preserveChanges) { targetRow.ClearErrors(); } return targetRow; }