From 1b3d7d363909892b099ed270cf1bdedf7dc80066 Mon Sep 17 00:00:00 2001
From: Bruce Toll <btoll@dhsus.com>
Date: Tue, 14 Jan 2014 19:48:58 -0500
Subject: [PATCH] Add support for deferrable FK constraints.

Create foreign key constraints as "deferrable initially
deferred", for Postgres and Sqlite3 backends.

Enable test dbo_test17, that now works with Postgres and Sqlite3
backends using deferred FK constraints.
---
 src/Wt/Dbo/Session.C          | 3 +++
 src/Wt/Dbo/SqlConnection      | 7 +++++++
 src/Wt/Dbo/SqlConnection.C    | 5 +++++
 src/Wt/Dbo/backend/Postgres   | 1 +
 src/Wt/Dbo/backend/Postgres.C | 5 +++++
 src/Wt/Dbo/backend/Sqlite3    | 1 +
 src/Wt/Dbo/backend/Sqlite3.C  | 5 +++++
 test/dbo/DboTest.C            | 4 ++--
 8 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/Wt/Dbo/Session.C b/src/Wt/Dbo/Session.C
index 216e46c..264ae41 100644
--- a/src/Wt/Dbo/Session.C
+++ b/src/Wt/Dbo/Session.C
@@ -846,6 +846,9 @@ std::string Session::constraintString(MappingInfo *mapping,
   else if (field.fkConstraints() & Impl::FKOnDeleteSetNull)
     sql << " on delete set null";
 
+  if (connection(false)->supportDeferrableFKConstraint()) //backend condition
+    sql << " deferrable initially deferred";
+
   return sql.str();
 }
 
diff --git a/src/Wt/Dbo/SqlConnection b/src/Wt/Dbo/SqlConnection
index a35828f..59c4ba4 100644
--- a/src/Wt/Dbo/SqlConnection
+++ b/src/Wt/Dbo/SqlConnection
@@ -212,6 +212,13 @@ public:
    */
   virtual bool supportAlterTable() const;
 
+  /*! \brief Returns true if the backend supports "deferrable initially
+   * deferred" foreign key constraints
+   *
+   * This method will return false by default.
+   */
+  virtual bool supportDeferrableFKConstraint() const;
+
   /*! \brief Returns the command used in alter table .. drop constraint ..
    *
    * This method will return "constraint" by default.
diff --git a/src/Wt/Dbo/SqlConnection.C b/src/Wt/Dbo/SqlConnection.C
index 738ebe9..51c0a94 100644
--- a/src/Wt/Dbo/SqlConnection.C
+++ b/src/Wt/Dbo/SqlConnection.C
@@ -91,6 +91,11 @@ bool SqlConnection::supportAlterTable() const
   return false;
 }
 
+bool SqlConnection::supportDeferrableFKConstraint() const
+{
+  return false;
+}
+
 const char *SqlConnection::alterTableConstraintString() const
 {
   return "constraint";
diff --git a/src/Wt/Dbo/backend/Postgres b/src/Wt/Dbo/backend/Postgres
index 746d251..4846e71 100644
--- a/src/Wt/Dbo/backend/Postgres
+++ b/src/Wt/Dbo/backend/Postgres
@@ -100,6 +100,7 @@ public:
   virtual const char *dateTimeType(SqlDateTimeType type) const;
   virtual const char *blobType() const;
   virtual bool supportAlterTable() const;
+  virtual bool supportDeferrableFKConstraint() const;
   //@}
 
 private:
diff --git a/src/Wt/Dbo/backend/Postgres.C b/src/Wt/Dbo/backend/Postgres.C
index 7621854..67f9edf 100644
--- a/src/Wt/Dbo/backend/Postgres.C
+++ b/src/Wt/Dbo/backend/Postgres.C
@@ -647,6 +647,11 @@ bool Postgres::supportAlterTable() const
   return true;
 }
 
+bool Postgres::supportDeferrableFKConstraint() const
+{
+  return true;
+}
+
 void Postgres::startTransaction()
 {
   PGresult *result = PQexec(conn_, "start transaction");
diff --git a/src/Wt/Dbo/backend/Sqlite3 b/src/Wt/Dbo/backend/Sqlite3
index 354755f..02a3746 100644
--- a/src/Wt/Dbo/backend/Sqlite3
+++ b/src/Wt/Dbo/backend/Sqlite3
@@ -123,6 +123,7 @@ public:
   virtual std::string autoincrementInsertSuffix() const;
   virtual const char *dateTimeType(SqlDateTimeType type) const;
   virtual const char *blobType() const;
+  virtual bool supportDeferrableFKConstraint() const;
   //@}
 private:
   DateTimeStorage dateTimeStorage_[2];
diff --git a/src/Wt/Dbo/backend/Sqlite3.C b/src/Wt/Dbo/backend/Sqlite3.C
index 3467ffe..994d43d 100644
--- a/src/Wt/Dbo/backend/Sqlite3.C
+++ b/src/Wt/Dbo/backend/Sqlite3.C
@@ -621,6 +621,11 @@ const char *Sqlite3::blobType() const
   return "blob not null";
 }
 
+bool Sqlite3::supportDeferrableFKConstraint() const
+{
+  return true;
+}
+
 void Sqlite3::setDateTimeStorage(SqlDateTimeType type,
 				 DateTimeStorage storage)
 {
diff --git a/test/dbo/DboTest.C b/test/dbo/DboTest.C
index 8a5fe35..0e38ba4 100644
--- a/test/dbo/DboTest.C
+++ b/test/dbo/DboTest.C
@@ -1631,7 +1631,6 @@ BOOST_AUTO_TEST_CASE( dbo_test16 )
   }
 }
 
-#if 0 // doesn't work, no solution yet
 BOOST_AUTO_TEST_CASE( dbo_test17 )
 {
   DboFixture f;
@@ -1646,6 +1645,7 @@ BOOST_AUTO_TEST_CASE( dbo_test17 )
     a.modify()->b = b;
   }
 
+#if !defined(FIREBIRD) && !defined(MYSQL)
   {
     dbo::Transaction t(*session_);
     dbo::ptr<A> a = session_->find<A>();
@@ -1655,8 +1655,8 @@ BOOST_AUTO_TEST_CASE( dbo_test17 )
     b.remove(); // 2
     a.remove(); // 3
   }
+#endif //!FIREBIRD && !MYSQL
 }
-#endif
 
 BOOST_AUTO_TEST_CASE( dbo_test18 )
 {
-- 
1.8.5.2

