Database & DATA Intents¶
DATA is a revision of an identity. FILE is bytes at a name.
The database-equivalent in D/BASIC is the DATA Intent family. An application asks for semantic database records, immutable views, exact revisions, and durable artifacts. The runner owns the actual store, sessions, authentication, snapshots, and recovery state. A BASIC program receives no host path, store handle, page ID, native pointer, or provider object.
Three similar names have three different jobs:
| Thing | Job |
|---|---|
DATA Intent |
database-style identities, revisions, snapshots, and artifacts |
FILE Intent |
named byte streams, directories, and manipulation; see Files & File Manipulation |
DATA / READ statement |
a small immutable table compiled into source; see Console I/O & Embedded DATA |
This distinction is a gift to future you. A document cannot accidentally become “whatever happens to be at this laptop path,” and a file copy does not pretend to have revision history it never received.
Ask for data, not the storage engine¶
When semantic data is essential, say so in the application contract. The runner can preflight that promise instead of presenting a window that can never do its job.
APP "IDEA CABINET"
LABEL "Idea Cabinet"
NEEDS DATA
END APP
IMPORT dworks.data BAKED
DIM Caps%(0 TO 27)
DworksDataQueryCaps Caps%()
PRINT "DATA PROVIDER ADMITTED"
END
dworks.data is a checked declaration layer. It does not link a database or
smuggle in a filesystem. BAKED keeps this sample self-contained; normal
imports also allow an exact shared D/Works library.
The runner admits and executes the underlying semantic operations through the
Intent and Service contract.
Identity, revision, snapshot¶
A team note is not identified by a filename. It has an opaque identity. A save says, “change this identity only if it is still at this revision.” A browse operation opens a stable view so a person's selected row does not quietly turn into another object after a concurrent edit.
The host owns live capability state. An adapter may represent it in source, but
its slot, generation, root receipt, provider handle, and native connection are
not values to place in a TYPE, CLASS, or DOBJ.
The friendly database projection¶
Most programs should feel like they are working with a small, careful database
library—not a packet builder. DataDatabase, DataView, and DataPage are
the object-oriented projection. They are bounded adapters over opaque
DATA records; they do not expose the host session's slot or generation.
IMPORT dworks.data BAKED
DIM Db AS DataDatabase
DIM View AS DataView
DIM Page AS DataPage
Db.OpenRead ProjectDatabaseId()
View.Open Db, BudgetDocumentsQuery()
DO
View.FetchPage Page
' Paint or inspect Page's stable object/class rows.
LOOP WHILE Page.HasMore
View.Accept SelectedObjects()
View.Close
Db.Close
END
The point of this shape is teaching as much as convenience: Db owns the
database session, View owns one immutable query binding, Page is only a
bounded observation, and Accept validates the exact selected identities.
Your own query/value helpers are application concepts; the host never has to
guess whether a string is a path, a SQL fragment, or a native handle.
Queries are semantic, not SQL strings¶
A snapshot query carries a nonzero query identity and scope, plus one bounded filter:
| Filter | Meaning |
|---|---|
ALL |
every visible object in the scope |
CLASS |
objects of one semantic class |
COLLECTION |
members of one collection |
REFERENCES |
objects related through one semantic reference |
PROPERTY_EQUALS |
objects whose named property equals one bounded predicate value |
An optional UTF-8 search term is bounded to 48 bytes; a property predicate is bounded to 96 bytes. The provider may use SQL, an object store, an index, or a tiny fixed database internally, but the query does not expose that implementation. The returned binding pins schema, content, and index revisions together with the snapshot identity.
Values keep their meaning¶
GET_VALUE can return unset, Boolean, signed 64-bit integer, decimal, money, percentage, text, bytes, date, time, date-time, duration, enum, quantity, resource, reference, Works link, or a bounded multiple value of up to eight elements. Each result carries the exact database revision that made it true. A typed D/Works adapter turns that semantic value into ordinary D/BASIC values and objects without exposing storage pages or native handles.
Beneath the objects: the typed carrier layer¶
Under the friendly objects, dworks.data provides a deliberately compact
carrier layer: checked encoders over exact rank-one INTEGER arrays. Each
element provides two little-endian bytes. Let the wrapper preserve wire sizes
and reserved fields; application code should not invent session records.
IMPORT dworks.data BAKED
DIM Session%(0 TO 7)
' Opens the host-selected semantic namespace. Its configured native directory,
' if it has one, remains host configuration rather than program data.
DworksDataOpenMounted Session%()
' ...perform typed DATA work with the owner-bound session...
DworksDataClose Session%()
END
The browser preview's admitted DATA mount
The playground currently admits one browser-local database identity: the
exact sixteen UTF-8 bytes D/BASIC-BROWSER1. Its DATA mutations and
artifact bodies are stored in the browser's durable local object store.
OPEN with any other identity refuses; a random nonzero identity is not an
implicit create-database operation. A packaged product supplies its own
admitted identity through the typed wrapper rather than copying this
developer-preview value.
| Wrapper | DATA row | Meaning |
|---|---|---|
DworksDataQueryCaps |
QUERY_CAPS |
supported values, record sizes, and session limits |
DworksDataOpen / DworksDataOpenMounted |
OPEN |
an owner-bound database session |
DworksDataGetValue |
GET_VALUE |
one typed value plus exact revision |
DworksDataOpenSnapshot |
OPEN_SNAPSHOT |
an immutable query binding |
DworksDataFetchPage |
FETCH_PAGE |
zero to sixteen stable rows |
DworksDataResolveRow / DworksDataRevalidateObject |
RESOLVE_ROW / REVALIDATE_OBJECT |
check a displayed object precisely |
DworksDataAcceptExact |
ACCEPT_EXACT |
validate one to sixteen selected IDs in caller order |
DworksDataCloseSnapshot / DworksDataClose |
CLOSE_SNAPSHOT / CLOSE |
release the view, then its parent session |
Close views before their parent database. Process exit is the final host-side revocation path, not a substitute for normal cleanup.
Browse without a race¶
A list is a promise to a person. Use this flow when the person will act on a selection:
- Open a database session.
- Open one immutable snapshot for the query.
- Fetch pages of at most sixteen stable rows.
- Retain stable object IDs, not just screen indices.
- Resolve or revalidate the chosen object before a consequential action.
- Use
ACCEPT_EXACTwhen the host must validate one to sixteen selected IDs. - Close snapshot, then session.
ACCEPT_EXACT is idempotent: repeating the same binding and object sequence
is still the same validation. It is not a database write transaction and not a
durable exactly-once ledger.
The carrier contract¶
Library authors may call generated Intent names directly. Their arrays must be rank-one, non-aliasing, and exactly sized. Output becomes visible only after a matching successful completion and reply decode—never partially on a pending, failed, stale, malformed, or aliased call.
DIM OpenRequest%(0 TO 9)
DIM Session%(0 TO 7)
' A library encoder fills this twenty-byte request. It is shown to expose the
' boundary; ordinary application code should call DworksDataOpen instead.
INTENT DATA.OPEN(OpenRequest%(), Session%())
END
| Row | Input carrier | Output carrier |
|---|---|---|
QUERY_CAPS |
— | 56 B / 28 INTEGERs |
OPEN |
20 B / 10 | 16 B / 8 |
GET_VALUE |
32 B / 16 | 864 B / 432 |
OPEN_SNAPSHOT |
192 B / 96 | 52 B / 26 |
FETCH_PAGE |
60 B / 30 | 296 B / 148 |
RESOLVE_ROW |
64 B / 32 | 16 B / 8 |
REVALIDATE_OBJECT |
60 B / 30 | 16 B / 8 |
ACCEPT_EXACT |
184 B / 92 | — |
CLOSE / CLOSE_SNAPSHOT |
16 B / 8 | — |
Every DATA request is tracked and asynchronous beneath the friendly projection. That lets the runner work or park without corrupting the last honest model.
Mutable records and streamed attachments¶
Snapshots make reading stable. The write-session family makes a database mutation equally explicit: it is a transaction against known base revisions, not an unguarded “update this row” side effect. It is especially useful when a record owns a large attachment such as an image, sound, or document body.
| DATA row | Job |
|---|---|
QUERY_WRITE_CAPS |
discover write sessions, transactions, attachment slots, max attachment size, and 256-byte chunk support |
OPEN_WRITE |
open an owner-bound write database session and receive its current revision binding |
BEGIN_WRITE |
begin one transaction with a nonzero transaction UUID and expected root/schema/content/index revisions |
BEGIN_ATTACHMENT |
name one object/property attachment, operation sequence, byte length, SHA-256, and media type |
WRITE_ATTACHMENT_CHUNK |
write one at-most-256-byte attachment segment at its explicit offset |
FINISH_ATTACHMENT |
prove the attachment's final length and SHA-256 |
COMMIT_WRITE |
request the transaction's terminal outcome |
WRITE_STATUS |
recover the outcome for a transaction UUID |
ABORT_WRITE |
deliberately abandon an in-progress transaction |
CLOSE_WRITE |
release the owner-bound write session |
The write sequence has two scopes. OPEN_WRITE creates a long-lived
owner-bound session. BEGIN_WRITE creates one transaction within it, bound to
all four expected revisions. A stale base is therefore a named state conflict,
not an opportunity to overwrite somebody else's newer document.
Attachments are staged and verified¶
BEGIN_ATTACHMENT names a nonzero object and property, a nonzero operation
sequence, exact byte length, full SHA-256, and a validated media type. It
returns an attachment binding tied to that transaction. Send ordered bounded
chunks through WRITE_ATTACHMENT_CHUNK; each reply carries the next expected
offset. Finish only with the same total length and digest promised at begin.
This gives the host a useful safety rule: attachment bytes are not a live resource merely because the first chunk arrived. A failed or abandoned stream does not turn into a half-image in a record. For a reusable packaged image or sound, see Resources, Images & Sound; DATA attachments belong to the database object's transaction and revision.
Commit, status, and recovery¶
COMMIT_WRITE and WRITE_STATUS return an 80-byte outcome. Its state is one
of PENDING, COMMITTED, ABORTED, or REOPEN_REQUIRED; it also carries the
transaction UUID and the root/schema/content/index revisions. A committed
outcome carries exactly one resulting resource ID. REOPEN_REQUIRED tells the
application to reopen and ask status, rather than guessing whether its mutation
made it through an interruption.
OPEN_WRITE and COMMIT_WRITE are deliberately not idempotent. Retain the
transaction UUID, ask WRITE_STATUS when completion is uncertain, then either
continue from the terminal fact or begin a new transaction. ABORT_WRITE and
CLOSE_WRITE are normal cleanup, not signs that the program did something
wrong.
For library authors, the exact carrier shapes are:
| Row | Request | Reply |
|---|---|---|
QUERY_WRITE_CAPS |
— | 96 B / 48 INTEGERs |
OPEN_WRITE |
20 B / 10 | 48 B / 24 |
BEGIN_WRITE |
64 B / 32 | 64 B / 32 |
BEGIN_ATTACHMENT |
176 B / 88 | 40 B / 20 |
WRITE_ATTACHMENT_CHUNK |
304 B / 152 | 48 B / 24 |
FINISH_ATTACHMENT |
80 B / 40 | — |
COMMIT_WRITE |
64 B / 32 | 80 B / 40 |
WRITE_STATUS |
32 B / 16 | 80 B / 40 |
ABORT_WRITE |
64 B / 32 | — |
CLOSE_WRITE |
16 B / 8 | — |
Like the read family, this is a DATA boundary: no attachment path, native
stream handle, or storage-provider pointer crosses into BASIC. A friendly
write-session adapter belongs above these records, just as DataDatabase and
DataView sit above their read records.
Artifacts: new, save, save as, publish¶
A D/Write document, D/Calc sheet, or future rich object is a semantic artifact: canonical bytes with an identity and revision. The verbs make their different promises explicit:
| Operation | Promise |
|---|---|
BEGIN_NEW |
create a new durable identity |
BEGIN_SAVE |
compare-and-save one identity against its expected base revision |
BEGIN_SAVE_AS |
create a new identity without mutating the source |
BEGIN_PUBLISH |
make an immutable publication while preserving source revision |
BEGIN_RETIRE |
withdraw an artifact through the same governed receipt flow |
The typed lifecycle is DworksDataQueryArtifactCaps, DworksDataBeginNew,
DworksDataBeginSave, DworksDataBeginSaveAs, DworksDataBeginPublish,
DworksDataBeginRetire,
DworksDataWriteArtifactChunk, DworksDataFinishArtifact,
DworksDataCommitArtifact, DworksDataArtifactStatus,
DworksDataAbortArtifact, DworksDataCloseArtifact, and
DworksDataAckArtifactReceipt.
The host issues the operation UUID through DworksDataAllocateArtifactOperation;
the application does not invent one. WRITE_ARTIFACT_CHUNK carries at most 256
bytes. FINISH_ARTIFACT proves the declared SHA-256 before commit. A replay of
one UUID with different parameters refuses. The resulting 192-byte receipt
records operation/kind/state, source/result identities, relevant revisions,
publication details, payload digest, and receipt identity/digest.
Keep that exact operation UUID and receipt until recovery is complete. An
interrupted operation may yield REOPEN_REQUIRED: call ARTIFACT_STATUS after
reopening and recover the byte-identical receipt rather than guessing whether a
save happened.
Library-author carrier shapes are exact here too:
| Artifact row | Request | Reply |
|---|---|---|
QUERY_ARTIFACT_CAPS |
— | 64 B / 32 INTEGERs |
each BEGIN_* |
96 B / 48 | 40 B / 20 |
WRITE_ARTIFACT_CHUNK |
280 B / 140 | 24 B / 12 |
FINISH_ARTIFACT |
56 B / 28 | — |
COMMIT_ARTIFACT / ARTIFACT_STATUS |
16 B / 8 | 192 B / 96 |
ABORT_ARTIFACT / CLOSE_ARTIFACT |
16 B / 8 | — |
ACK_ARTIFACT_RECEIPT |
64 B / 32 | — |
ALLOCATE_ARTIFACT_OPERATION |
— | 16 B / 8 |
LIST_ARTIFACTS / LIST_PUBLICATIONS |
16 B / 8 | 272 B / 136 |
OPEN_ARTIFACT_READ / OPEN_PUBLICATION_READ |
24 B / 12 | 80 B / 40 |
READ_ARTIFACT_CHUNK |
24 B / 12 | 280 B / 140 |
CLOSE_ARTIFACT_READ |
16 B / 8 | — |
For artifact readback, use DworksDataListArtifacts or
DworksDataListPublications (each page is at most eight rows), then open one
exact identity/revision through DworksDataOpenArtifactRead or
DworksDataOpenPublicationRead. DworksDataReadArtifactChunk returns at most
256 bytes, and DworksDataCloseArtifactRead revokes the owner-bound read
session. Host authentication filters lists and exact opens; no path or provider
iterator crosses the DATA boundary.
Refusals keep the database honest¶
Missing providers/rows, unsupported values, malformed shapes, stale bindings, capability mismatches, and capacity pressure are named refusals. An ordinary not-found observation may remain a normal status. Catch a refusal only when an alternative recovery path exists:
IMPORT dworks.data BAKED
DIM Session%(0 TO 7)
ON REFUSAL GOTO DataUnavailable
DworksDataOpenMounted Session%()
PRINT "DATA SESSION OPEN"
DworksDataClose Session%()
END
DataUnavailable:
PRINT "DATA OPERATION REFUSED. RULE "; ERR
END
Keep the last verified document visible until a terminal result says otherwise. Do not paint an artifact prefix, replace an old revision before a receipt, or equate a pressed Save button with durability.
One source, several honest hosts¶
| Host | What the runner may do |
|---|---|
| browser / WebAssembly | expose an admitted semantic provider without leaking browser storage internals or ambient files |
| Windows, Linux, macOS | use a durable host provider with atomicity and recovery checks |
| D/OS with DATA | retain sessions/artifacts behind the trusted runtime |
| no provider | refuse the DATA route by name; never offer a pretend empty database |
Richer hosts can improve capacity or durability. They cannot turn an identity into a path, publish partial output, or claim an unadmitted operation succeeded.
Import and export cross the boundary deliberately¶
Exporting a database artifact to a mount is two honest operations: open and read the exact DATA identity/revision, then create, write, and commit a new FILE. Importing is the reverse: read the named FILE, validate and canonicalize it privately, then create a new DATA artifact with BEGIN_NEW.
Both are copies. Export does not give the file a live database link, and import does not grant the application arbitrary filesystem authority. If either half fails, report which side succeeded and keep the previously verified object visible.
Data checklist¶
- Use DATA Intents for identities/revisions and FILE for named bytes.
- Keep embedded
DATAtables separate from both. - Prefer
dworks.dataover hand-packed carriers. - Close snapshots before sessions.
- Revalidate a selected stable ID before consequential work.
- Treat Save, Save As, and Publish as different identity operations.
- Retain the operation UUID and receipt through recovery.
- Make refusal, cancellation, and close paths first-class.
Next: Windows & Events →