• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Why doesn't EOF sort our PK problems itself ?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why doesn't EOF sort our PK problems itself ?


  • Subject: Re: Why doesn't EOF sort our PK problems itself ?
  • From: Chuck Hill <email@hidden>
  • Date: Wed, 23 Jan 2008 13:19:11 -0800


On Jan 23, 2008, at 12:06 PM, David Elliott wrote:

Hi Mike,

Note that I am not the one complaining about the PK problem, only saying that it's possible to fix it.

On Jan 23, 2008, at 2:19 PM, Mike Schrag wrote:

On failed save EOF does not update the global IDs with integer PKs. Do something trivial like adding a null-allowed column in EO but making nulls not allowed in the DB. Attempt to save. When it fails change the DB to allow nulls or fill in the property that cannot be null. Save again. You'll notice that the PKs grabbed for the first attempt are skipped and that EOF will ask for PKs again and will use those.
You might be able to wrap your saveChanges in a loop until it succeeds, but you'd need to intercept and parse the duplicate primary key exception, which would be db-specific. What I don't know is if you have deferred constraints if that also includes PK conflicts, and if so, would you only get a single exception on save and not know which item it actually correlated with (or even that it was a dupe PK error -- every db sends this back in different ways, and some don't even support codes on these, so you literally have to parse the exception messages, which is a disaster in the making). Definitely a lot of unfun things you would likely have to do to try and get this to work, which is why I think the better solution is to fix pk generation period and support autoincrement columns in the first place (so you wouldn't even have to deal with this). Not to say that's a trivial change by any means, but EOF really should be capable of using them. That eo_pk_table thing always felt like a huge hack to me.


You're correct in thinking such a fix would be a DB-specific thing. One advantage though is that at least as far as I know, PK constraints are rarely deferred as there is no reason I know of to do so. At least with Posstgres, PK constraints cannot be deferred as far as I know. It completely defeats the point of a primary key.

I defer the ones on join tables. EOF can update these out of sync when relationships between two objects are removed and restored. So it can do the insert before the delete. Of course, EOF could be fixed to do the ordering properly...



Also, you ought to know why EO does not use auto-increment PKs in the first place. To do so would require a huge rethink of the way the EOAccess layer operates. At the moment it grabs all of the new PKs from the DB in one piece of code and then actually issues the changes in another piece.

With auto-increment PKs you would not know the PK until after you did the insert. That means that the PK propagation phase would have to be done concurrently with the insertion phase. Right now that's not possible because the inserts aren't ordered in any particular manner. For instance, what do you do when you've got a hierarchical structure with one PK propagating into a compound PK on another entity?

Worse yet, what do you do when you have cyclical dependencies? One pattern I use is to relate Foo to-many Bar but then also have an FK in Foo for the Bar that is most current (e.g. a cache of sorts). The way EOF works now the PK propagation happens before any inserts so EOF can generate a PK for Foo and a PK for all of the Bar records, propagate the Foo PK into the foo FK in each Bar and propagate the one Bar's PK into the Foo FK for the most current Bar.

It is impossible to do this if you defer PK creation until the insert phase. A hack would be to insert Foo with a null active_bar_id, then insert all of the bar records, then update foo's active_bar_id. But the question then becomes how to figure this out automatically. It's a very non-trivial problem that EOF already solves by grabbing unique PKs and propagating them itself before inserting records.

A slightly different design is to make Bar's PK compound such that it is composed of (foo_id,i). In that case one has to manually assign Bar's "i" component but it does make it simpler in the sense that Foo then only has an active_bar_i which is known even earlier. Careful though, don't make the activeBar relationship a class property or you'll kill foo_id and not just active_bar_i if activeBar is null. That's of course trivial to work around by synthesizing the activeBar relationship by knowing Foo (which is this after all) and the activeBarI which you can use to pull the right bars object.

Anyway, the bottom line is that EOF's style of PK generation is a feature, not a bug. It's very difficult to understand why EOF does things the way it does until you hit one of these cyclical cases and then you finally get it. In fact, these cyclical cases are not uncommon at all and it's one of the things that non-EOF developers fight with. A typical solution is to move to GUID keys.

There's already an example of some auto-PK fixes in the PostgresqlPlugin. Should the sequence object not exist, the plugin will recreate it. Furthermore, should it exist but be returning IDs that are too low then assuming you catch adaptor exceptions you can try saving again and eventually you'll bump the sequence high enough. You can also stop after the first save, regenerate primary key support, then save again and it will pull new PKs.
This is different, though ... This is a failure in the pk generator, which is pretty straightforward to catch and handle in the plugin. The problem you're talking about is a failure during commit, after the plugin's pk generator has already run.

That is true. But it's still before EOF commits to actually using the specific key values. So it's possible to correct these problems. Assuming PK constraints are not deferred then regardless of database you should get an exception immediately on the insert line. Then you get into a situation where you need to figure out why you got the exception. That's DB dependent but on a DB like Postgres it will be a failure on the index which has a well-known name. So simply grepping the error message for the index name should be sufficient for postgres and a similar solution can be used for most other databases.

Do I think this is something that ought to go into EOF proper? Not really. But the original poster was looking for a way to automatically fix his PK sequences and so I'm giving him the outline of how he could do this. He may decide (and I would if I were him) that ultimately it's cheaper to remind yourself to update the PK sequence if you make changes outside of EOF.

So clearly it's not impossible to add some code that upon primary key conflicts will simply regenerate the PK support. One drawback is that while you are regenerating the PK support you really ought to block all other access to the database or else you could easily get two DB clients trying to do the regeneration concurrently.
Nothing's _impossible_ :), but I suspect it is pretty tricky to get it to work right. You basically have all the same context the framework does at this point, though. I suspect you could try to prototype this in your own code at a higher level to see if there's even enough info available to pull it off.

I assure you there's enough information to pull it off, but it would have to be done very deep in the EOAccess layer, probably via a delegate, and doing it requires a very deep understanding of EOF and a very deep understanding of why EOF works the way it does. Every problem with PKs in EOF translates to a lack of understanding on the part of the developer as to how EOF does its thing. The best reference on this stuff is Chuck and Sacha's book with the bumble-bee cover but even that does not (believe it or not) go deep enough.

Mmmm. Mike is the person that _I_ ask when I have a question on the deep down EOF internals. I'm pretty sure he "gets" it.



Chuck

--

Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems.
http://www.global-village.net/products/practical_webobjects






_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: Why doesn't EOF sort our PK problems itself ?
      • From: David Elliott <email@hidden>
References: 
 >Why doesn't EOF sort our PK problems itself ? (From: Simon McLean <email@hidden>)
 >Re: Why doesn't EOF sort our PK problems itself ? (From: Mike Schrag <email@hidden>)
 >Re: Why doesn't EOF sort our PK problems itself ? (From: David Elliott <email@hidden>)
 >Re: Why doesn't EOF sort our PK problems itself ? (From: Mike Schrag <email@hidden>)
 >Re: Why doesn't EOF sort our PK problems itself ? (From: David Elliott <email@hidden>)

  • Prev by Date: Re: Why doesn't EOF sort our PK problems itself ?
  • Next by Date: Re: WOLips: Project Triangles do not work.
  • Previous by thread: Re: Why doesn't EOF sort our PK problems itself ?
  • Next by thread: Re: Why doesn't EOF sort our PK problems itself ?
  • Index(es):
    • Date
    • Thread