2. Data Model
Public Model
pg_liquid now exposes the Liquid blog data model directly:
- all persistent data is stored as graph edges
(subject, predicate, object) - schema is also graph data
- Datalog rules are query-local, not persisted
- compounds use relative identity with
Type@(cid=..., role=...)
The public SQL execution surface is:
liquid.query(program text)
liquid.query_as(principal text, program text)
liquid.read_as(principal text, program text)
program is a Liquid program containing zero or more assertions and rules,
followed by one terminal ? query.
liquid.query(...) is the base extension entrypoint.
liquid.query_as(...) and liquid.read_as(...) bind trusted principal context
for the duration of one call:
liquid.query_as(...)supports trusted write-capable flows that may use top-level assertions before queryingliquid.read_as(...)is the least-privilege read surface and rejects top-level assertions
Query Language
Supported surface syntax:
%line comments.-terminated assertions and rule definitions- one terminal
?query - bare variables such as
x _anonymous variables- double-quoted string literals
Edge(s, "predicate", o)Type@(cid=x, role="value", ...)
Legacy extension syntax is intentionally rejected:
?xvariablesquery_subgraph(...)- subgraph arguments
sys:*schema and security APIs
Bootstrap Schema
Schema is encoded using Liquid bootstrap predicates:
liquid/typeliquid/cardinalityliquid/subject_metaliquid/object_metaliquid/compound_predicateliquid/mutable
DefPred(...), DefCompound(...), and TypeAndCardinality(...) are query
predicates synthesized from that graph data so the Liquid blog examples can be
executed directly.
pg_liquid also ships a first-class policy vocabulary in graph data:
ReadPredicate@(principal=..., predicate=...)ReadCompound@(principal=..., compound_type=...)ReadTriple@(principal=..., subject=..., predicate=..., object=...)PredicateReadBySubject@(predicate=..., relation=...)PredicateReadByObject@(predicate=..., relation=...)CompoundReadByRole@(compound_type=..., role=...)Principal@(id=..., kind=...)Edge(child_principal, "liquid/acts_for", parent_principal)
Compounds
Compounds are stored as ordinary vertices plus role edges:
- the compound vertex literal is a canonical relative identity string such as
FilmPerf@(actor='Harrison Ford', film='Star Wars', role='Han Solo') - each named role becomes a graph edge from the compound vertex
cid=is optional in queries and assertions; when omitted, the identity is still computed and used internally
DefCompound("Type", "role", "cardinality", "type") declares compound roles
and also exposes the implicit Type@(...) query form from the Liquid blog.