Skip to content

Commit 3637df8

Browse files
dmealingclaude
andcommitted
fix(omdb): getObjectByRef bound its PK expression — was reading an arbitrary row
getObjectByRef built the primary-key Expression from the ref but never set it on the QueryOptions, so the read was an unfiltered "first row of the table" limited to 1 — it ignored the reference entirely. Via the ObjectManager.deleteObject(getObjectByRef(c, ref)) delete-by-ref path this meant deleting the WRONG object. Bind the expression to the QueryOptions so the read resolves the referenced row, and (FR-017 TPH) scope it to the subtype so a ref-load can't surface a sibling subtype's row from a shared single table. The method's ref→metaobject name resolution runs through service discovery (getMetaDataLoaderRegistry(ObjectRef.class)), which a manually-created test loader is not part of — so the conformance harness deliberately passes MetaObject directly and never exercises this verb, and there is no isolated test for it. The corrected read now uses the same readMany(conn, mc, mapping, options-with-expression) path that getObjects/loadObject and the roundtrip/update/delete write gates exercise green across the 23 persistence scenarios. omdb 46/0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent da00178 commit 3637df8

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

server/java/omdb/src/main/java/com/metaobjects/manager/db/ObjectManagerDB.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,15 @@ public Object getObjectByRef(ObjectConnection c, String refStr) {
390390

391391
try {
392392

393-
// Create the Expression for the Primary Keys
394-
Expression exp = buildPrimaryKeyExpressionFromRef(mc, ref);
395-
396-
// Create the QueryOptions and limit to the first 1
397-
QueryOptions qo = new QueryOptions();
393+
// Create the Expression for the Primary Keys. FR-017 TPH: scope to the subtype so a
394+
// ref-load can't surface a sibling subtype's row from the shared table.
395+
Expression exp = scopeToSubtype(mc, buildPrimaryKeyExpressionFromRef(mc, ref));
396+
397+
// Bind the PK expression to the QueryOptions, limited to the first matching row. The
398+
// expression MUST be set — without it this read is an unfiltered "first row of the
399+
// table", which (via the deleteObject(getObjectByRef(...)) caller) would delete the
400+
// wrong object.
401+
QueryOptions qo = new QueryOptions(exp);
398402
qo.setRange(1, 1);
399403

400404
// Read the objects from the database driver

0 commit comments

Comments
 (0)