private void btnCopyRightToLeft_Click(object sender, EventArgs e) { List <TableChangesRange> rows = new List <TableChangesRange>(); foreach (FastGridApp.SelectionRange range in grdLeft.Selection.SelectionRanges) { rows.Add(new TableChangesRange(range.StartRowId, range.EndRowId)); } RowsCopier copier = new RowsCopier(_tableChanges, _diff, rows, false); ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, copier); grdRight.RefreshLayout(); grdLeft.RefreshLayout(); if (RowsChanged != null) { RowsChanged(this, EventArgs.Empty); } if (StateChanged != null) { StateChanged(this, EventArgs.Empty); } }
private void DeleteRows(bool right) { List <TableChangesRange> rows = new List <TableChangesRange>(); FastGrid grid; long totalDeleted = 0; if (right) { grid = grdRight; foreach (FastGridApp.SelectionRange range in grdRight.Selection.SelectionRanges) { rows.Add(new TableChangesRange(range.StartRowId, range.EndRowId)); totalDeleted += range.EndRowId - range.StartRowId + 1; } } else { grid = grdLeft; foreach (FastGridApp.SelectionRange range in grdLeft.Selection.SelectionRanges) { rows.Add(new TableChangesRange(range.StartRowId, range.EndRowId)); totalDeleted += range.EndRowId - range.StartRowId + 1; } } DialogResult res = MessageBox.Show(this, string.Format("Are you sure you want to delete {0} rows from the {1} database table?", totalDeleted, (right?"right":"left")), "Confirm Deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (res == DialogResult.No) { return; } RowsDeleter deleter = new RowsDeleter(_tableChanges, _diff, rows, !right); ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, deleter); GC.Collect(); // Notify that row(s) were deleted if (RowsChanged != null) { RowsChanged(this, EventArgs.Empty); } // Refresh the right/left grids again from the database. grdRight.RefreshLayout(); grdLeft.RefreshLayout(); }
private void StartTableUpdate(string leftSQL, string rightSQL, bool skipNullRows) { // Create and start the updater object SchemaObjectUpdater updater = new SchemaObjectUpdater(_item, _leftSchema, _rightSchema, _leftdb, _rightdb, leftSQL, rightSQL, skipNullRows); ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, updater); if (dlg.Error == null) { // Compare again based on the updated schema objects found in the item object. CompareSchema(_item); // Notify about the change if (SchemaChanged != null) { SchemaChanged(this, EventArgs.Empty); } } // else else { if (dlg.Error is UpdateTableException) { UpdateTableException ue = (UpdateTableException)dlg.Error; if (ue.CanRestart) { DialogResult res = MessageBox.Show(this, "Press [Yes] to restart the operation and skip problem rows\r\n" + "Press [No] to abort the operation", "Information", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2); if (res == DialogResult.No) { return; } StartTableUpdate(leftSQL, rightSQL, true); } } // if } // else // Remove the data tab tbcViews.TabPages.Remove(tbpData); }
private void ExportToFile(bool openInExternal) { AbstractWorker worker = null; if (_changes != null) { worker = new DiffExporter(_changes, txtFile.Text.Trim(), cbxExportUpdates.Checked, cbxExportAdded.Checked, cbxExportDeleted.Checked); } else { worker = new DiffExporter(_multiChanges, txtFile.Text.Trim(), cbxExportUpdates.Checked, cbxExportAdded.Checked, cbxExportDeleted.Checked); } ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, worker); if (dlg.Error == null) { this.Close(); if (openInExternal) { try { // Open in external application Process p = new Process(); ProcessStartInfo psi = new ProcessStartInfo(txtFile.Text.Trim()); p.StartInfo = psi; psi.UseShellExecute = true; p.Start(); } catch (Exception ex) { DialogResult res = MessageBox.Show(this, "There is no external viewer for this type of file. Do yo want to open the file using notepad?", "No Viewer Available", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1); if (res == DialogResult.Yes) { // Try to open using notepad OpenAsTextFile(txtFile.Text.Trim()); } } // catch } } // if }
/// <summary> /// Allows to refresh the comparison results /// </summary> /// <param name="cancellable">TRUE means that the user will be allowed to cancel /// the comparison process. FALSE prevents this from happening (by making the CANCEL /// button disabled).</param> private void RefreshComparison(bool cancellable) { CompareWorker worker = new CompareWorker(_compareParams); ProgressDialog pdlg = new ProgressDialog(); if (cancellable) { pdlg.Start(this, worker); } else { pdlg.StartNonCancellable(this, worker); } Dictionary <SchemaObject, List <SchemaComparisonItem> > results = (Dictionary <SchemaObject, List <SchemaComparisonItem> >)pdlg.Result; if (results != null) { // Create the schema comparison view and populate it with the results if (_schemaView == null) { _schemaView = new SchemaComparisonView(); _schemaView.BackColor = SystemColors.Control; pnlContents.Controls.Add(_schemaView); _schemaView.Dock = DockStyle.Fill; _schemaView.SelectionChanged += new EventHandler(_schemaView_SelectionChanged); } _leftSchema = worker.LeftSchema; _rightSchema = worker.RightSchema; _results = results; _leftdb = _compareParams.LeftDbPath; _rightdb = _compareParams.RightDbPath; _schemaView.ShowComparisonResults(results, _compareParams.LeftDbPath, _compareParams.RightDbPath, worker.LeftSchema, worker.RightSchema, _compareParams.ComparisonType == ComparisonType.CompareSchemaAndData); } UpdateState(); }
private void HandleCellEdit(bool right) { FastGrid grid; SQLiteCreateTableStatement table; string dbpath; if (right) { grid = grdRight; table = (SQLiteCreateTableStatement)_item.RightDdlStatement; dbpath = _rightdb; } else { grid = grdLeft; table = (SQLiteCreateTableStatement)_item.LeftDdlStatement; dbpath = _leftdb; } FastGridLocation sloc = grid.SelectedCellLocation; string columnName = (string)grid.Columns[sloc.ColumnIndex].Tag; SQLiteColumnStatement column = Utils.FindColumn(table.Columns, columnName); if (column == null) { return; } TableChangeItem citem = null; try { citem = _tableChanges.GetChangeItem(_diff, sloc.RowIndex); } catch (IndexOutOfRangeException iox) { // Ignore (the user must have pressed on a cell when the table is actually empty) return; } // catch // Can't edit a cell that belongs to a row that doesn't exist if (right && citem.Result == ComparisonResult.ExistsInLeftDB) { return; } else if (!right && citem.Result == ComparisonResult.ExistsInRightDB) { return; } object otherBlob = null; // The row id is needed when displaying editor dialog for a BLOB field long rowId = -1; if (right) { rowId = citem.RightRowId; if (citem.LeftFields != null && TableContainsColumn((SQLiteCreateTableStatement)_item.LeftDdlStatement, column)) { otherBlob = GetRowFieldValue(citem, false, columnName); } } else { rowId = citem.LeftRowId; if (citem.RightFields != null && TableContainsColumn((SQLiteCreateTableStatement)_item.RightDdlStatement, column)) { otherBlob = GetRowFieldValue(citem, true, columnName); } } // Extract the current field value from the change item object value = GetRowFieldValue(citem, right, columnName); // Adjust the BLOB value since it was fetched as the IS NOT NULL expression // in order to avoid loading the BLOB field into main memory. if (Utils.GetDbType(column.ColumnType) == DbType.Binary) { long v = (long)value; if (v == 0) // means NULL { value = DBNull.Value; } } // When the user is clicking on a BLOB field - we need to extract its value // to a local file before opening the cell-edit dialog. Be.Windows.Forms.DynamicFileByteProvider origProvider = null; if (value != DBNull.Value && Utils.GetDbType(column.ColumnType) == DbType.Binary) { // In case of BLOBs - we have to first load them to the local file-system and // only then we can allow the user to edit their contents using (BlobLoader loader = new BlobLoader(dbpath, table.ObjectName.ToString(), column.ObjectName.ToString(), rowId, Configuration.TempBlobFilePath)) { ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, loader); if (dlg.Error != null) { return; } } // using // Instead of passing a byte[] array to the cell editor dialog - we'll pass // a reference to the dynamic file byte provider that is opened on the data file // that was written with the BLOB data. This allows us to conserve memory (BLOB // fields can be quite large). origProvider = new Be.Windows.Forms.DynamicFileByteProvider(Configuration.TempBlobFilePath); value = origProvider; } // Open the cell editor dialog and allow the user to edit the contents of the field. DialogResult res = OpenCellEditDialog(table, column, ref value); if (res == DialogResult.Cancel) { return; } // This part of the IF statement deals with BLOB fields - these require // a special (and lengthy) handling. if (Utils.GetDbType(column.ColumnType) == DbType.Binary || value is Be.Windows.Forms.DynamicFileByteProvider) { if (otherBlob != null && (citem.Result == ComparisonResult.Same || citem.Result == ComparisonResult.DifferentData)) { if (otherBlob is long) { // Another adjustment for the other BLOB field value long ob = (long)otherBlob; if (ob == 0) // means NULL blob field { otherBlob = DBNull.Value; } } } if (value != DBNull.Value) { string fpath = null; long blobLength = 0; if (value is Be.Windows.Forms.DynamicFileByteProvider) { Be.Windows.Forms.DynamicFileByteProvider dp = (Be.Windows.Forms.DynamicFileByteProvider)value; if (dp.HasChanges()) { dp.ApplyChanges(); } dp.Dispose(); blobLength = dp.Length; } else { throw new InvalidOperationException("cell editor returned unexpected value"); } BlobSaver saver = null; try { // In this case we need to store the updated file/buffer back to the BLOB field // and run BLOB comparison in order to check if the BLOB is different then // the one in the other database. // Save the file specified in the call as a BLOB saver = new BlobSaver(dbpath, table.ObjectName.ToString(), column.ObjectName.ToString(), rowId, fpath); ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, saver); if (dlg.Error != null) { // Notify that a row has changed if (RowsChanged != null) { RowsChanged(this, EventArgs.Empty); } return; } } finally { saver.Dispose(); } // finally // Update the table change item with an indication that the BLOB field that was just saved // is not null. citem.SetField(column.ObjectName.ToString(), !right, (long)1); if (otherBlob != null && (citem.Result == ComparisonResult.DifferentData || citem.Result == ComparisonResult.Same)) { // At this point we need to compare the BLOB that was saved with the BLOB field in the other // database in order to update the ChangedBlobsColumnNames field of the table change item so // that the user can know if the BLOB is equal to the other BLOB or if the BLOB is different. if (otherBlob != DBNull.Value) { // Run BLOB comparison bool equalBlobs = false; using (BlobCompareWorker bcw = new BlobCompareWorker(_leftdb, _rightdb, SQLiteParser.Utils.Chop(table.ObjectName.ToString()), SQLiteParser.Utils.Chop(column.ObjectName.ToString()), citem.LeftRowId, citem.RightRowId)) { ProgressDialog pdlg = new ProgressDialog(); pdlg.Start(this, bcw); if (pdlg.Error != null) { // Notify that a row has changed if (RowsChanged != null) { RowsChanged(this, EventArgs.Empty); } return; } equalBlobs = bcw.IsBlobsEqual; } // using if (equalBlobs) { // The two BLOBs are equal so remove any difference mark if (citem.ChangedBlobsColumnNames != null && citem.ChangedBlobsColumnNames.Contains(column.ObjectName.ToString())) { citem.ChangedBlobsColumnNames.Remove(column.ObjectName.ToString()); } } else { // The two BLOBs are different so add a difference mark if necessary if (citem.ChangedBlobsColumnNames == null) { citem.ChangedBlobsColumnNames = new List <string>(); } if (!citem.ChangedBlobsColumnNames.Contains(column.ObjectName.ToString())) { citem.ChangedBlobsColumnNames.Add(column.ObjectName.ToString()); } citem.Result = ComparisonResult.DifferentData; } // else } else { // If the other BLOB field is NULL - it means that the two BLOBs are different // because one is NULL and the other is not. if (citem.ChangedBlobsColumnNames == null) { citem.ChangedBlobsColumnNames = new List <string>(); } if (!citem.ChangedBlobsColumnNames.Contains(column.ObjectName.ToString())) { citem.ChangedBlobsColumnNames.Add(column.ObjectName.ToString()); } citem.Result = ComparisonResult.DifferentData; } // else } // if } else { // Ask the table changes object to set this field to null _tableChanges.SetColumnField(_diff, sloc.RowIndex, column.ObjectName.ToString(), right, DBNull.Value); citem.SetField(column.ObjectName.ToString(), !right, (long)0); if (otherBlob != null && (citem.Result == ComparisonResult.Same || citem.Result == ComparisonResult.DifferentData)) { // A BLOB field was set to NULL - compare it again to the other BLOB field and decide // if the ChangedBlobsColumnNames field should be updated to reflect this. if (otherBlob == DBNull.Value) { // The other BLOB field is NULL so the two fields are equal if (citem.ChangedBlobsColumnNames != null && citem.ChangedBlobsColumnNames.Contains(column.ObjectName.ToString())) { citem.ChangedBlobsColumnNames.Remove(column.ObjectName.ToString()); } } else { if (citem.ChangedBlobsColumnNames == null) { citem.ChangedBlobsColumnNames = new List <string>(); } // The other BLOB field is not NULL so the two fields are not equal if (!citem.ChangedBlobsColumnNames.Contains(column.ObjectName.ToString())) { citem.ChangedBlobsColumnNames.Add(column.ObjectName.ToString()); } citem.Result = ComparisonResult.DifferentData; } // else } // if } // else } else { // The field that was edited is not a BLOB so we can deal with it normally try { _tableChanges.SetColumnField(_diff, sloc.RowIndex, column.ObjectName.ToString(), right, value); } catch (Exception ex) { _log.Error("Failed to set column field", ex); MessageBox.Show(this, ex.Message, "Operation Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); } // catch } // else GC.Collect(); // Mark that the table changes object does not contain precise results _tableChanges.HasPreciseResults = false; // Notify that a row has changed if (RowsChanged != null) { RowsChanged(this, EventArgs.Empty); } // Refresh the right/left grids again from the database. grdRight.RefreshLayout(); grdLeft.RefreshLayout(); }
private void btnCompareData_Click(object sender, EventArgs e) { // Before comparing data we have to check if there are any BLOB columns // in the any common columns of the tables. If there are any - we have to // ask the user if he wants to compare BLOB fields or not. SQLiteCreateTableStatement leftTable = _item.LeftDdlStatement as SQLiteCreateTableStatement; SQLiteCreateTableStatement rightTable = _item.RightDdlStatement as SQLiteCreateTableStatement; List <SQLiteColumnStatement> common = Utils.GetCommonColumns(leftTable, rightTable); bool allowBlobComparison = false; if (Utils.ContainsBlobColumn(common)) { DialogResult res = MessageBox.Show(this, "At least one column that will be compared is a BLOB.\r\nComparing BLOB fields can potentially take " + "a lot of time to perform.\r\nDo you want to disable BLOB content comparison in order\r\nto make " + "the comparison go faster?", "Disable BLOB Contents Comparison?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (res == DialogResult.No) { allowBlobComparison = true; } } string errmsg; if (!Utils.IsTableComparisonAllowed(leftTable, rightTable, out errmsg, allowBlobComparison)) { MessageBox.Show(this, errmsg, "Data comparison is not allowed", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } TableCompareWorker worker = new TableCompareWorker( leftTable, rightTable, _leftdb, _rightdb, allowBlobComparison); ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, worker); if (dlg.Error != null) { if (dlg.Error.GetType() != typeof(UserCancellationException)) { _item.ErrorMessage = dlg.Error.Message; } return; } _tableChanges = (TableChanges)dlg.Result; if (!tbcViews.TabPages.Contains(tbpData)) { tbcViews.TabPages.Add(tbpData); } // Update the schema comparison item panel1.Visible = false; _item.ErrorMessage = null; _item.TableChanges = _tableChanges; if (SchemaChanged != null) { SchemaChanged(this, EventArgs.Empty); } // Set the table changes object into the table diff control UpdateDataTab(); tbcViews.SelectedTab = tbpData; }
private void btnOK_Click(object sender, EventArgs e) { SearchDataWorker worker = null; string sql; if (tbcSearch.SelectedTab == tbpExact) { string colName = (string)cboColumnName.SelectedItem; if (cbxValue.Checked) { sql = FormatColumnValue(colName); } else { sql = SQLiteParser.Utils.QuoteIfNeeded(colName) + " IS NULL"; } } else { sql = txtSQL.Text.Trim(); } worker = new SearchDataWorker(_isLeft, _diff, _changes, _rowIndex, -1, sql); ProgressDialog dlg = new ProgressDialog(); dlg.Start(this, worker); if (dlg.Result != null) { _matchedRowIndex = (long)dlg.Result; } if (_matchedRowIndex == -1 && dlg.Error == null) { if (_rowIndex > 0) { DialogResult res = MessageBox.Show(this, "No match was found, do you want to search from the beginning?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (res == DialogResult.Yes) { worker = new SearchDataWorker(_isLeft, _diff, _changes, 0, _rowIndex - 1, sql); dlg = new ProgressDialog(); dlg.Start(this, worker); if (dlg.Result != null) { _matchedRowIndex = (long)dlg.Result; } if (_matchedRowIndex != -1 || dlg.Error != null) { this.DialogResult = DialogResult.OK; } else { MessageBox.Show(this, "No match was found", "Search Completed", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } else { MessageBox.Show(this, "No match was found", "Search Completed", MessageBoxButtons.OK, MessageBoxIcon.Information); } } else { this.DialogResult = DialogResult.OK; } }