Skip to content

Database layout

Compound values occupy columns in the host field's current and revision tables, such as node__field_speakers and node_revision__field_speakers. Each row identifies a host entity, language and outer delta; revision rows also identify the historical revision.

Item identity

Every row also carries a cfi_uuid column: the UUID of that row's logical compound item, distinct from the host's own UUID and from every other item's. Nested items and capped slots each have their own cfi_uuid column, following the same naming rules as any other flattened column (see below).

A compound item's revision identity is <host revision ID>:<item UUID>, split at the final colon (a nested item's outer UUID is itself part of the host revision address it is materialised from). CompoundFieldItem::getRevisionId() and ::getLoadedRevisionId() both answer this composite so that \Drupal::entityTypeManager()->getStorage('cfi_<id>')->loadRevision(...) resolves the same historical item a host revision load already reached — not the item's current, possibly different, default-revision row.

Outer delta Name Topic slot 0 Topic slot 1 Topic slot 2
0 Ada Lovelace Computing history Analytical engines NULL
1 Grace Hopper Compilers NULL NULL

Direct string sub-fields produce schema keys such as name__value, topic__value, topic__value_1 and topic__value_2. Drupal's table mapping adds the host field prefix. References use properties such as target_id.

Unlimited outer cardinality adds rows. Raising a sub-field cap adds nullable column sets; slot zero has no suffix. Saving compacts values into dense slots. Nested compounds multiply these columns. The budget guard refuses schemas beyond InnoDB's column and row-size limits.

Long nested names use derived identifiers. Resolve physical columns through the schema and Drupal's table mapping instead of constructing names yourself. Use nested sub-field paths in the Field API and wire format.

Follow the deployment guide for schema changes.