As mentioned is this issue
(http://github.com/dpp/liftweb/issues#issue/19), and as came up on the
list recently, Lift currently has no way to specify that a field or an
index be unique. I've coded up a patch that addresses this, and could
also be used for other index types on a project specific basis (for
instance, FULLTEXT or SPATIAL indexes in mysql).

-Cale

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

From 4436bd234d5a80ebe5e0f027256979fc14b3dea8 Mon Sep 17 00:00:00 2001
From: Calen Pennington <cpenn...@flying-pickle.(none)>
Date: Wed, 8 Jul 2009 22:48:31 -0400
Subject: [PATCH] Adding the ability to create UNIQUE indexes over single or multiple columns

---
 .../scala/net/liftweb/mapper/MappedField.scala     |   14 ++++++++++++++
 .../main/scala/net/liftweb/mapper/MetaMapper.scala |    7 ++++++-
 .../main/scala/net/liftweb/mapper/Schemifier.scala |   15 ++++++++-------
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala b/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala
index 01c739c..298211f 100644
--- a/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala
+++ b/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala
@@ -98,6 +98,11 @@ trait BaseMappedField extends SelectableField with Bindable {
   def dbIndexed_? : Boolean
 
   /**
+   * What type of index is this?
+   */
+  def dbIndexType : String
+
+  /**
    * Is the field the table's primary key
    */
   def dbPrimaryKey_? : Boolean
@@ -165,6 +170,13 @@ trait DBIndexed extends BaseMappedField {
 }
 
 /**
+ * Mix this trait into a DBIndexed and it will use a unique index
+ */
+trait UniqueIndexed extends DBIndexed {
+  override def dbIndexType = "UNIQUE"
+}
+
+/**
  * The Trait that defines a field that is mapped to a foreign key
  */
 trait MappedForeignKey[KeyType, MyOwner <: Mapper[MyOwner], Other <: KeyedMapper[KeyType, Other]] extends MappedField[KeyType, MyOwner] {
@@ -521,6 +533,8 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
 
   def dbPrimaryKey_? : Boolean = false
 
+  def dbIndexType : String = ""
+
   /**
    * Is the field a foreign key reference
    */
diff --git a/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala b/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala
index 0d36c8b..a59a0a8 100644
--- a/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala
+++ b/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala
@@ -1118,8 +1118,13 @@ object OprEnum extends Enumeration {
   val Like = Value(9, "LIKE")
 }
 
+case class Index[A <: Mapper[A]](columns: IndexItem[A]*) {
+  def dbIndexType : String = ""
+}
 
-case class Index[A <: Mapper[A]](columns: IndexItem[A]*)
+case class UniqueIndex[A <: Mapper[A]](override val columns: IndexItem[A]*) extends Index[A] {
+  override def dbIndexType = "UNIQUE"
+}
 
 abstract class IndexItem[A <: Mapper[A]] {
   def field: BaseMappedField
diff --git a/lift-mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala b/lift-mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala
index f24851b..85e0a7f 100644
--- a/lift-mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala
+++ b/lift-mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala
@@ -251,20 +251,21 @@ object Schemifier {
       field =>
 	if (!indexedFields.contains(List(field.dbColumnName.toLowerCase))) {
           cmds += maybeWrite(performWrite, logFunc, connection) {
-            () => "CREATE INDEX "+(table.dbTableName+"_"+field.dbColumnName)+" ON "+table.dbTableName+" ( "+field.dbColumnName+" )"
+            () => "CREATE "+field.dbIndexType+" INDEX "+(table.dbTableName+"_"+field.dbColumnName)+" ON "+table.dbTableName+" ( "+field.dbColumnName+" )"
           }
           field.dbAddedIndex.toList
 	} else Nil
     }
 
     table.dbIndexes.foreach {
-      index =>
+      index => {
 	val columns = index.columns.toList
-      val fn = columns.map(_.field.dbColumnName.toLowerCase).sort(_ < _)
-      if (!indexedFields.contains(fn)) {
-        cmds += maybeWrite(performWrite, logFunc, connection) {
-          () => "CREATE INDEX "+(table.dbTableName+"_"+columns.map(_.field.dbColumnName).mkString("_"))+" ON "+table.dbTableName+" ( "+columns.map(_.indexDesc).comma+" )"
-        }
+	val fn = columns.map(_.field.dbColumnName.toLowerCase).sort(_ < _)
+	if (!indexedFields.contains(fn)) {
+          cmds += maybeWrite(performWrite, logFunc, connection) {
+            () => "CREATE "+index.dbIndexType+" INDEX "+(table.dbTableName+"_"+columns.map(_.field.dbColumnName).mkString("_"))+" ON "+table.dbTableName+" ( "+columns.map(_.indexDesc).comma+" )"
+          }
+	}
       }
     }
 
-- 
1.6.0.4

Reply via email to