[Lift] Re: Mapper with custom id
I'm probably missing something here, but wouldn't putting those 5 lines of code into a trait work? trait ManualValue { /* allow user-defined primary key */ override def writePermission_? = true override def dbAutogenerated_? = false private var myDirty = false override def dirty_? = myDirty override def dirty_?(b : Boolean) = { myDirty = b; super.dirty_?(b) } } object myId extends MappedLongIndex(this) with ManualValue If that does work, I don't see any issue with adding that trait to the Mapper library for others to use... Derek On Tue, Aug 25, 2009 at 12:42 PM, Naftoli Gugenheim naftoli...@gmail.comwrote: On Tue, Aug 25, 2009 at 2:31 PM, David Pollak feeder.of.the.be...@gmail.com wrote: On Tue, Aug 25, 2009 at 10:56 AM, Naftoli Gugenheim naftoli...@gmail.com wrote: It definitely would have been an option, although it would have been more difficult due to the complex structure of the new database. But I want to understand why it can't work the way I thought it would. Peter provided code that allows you to override autogeneration of keys. Like I said, it doesn't make sense to add 5 lines of code to 13 mappers each just to make importing simpler. That code is good for a non-autogenerated primary key. Why does it work the way it does? Because in the nearly 3 year life of Mapper, you're the first person that's asked for the feature. Because the cost of changing Mapper to work differently (especially when there's a work-around) and testing it and making sure it doesn't break isn't worth it. Well, I can't argue with that... But is it really so complicated to change? Would the following not cover all the bases? 1) A private var on the mapper, _saved_? etc., initialized to false 2) When find etc. creates an instance it uses reflection to set this variable to true 3) When save is successful it sets this variable to true 4) def saved_? returns the value of the var. Wouldn't that be more accurate from a logical standpoint? I'm not coming from the angle of, I have a use case for a feature, but from, doesn't this use case bring out a hole in the logic and demonstrate that the index can be nondefault and still represent a new record (aside from MSAccess)? Regards --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[Lift] Re: Mapper with custom id
I had seen that thread, but it doesn't make sense to add all that code to all of my mapper models when they're ordinary mappers with ordinary auto-increment primary keys, which I happen to be importing from the database used by the previous, PHP version of this app. The foreign keys have to match up properly. Meanwhile I changed it so that it keeps a Map in memory from old ids to mapper instances, and linked children to the mapper with the new id. But wouldn't the logic of saved_? make more sense the way I proposed? - Peter Robinettpe...@bubblefoundry.com wrote: You need to set the mapper id field as editable. Here is what I had to do to use a MappedStringIndex as a primary key that I can set manually: /* MAC address as primary key */ def primaryKeyField = mac object mac extends MappedStringIndex(this, 17) with IndexedField [String] { override def dbDisplay_? = true override lazy val defaultValue = randomString(maxLen) /* allow user-defined primary key */ override def writePermission_? = true override def dbAutogenerated_? = false private var myDirty = false override def dirty_? = myDirty override def dirty_?(b : Boolean) = { myDirty = b; super.dirty_?(b) } override def fieldCreatorString(dbType: DriverType, colName: String): String = colName+ CHAR(+maxLen+) NOT NULL } Peter On Aug 24, 5:30 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: I'm trying to import data from a non-mapper-based database to one that is. I'm reading data with DB.exec and trying to save it using Mapper, but it's not getting saved. I'm guessing that since I'm setting the id (in runSafe) it thinks it needs to do an update, not an insert. Is there a workaround? Also, doesn't this scenario break the logic of MetaMapper.saved_?() ? Wouldn't it make more sense to have a saved flag that is cleared by default and set when it's created as a result of a find, and after it's saved? --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[Lift] Re: Mapper with custom id
On Tue, Aug 25, 2009 at 7:08 AM, Naftoli Gugenheim naftoli...@gmail.comwrote: I had seen that thread, but it doesn't make sense to add all that code to all of my mapper models when they're ordinary mappers with ordinary auto-increment primary keys, which I happen to be importing from the database used by the previous, PHP version of this app. The foreign keys have to match up properly. Meanwhile I changed it so that it keeps a Map in memory from old ids to mapper instances, and linked children to the mapper with the new id. But wouldn't the logic of saved_? make more sense the way I proposed? For the load operation where you're moving databases, why not just write some custom code to dump the data? - Peter Robinettpe...@bubblefoundry.com wrote: You need to set the mapper id field as editable. Here is what I had to do to use a MappedStringIndex as a primary key that I can set manually: /* MAC address as primary key */ def primaryKeyField = mac object mac extends MappedStringIndex(this, 17) with IndexedField [String] { override def dbDisplay_? = true override lazy val defaultValue = randomString(maxLen) /* allow user-defined primary key */ override def writePermission_? = true override def dbAutogenerated_? = false private var myDirty = false override def dirty_? = myDirty override def dirty_?(b : Boolean) = { myDirty = b; super.dirty_?(b) } override def fieldCreatorString(dbType: DriverType, colName: String): String = colName+ CHAR(+maxLen+) NOT NULL } Peter On Aug 24, 5:30 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: I'm trying to import data from a non-mapper-based database to one that is. I'm reading data with DB.exec and trying to save it using Mapper, but it's not getting saved. I'm guessing that since I'm setting the id (in runSafe) it thinks it needs to do an update, not an insert. Is there a workaround? Also, doesn't this scenario break the logic of MetaMapper.saved_?() ? Wouldn't it make more sense to have a saved flag that is cleared by default and set when it's created as a result of a find, and after it's saved? -- 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 -~--~~~~--~~--~--~---
[Lift] Re: Mapper with custom id
It definitely would have been an option, although it would have been more difficult due to the complex structure of the new database. But I want to understand why it can't work the way I thought it would. Anyway, here's the code that I used in the end. There may still be a few bugs but it demonstrates the approach. I attached the whole file but here's a little sample. val clients = scala.collection.mutable.Map[Long, Client]() ... DB.exec(sourceCon, select * from clients) {rs = import rs._ while(rs.next) { val c = Client.create.last(getString(last)).first(getString(first)). home(getString(home)).cell(getString(cell)).address(getString(address)). area(getString(area)).created(getDate(created)).modified(getDate(modified)) if(!c.save) println(Couldn't save: + c) clients += getLong(id) - c } } Then I have a Map from the old id to the Client, and when I process the Request which has a client_id I can write req.client(clients(getLong(client_id))) So I guess I could do this by writing direct SQL, but then after I wrote each client I would have to retrieve its new id. Now I know that some databases like MS Access don't let you specify a value for an autonumber field, and in most cases there's no reason to specify it, but I think that the use case is enough to question the logic of always assuming that if the id is 0 then it's not a new record, if there is a more straightforward and accurate way to determine that. On Tue, Aug 25, 2009 at 11:17 AM, David Pollakfeeder.of.the.be...@gmail.com wrote: On Tue, Aug 25, 2009 at 7:08 AM, Naftoli Gugenheim naftoli...@gmail.com wrote: I had seen that thread, but it doesn't make sense to add all that code to all of my mapper models when they're ordinary mappers with ordinary auto-increment primary keys, which I happen to be importing from the database used by the previous, PHP version of this app. The foreign keys have to match up properly. Meanwhile I changed it so that it keeps a Map in memory from old ids to mapper instances, and linked children to the mapper with the new id. But wouldn't the logic of saved_? make more sense the way I proposed? For the load operation where you're moving databases, why not just write some custom code to dump the data? - Peter Robinettpe...@bubblefoundry.com wrote: You need to set the mapper id field as editable. Here is what I had to do to use a MappedStringIndex as a primary key that I can set manually: /* MAC address as primary key */ def primaryKeyField = mac object mac extends MappedStringIndex(this, 17) with IndexedField [String] { override def dbDisplay_? = true override lazy val defaultValue = randomString(maxLen) /* allow user-defined primary key */ override def writePermission_? = true override def dbAutogenerated_? = false private var myDirty = false override def dirty_? = myDirty override def dirty_?(b : Boolean) = { myDirty = b; super.dirty_?(b) } override def fieldCreatorString(dbType: DriverType, colName: String): String = colName+ CHAR(+maxLen+) NOT NULL } Peter On Aug 24, 5:30 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: I'm trying to import data from a non-mapper-based database to one that is. I'm reading data with DB.exec and trying to save it using Mapper, but it's not getting saved. I'm guessing that since I'm setting the id (in runSafe) it thinks it needs to do an update, not an insert. Is there a workaround? Also, doesn't this scenario break the logic of MetaMapper.saved_?() ? Wouldn't it make more sense to have a saved flag that is cleared by default and set when it's created as a result of a find, and after it's saved? -- 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 -~--~~~~--~~--~--~--- Import.scala Description: Binary data
[Lift] Re: Mapper with custom id
On Tue, Aug 25, 2009 at 10:56 AM, Naftoli Gugenheim naftoli...@gmail.comwrote: It definitely would have been an option, although it would have been more difficult due to the complex structure of the new database. But I want to understand why it can't work the way I thought it would. Peter provided code that allows you to override autogeneration of keys. Why does it work the way it does? Because in the nearly 3 year life of Mapper, you're the first person that's asked for the feature. Because the cost of changing Mapper to work differently (especially when there's a work-around) and testing it and making sure it doesn't break isn't worth it. Anyway, here's the code that I used in the end. There may still be a few bugs but it demonstrates the approach. I attached the whole file but here's a little sample. val clients = scala.collection.mutable.Map[Long, Client]() ... DB.exec(sourceCon, select * from clients) {rs = import rs._ while(rs.next) { val c = Client.create.last(getString(last)).first(getString(first)). home(getString(home)).cell(getString(cell)).address(getString(address)). area(getString(area)).created(getDate(created)).modified(getDate(modified)) if(!c.save) println(Couldn't save: + c) clients += getLong(id) - c } } Then I have a Map from the old id to the Client, and when I process the Request which has a client_id I can write req.client(clients(getLong(client_id))) So I guess I could do this by writing direct SQL, but then after I wrote each client I would have to retrieve its new id. Now I know that some databases like MS Access don't let you specify a value for an autonumber field, and in most cases there's no reason to specify it, but I think that the use case is enough to question the logic of always assuming that if the id is 0 then it's not a new record, if there is a more straightforward and accurate way to determine that. On Tue, Aug 25, 2009 at 11:17 AM, David Pollakfeeder.of.the.be...@gmail.com wrote: On Tue, Aug 25, 2009 at 7:08 AM, Naftoli Gugenheim naftoli...@gmail.com wrote: I had seen that thread, but it doesn't make sense to add all that code to all of my mapper models when they're ordinary mappers with ordinary auto-increment primary keys, which I happen to be importing from the database used by the previous, PHP version of this app. The foreign keys have to match up properly. Meanwhile I changed it so that it keeps a Map in memory from old ids to mapper instances, and linked children to the mapper with the new id. But wouldn't the logic of saved_? make more sense the way I proposed? For the load operation where you're moving databases, why not just write some custom code to dump the data? - Peter Robinettpe...@bubblefoundry.com wrote: You need to set the mapper id field as editable. Here is what I had to do to use a MappedStringIndex as a primary key that I can set manually: /* MAC address as primary key */ def primaryKeyField = mac object mac extends MappedStringIndex(this, 17) with IndexedField [String] { override def dbDisplay_? = true override lazy val defaultValue = randomString(maxLen) /* allow user-defined primary key */ override def writePermission_? = true override def dbAutogenerated_? = false private var myDirty = false override def dirty_? = myDirty override def dirty_?(b : Boolean) = { myDirty = b; super.dirty_?(b) } override def fieldCreatorString(dbType: DriverType, colName: String): String = colName+ CHAR(+maxLen+) NOT NULL } Peter On Aug 24, 5:30 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: I'm trying to import data from a non-mapper-based database to one that is. I'm reading data with DB.exec and trying to save it using Mapper, but it's not getting saved. I'm guessing that since I'm setting the id (in runSafe) it thinks it needs to do an update, not an insert. Is there a workaround? Also, doesn't this scenario break the logic of MetaMapper.saved_?() ? Wouldn't it make more sense to have a saved flag that is cleared by default and set when it's created as a result of a find, and after it's saved? -- 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 -- 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
[Lift] Re: Mapper with custom id
On Tue, Aug 25, 2009 at 2:31 PM, David Pollak feeder.of.the.be...@gmail.com wrote: On Tue, Aug 25, 2009 at 10:56 AM, Naftoli Gugenheim naftoli...@gmail.comwrote: It definitely would have been an option, although it would have been more difficult due to the complex structure of the new database. But I want to understand why it can't work the way I thought it would. Peter provided code that allows you to override autogeneration of keys. Like I said, it doesn't make sense to add 5 lines of code to 13 mappers each just to make importing simpler. That code is good for a non-autogenerated primary key. Why does it work the way it does? Because in the nearly 3 year life of Mapper, you're the first person that's asked for the feature. Because the cost of changing Mapper to work differently (especially when there's a work-around) and testing it and making sure it doesn't break isn't worth it. Well, I can't argue with that... But is it really so complicated to change? Would the following not cover all the bases? 1) A private var on the mapper, _saved_? etc., initialized to false 2) When find etc. creates an instance it uses reflection to set this variable to true 3) When save is successful it sets this variable to true 4) def saved_? returns the value of the var. Wouldn't that be more accurate from a logical standpoint? I'm not coming from the angle of, I have a use case for a feature, but from, doesn't this use case bring out a hole in the logic and demonstrate that the index can be nondefault and still represent a new record (aside from MSAccess)? Regards --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---