Esempio n. 1
0
        private object GetRowFieldValue(TableChangeItem citem, bool right, string columnName)
        {
            if (right)
            {
                for (int i = 0; i < citem.RightColumnNames.Length; i++)
                {
                    if (citem.RightColumnNames[i].ToLower() == columnName.ToLower())
                    {
                        return(citem.RightFields[i]);
                    }
                } // for
            }
            else
            {
                for (int i = 0; i < citem.LeftColumnNames.Length; i++)
                {
                    if (citem.LeftColumnNames[i].ToLower() == columnName.ToLower())
                    {
                        return(citem.LeftFields[i]);
                    }
                } // for
            }

            throw new ArgumentException("Illegal row index, column index or column name");
        }
Esempio n. 2
0
        private bool CanEditGrid(bool right, out TableChangeItem citem, out FastGridLocation sloc)
        {
            citem = null;
            sloc  = FastGridLocation.Empty;
            if (_item == null)
            {
                return(false);
            }

            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;
            }

            sloc = grid.SelectedCellLocation;

            string columnName            = (string)grid.Columns[sloc.ColumnIndex].Tag;
            SQLiteColumnStatement column = Utils.FindColumn(table.Columns, columnName);

            if (column == null)
            {
                return(false);
            }

            long total = _tableChanges.GetTotalChangesCount(new string[] { _diff });

            if (sloc.RowIndex >= total)
            {
                return(false);
            }
            citem = _tableChanges.GetChangeItem(_diff, sloc.RowIndex);

            // Can't edit a cell that belongs to a row that doesn't exist
            if (right && citem.Result == ComparisonResult.ExistsInLeftDB)
            {
                return(false);
            }
            else if (!right && citem.Result == ComparisonResult.ExistsInRightDB)
            {
                return(false);
            }

            return(true);
        }
Esempio n. 3
0
        /// <summary>
        /// This purpose of this method is to fill the needed row with data
        /// taken from the table-changes object. This is part of a virtual mode
        /// implementation of the FastGrid control designed to minimize memory
        /// requirements only to the bare essentials.
        /// </summary>
        /// <param name="grid">The grid that issued to the RowNeeded request</param>
        /// <param name="rowIndex">The index of the row to fill</param>
        /// <param name="row">The row to fill</param>
        private void FillRow(FastGrid grid, long rowIndex, FastGridRow row)
        {
            // Fetch the table change item from the cache/database
            TableChangeItem item = _tableChanges.GetChangeItem(_diff, rowIndex);

            bool empty;
            bool isLeft;
            SQLiteCreateTableStatement table = null;

            if (grid == grdLeft)
            {
                isLeft = true;
                empty  = item.LeftFields == null;
                table  = _tableChanges.LeftTable;
            }
            else
            {
                isLeft = false;
                empty  = item.RightFields == null;
                table  = _tableChanges.RightTable;
            } // else

            if (empty)
            {
                for (int i = 0; i < row.Cells.Length; i++)
                {
                    row.Cells[i].Style.BackColor = EMPTY_ROW_BACK_COLOR;
                }
            }
            else
            {
                for (int i = 0; i < row.Cells.Length; i++)
                {
                    string cname = (string)grid.Columns[i].Tag;
                    SQLiteColumnStatement col = Utils.GetColumnByName(table, cname);
                    object fval = item.GetField(cname, isLeft);
                    if (fval == DBNull.Value || fval == null)
                    {
                        row.Cells[i].Value      = "NULL";
                        row.Cells[i].Style.Font = _italic;
                    }
                    else if (Utils.GetDbType(col.ColumnType) == DbType.Binary)
                    {
                        long v = (long)fval;
                        if (v == 1)
                        {
                            row.Cells[i].Value = "BLOB";
                        }
                        else
                        {
                            row.Cells[i].Value = "NULL";
                        }
                        row.Cells[i].Style.Font = _italic;
                    }
                    else
                    {
                        if (fval is byte[])
                        {
                            string tmp = Encoding.ASCII.GetString((byte[])fval);
                            row.Cells[i].Value = tmp;
                        }
                        else
                        {
                            row.Cells[i].Value = fval;
                        }
                    } // else

                    // Mark different cells with special background color
                    if (item.Result == ComparisonResult.DifferentData)
                    {
                        if (i < item.LeftFields.Length && i < item.RightFields.Length)
                        {
                            if (item.ChangedBlobsColumnNames != null && item.ChangedBlobsColumnNames.Contains(col.ObjectName.ToString()))
                            {
                                row.Cells[i].Style.BackColor = DIFFERENT_CELL_BACK_COLOR;
                            }
                            else
                            {
                                // Check only if the field appears in both tables and has different values
                                if (item.HasField(cname, true) && item.HasField(cname, false) && !item.GetField(cname, true).Equals(item.GetField(cname, false)))
                                {
                                    object tmp = item.GetField(cname, isLeft);
                                    if (tmp is long && ((long)tmp) == 0 && Utils.GetDbType(col.ColumnType) == DbType.Binary &&
                                        item.GetField(cname, !isLeft) == DBNull.Value)
                                    {
                                        // Ignore the case when the values are not equal when one of the fields is a BLOB and the
                                        // other is not, but both values indicate NULL content.
                                    }
                                    else
                                    {
                                        tmp = item.GetField(cname, !isLeft);
                                        SQLiteCreateTableStatement tbl;
                                        if (isLeft)
                                        {
                                            tbl = _tableChanges.RightTable;
                                        }
                                        else
                                        {
                                            tbl = _tableChanges.LeftTable;
                                        }
                                        object tmp2 = item.GetField(cname, isLeft);
                                        SQLiteColumnStatement ocol = Utils.GetColumnByName(tbl.Columns, cname);
                                        if (tmp2 == DBNull.Value && tmp != null && tmp is long && ((long)tmp) == 0)
                                        {
                                            // Ignore the reverse case when both fields are actually NULL, but one of them is BLOB
                                            // and ther other is not.
                                        }
                                        else
                                        {
                                            row.Cells[i].Style.BackColor = DIFFERENT_CELL_BACK_COLOR;
                                        }
                                    } // else
                                }     // if
                            }         // else
                        }             // if
                    }                 // if
                }                     // for
            }                         // else
        }
Esempio n. 4
0
        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();
        }