Index: SQLite.Designer/Design/ForeignKey.cs ================================================================== --- SQLite.Designer/Design/ForeignKey.cs +++ SQLite.Designer/Design/ForeignKey.cs @@ -281,11 +281,13 @@ } [DefaultProperty("From")] internal class ForeignKey : IHaveConnection, ICloneable { - internal Table _table; + internal Table _table; + internal int _id; + internal int _ordinal; internal ForeignKeyFromItem _from; internal ForeignKeyToItem _to; internal string _name; internal string _onUpdate; internal string _onDelete; @@ -292,11 +294,13 @@ internal string _match; private bool _dirty; private ForeignKey(ForeignKey source) { - _table = source._table; + _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; @@ -322,20 +326,24 @@ 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, "", ""); } } @@ -355,11 +363,11 @@ { get { if (String.IsNullOrEmpty(_name) == false) return _name; - return String.Format(CultureInfo.InvariantCulture, "FK_{0}_{1}_{2}_{3}", _from.Table, _from.Column, _to.Table, _to.Column); + return String.Format(CultureInfo.InvariantCulture, "FK_{0}_{1}_{2}", _from.Table, _id, _ordinal); } set { if (_name != value) { @@ -380,11 +388,27 @@ public DbConnection GetConnection() { return ((IHaveConnection)_table).GetConnection(); } - #endregion + #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 Index: SQLite.Designer/Design/Table.cs ================================================================== --- SQLite.Designer/Design/Table.cs +++ SQLite.Designer/Design/Table.cs @@ -406,39 +406,15 @@ } } builder.Append(separator); builder.AppendFormat("CONSTRAINT [CK_{0}_{1}] CHECK {2}", Name, n + 1, check); } - - List keys = new List(); - - for (int x = 0; x < ForeignKeys.Count; x++) - { - ForeignKey key = ForeignKeys[x]; - - if (String.IsNullOrEmpty(key.From.Column) == true || String.IsNullOrEmpty(key.From.Catalog) == true || - String.IsNullOrEmpty(key.To.Table) == true || String.IsNullOrEmpty(key.To.Column) == true) - continue; - - if (keys.Count > 0) - { - if (keys[0].Name == key.Name && keys[0].To.Catalog == key.To.Catalog && keys[0].To.Table == key.To.Table) - { - keys.Add(key); - continue; - } - builder.Append(separator); - WriteFKeys(keys, builder); - keys.Clear(); - } - keys.Add(key); - } - - if (keys.Count > 0) - { - builder.Append(separator); - WriteFKeys(keys, builder); + + if (ForeignKeys.Count > 0) + { + builder.Append(separator); + WriteFKeys(ForeignKeys, builder); } builder.Append("\r\n);\r\n"); // Rebuilding an existing table @@ -494,41 +470,66 @@ } builder.AppendLine(); } return builder.ToString(); - } - - private void WriteFKeys(List keys, StringBuilder builder) - { - builder.AppendFormat("CONSTRAINT [{0}] FOREIGN KEY (", keys[0].Name); - string separator = ""; - - foreach (ForeignKey key in keys) - { - builder.AppendFormat("{0}[{1}]", separator, key.From.Column); - separator = ", "; - } - - builder.AppendFormat(") REFERENCES [{0}] (", keys[0].To.Table); - - separator = ""; - foreach (ForeignKey key in keys) - { - builder.AppendFormat("{0}[{1}]", separator, key.To.Column); - separator = ", "; - } - builder.Append(")"); - - if (!String.IsNullOrEmpty(keys[0].Match)) - builder.AppendFormat(" MATCH {0}", keys[0].Match); - - if (!String.IsNullOrEmpty(keys[0].OnUpdate)) - builder.AppendFormat(" ON UPDATE {0}", keys[0].OnUpdate); - - if (!String.IsNullOrEmpty(keys[0].OnDelete)) - builder.AppendFormat(" ON DELETE {0}", keys[0].OnDelete); + } + + private void WriteFKeys(List keys, StringBuilder builder) + { + for (int index = 0; index < keys.Count; ) + { + ForeignKey key = keys[index]; + + if (index > 0) + builder.Append(",\r\n "); + + builder.AppendFormat( + "CONSTRAINT [{0}] FOREIGN KEY (", key.Name); + + int startIndex = index; + + do + { + builder.AppendFormat("{0}[{1}]", + index > startIndex ? ", " : String.Empty, + keys[index].From.Column); + + index++; + } while (index < keys.Count && keys[index].Id == key.Id); + + builder.AppendFormat(") REFERENCES [{0}]", key.To.Table); + + if (!String.IsNullOrEmpty(key.To.Column)) + { + builder.Append(" ("); + index = startIndex; + + do + { + builder.AppendFormat("{0}[{1}]", + index > startIndex ? ", " : String.Empty, + keys[index].To.Column); + + index++; + } while (index < keys.Count && keys[index].Id == key.Id); + + builder.Append(')'); + } + + if (!String.IsNullOrEmpty(key.Match)) + builder.AppendFormat(" MATCH {0}", key.Match); + + if (!String.IsNullOrEmpty(key.OnUpdate)) + builder.AppendFormat(" ON UPDATE {0}", key.OnUpdate); + + if (!String.IsNullOrEmpty(key.OnDelete)) + builder.AppendFormat(" ON DELETE {0}", key.OnDelete); + + if (index == startIndex) + index++; + } } [Browsable(false)] public override ViewTableBase DesignTable { Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -2348,10 +2348,11 @@ tbl.Columns.Add("TABLE_SCHEMA", typeof(string)); tbl.Columns.Add("TABLE_NAME", typeof(string)); tbl.Columns.Add("CONSTRAINT_TYPE", typeof(string)); tbl.Columns.Add("IS_DEFERRABLE", typeof(bool)); tbl.Columns.Add("INITIALLY_DEFERRED", typeof(bool)); + tbl.Columns.Add("FKEY_ID", typeof(int)); tbl.Columns.Add("FKEY_FROM_COLUMN", typeof(string)); tbl.Columns.Add("FKEY_FROM_ORDINAL_POSITION", typeof(int)); tbl.Columns.Add("FKEY_TO_CATALOG", typeof(string)); tbl.Columns.Add("FKEY_TO_SCHEMA", typeof(string)); tbl.Columns.Add("FKEY_TO_TABLE", typeof(string)); @@ -2383,16 +2384,17 @@ { while (rdKey.Read()) { row = tbl.NewRow(); row["CONSTRAINT_CATALOG"] = strCatalog; - row["CONSTRAINT_NAME"] = String.Format(CultureInfo.InvariantCulture, "FK_{0}_{1}", rdTables[2], rdKey.GetInt32(0)); + row["CONSTRAINT_NAME"] = String.Format(CultureInfo.InvariantCulture, "FK_{0}_{1}_{2}", rdTables[2], rdKey.GetInt32(0), rdKey.GetInt32(1)); row["TABLE_CATALOG"] = strCatalog; row["TABLE_NAME"] = builder.UnquoteIdentifier(rdTables.GetString(2)); row["CONSTRAINT_TYPE"] = "FOREIGN KEY"; row["IS_DEFERRABLE"] = false; row["INITIALLY_DEFERRED"] = false; + row["FKEY_ID"] = rdKey[0]; row["FKEY_FROM_COLUMN"] = builder.UnquoteIdentifier(rdKey[3].ToString()); row["FKEY_TO_CATALOG"] = strCatalog; row["FKEY_TO_TABLE"] = builder.UnquoteIdentifier(rdKey[2].ToString()); row["FKEY_TO_COLUMN"] = builder.UnquoteIdentifier(rdKey[4].ToString()); row["FKEY_FROM_ORDINAL_POSITION"] = rdKey[1]; Index: Tests/basic.eagle ================================================================== --- Tests/basic.eagle +++ Tests/basic.eagle @@ -259,10 +259,11 @@ [$foreignKey Item TABLE_CATALOG] \ [$foreignKey Item TABLE_NAME] \ [$foreignKey Item CONSTRAINT_TYPE] \ [$foreignKey Item IS_DEFERRABLE] \ [$foreignKey Item INITIALLY_DEFERRED] \ + [$foreignKey Item FKEY_ID] \ [$foreignKey Item FKEY_FROM_COLUMN] \ [$foreignKey Item FKEY_TO_CATALOG] \ [$foreignKey Item FKEY_TO_TABLE] \ [$foreignKey Item FKEY_TO_COLUMN] \ [$foreignKey Item FKEY_FROM_ORDINAL_POSITION] \ @@ -279,13 +280,13 @@ unset -nocomplain result rows foreignKey foreignKeys results errors code \ dataSource id db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ -match regexp -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0\ -\{\{main FK_t1_0 main t1 \{FOREIGN KEY\} False False x main t2 \{\} 0 \{SET\ -DEFAULT\} CASCADE NONE\} \{main FK_t2_0 main t2 \{FOREIGN KEY\} False False x\ -main t3 \{\} 0 \{NO ACTION\} \{NO ACTION\} NONE\}\}$}} +\{\{main FK_t1_0_0 main t1 \{FOREIGN KEY\} False False 0 x main t2 \{\} 0 \{SET\ +DEFAULT\} CASCADE NONE\} \{main FK_t2_0_0 main t2 \{FOREIGN KEY\} False False 0\ +x main t3 \{\} 0 \{NO ACTION\} \{NO ACTION\} NONE\}\}$}} ############################################################################### runTest {test data-1.6 {SQLITE_FCNTL_WIN32_AV_RETRY} -setup { setupDb [set fileName data-1.6.db]