   }
 }
 
+fileprivate extension Relationship {
+  
+  var constraintKey : String? {
+    guard !joins.isEmpty else { return nil }
+    
+    func keyForJoin(_ join: Join) -> String {
+      return (join.sourceName ?? "_") + "=>" + (join.destinationName ?? "_")
+    }
+    
+    if joins.count == 1 { return keyForJoin(joins[0]) }
+    
+    let sortedJoins = joins.map(keyForJoin).sorted()
+    return sortedJoins.joined(separator: ",")
+  }
+  
+}
+
+fileprivate extension Sequence where Iterator.Element == Entity {
+  
+  func extractEntityGroups() -> [ [ Entity ] ] {
+    var nameToIndex  = [ String : Int ]()
+    var entityGroups = [ [ Entity ] ]()
+    
+    for entity in self {
+      if let key = entity.externalName, !key.isEmpty {
+        if let idx = nameToIndex[key] {
+          entityGroups[idx].append(entity)
+        }
+        else {
+          nameToIndex[key] = entityGroups.count
+          entityGroups.append([ entity ])
+        }
+      }
+      else {
+        entityGroups.append([ entity ])
+      }
+    }
+    
+    return entityGroups
+  }
+
+  /**
+   * Returns the names of the entities referenced by an entity group from
+   * within to-one relationships (aka foreign keys).
+   *
+   * Excluded are self-references.
+   */
+  func entityNamesReferencedBySchemaGroup() -> Set<String> {
+    let ownNames = Set<String>(self.map( { $0.name } ))
+    var names    = Set<String>()
+    
+    for entity in self {
+      for relship in entity.relationships {
+        guard !relship.isToMany      else { continue }
+        guard !relship.joins.isEmpty else { continue }
+        
+        let name = relship.destinationEntity?.name
+                ?? (relship as? ModelRelationship)?.destinationEntityName
+        
+        if let name = name {
+          guard !ownNames.contains(name) else { continue }
+          names.insert(name)
+        }
+      }
+    }
+    return names
+  }
+  
+}
+
 
 // MARK: - Synchronization
 

    var statements = [ SQLExpression ]()
    statements.reserveCapacity(entities.count * 2)
    
    let entityGroups = extractEntityGroups(entities)
    
    if options.dropTables {
      for group in entityGroups {

    sb += expr.statement
  }
  
  func schemaCreationStatementsForEntities(_ entities: [ Entity ],
                                           options: SchemaGenerationOptions)
       -> [ SQLExpression ]
