Explanation: Inline inputs
Start
OverviewConceptsGuides
Run and configureREST API walkthroughCommand lineQuery groupsNotebooksRules and SRLPrefixesTestingMCP clientsPublish as toolsQuery bench in chatStatic exportETLDeployingReference
ConfigurationFeature flagsEntity modelSRL languageScriptsExplanation
ArchitectureVersioningEnvironmentsStorage and cachingSecurity modelRDF PatchInline inputsExamples
Sudoku solverInline inputs and the rail
Where a saved input lives, and why each kind lives where it does.
Inline is a door, not a storage class
A graph pasted into a call and a graph stored in the library are the same bytes, in the same serialisation, under the same size ceiling, consumed by the same loader. The only thing that used to differ was which screen they were typed on.
So a graph has one storage class: a DataGraphVersion. An
argument set holds no graphs at all. A rule set or a query group names
its graphs beside its arguments. Pasted RDF that is worth keeping
becomes a data graph: on the Graphs screen, or with Save to
Data on the rule set screen.
One counter-rule keeps this honest, and it is the whole boundary:
Running is not saving. Inline content in an execute request mints nothing.
/executeand/sparqlkeep taking inline graphs, tables and numbers as transport, and an ad-hoc run leaves no trace in any rail.
One storage class per input kind
| Kind | Where the content lives when saved | Rail entry | Why |
|---|---|---|---|
| Graph | DataGraphVersion, named beside the argument set by the
run or the test case |
Graphs | RDF content is what a DataGraph is. An
argument set holding RDF duplicated an entity that already exists, and
gave a group two ways to receive the same graph. |
| Table | ArgumentTupleBinding.contentString (SRJ) on the
argument set version |
Argument sets | The argument set is already the entity, already in the rail, already versioned and pinnable. There is no second home to need. |
| Number | ArgumentScalarBinding on the argument set version |
Argument sets | Trivially the same. |
Read the middle column as the answer to "if I save this, where does it end up?" and the design is one sentence: every saved input is stored exactly once, in the entity whose job it is to hold that kind of content, and that entity is in a rail.
The test is not "was this typed inline?" but:
Is there already an entity whose job is to hold this content? For RDF, yes, and it is not the argument set — so the graph is named beside it. For rows supplied to a
VALUESclause, yes, and it is the argument set — so they stay put.
Minting a tuple set from a saved VALUES table would not
remove a second-class copy. It would create a second entity, in
a section governed by a different matching discipline, holding the same
rows for no reuse that a person asked for.
Deleting a graph
Deleting a DataGraph is refused while a saved test
version pins one of its versions, as for any pinned entity
(lib/versionPins.ts). Argument sets no longer pin graphs,
because they hold none. A browser default that names the graph or one of
its versions is cleared, because a default is a starting selection, not
a pin: losing one costs a pick and breaks no run.
Conversions between the two table shapes
Both shapes are SPARQL Results JSON, so each direction is a
projection plus one question. Both are explicit, user-invoked, and
record copiedFrom where a new entity is created, so "used
by" can be answered loosely without pins.
Tuple set → argument table. The dialog asks for the
variable name each column fills, pre-filled from the tuple set's labels
and marked as unverified — they are labels, so a pre-fill is a guess,
and the person confirms it. The existing
fits / partial / mismatch verdict judges the result.
Argument table → tuple set. The names are kept — as labels.
Neither direction is a link. A conversion is a copy, taken once, and the two entities go their own ways afterwards — which is the whole reason this is safe where a save-time side effect was not.
What the rail shows: origin, not tags
What was missing was the ability to tell at a glance where something came from. The section sidebar's grouping control offers a third mode, Origin:
- Composed here — made with
+ Newon the rail. - From queries / From groups — an argument set born
on a callable's screen, read off its
targetEntity.
A graph is always Composed here: no callable mints one.
Bucket by kind of origin, not one cluster per callable, or a real library shatters into dozens of single-row clusters. The callable stays in the subtitle.
Not tags. Tags are user-authored and library-wide. Auto-tagging by provenance makes a tag mean both I decided this and the system asserted this, which destroys the one job tags do well. Origin is how you find things; tags are how you mean things.
And origin is deliberately a weak organiser: a set made on one query is legitimately what another wants. Scope is provenance, not a fence — which is why the argument set switcher computes a fits/partial/mismatch verdict at all.
One browser-local draft store, keyed by section
Unsaved argument sets used to live in a store of their own, kept separate so that argument sets would stay out of the nav rail. That reason was retired the day an argument set became a rail entity, and the split outlived it: the query screen wrote to one key and the rail read another, so a set made on a query never reached the rail in that session, appeared after a reload — which made a missing write read as a caching glitch — and could lose its edits to the next one.
There is one browser-local draft store, keyed by section
(useCallableDrafts), and useArgumentSetDrafts
is a view over its argumentSet section rather than a second
store.
Still open
- Ad-hoc runs and the size ceiling. Running is not saving, so a big pasted graph can be executed repeatedly without ever becoming an entity. That is correct, and it means the "this call carries 40 MB of RDF, save it as a graph" nudge belongs on the run path, not only on save.
immutableoutlived the freeze vocabulary. The flag carries no information now that versions are created frozen.