Mailing List webobjects-dev@wocommunity.org Message #191
From: OCsite <webobjects-dev@wocommunity.org>
Subject: Re: [WO-DEV] Cannot determine primary key for entity
Date: Sat, 12 Jun 2021 02:09:26 +0200
To: WebObjects & WOnder Development <webobjects-dev@wocommunity.org>
Samuel,

On 11. 6. 2021, at 23:35, Samuel Pelletier <webobjects-dev@wocommunity.org> wrote:
First thing to check is your data. Is the "uid" column has a non null or primary key constraint ?

Absolutely, it is the very PK; modelled as (the only) non-null integer key:

=== DBRecord.plist ===
...
    {
      className = NSNumber;
      columnName = "C_UID";
      externalType = INTEGER;
      name = uid;
      valueType = i;
    },
...
  attributesUsedForLocking = (
    uid
  );
...
  primaryKeyAttributes = (
    uid
  );
...
=== Database ===
CREATE TABLE "T_RECORD" (
...
  "C_UID" INTEGER NOT NULL,
...
);
SET UNIQUE = 1000000 FOR "T_RECORD";
ALTER TABLE "T_RECORD" ADD PRIMARY KEY ("C_UID") NOT DEFERRABLE INITIALLY IMMEDIATE;
===

Besides, it usually fetches all right, only occasionally fails — far as I can say, only when the background task happens to fetch at the same time. It is pretty difficult to catch the fail; I'm playing for hours and hours with the thing now, and so far I've succeeded to see ten-odd fails only (and I've tried to repeat the background threads unnecessarily, increase their number, etc., to increase the probability — so far in vain).

I've also meantime tried to
- lock the background thread ECs
- lock the background thread OSCs
- replace the return ERXEOControlUtilities.objectCountWithQualifier(this.editingContext, 'DBRecord', mymasterrow) code by
===
EOFetchSpecification fs=new EOFetchSpecification('DBRecord', mymasterrow, nil)
fs.fetchesRawRows=YES
fs.rawRowKeyPaths=new NSArray('uid')
return this.editingContext.objectsWithFetchSpecification(fs).count()
===
Nothing helped. On the other hand, when I've
- switched off the background threads completely
- or, reduced ERXObjectStoreCoordinatorPool.maxCoordinators to 1 (which of course considerably slowed the app, for now the worker threads had to wait for the background tasks, using all the same DB channel)...

... the problem never occurred; either it really fixed it, or I was just not lucky enough to see it (see the low probability above).

Real weird.

If there is a constraint, can you indicate the database column type and model type used ?

Not sure what is a model type? Normal model, the .eomodeld folder containing all those plists; I've never seen any other. As for the rest, see please above.

Thanks and all the best,
OC

Le 11 juin 2021 à 07:37, OCsite <webobjects-dev@wocommunity.org> a écrit :

Hi there,

just bumped into another weird EOF case. A pretty plain fetch caused a “Cannot determine primary key for entity” exception. The row contains a number of columns whose values makes sense, some null, some non-null, with one exception — the primary key, modelled as an attribute uid, is indeed a null, thus the exception makes a perfect sense.

How can this happen?

===
IllegalArgumentException: Cannot determine primary key for entity DBRecord from row: {... uid = <com.webobjects.foundation.NSKeyValueCoding$Null>; ... }
  at com.webobjects.eoaccess.EODatabaseChannel._fetchObject(EODatabaseChannel.java:348)
     ... skipped 2 stack elements
  at com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsWithFetchSpecification(EOObjectStoreCoordinator.java:488)
  at com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecification(EOEditingContext.java:4069)
  at er.extensions.eof.ERXEC.objectsWithFetchSpecification(ERXEC.java:1215)
     ... skipped 1 stack elements
  at com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsForSourceGlobalID(EOObjectStoreCoordinator.java:634)
  at com.webobjects.eocontrol.EOEditingContext.objectsForSourceGlobalID(EOEditingContext.java:3923)
  at er.extensions.eof.ERXEC.objectsForSourceGlobalID(ERXEC.java:1178)
     ... skipped 1 stack elements
  at com.webobjects.eoaccess.EOAccessArrayFaultHandler.completeInitializationOfObject(EOAccessArrayFaultHandler.java:77)
  at com.webobjects.eocontrol._EOCheapCopyMutableArray.willRead(_EOCheapCopyMutableArray.java:45)
  at com.webobjects.eocontrol._EOCheapCopyMutableArray.count(_EOCheapCopyMutableArray.java:103)
  at com.webobjects.foundation.NSArray.isEmpty(NSArray.java:1888)
...
===

Just in case it happens to be important (I believe it is not), the problem happens at row

        ... =eolist.representedObject.records().isEmpty()?...:...

where records just returns storedValueForKey('records'), self-evidently a fault, which fires to fetch the rows.

Searching the Web, all I've found is this (linked from here), which does not really help :) Truth is, some background threads do run at the moment; they are comparatively plain though and I can't see why they should cause the problem for the R/R thread. All they do is to

1. get their own OSC from the pool, making sure they never get the same OSC normal sessions have
2. create a new ERXEC in this OSC
3. get a local instance of an object in the EC

=== this is the code of the background thread; a number of those runs:
        def store
        for (def pool=ERXObjectStoreCoordinatorPool._pool();;) {
            store=pool.nextObjectStore
            if (store!=_sessionosc) break // there's one OSC for all sessions, stored in _sessionosc
        }
        return eo.localInstanceIn(ERXEC.newEditingContext(store)).numberOfMasterRowsWithoutOwner()
===

and the method simply fetches:

===
    int numberOfMasterRowsWithoutOwner {
        def mymasterrow=EOQualifier.qualifierWithQualifierFormat("importObject.dataBlock = %@ AND recordOwner = NULL",[this] as NSA)
        return ERXEOControlUtilities.objectCountWithQualifier(this.editingContext, 'DBRecord', mymasterrow)
    }
===

Most time it works properly. Occasionally — rather rarely — the problem above happens. Can you see what am I doing wrong?

Thanks a lot,
OC




Subscribe (FEED) Subscribe (DIGEST) Subscribe (INDEX) Unsubscribe Mail to Listmaster