>> Why does Session.merge only look at primary key and not all unique >> keys? > > Well the theory of operation regarding merge() is based on that of > the identity map, which is linked to object/row identity. > Consider that it also cascades along relationship paths. It would > be a difficult operation to define if it had to choose among > multiple ways to determine the "identity" of each object along the > cascade chain.
Ok. That certainly makes sense for following relationships in the merge (and in general). But for the basic existence checking that is required in the first step(s) of the merge to figure out whether the object being merged already exists or not, it does not seem unreasonable for it to check all unique keys. ie: in your docs you say the first merge step is "It examines the primary key of the instance". Can't it be "It checks any provided unique elements of the instance". From that point, normal/sensible identity map rules could resume for cascade. "Is a" checking is not the same as "is related to" checking, which is clearly nuttier. Although... you do mention later that ORM level has no knowledge of "unique" attributes, so perhaps this is also impossible? Is the "unique = True" kwarg on the Column not kept anywhere? Is it just used for table creation and then turfed? >> Leaving aside some irritating DBMS restrictions on PKs and some >> automatic indexing that tends to happen, the PK is not fundamentally >> different than other unique keys > > It is fundamentally different in that a database row within a > reasonable schema has only one "identity". The usage of surrogate > primary keys perhaps pollutes this concept to some degree. Ok again... but you also agree that the use of surrogate keys is standard (and some say "necessary") practice. In the case of Sqlite (as in my example), adding this surrogate key automatically makes the schema "unreasonable" because you now need to have the primary key as the meaningless surrogate key (single id column), and the natural key ends up being relegated to just another unique index. Unfortunately, the latter renders the object/table useless for use with the useful session.merge() function. I don't recall the details, but I think there may be a similar PostgreSQL limitation regarding autoincrements as well. > for some recent insight into my epic battle with time consumption, > see http://techspot.zzzeek.org/2010/12/12/a-tale-of-three-profiles Great link/post! Seeing successful optimizations is always good, and the writeup is quite informative. Regarding RunSnakeRun, I've used it as well and like it. However, I'm a bit of a resolution junkie and the box frames in RunSnakeRun's visual output are limited in how they will squish all the box borders together. If you haven't given kcachegrind a shot yet for viewing cProfile results, you might want to give it a trial run as the visual output is a better representation of timing scale, and the viewing is more powerful as well (if resolution is too weak if an argument). Some tips to get it to work well for python are here: http://stackoverflow.com/questions/1896032/using-cprofile-results-with-kcachegrind > The generic "insert if not exists" pattern that is extensible to > whatever attributes you want is at: > http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject Thanks for the example... I would have been worried about how fiddling with the __new__ constructor would interfere with query loads, but that example shows how to make it work. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.