|
From: <pa...@us...> - 2011-03-26 18:27:37
|
Revision: 5543
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5543&view=rev
Author: patearl
Date: 2011-03-26 18:27:30 +0000 (Sat, 26 Mar 2011)
Log Message:
-----------
Support foreign keys on SQLite. Breaking change for databases that don't support alter table and have DDL-time foreign key correctness checks.
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs
trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs
trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs
trunk/nhibernate/src/NHibernate/Dialect/Schema/SQLiteMetaData.cs
trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs
trunk/nhibernate/src/NHibernate/Mapping/Table.cs
Modified: trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2011-03-26 16:35:24 UTC (rev 5542)
+++ trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2011-03-26 18:27:30 UTC (rev 5543)
@@ -813,7 +813,10 @@
var script = new List<string>();
- // drop them in reverse order in case db needs it done that way...
+ if (!string.IsNullOrEmpty(dialect.BeforeDropSchemaCommand))
+ script.Add(dialect.BeforeDropSchemaCommand);
+
+ // drop them in reverse order in case db needs it done that way...););
for (int i = auxiliaryDatabaseObjects.Count - 1; i >= 0; i--)
{
IAuxiliaryDatabaseObject auxDbObj = auxiliaryDatabaseObjects[i];
@@ -861,6 +864,9 @@
}
}
+ if (!string.IsNullOrEmpty(dialect.AfterDropSchemaCommand))
+ script.Add(dialect.AfterDropSchemaCommand);
+
return script.ToArray();
}
Modified: trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs 2011-03-26 16:35:24 UTC (rev 5542)
+++ trunk/nhibernate/src/NHibernate/Dialect/Dialect.cs 2011-03-26 18:27:30 UTC (rev 5543)
@@ -645,7 +645,10 @@
{
var res = new StringBuilder(200);
- res.Append(" add constraint ")
+ if (SupportsForeignKeyConstraintInAlterTable)
+ res.Append(" add");
+
+ res.Append(" constraint ")
.Append(constraintName)
.Append(" foreign key (")
.Append(StringHelper.Join(StringHelper.CommaSpace, foreignKey))
@@ -2413,5 +2416,15 @@
{
return false;
}
- }
+
+ public virtual string BeforeDropSchemaCommand
+ {
+ get { return null; }
+ }
+
+ public virtual string AfterDropSchemaCommand
+ {
+ get { return null; }
+ }
+ }
}
Modified: trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-26 16:35:24 UTC (rev 5542)
+++ trunk/nhibernate/src/NHibernate/Dialect/SQLiteDialect.cs 2011-03-26 18:27:30 UTC (rev 5543)
@@ -261,6 +261,23 @@
get { return "select randomblob(16)"; }
}
+ /// <summary>
+ /// SQLite does not currently support dropping foreign key constraints by alter statements.
+ /// This means that tables cannot be dropped if there are any rows that depend on those.
+ /// If there are cycles between tables, it would even be excessively difficult to delete
+ /// the data in the right order first. Because of this, we just turn off the foreign
+ /// constraints before we drop the schema and hope that we're not going to break anything. :(
+ /// </summary>
+ public override string BeforeDropSchemaCommand
+ {
+ get { return "PRAGMA foreign_keys = OFF"; }
+ }
+
+ public override string AfterDropSchemaCommand
+ {
+ get { return "PRAGMA foreign_keys = ON"; }
+ }
+
[Serializable]
protected class SQLiteCastFunction : CastFunction
{
Modified: trunk/nhibernate/src/NHibernate/Dialect/Schema/SQLiteMetaData.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Dialect/Schema/SQLiteMetaData.cs 2011-03-26 16:35:24 UTC (rev 5542)
+++ trunk/nhibernate/src/NHibernate/Dialect/Schema/SQLiteMetaData.cs 2011-03-26 18:27:30 UTC (rev 5543)
@@ -30,8 +30,8 @@
protected override string GetConstraintName(DataRow rs)
{
- throw new NotImplementedException();
- }
+ return Convert.ToString(rs["CONSTRAINT_NAME"]);
+ }
protected override IForeignKeyMetadata GetForeignKeyMetadata(DataRow rs)
{
Modified: trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs 2011-03-26 16:35:24 UTC (rev 5542)
+++ trunk/nhibernate/src/NHibernate/Driver/SQLite20Driver.cs 2011-03-26 18:27:30 UTC (rev 5543)
@@ -1,4 +1,6 @@
using System;
+using System.Data;
+using System.Data.Common;
namespace NHibernate.Driver
{
@@ -33,6 +35,28 @@
{
}
+ public override IDbConnection CreateConnection()
+ {
+ DbConnection connection = (DbConnection)base.CreateConnection();
+ connection.StateChange += Connection_StateChange;
+ return connection;
+ }
+
+ private static void Connection_StateChange(object sender, StateChangeEventArgs e)
+ {
+ if ((e.OriginalState == ConnectionState.Broken || e.OriginalState == ConnectionState.Closed || e.OriginalState == ConnectionState.Connecting) &&
+ e.CurrentState == ConnectionState.Open)
+ {
+ DbConnection connection = (DbConnection)sender;
+ using (DbCommand command = connection.CreateCommand())
+ {
+ // Activated foreign keys if supported by SQLite. Unknown pragmas are ignored.
+ command.CommandText = "PRAGMA foreign_keys = ON";
+ command.ExecuteNonQuery();
+ }
+ }
+ }
+
public override bool UseNamedPrefixInSql
{
get { return true; }
Modified: trunk/nhibernate/src/NHibernate/Mapping/Table.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/Table.cs 2011-03-26 16:35:24 UTC (rev 5542)
+++ trunk/nhibernate/src/NHibernate/Mapping/Table.cs 2011-03-26 18:27:30 UTC (rev 5543)
@@ -427,6 +427,17 @@
}
}
+ if (!dialect.SupportsForeignKeyConstraintInAlterTable)
+ {
+ foreach (ForeignKey foreignKey in ForeignKeyIterator)
+ {
+ if (foreignKey.HasPhysicalConstraint)
+ {
+ buf.Append(",").Append(foreignKey.SqlConstraintString(dialect, foreignKey.Name, defaultCatalog, defaultSchema));
+ }
+ }
+ }
+
buf.Append(StringHelper.ClosedParen);
if (string.IsNullOrEmpty(comment) == false)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|