Patches
A mutation selects the entities that a patch changes. A direct patch supplies entity ids without a selection query. It changes many entities in one transaction. The native database merge patch call commits every change together or commits nothing.
The document follows JSON Merge Patch semantics in the selected document format. It does not use JSON Patch operations. Patches explains why Stardust records intended state in this form.
Start with an empty database. Submit this merge patch. The temporary IDs
#_ada, #_bob and #_cy request new entities. Bob's mentor links to Ada
within the same patch.
#_ada {name Ada
role engineer
age 36
active true
retired false}
#_bob {name Bob
role engineer
age 41
mentor {#link #_ada}
active false}
#_cy {name Cy
role designer
age 29}
#_tx {author tutorial
reason create-people}
The commit result includes the transaction ID and an ids mapping from each
temporary ID to its allocated entity ID. In this fresh database, these fields
are:
{transaction 4
ids {#_ada 1
#_bob 2
#_cy 3}}Keep the IDs from your actual result. An existing database can allocate
different numbers. The examples below use the returned IDs 1 for Ada,
2 for Bob and 3 for Cy. The special temporary ID #_tx attaches its
author and reason metadata to transaction 4.
Merge patch keyed by id
A patch is a document whose keys are entity ids. Each key is the id of a data entity. Its value contains the fields to change.
1 {active false
retired null
role engineer}
2 {active true
note reviewed}
This patch gives:
{1 {name Ada
role engineer
age 36
active false}
2 {name Bob
role engineer
age 41
mentor {#link 1}
active true
note reviewed}}The merge patch rules produce that result:
- An omitted member stays as it is.
- The patch removes a member set to
null. - Each other value replaces the current value.
Stardust applies those rules to each entity that the patch names. The members
of an entity object are its fields. That is why bob keeps role engineer,
ada loses retired, and each other supplied field gets its new value. A transaction document uses the same decimal ID keys.
Creating with temporary names
A key that starts with #_ is a temporary name for an entity the patch
creates. Stardust allocates an id for the entity when the patch commits.
{#link #_name} refers to that id anywhere in the same patch, including in a
new or existing entity. The temporary name applies only within the patch. After the commit, use the
entity ID to address the entity. The engine rejects a repeated name, an undeclared temporary link target,
and null on a temporary name.
#_carol {name Carol
mentor {#link 1}}
#_dave {name Dave
buddy {#link #_carol}}
1 {protege {#link #_carol}}
This commits two new entities and one change to Ada, all in one transaction. After the preceding examples, the commit returns these fields:
{transaction 8
ids {#_carol 6
#_dave 7}}Use the returned IDs to refer to Carol and Dave in later calls.
#_tx is a special temporary ID for the transaction that commits the patch.
Its object supplies metadata, such as author and reason, on that transaction.
It does not create an ordinary data entity. {#link #_tx} links to the same
transaction from elsewhere in the patch. This metadata accompanies data
changes. Stardust rejects a patch that contains only #_tx.
One value at a time
A list or a map stored in a field is one Stardust value. The patch gives the complete intended value for that field. It does not give editing operations inside the value. An object inside an entity is a map in that field, never a second entity: a data entity has no children.
Stardust compares each field with the current facts before it writes. Stardust skips a field
that already matches. It also skips null for a field that is absent. A patch with no effect commits no transaction.
Deleting
An entity id set to null deletes that entity.
2 null
After this patch, bob has no facts:
{2 null}Entities elsewhere that link to a deleted entity survive, and their links keep the deleted target's stable numeric id.
Invalid patch forms
The keys of a patch are ids, so a field at the root is an error.
missing true
Error
Rejected
An invalid id is an error, and the patch changes nothing:
ffffffffffff {role visitor}
Error
Rejected
A #_name key creates a data entity. References to that temporary name resolve
within the patch. The native commit result gives the resolved ids.
Stardust also rejects text that is not a document. No rejected patch changes a stored fact.
A schema-checked patch
The core patch operation can validate each staged entity against a schema before it commits. A deleted entity has no document to validate. The current public merge-patch call does not expose that schema scope. Schemas explains this validation boundary.
Reading the committed transaction
A commit result identifies its transaction. Reading that transaction document
gives the patch for the commit, keyed by entity id. Each value holds asserted
fields and null for retractions. Unchanged fields are absent.
The transaction entity appears under its own ID with stardust/transaction and
stardust/committedAt. There are no entities or transaction wrappers.
Definition and object changes include their structural facts and numeric
references. The recorded patch stays the same after a later rename or deletion.
Native documents and DUST contain the same changes.