/********************************************************
* ADO.NET 2.0 Data Provider for SQLite Version 3.X
* Written by Robert Simpson (robert@blackcastlesoft.com)
*
* Released to the public domain, use at your own risk!
********************************************************/
namespace SQLite.Designer.Design
{
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Globalization;
internal class ForeignKeyEditor : CollectionEditor
{
Table _table;
CollectionEditor.CollectionForm _form;
object[] _items;
object[] _orig;
int _count;
internal ForeignKeyEditor(Table parent)
: base(typeof(List<ForeignKey>))
{
_table = parent;
_count = _table.ForeignKeys.Count;
}
protected override CollectionEditor.CollectionForm CreateCollectionForm()
{
_form = base.CreateCollectionForm();
_form.Text = "Foreign Key Editor";
foreach (Control c in _form.Controls[0].Controls)
{
PropertyGrid grid = c as PropertyGrid;
if (grid != null)
{
grid.HelpVisible = true;
break;
}
}
_form.Width = (int)(_form.Width * 1.25);
_form.Height = (int)(_form.Height * 1.25);
return _form;
}
protected override object CreateInstance(Type itemType)
{
if (itemType == typeof(ForeignKey))
{
return new ForeignKey(null, _table, null);
}
throw new NotSupportedException();
}
protected override object[] GetItems(object editValue)
{
if (_items == null)
{
List<ForeignKey> items = editValue as List<ForeignKey>;
_items = new object[items.Count];
_orig = new object[items.Count];
for (int n = 0; n < _items.Length; n++)
{
_items[n] = ((ICloneable)items[n]).Clone();
_orig[n] = items[n];
}
}
return _items;
}
protected override object SetItems(object editValue, object[] value)
{
bool dirty = false;
if (_form.DialogResult == DialogResult.Cancel) value = _orig;
if (editValue != null)
{
if (!(editValue is IList))
{
return editValue;
}
IList list = (IList)editValue;
list.Clear();
for (int i = 0; i < value.Length; i++)
{
ForeignKey fkey = value[i] as ForeignKey;
if (fkey != null && String.IsNullOrEmpty(fkey.From.Column) == false && String.IsNullOrEmpty(fkey.To.Catalog) == false &&
String.IsNullOrEmpty(fkey.To.Table) == false && String.IsNullOrEmpty(fkey.To.Column) == false)
{
if (fkey.IsDirty) dirty = true;
list.Add(value[i]);
}
}
if ((dirty == true || list.Count != _count) && _form.DialogResult == DialogResult.OK)
_table.MakeDirty();
}
return editValue;
}
}
internal class ForeignKeyItem : IHaveConnectionScope
{
private string _catalog;
private string _table;
private string _column;
private ForeignKey _fkey;
internal ForeignKeyItem(ForeignKey fkey, string catalog, string table, string column)
{
_catalog = catalog;
_table = table;
_column = column;
_fkey = fkey;
}
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture, "[{0}].[{1}].[{2}]", _catalog, _table, _column);
}
#region IHaveConnection Members
[Browsable(false)]
public ViewTableBase DesignTable
{
get { return _fkey.DesignTable; }
}
public DbConnection GetConnection()
{
return ((IHaveConnection)_fkey).GetConnection();
}
[Browsable(false)]
public string TableScope
{
get { return _table; }
}
[Browsable(false)]
public string CatalogScope
{
get { return _catalog; }
}
#endregion
[Browsable(false)]
[Editor(typeof(CatalogTypeEditor), typeof(UITypeEditor))]
public virtual string Catalog
{
get { return _catalog; }
}
[Editor(typeof(TablesTypeEditor), typeof(UITypeEditor))]
public virtual string Table
{
get { return _table; }
}
[Editor(typeof(ColumnsTypeEditor), typeof(UITypeEditor))]
public virtual string Column
{
get { return _column; }
}
protected void SetCatalog(string value)
{
if (_catalog != value)
{
_catalog = value;
_fkey.MakeDirty();
}
}
protected void SetTable(string value)
{
if (_table != value)
{
_table = value;
_fkey.MakeDirty();
}
}
protected void SetColumn(string value)
{
if (_column != value)
{
_column = value;
_fkey.MakeDirty();
}
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
internal class ForeignKeyFromItem : ForeignKeyItem
{
internal ForeignKeyFromItem(ForeignKey fkey, string column)
: base(fkey, fkey._table.Catalog, fkey._table.Name, column)
{
}
[Editor(typeof(ColumnsTypeEditor), typeof(UITypeEditor))]
[Description("The column of the current table that refers to the foreign key relationship")]
public new string Column
{
get { return base.Column; }
set { SetColumn(value); }
}
[Browsable(false)]
public override string Catalog
{
get
{
return base.Catalog;
}
}
[Browsable(false)]
public override string Table
{
get
{
return base.DesignTable.Name;
}
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
internal class ForeignKeyToItem : ForeignKeyItem
{
internal ForeignKeyToItem(ForeignKey fkey, string catalog, string table, string column)
: base(fkey, catalog, table, column)
{
}
[Browsable(false)]
[Editor(typeof(CatalogTypeEditor), typeof(UITypeEditor))]
[Description("The database catalog (main, temp, or the name of an attached database) to which the foreign key refers.")]
public new string Catalog
{
get
{
return base.Catalog;
}
set
{
SetCatalog(value);
}
}
[DisplayName("Base Table")]
[Editor(typeof(TablesTypeEditor), typeof(UITypeEditor))]
[Description("The table to which the foreign key refers.")]
public new string Table
{
get { return base.Table; }
set { SetTable(value); }
}
[Editor(typeof(ColumnsTypeEditor), typeof(UITypeEditor))]
[Description("The column to which the foreign key refers.")]
public new string Column
{
get { return base.Column; }
set { SetColumn(value); }
}
}
[DefaultProperty("From")]
internal class ForeignKey : IHaveConnection, ICloneable
{
internal Table _table;
internal int _id;
internal int _ordinal;
internal ForeignKeyFromItem _from;
internal ForeignKeyToItem _to;
internal string _name;
internal string _onUpdate;
internal string _onDelete;
internal string _match;
private bool _dirty;
private ForeignKey(ForeignKey source)
{
_table = source._table;
_id = source._id;
_ordinal = source._ordinal;
_from = new ForeignKeyFromItem(this, source._from.Column);
_to = new ForeignKeyToItem(this, source._to.Catalog, source._to.Table, source._to.Column);
_name = source._name;
_onUpdate = source._onUpdate;
_onDelete = source._onDelete;
_match = source._match;
_dirty = source._dirty;
}
internal void MakeDirty()
{
_dirty = true;
}
[Browsable(false)]
internal bool IsDirty
{
get { return _dirty; }
}
internal void ClearDirty()
{
_dirty = false;
}
internal ForeignKey(DbConnection cnn, Table table, DataRow row)
{
_table = table;
if (row != null)
{
_id = (int)row["FKEY_ID"];
_ordinal = (int)row["FKEY_FROM_ORDINAL_POSITION"];
_from = new ForeignKeyFromItem(this, row["FKEY_FROM_COLUMN"].ToString());
_to = new ForeignKeyToItem(this, row["FKEY_TO_CATALOG"].ToString(), row["FKEY_TO_TABLE"].ToString(), row["FKEY_TO_COLUMN"].ToString());
_name = row["CONSTRAINT_NAME"].ToString();
_onUpdate = row["FKEY_ON_UPDATE"].ToString();
_onDelete = row["FKEY_ON_DELETE"].ToString();
_match = row["FKEY_MATCH"].ToString();
}
else
{
_id = -1;
_ordinal = -1;
_from = new ForeignKeyFromItem(this, "");
_to = new ForeignKeyToItem(this, _table.Catalog, "", "");
}
}
//internal void WriteSql(StringBuilder builder)
//{
// if (String.IsNullOrEmpty(_from.Column) == false && String.IsNullOrEmpty(_to.Catalog) == false &&
// String.IsNullOrEmpty(_to.Table) == false && String.IsNullOrEmpty(_to.Column) == false)
// {
// builder.AppendFormat("CONSTRAINT [{0}] FOREIGN KEY ([{1}]) REFERENCES [{3}] ([{4}])", Name, _from.Column, _to.Catalog, _to.Table, _to.Column);
// }
//}
[ParenthesizePropertyName(true)]
[Category("Identity")]
[Description("The name of the foreign key.")]
public string Name
{
get
{
if (String.IsNullOrEmpty(_name) == false) return _name;
return String.Format(CultureInfo.InvariantCulture, "FK_{0}_{1}_{2}", _from.Table, _id, _ordinal);
}
set
{
if (_name != value)
{
_name = value;
MakeDirty();
}
}
}
#region IHaveConnection Members
[Browsable(false)]
public ViewTableBase DesignTable
{
get { return _table; }
}
public DbConnection GetConnection()
{
return ((IHaveConnection)_table).GetConnection();
}
#endregion
[DisplayName("Id")]
[Category("Id")]
[Description("The identifier of this foreign key.")]
public int Id
{
get { return _id; }
}
[DisplayName("Ordinal")]
[Category("Ordinal")]
[Description("The column ordinal of this foreign key.")]
public int Ordinal
{
get { return _ordinal; }
}
[DisplayName("From Key")]
[Category("From")]
[Description("The source column in the current table that refers to the foreign key.")]
public ForeignKeyFromItem From
{
get { return _from; }
}
[DisplayName("To Key")]
[Category("To")]
[Description("The table and column to which the specified from column is related.")]
public ForeignKeyToItem To
{
get { return _to; }
}
[DisplayName("On Update")]
[Category("Action")]
[Description("The action to take when modifying the parent key values of an existing row.")]
public string OnUpdate
{
get { return _onUpdate; }
}
[DisplayName("On Delete")]
[Category("Action")]
[Description("The action to take when deleting a row from the parent table.")]
public string OnDelete
{
get { return _onDelete; }
}
[DisplayName("Match")]
[Category("Match")]
[Description("Used with composite foreign key definitions to modify the way NULL values that occur in child keys are handled. Not currently supported.")]
public string Match
{
get { return _match; }
}
#region ICloneable Members
public object Clone()
{
return new ForeignKey(this);
}
#endregion
}
}