Appearance
Relationship inheritance & OWNED editing
When you build a view that pulls in fields from a related entity (e.g. a Customer view showing the customer's Address.street), SchemaStack treats those fields intelligently:
- The widget type, label, and validation rules are inherited from the entity's canonical view — set them once on Address and every view that pulls in Address fields renders them the same way.
- You can opt to edit related rows inline ("OWNED" mode) — change the address from inside the customer view, without leaving the table. SchemaStack enforces who's allowed to do that and blocks it when sharing the related row with other parents would cause silent side effects.
This page explains how it works and how to configure it.
Canonical view per entity
Every entity in SchemaStack has exactly one canonical view — the source of truth for that entity's display configuration (widget types, labels, widget options, inline-edit fields).
When a table is imported via schema sync, SchemaStack creates a default view for it and marks that view canonical. If you create additional views for the same entity, they inherit display configuration from the canonical view by default — so a "DATE" widget you set on CourseYear.year_value in the canonical view shows up as a DATE widget in every other view that pulls in year_value, including views displaying it through a relationship.
Overriding inheritance per view
Each inheritable property can be overridden per view. In the column properties panel, fields with an inheritance source show a small badge:
Inherited from
CourseYear.year_value· Override
Click Override to set a custom value just for this view. The badge switches to:
Overridden · Reset to inherited
Click Reset to inherited to drop the override and resume following the canonical view.
The properties that participate in inheritance:
| Property | Inherited from | Override scope |
|---|---|---|
| Widget type | Canonical view's column | Per ViewColumn |
| Display name | Canonical view's column | Per ViewColumn |
| Widget options | Canonical view's column | Per ViewColumn |
| Inline-edit fields | Canonical view's column | Per ViewColumn |
| Constraints / rules | Entity-level (locked, always apply) | Add view-level rules on top |
Constraints defined at the entity level are always enforced — you cannot disable them per view. You can only add view-level rules that layer on top.
Relationship types
When you create a relationship column from an entity, you pick the shape of the relationship:
| Shape | Meaning |
|---|---|
| Many-to-one | This row references one related row; many rows can reference the same target. |
| One-to-one | Each row links to at most one related row; each related row is referenced from at most one row here. |
| Many-to-many | Either side can link to multiple rows on the other side via a join table. |
| One-to-many | Inverse of many-to-one — read-only display of rows that reference this one. |
One-to-one is implemented as a many-to-one with a UNIQUE constraint on the FK column at the database level — but SchemaStack tracks the intent so the UI treats it as 1:1.
Ownership
Each relationship has an isOwned flag:
- Owned — the related row exclusively belongs to the parent. Editing the related row from the parent view is safe, because no other parent references it. (Typical: Customer→Address, User→Profile, Order→Shipment.)
- Shared — the related row is referenced by multiple parents. Editing it from one parent would silently affect the others. (Typical: Order→Country, Product→Category.)
Defaults:
- 1:1 → owned (you usually want this)
- M:1 → shared (you almost always want this)
- M:M, 1:M → never owned (semantically meaningless to "own" a many-side)
You can flip the default in the picker when creating a relationship column.
Edit modes for relationship columns
A relationship column can be edited in one of three modes (set in the column properties panel under Edit Mode):
Reference (the default for shared relationships)
Picking a value changes which row is referenced (the FK). The related row itself is not modified.
"Switch this customer's country from France to Germany."
Owned (the default for 1:1 owned relationships)
Editing changes the field on the related row directly. The FK is unchanged.
"Change the street on this customer's address."
The OWNED option is only enabled when every hop in the relationship path is owned. For multi-hop columns (e.g. Customer → Address → Geolocation), all hops must be marked owned. If any hop is shared, OWNED is disabled with a message naming the offending hop:
OWNED edit blocked — relationship
countryis shared. Editing through it would affect other rows that reference the same target.
Association (M:M)
Add or remove links in the join table without modifying either endpoint row.
Permissions
OWNED edits write to a row in a different table than the one the source view exposes. SchemaStack checks permissions against the terminal entity, not the source view — so reading the customer view does not imply permission to edit the address. The user needs EDIT_ROW on the entity whose row is actually being modified.
What happens on save
When you save an OWNED edit, SchemaStack:
- Walks the relationship path to find the actual row to update (one query per hop, following FK values through real data).
- Verifies every hop in the path is owned.
- Checks you have permission on the target entity.
- Validates the new value against the target column's constraints.
- Updates the related row.
- Refetches the source row so the table reflects the joined update immediately.
- Broadcasts a
terminal.row.editedevent so other open views joining the target entity refresh.
If the relationship path passes through a row that hasn't been created yet (e.g. the customer has no Address row), SchemaStack returns a clear error naming the missing intermediate — you can create that row first and try again.
See also
- Schema migrations — how SchemaStack manages underlying database changes.
- Key concepts — entities, views, columns explained.