SamDonaldson wrote:
> Hello,
> 
> It seems almost impossible to catch a mysql duplicate key exception
> through sqlalchemy.  Can anybody help with understanding this?  How do
> I catch a duplicate key exception in mysql?  I tried catching the
> flush exception from sqlalchemy but that's definitely not doing the
> job.  Do I have access to lower level dbapi exceptions that I can use
> in my code.
> 
> Thanks.
> 

Hi Sam,
    The same problem exists for other databases (SQLite, etc).  When I 
ran into this problem earlier, I grepped code until I found that 
SQLObject (not SQLAlchemy, but probably a similar situation) ONLY 
returns an SQLObjectNotFound error... that's just about the only DB 
error it traps, if no object is found by the query.  Otherwise it just 
passes the native RDBMS error message thru.
   Each RDBMS behind these ORMs returns different errors, therefore it 
is difficult to trap them all in a try:except pattern... the ORMs don't 
give us that functionality per se.  I think they could (pass through the 
native errors), but they don't.  And it's probably a good idea so that 
the ORMs (SQLObject and Alchemy) remain high-level and above the fray of 
which RDBMS to use behind the scenes.  And also not have to keep up with 
changing error message styles through all the many releases that each 
RDBMS has had over the years.

   Solution:  One solution is to make your code test first for the 
availability of that name you want to use, and build a try:except around 
the message returned by your ORM if there is a name conflict.
   Example:  Using SQLObject, you can do something like this to create a 
'save' method that tests for new page name collisions using 
SQLObjectNotFound instead of getting the ugly duplicate name error message:

     @expose()
     def save(self, pagename, newpagename, data, submit):
         if pagename == pagenewname:
             page = Page.byPagename(pagename)
             page.data = data
             turbogears.flash("Page changes saved.")
             raise redirect("/", pagename=newpagename)
         else:
             try:
                 page = Page.byPagename(newpagename)
             except SQLObjectNotFound:
                 page = Page.byPagename(pagename)
                 page.pagename = newpagename
                 page.data = data
                 turbogears.flash("Page changes saved with a new name.")
                 raise redirect("/", pagename=newpagename)
             page = Page.byPagename(pagename)
             page.data = data
             ermsg = "Sorry, that page name ('" + newpagename + \
               "') is already in use.  Choose another, or leave \
               it as '" + pagename + "'."
             turbogears.flash(ermsg)
             raise redirect("/edit", pagename=pagename)


    I don't really like this solution, as I don't like using try:except 
error trapping in general, especially in this instance where it twists 
the logic around in an unpythonic way.  But it works for changing the 
name on an already existing Page (as in a wiki, etc) and making sure 
that there is not already one with that name being used.
    For SQLAlchemy, I am not sure of the answer, but it seems that there 
is no comparable error message to SQLObject's SQLObjectNotFound.  If 
there isn't one, then a query for an object with newname should likely 
return None instead of some NotFound error... and you then can simply 
test for the None value instead of for a NotFound error, and no 
try:except will be needed.

   In short, test your database with a query to make sure you won't have 
a name collision first, then do the object save, rather than trying a 
save first and getting a name collision error for your effort.  It's the 
equivalent of validating a form...
   In fact, that would be a GREAT form validation trick... use 
Ajax-style methods to check behind the scenes that a new name will be 
valid BEFORE the user actually submits the form.
   In fact, wouldn't it be nice if ALL validation of user form entries 
were done by Ajax-style methods BEFORE the user ever gets to the point 
of hitting the submit button?  Do all the validation client-side or 
using Ajax messaging that works as each form portion loses focus? Hmmmm. 
  Just thinking out loud now.
   Hope there was help up there in my rambling, Sam.
Paul


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"TurboGears" 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/turbogears?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to