ZCatalog compatibility

PlonePGCatalogTool does not inherit from ZCatalog or CatalogTool. It implements the same public API so existing Plone code continues to work. This page documents the compatibility surface.

Supported methods

These methods behave identically to their ZCatalog counterparts:

Method

Permission

Description

searchResults(**kw)

Search ZCatalog

Query the catalog with security filters

__call__(**kw)

Search ZCatalog

Alias for searchResults()

unrestrictedSearchResults(**kw)

Private

Query without security filters

catalog_object(obj, uid, idxs)

Manage ZCatalog Entries

Index an object

uncatalog_object(uid)

Manage ZCatalog Entries

Remove an object from the catalog

refreshCatalog(clear)

Manage ZCatalog Entries

Re-catalog all objects

reindexIndex(name)

Manage ZCatalog Entries

Re-apply a single index

clearFindAndRebuild()

Manage ZCatalog Entries

Clear and rebuild from content

getpath(rid)

Search ZCatalog

Physical path for a record ID (ZOID)

getrid(path)

Search ZCatalog

Record ID (ZOID) for a path

getIndexDataForRID(rid)

Search ZCatalog

idx JSONB dict for a record

indexes()

Search ZCatalog

List of index names

schema()

Search ZCatalog

List of metadata column names

addIndex(name, type, extra)

Manage ZCatalogIndex Entries

Register a new index (see Architecture for runtime behavior)

delIndex(name)

Manage ZCatalogIndex Entries

Remove an index

addColumn(name)

Manage ZCatalogIndex Entries

Register a metadata column

delColumn(name)

Manage ZCatalogIndex Entries

Remove a metadata column

uniqueValuesFor(name)

Search ZCatalog

Unique values for an index

getIndexObjects()

Manage ZCatalogIndex Entries

List of index objects

Blocked methods

These ZCatalog methods are not supported. They raise NotImplementedError with a guidance message.

Method

Migration Path

getAllBrains()

Use searchResults() or direct PostgreSQL queries

searchAll()

Use searchResults() or direct PostgreSQL queries

getobject()

Use brain.getObject() instead

getMetadataForUID()

Metadata is in the idx JSONB column – use searchResults()

getMetadataForRID()

Metadata is in the idx JSONB column – use searchResults()

getIndexDataForUID()

Use getIndexDataForRID(zoid) instead

index_objects()

Use getIndexObjects() instead

All blocked methods are assigned the Search ZCatalog permission so callers receive NotImplementedError, not Unauthorized.

Deprecated methods

These methods work but emit DeprecationWarning:

Method

Replacement

search(*args, **kw)

searchResults(*args, **kw)

_CatalogCompat shim

PlonePGCatalogTool._catalog is a _CatalogCompat instance providing the minimal API that ZCatalog-aware code expects:

Attribute / Method

Type

Description

_catalog.indexes

PersistentMapping

Map of index name to index object

_catalog.schema

PersistentMapping

Map of metadata column names

_catalog.getIndex(name)

method

Return index object by name

For existing ZODB instances that were migrated from ZCatalog, the old Catalog object persists in ZODB and already has .indexes and .schema attributes. The code only reads these attributes, so it works without an additional migration step.

PGCatalogIndexes and PGIndex

catalog.Indexes returns a PGCatalogIndexes wrapper. Accessing an index by name returns a PGIndex proxy:

index = catalog.Indexes["portal_type"]
index.uniqueValues()           # SELECT DISTINCT from PostgreSQL
index._index.get("Document")   # PG query returning matching ZOIDs

PGIndex._index is a _PGIndexMapping that translates dict-style get(value) calls into PostgreSQL queries.

Brain attribute resolution

PGCatalogBrain attribute access follows these rules:

Attribute Type

Resolution Order

Known index or metadata (in IndexRegistry)

1. idx["@meta"] (codec-decoded, for non-JSON-native types like DateTime) → 2. top-level idx JSONB → 3. None if missing from both

Unknown attribute

Raises AttributeError

Non-JSON-native metadata values (Zope DateTime, datetime, date, etc.) are stored under idx["@meta"] at write time via the Rust codec (pickle_to_dict). On first access, the @meta dict is decoded via dict_to_pickle + pickle.loads and cached per brain for the lifetime of the result set. This ensures brain.effective returns a DateTime object, not an ISO string.

The AttributeError for unknown attributes is intentional: CatalogContentListingObject.__getattr__() catches it and falls back to getObject(), loading the real content object. Returning None instead would cause plone.restapi and listing views to display None values.