You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -233,6 +234,36 @@ The active backend is a module-level singleton. `config.py` calls `detect_and_se
233
234
234
235
`_pending_brains_for_path()` scans the pending store, matches paths, and returns `_PendingBrain` instances with just enough interface (`getPath()`, `_unrestrictedGetObject()`) for `reindexObjectSecurity` to work.
235
236
237
+
## ZCatalog Internal API Compatibility
238
+
239
+
Plone code accesses ZCatalog internal data structures directly. Since PlonePGCatalogTool never populates ZCatalog's BTrees, these are replaced with PG-backed implementations.
240
+
241
+
### PGIndex Wrappers (`pgindex.py`)
242
+
243
+
`PGCatalogIndexes` (class attribute `Indexes` on `PlonePGCatalogTool`) overrides `ZCatalogIndexes._getOb()` to wrap each returned index with `PGIndex`. Special indexes with `idx_key=None` are returned unwrapped.
244
+
245
+
`PGIndex` proxies a real ZCatalog index object, delegating all standard methods via `__getattr__`. It overrides:
246
+
247
+
-**`_index`** (property): Returns a `_PGIndexMapping` that translates `_index.get(value)` into a PG query on `idx` JSONB, returning ZOID as the record ID. Used by `plone.app.uuid.uuidToPhysicalPath()`.
248
+
-**`uniqueValues()`**: PG `SELECT DISTINCT` / `GROUP BY` on idx JSONB. Used by `plone.app.dexterity` and `plone.restapi`.
249
+
250
+
### getpath / getrid (`catalog.py`)
251
+
252
+
-**`getpath(rid)`**: `SELECT path FROM object_state WHERE zoid = %(rid)s`. Raises `KeyError` if not found (matching ZCatalog). Used by `plone.app.uuid`.
253
+
-**`getrid(path)`**: `SELECT zoid FROM object_state WHERE path = %(path)s`. Returns `default` if not found. Used by `plone.app.vocabularies`.
254
+
255
+
ZOID serves as the record ID (RID), matching the integer PK in PostgreSQL.
256
+
257
+
### Brain Attribute Resolution (`brain.py`)
258
+
259
+
`PGCatalogBrain.__getattr__` uses `_resolve_from_idx()` to distinguish known catalog fields from unknown attributes:
260
+
261
+
-**In idx**: Return the value
262
+
-**Known field** (in `IndexRegistry` indexes or metadata) but absent from idx: Return `None` (Missing Value behavior, matching ZCatalog)
263
+
-**Unknown field**: Raise `AttributeError`
264
+
265
+
This enables `CatalogContentListingObject.__getattr__` to fall back to `getObject()` for non-catalog attributes (e.g. `content_type`), matching the behavior of ZCatalog's `AbstractCatalogBrain` (which inherits from `Record` and only knows schema-defined attributes).
266
+
236
267
## Query Translation
237
268
238
269
`query.py` translates ZCatalog query dicts into parameterized SQL.
0 commit comments