liveBook · Manning

Primary key

As explained in Functional Design and Architecture: Examples in Haskell

A primary key is a field or combination of fields that uniquely identifies a record in a database.

A primary key identifies a stored entity and gives persistence code a stable handle for loading it. In a type-safe model, the key should belong to the entity it identifies, so a meteor key cannot be used where a comet key is required. section 11.2.3 section 11.2.2

A tempting relational design uses existing domain fields as a composite natural key. For meteors, azimuth, altitude, and timestamp were marked as a key, but floating-point values are poor keys and natural keys should be exceptional. Keeping database and domain models separate limits the effect of later domain changes. section 12.1.1 section 12.1.1

A typed meteor identifier

The relational meteor table adds an integer _id column. Its Beam Table instance wraps that column in DBMeteorId, and primaryKey extracts it from a row. The table therefore accepts its own associated key type rather than an untyped value. section 12.2.2 section 12.2.2

instance Table DBMeteorT where
 
 data PrimaryKey DBMeteorT f = DBMeteorId (Columnar f Int)
   deriving (Generic, Beamable)
 
 primaryKey k = DBMeteorId (_id k)

This instance makes the table-specific primary-key representation explicit: DBMeteorId contains the table’s columnar integer identifier, and primaryKey selects _id. section 12.2.2

The same principle applies to a key–value database: KeyEntity MeteorEntity and KeyEntity CometEntity are distinct ADTs, even though generic loading can abstract over the entity. This removes a class of accidental cross-entity key use without requiring per-entity loading wrappers. section 11.2.3 section 11.2.2

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Contrasts composite natural keys with identifiers, then implements entity- and table-specific key ADTs through Haskell type-level machinery.
Examples
Uses meteor and comet records, a composite coordinate-and-time key, and Beam’s DBMeteorId associated ADT.
What it assumes
Assumes familiarity with Haskell ADTs and introduces the relevant type-level key design incrementally.
What you can do after
Build it from scratch by declaring entity-specific key types and extracting a table’s associated primary key.
How it connects
Connects primary keys to natural keys, composite keys, ADTs, type classes, relational schemas, and key–value databases.

Also explained in

Compare how 21 books explain primary key →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.