[Lift] Re: Autogenerated PKs and MetaMapper

2009-09-23 Thread Thomas Rampelberg

You'd think I could read the only sticky post without getting linked to it!

Let's see if I can clearly explain my use cases. The simplest to
explain is that I'd like to use UUIDs as the primary key of a table.
To do this, I've done something like this:

class MappedStringPrimaryKey[T:Mapper[T]] (
override val fieldOwner: T, override val maxLen: Int)
  extends MappedStringIndex[T](fieldOwner, maxLen)
with LifecycleCallbacks {
  override def writePermission_? = true
  override def dbDisplay_? = true
  override def dbAutogenerated_? = false

  override def fieldCreatorString(
  dbType: DriverType, colName: String): String =
colName+ CHAR(+maxLen+) NOT NULL 
}

class UUIDPrimaryKey[T:Mapper[T]] (
  override val fieldOwner: T) extends MappedStringPrimaryKey[T](
fieldOwner, 16) {
  override def dbDisplay_? = false
  override def dbIndexFieldIndicatesSaved_? = (i_is_! != defaultValue)
  override lazy val defaultValue = {
val uuid = UUID.randomUUID.toString.replaceAll(-, ).elements
(new URLCodec).decode(uuid.zip(uuid).map(x=%+x._1+x._2).mkString)
  }
}

The first problem is that while MappedStringIndex is setup as a
primary key, the field is required to be NOT NULL. Secondly, the
dbIndexFieldIndicatesSaved_? ends up being a little non-intuitive (I
would have expected it to be part of MappedStringIndex as well).

Also, with this use case, I had to make a couple modifications to
MetaMapper itself. The first one:

@@ -884,7 +891,7 @@ trait MetaMapper[A:Mapper[A]] extends
BaseMetaMapper with Mapper[A] {
 mappedColumnInfo(colName) = mf
 mappedColumns(colName) = v
   }
-  if (mf.dbPrimaryKey_?  mf.dbAutogenerated_?) {
+  if (mf.dbPrimaryKey_?) {
 indexMap =
Full(MapperRules.quoteColumnName(mf.dbColumnName)) //
Full(v.getName.toLowerCase)
   }

Without indexMap being defined, if I do something along these lines:

Field.save
Field.save

(save twice in succession) I get a duplicate key value error because
the save call is trying to insert the object again.

The second modification that I made to MetaMapper:

@@ -600,10 +603,13 @@ trait MetaMapper[A:Mapper[A]] extends
BaseMetaMapper with Mapper[A] {
   try {
 if (rs.next) {
   val meta = rs.getMetaData
-  toSave.runSafe {
-findApplier(indexMap.open_!, rs.getObject(1)) match {
-  case Full(ap) = ap.apply(toSave, rs.getObject(1))
-  case _ =
+  if (indexedField(toSave).map(_.dbAutogenerated_?)
+  getOrElse false) {
+toSave.runSafe {
+  findApplier(indexMap.open_!, rs.getObject(1)) match {
+case Full(ap) = ap.apply(toSave, rs.getObject(1))
+case _ =
+  }
 }
   }
   !rs.next

If I don't do this patch, when the object is saved, the value gets
reset from foobar to 1. The database stores it correctly, it's
simply the object that has its attributes wrong.

My other use case is documented below. I'm trying to set the value of
the primary key before submitting. At this point, i_is_! is always
different than the defaultValue and without using the afterSave hook,
the object tries to update instead of insert itself. While this isn't
a big issue, it just seems like there must be a better solution to the
problem.

Overall, if some general kind of solution for both of these problems
(updates to MappedStringIndex perhaps) made it in, I'd be ecstatic.

On Tue, Sep 22, 2009 at 8:36 AM, David Pollak
feeder.of.the.be...@gmail.com wrote:
 Thomas,

 We, as a rule, do not accept patches.  For a complete discussion, please
 see:
 http://groups.google.com/group/liftweb/browse_frm/thread/0c7a97cbf60780f0?hl=en#

 The current state of mapper's primary key support is sub-optimal.  There
 have been a couple of discussions of the issues on-list.  I am hoping to
 spend some time on this issue on Thursday.  If you've got specific
 requirements or specific tests, please post them.

 Thanks,

 David

 On Mon, Sep 21, 2009 at 9:33 PM, Thomas Rampelberg pyronic...@gmail.com
 wrote:

 I've been working at getting MetaMapper to work with primary keys that
 aren't auto-generated (or longs). Towards this end, I've got a patch
 for MetaMapper.scala that I'd like to get in. Who could I talk about
 the process for that?

 In addition, as part of implementing the functionality, I ran into
 some interesting problems. The most interesting one has to do with
 dbIndexFieldIndicatesSaved_?. The default (i_is_! != defaultValue)
 works great for cases where you're using the default value for the
 actual primary key. Unfortunately, if you use something like this when
 you're actively setting the primary key yourself there are some
 unfortunate side effects (nothing gets saved to the database).

 To get around this, I'm doing something along these lines:

 class 

[Lift] Re: Autogenerated PKs and MetaMapper

2009-09-22 Thread David Pollak
Thomas,

We, as a rule, do not accept patches.  For a complete discussion, please
see:
http://groups.google.com/group/liftweb/browse_frm/thread/0c7a97cbf60780f0?hl=en#

The current state of mapper's primary key support is sub-optimal.  There
have been a couple of discussions of the issues on-list.  I am hoping to
spend some time on this issue on Thursday.  If you've got specific
requirements or specific tests, please post them.

Thanks,

David

On Mon, Sep 21, 2009 at 9:33 PM, Thomas Rampelberg pyronic...@gmail.comwrote:


 I've been working at getting MetaMapper to work with primary keys that
 aren't auto-generated (or longs). Towards this end, I've got a patch
 for MetaMapper.scala that I'd like to get in. Who could I talk about
 the process for that?

 In addition, as part of implementing the functionality, I ran into
 some interesting problems. The most interesting one has to do with
 dbIndexFieldIndicatesSaved_?. The default (i_is_! != defaultValue)
 works great for cases where you're using the default value for the
 actual primary key. Unfortunately, if you use something like this when
 you're actively setting the primary key yourself there are some
 unfortunate side effects (nothing gets saved to the database).

 To get around this, I'm doing something along these lines:

 class InfoHashPrimaryKey[T:Mapper[T]] (
  override val fieldOwner: T) extends MappedStringPrimaryKey[T] (
fieldOwner, 20) with LifecycleCallbacks {
private var _saved = false
override def dbIndexFieldIndicatesSaved_? = _saved
override def afterSave = _saved = true
  }

 Would there happen to be a better way to do this? Leveraging an
 afterSave hook seems like potential overkill.

 



-- 
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

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