# How Apache Ossie Supports Composite Primary Keys with Multiple Columns

> Apache Ossie supports composite primary keys using ordered arrays of column names. Learn how Ossie preserves order across relationships and conversions for multi-column keys.

- Repository: [The Apache Software Foundation/ossie](https://github.com/apache/ossie)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Apache Ossie treats primary keys as ordered arrays of column names, allowing datasets to define composite keys consisting of multiple columns while preserving order across relationships and conversions.**

Apache Ossie is an open-source semantic modeling framework that enables data teams to define portable dataset schemas. Unlike systems that restrict primary keys to single columns, Ossie natively supports **composite primary keys with multiple columns** by representing them as ordered arrays in the core specification, Python runtime models, and vendor-specific converters.

## Core Specification: Arrays Enable Composite Keys

In [`core-spec/spec.md`](https://github.com/apache/ossie/blob/main/core-spec/spec.md), the `primary_key` field is defined as an optional **array** rather than a scalar string (lines 28-34). This architectural decision explicitly allows datasets to declare keys spanning multiple columns. The specification demonstrates this flexibility with concrete examples showing both a simple single-column key (`primary_key: [customer_id]`) and a composite key spanning multiple columns (`primary_key: [order_id, line_number]`) (lines 35-43).

## Python Runtime Model

The Python implementation stores composite keys using the exact array structure defined in the specification. In [`python/src/ossie/models.py`](https://github.com/apache/ossie/blob/main/python/src/ossie/models.py), the Dataset class declares `primary_key` as `Optional[list[str]]` (lines 153-158). This type annotation ensures that the runtime preserves the exact sequence of column names, maintaining the integrity of composite keys throughout the model's lifecycle.

## Order Enforcement in Relationships

When datasets with composite keys participate in relationships, **column order becomes critical**. The Relationships definition in [`core-spec/spec.md`](https://github.com/apache/ossie/blob/main/core-spec/spec.md) mandates that the `from_columns` and `to_columns` arrays must follow matching order (lines 95-99). This constraint prevents ambiguity when joining tables on multiple columns, ensuring that the first column in the source composite key maps to the first column in the target composite key.

## Converter Architecture

Ossie's converter layer propagates composite key structures across vendor-specific formats without losing the multi-column definition.

### Omni Converter

The Omni converter explicitly preserves composite keys through dedicated metadata fields. In [`converters/omni/src/osi_omni/osi_to_omni.py`](https://github.com/apache/ossie/blob/main/converters/omni/src/osi_omni/osi_to_omni.py), the converter extracts the primary key array and records it as `custom_compound_primary_key_sql` (lines 300-307). The reverse converter in [`omni_to_osi.py`](https://github.com/apache/ossie/blob/main/omni_to_osi.py) restores the composite key from this metadata (lines 313-371), ensuring round-trip fidelity even when translating between Ossie and Omni view definitions.

### Orionbelt Converter

For legacy system migrations, [`converters/orionbelt/src/ossie_orionbelt/osi_to_obml.py`](https://github.com/apache/ossie/blob/main/converters/orionbelt/src/ossie_orionbelt/osi_to_obml.py) promotes primary key information from older OBML representations into the first-class `primary_key` array (lines 65-73). This promotion supports both simple and composite key definitions during format translation.

### Honeydew Converter

The Honeydew converter handles composite keys by emitting them as unique keys in the target format, ensuring that multi-column uniqueness constraints survive the conversion process in [`converters/honeydew/src/honeydew_osi/converter.py`](https://github.com/apache/ossie/blob/main/converters/honeydew/src/honeydew_osi/converter.py).

## Practical Implementation Examples

Define a dataset with a composite primary key in your semantic model YAML:

```yaml
datasets:
  - name: order_lines
    source: sales.public.order_lines
    primary_key: [order_id, line_number]   # ← composite key

    fields: []

```

Inspect the primary key structure in Python:

```python
from ossie.models import Dataset

# Assume `ds` is a Dataset loaded from a semantic model

print(ds.name)                # → "order_lines"

print(ds.primary_key)         # → ["order_id", "line_number"]

```

Create a relationship that correctly references the composite key:

```yaml
relationships:
  - name: order_lines_to_orders
    from: order_lines
    to: orders
    from_columns: [order_id, line_number]   # matches the composite PK order

    to_columns:   [order_id, line_number]   # target also has a composite PK

```

## Summary

- Ossie defines primary keys as **ordered arrays** in [`core-spec/spec.md`](https://github.com/apache/ossie/blob/main/core-spec/spec.md), enabling multi-column composite keys without artificial constraints.
- The Python model stores keys as `Optional[list[str]]` in [`python/src/ossie/models.py`](https://github.com/apache/ossie/blob/main/python/src/ossie/models.py) to preserve column sequences.
- Relationship definitions enforce **matching column order** between `from_columns` and `to_columns` arrays to prevent ambiguous joins.
- Omni and Orionbelt converters maintain composite key integrity during format translations using explicit metadata preservation and promotion logic.

## Frequently Asked Questions

### How many columns can an Ossie composite primary key contain?

There is **no artificial limit** imposed by the specification. The array-based design in [`core-spec/spec.md`](https://github.com/apache/ossie/blob/main/core-spec/spec.md) allows you to define primary keys with two, three, or more columns as required by your data model, provided each column name exists within the dataset's field definitions.

### Does the order of columns matter in composite primary keys?

Yes. Ossie treats the `primary_key` array as **ordered**. When referencing composite keys in relationships, the `from_columns` and `to_columns` arrays must list columns in the exact same sequence as defined in the respective primary keys, as mandated by the Relationships section of the core specification.

### How do converters handle composite keys when the target platform uses a different representation?

Converters like the Omni implementation explicitly preserve composite key metadata using vendor-specific extensions such as `custom_compound_primary_key_sql`. This ensures the composite structure survives round-trip conversions even when the target format uses different native representations for multi-column keys.

### What validation errors occur if column order is mismatched in a relationship?

The Ossie validator will reject the relationship definition because the specification requires that `from_columns` and `to_columns` arrays match in order and length. This prevents runtime join errors that would occur if the system attempted to join tables on mismatched composite key columns.