Documentation
¶
Overview ¶
Package core is the thin OpenVaultDB layer between the HTTP API and DALgo drivers. Storage access goes through dal.DB natively — inGitDB via dalgo2ingitdb, SQLite via dalgo2sqlite — so ovdb's job is schema-mode enforcement, collection provisioning (via ddl.SchemaModifier), inferred schema observation, and (future) authentication. Reads, writes, updates and queries pass through to the driver.
Index ¶
- Constants
- Variables
- func AggregateFunctions() []string
- func DeserializeDTQL(doc []byte) (dal.StructuredQuery, error)
- func EngineCanQuery(engine string) bool
- func IsAggregateFunction(name string) bool
- func ParseDTQL(doc []byte) (dal.StructuredQuery, string, error)
- func ParseKey(segments ...string) (*record.Key, error)
- func ParseKeyPath(raw string) (*record.Key, error)
- func QueryCollections(query dal.StructuredQuery) ([]string, error)
- func RootCollection(key *record.Key) string
- func SQLiteLogicalName(name string) (string, bool)
- func ValidateCollectionName(name string) error
- func ValidateFieldName(name string) error
- func ValidateFieldNames(names []string) error
- func ValidateSegment(s string) error
- type Database
- func (d *Database) Apply(ctx context.Context, ops []Op, message string) (int, error)
- func (d *Database) CanCollectionQuery() bool
- func (d *Database) CanQuery() bool
- func (d *Database) CanonicalCollection(name string) (string, bool)
- func (d *Database) CheckRead(query dal.Query) error
- func (d *Database) Close() error
- func (d *Database) CollectionForeignKeys(ctx context.Context, collection string) ([]dbschema.ForeignKeyDef, error)
- func (d *Database) CollectionSpellings(name string) []string
- func (d *Database) Collections(ctx context.Context) ([]string, error)
- func (d *Database) Coordinator() *access.EnforcementCoordinator
- func (d *Database) DB() dal.DB
- func (d *Database) Engine() string
- func (d *Database) Execute(ctx context.Context, q Query) ([]Record, error)
- func (d *Database) ExecuteDTQL(ctx context.Context, doc []byte) ([]Record, error)
- func (d *Database) ExecuteDTQLQuery(ctx context.Context, query dal.StructuredQuery) ([]Record, error)
- func (d *Database) Executor() dal.QueryExecutor
- func (d *Database) Exists(ctx context.Context, key *record.Key) (bool, error)
- func (d *Database) Get(ctx context.Context, key *record.Key) (map[string]any, error)
- func (d *Database) GuardCanonicalCollection(name string) error
- func (d *Database) GuardCollection(name string) error
- func (d *Database) GuardKey(key *record.Key) error
- func (d *Database) HTTPProfile() string
- func (d *Database) HasAccessPolicies() bool
- func (d *Database) HasImmutableSQLiteKeys() bool
- func (d *Database) HasLicenseDeclarations() bool
- func (d *Database) ID() string
- func (d *Database) InferredSnapshot() *inferred.Snapshot
- func (d *Database) NativePostgresReadOnly() bool
- func (d *Database) NativePostgresSource(id string) (schema.NativeCollectionSource, bool)
- func (d *Database) NoRetention() bool
- func (d *Database) OnClose(fn func() error)
- func (d *Database) PolicyLayers(ctx context.Context) []PolicyLayer
- func (d *Database) PublishPolicies(ctx context.Context, expected string, documents []access.DTQLDocument) (policystore.Snapshot, error)
- func (d *Database) ReadOnly() bool
- func (d *Database) ReadOnlyHTTP() bool
- func (d *Database) ReadTx(ctx context.Context, fn func(dal.QueryExecutor) error) error
- func (d *Database) ReloadPolicies(ctx context.Context) (policystore.Snapshot, error)
- func (d *Database) ResolveNativePostgresCollection(schemaName, relationName string) (string, bool)
- func (d *Database) Retention() string
- func (d *Database) SelectAccessSample(ctx context.Context, query dal.StructuredQuery, n int, ...) ([]Record, []dal.OrderExpression, error)
- func (d *Database) ServingKey(collection string) (string, bool)
- func (d *Database) SetAfterWrite(fn func(ctx context.Context) error)
- func (d *Database) SourceRight(serverID string, server *license.Declaration, collection string) (*license.SourceRight, error)
- func (d *Database) StreamDTQLSnapshot(ctx context.Context, query dal.StructuredQuery, emit func(Record) error) error
- func (d *Database) ValidateDataKeys(data map[string]any) error
- func (d *Database) ValidateFieldPath(path []string) error
- func (d *Database) ValidateRetentionCache() error
- func (d *Database) ValidateUpdatePath(path []string) error
- type Filter
- type ModeCompatibilityError
- type Op
- type OrderBy
- type PolicyLayer
- type Profile
- type ProfileBounds
- type ProfileKind
- type ProfileSource
- type Query
- type QueryUnsupportedError
- type Record
- type UnreachableError
- type UpdateOp
Constants ¶
const EngineInGitDBGitHub = "ingitdb-github"
EngineInGitDBGitHub is the Engine of an inGitDB mount whose backend is a GitHub repository. Its reads go over the network, so a caller routing by engine can tell it from the local "ingitdb" engine, which shares the manifest engine name.
const PreviewPostgresQueriesEnv = "OVDB_PREVIEW_POSTGRES_QUERIES"
PreviewPostgresQueriesEnv names the environment variable of the preview of structured queries on PostgreSQL mounts. The preview is on only when the variable holds exactly "1". It is read once, when a mount opens (see open), so a mount answers by what it read and a change of the environment later changes nothing for it.
The switch is temporary. Removing it takes this file, the previewPostgres field of Database and its two lines in open, and the one test file of the switch; the server's engineCleared, which asks CanQuery of the mounted databases only to learn that the preview is on; and Server.nativeEngines (in pkg/server/dtql_relational.go), which names PostgreSQL among the engines that run a whole relational document in the database only while the preview is on, and which then names it always, or goes with the default of pkg/joinexec being changed to include it. PostgreSQL then joins queryEngines, after the security review of the whole path.
const ResultBufferBytes = 8 << 20
ResultBufferBytes is the most bytes of JSON (of the rows and of their keys) that the server buffers for the result of one structured read of one collection. It is the same number as joinexec.MaxResultBytes, the bound of a relational answer; a test of the server holds the two together.
Variables ¶
var ErrAlreadyExists = errors.New("record already exists")
ErrAlreadyExists is the insert-conflict sentinel (mapped to HTTP 409).
var ErrCollectionNamesConflict = errors.New("conflicting collection names")
ErrCollectionNamesConflict identifies a manifest whose collection names cannot each designate one table: a name that is a spelling of one declared collection and the canonical name of another, or two keys that are one table and declare different fields. Opening a database refuses such a manifest.
var ErrDatabaseUnreachable = errors.New("the database of the mount cannot be reached")
ErrDatabaseUnreachable identifies a failure to reach the database server of a mount: the adapter reported a connection that cannot be made or that failed while a call was running (a refused or reset connection, a timeout, a failed TLS handshake, a server that rejects the connection). The HTTP server answers it `503 database_unavailable` on every route that reads or writes the mount, with one fixed message, and logs it with the ID of the mount. It is not a mistake of the caller and not a fault in the server's own code, and it is always a *UnreachableError.
var ErrEmptyWrite = errors.New("empty write")
ErrEmptyWrite identifies a write that names nothing to change, on an engine whose adapter builds SQL and cannot carry it out: an update with no operation, and a set that names no field but the record's id for a record that exists (mapped to HTTP 400 bad_request). A set of no field for a record that does not exist inserts a record that holds only its id, and is not refused.
var ErrFieldNamesConflict = errors.New("conflicting field names")
ErrFieldNamesConflict identifies a manifest that declares, on an engine whose adapter builds SQL, a field that is the record's key column in a case other than "id": it would be the key column and not a field. Opening a database refuses such a manifest.
var ErrHTTPOperationUnsupported = fmt.Errorf("%w: HTTP source operation unsupported", dal.ErrNotSupported)
ErrHTTPOperationUnsupported identifies a safe, pre-read refusal of a live resource capability. Adapter details and source values are never reflected.
var ErrInvalidDTQL = errors.New("invalid or unsupported DTQL query")
ErrInvalidDTQL identifies invalid or unsupported DTQL query shapes.
var ErrInvalidFieldName = errors.New("invalid field name")
ErrInvalidFieldName identifies a write that carries a field name that is not a plain name (mapped to HTTP 400 bad_request). See ValidateFieldName.
var ErrInvalidKey = errors.New("invalid key")
ErrInvalidKey identifies a malformed or unsafe key, collection name or parent path (mapped to HTTP 400 invalid_key).
var ErrInvalidQuery = errors.New("invalid query")
ErrInvalidQuery identifies a structurally invalid wire query (mapped to HTTP 400).
var ErrKeyColumnCase = fmt.Errorf("%w: a field cannot be the record's key column in another case", ErrInvalidFieldName)
ErrKeyColumnCase identifies a write whose data names the record's key column in a case other than "id", on an engine whose adapter builds SQL: every spelling is the one column, and the adapter skips only "id" when it lists the columns to write (mapped to HTTP 400 bad_request, as ErrInvalidFieldName is). See Database.ValidateDataKeys.
var ErrKeyUpdate = fmt.Errorf("%w: an update cannot name the record's key column", ErrInvalidFieldName)
ErrKeyUpdate identifies an update that names the record's key column, on an engine whose adapter builds SQL: the key of a record is not a field an update changes (mapped to HTTP 400 bad_request, as ErrInvalidFieldName is). See Database.ValidateUpdatePath.
var ErrNativePostgresCollectionQueryUnsupported = errors.New("native PostgreSQL mounts support DTQL reads; the collection-key /query contract is unavailable")
ErrNativePostgresCollectionQueryUnsupported identifies the legacy /query contract, which requires OVDB record keys and declared collection names that a native PostgreSQL catalog mount does not provide.
var ErrNativePostgresOperationUnsupported = fmt.Errorf("%w: native PostgreSQL mount supports structured reads only", dal.ErrNotSupported)
ErrNativePostgresOperationUnsupported identifies a keyed or mutating operation that the native PostgreSQL catalog mount does not expose.
var ErrNotFound = errors.New("record not found")
ErrNotFound is the server-side not-found sentinel (mapped to HTTP 404).
var ErrProtectedReadTx = errors.New("a policy-protected database is read through Executor, not a read transaction")
ErrProtectedReadTx is returned by ReadTx for a database that has access policies: such a database is read through Executor, one single-source query at a time, never inside a joined read transaction.
var ErrProtectedSingleSource = errors.New("a policy-protected database is read one source at a time: no join, derived source or subquery")
ErrProtectedSingleSource is returned, on a database that has access policies, for a structured query that is not a plain read of one collection (see singleSourceRead): one with a join, a derived source, a subquery anywhere, a scan bound, or a source that is not a plain collection. DALgo's access layer authorises the base and first-level join sources of a query and not what is nested deeper, so such a database is read one collection at a time instead of partly authorising a query. The decision depends on the shape of the query alone, before any collection name is looked at, so the error is the same whichever collections the query names and says nothing of which exist. The executor of Executor and the entry points that take one query (ExecuteDTQLQuery, StreamDTQLSnapshot, SelectAccessSample) return it; ReadTx refuses such a database whole (ErrProtectedReadTx).
var ErrQueryDoesNotFit = errors.New("a value or a name of the query does not fit the field it is used with")
ErrQueryDoesNotFit identifies a structured query that the database server of the mount refused because a value or a name of it does not fit the table: a value that is no value of the type of its field (a word compared with an integer), a number compared with text, a name the table does not have. It is the caller's mistake, mapped to HTTP 400 invalid_dtql with a fixed message and not logged. The error is built here: it holds no text of the server's, which can repeat the value.
var ErrQueryNotRunnable = errors.New("the storage engine cannot run this query")
ErrQueryNotRunnable identifies a structured query that the adapter of the storage engine refused to run: it reports dal.ErrNotSupported (a condition, an aggregation or a join it cannot compile), or it does not know the structured-query dialect its mount asked for (mapped to HTTP 422 query_unsupported with a fixed message). The error is built here: it holds no text of the adapter's.
var ErrQueryUnsupported = errors.New("structured queries are not supported on this engine")
ErrQueryUnsupported identifies a structured query refused because the mounted storage engine cannot run structured queries safely yet (mapped to HTTP 501 query_unsupported). Use errors.As with *QueryUnsupportedError for the engine name.
var ErrResultTooLarge = errors.New("the result is larger than the response buffer of the server")
ErrResultTooLarge identifies a structured read whose result is larger than the buffer of the server (ResultBufferBytes). It is a request the caller can change, not a fault of the server: the HTTP server answers it `422 query_budget_exceeded`, with a hint that says to narrow or to page the read, and does not log it as an error. It states no figure: the result is not read to its end.
var ErrUpdateOfMissingRecord = errors.New("cannot update: record not found")
ErrUpdateOfMissingRecord is returned when an update op targets a record that neither exists in the store nor was written earlier in the batch.
Functions ¶
func AggregateFunctions ¶ added in v0.12.0
func AggregateFunctions() []string
AggregateFunctions returns the aggregate functions of the relational profile in lower case, in the order discovery lists them. The caller owns the slice.
func DeserializeDTQL ¶ added in v0.13.0
func DeserializeDTQL(doc []byte) (dal.StructuredQuery, error)
DeserializeDTQL deserializes a DTQL document with DALgo and says what is wrong with one it refuses: the error wraps ErrInvalidDTQL (HTTP 400 invalid_dtql). The refusal of an aggregate function DALgo does not know is a message built here that lists the functions of the profile and repeats none of the caller's text; every other refusal carries DALgo's own message.
func EngineCanQuery ¶ added in v0.12.0
EngineCanQuery reports whether the storage engine, as a manifest writes it, is cleared for structured queries whatever the environment says: the allow-list CanQuery asks, for a caller that holds an engine name and no database. It is false for PostgreSQL, which the preview switch clears for the mounts that read it (see Database.CanQuery).
func IsAggregateFunction ¶ added in v0.12.0
IsAggregateFunction reports whether name is an aggregate function of the relational profile, in any ASCII letter case. A name with a byte of 0x80 or above is none: the case of such a name is not folded (see foldAggregateName), so that this predicate and the walk of pkg/joinexec, which repeats it, read one rule.
func ParseDTQL ¶ added in v0.4.0
func ParseDTQL(doc []byte) (dal.StructuredQuery, string, error)
ParseDTQL validates the server's bounded single-collection query profile. The returned collection is suitable for checking the token's capabilities. It knows no engine, so it checks field names with the widest rule (the one of quotedNameEngines); the Database that runs the query checks them again with the rule of its own engine, before any adapter is reached.
func ParseKey ¶
ParseKey builds a *record.Key from already-unescaped path segments (alternating collection/id pairs, root first). Segments are validated for path-traversal safety (ValidateSegment) before the key is constructed.
func ParseKeyPath ¶
ParseKeyPath parses a dal-escaped key path ("collection/id[/sub/id...]") into a dalgo key: segments are split on '/' and percent-unescaped individually, so dal.EscapeID-encoded characters inside IDs survive.
func QueryCollections ¶ added in v0.11.13
func QueryCollections(query dal.StructuredQuery) ([]string, error)
QueryCollections lists the root collections a query reads, once each and in document order: the root source, every joined source at any depth, every derived source and every subquery, wherever it sits (the walk of the source guard, whatever the engine). A caller that scopes a capability to a collection uses it to authorise every read a query makes, not only the one the route names. A source that a parent record, a schema or another database qualifies is not named by one root collection of this database, and a shape the walk does not know cannot be read: both are refused with ErrInvalidDTQL and nothing is listed. The cost is linear in the size of the query.
func RootCollection ¶ added in v0.6.1
RootCollection returns the root collection name of key: the collection a per-collection capability scopes, and the top-level directory/table the driver writes under.
func SQLiteLogicalName ¶ added in v0.11.8
SQLiteLogicalName returns the public identifier inside a SQL-quoted schema key of a SQLite manifest, where a doubled quote stands for one literal quote. It is the one definition the declared set (newCollectionNames) and the mount (the recordsets it registers with the driver) share.
func ValidateCollectionName ¶ added in v0.6.1
ValidateCollectionName applies ValidateSegment to a collection name taken from a request body (query collection, DTQL source).
func ValidateFieldName ¶ added in v0.11.4
ValidateFieldName checks one field name from a request body against the strict rule. The rule a mount applies depends on its engine.
func ValidateFieldNames ¶ added in v0.11.8
ValidateFieldNames checks every name with ValidateFieldName, in order; no names is fine. The error wraps ErrInvalidFieldName.
func ValidateSegment ¶ added in v0.6.1
ValidateSegment checks one decoded key segment (collection name or record id) for path-traversal safety on every engine. A segment must be non-empty, must not be "." or "..", must not contain control characters (U+0000–U+001F, U+007F), and — because IDs may legitimately carry an escaped '/' — none of its '/'- or '\'-separated components may be "." or "..": file-backed engines join segments into filesystem paths, so "../../secrets" inside an id would escape its collection.
Types ¶
type Database ¶
Database is one mounted logical database: a DALgo driver plus mode enforcement.
func Open ¶
func Open(m *manifest.Manifest, db dal.DB, supportedModes []schema.Mode, cataloguePath string, policies ...access.Policy) (*Database, error)
Open validates driver/schema-mode compatibility and prepares the database: declared collections are provisioned through the driver's ddl.SchemaModifier, and (for partial/schemaless modes) the inferred schema catalogue is loaded from cataloguePath.
func OpenWithPolicyController ¶ added in v0.5.0
func OpenWithPolicyController(m *manifest.Manifest, db dal.DB, modes []schema.Mode, cataloguePath string, controller *policystore.Controller) (*Database, error)
OpenWithPolicyController mounts an immutable owner generation provider. The controller's publication APIs remain trusted owner-administration APIs.
func (*Database) Apply ¶
Apply validates a batch of ops (pre-flight, since inGitDB cannot roll back files already written) and then passes them through to the driver in order inside one dal.RunReadwriteTransaction — for inGitDB that is at most one git commit per batch, with message as the commit message.
func (*Database) CanCollectionQuery ¶ added in v0.21.0
CanCollectionQuery reports whether the legacy /query endpoint can address collections and return OVDB record keys on this mount.
func (*Database) CanQuery ¶ added in v0.11.4
CanQuery reports whether DALgo structured reads are allowed on this mount. Native PostgreSQL supports catalog-backed DTQL reads but not the legacy collection-key /query contract (see CanCollectionQuery).
func (*Database) CanonicalCollection ¶ added in v0.11.12
CanonicalCollection returns the name the adapter is given for a collection a caller named, and whether the database declares that name: a key of its schemas, or on SQLite the public name of a key that is a quoted SQL identifier. Every spelling of one collection has one canonical name. A name the database does not declare returns "" and false.
func (*Database) CheckRead ¶ added in v0.14.1
CheckRead runs, without starting a transaction or sending a statement, the checks every read through ReadTx or Executor runs before the driver is reached (guardStructured): the query is a structured one, its names are plain for the engine, it is a read the access policies allow, it reads collections the database declares, and the engine is cleared for queries. A caller that is about to open a read transaction asks first, so a query that is refused costs the database no BEGIN either: a name that PostgreSQL would cut is then refused before any statement of the mount, and the answer is the one the read would have given from inside the transaction.
func (*Database) Close ¶
Close releases the engine resources behind the database: it propagates to the underlying DALgo driver when that driver implements io.Closer (SQLite, PostgreSQL, MySQL) and runs callbacks registered with OnClose. It is idempotent; later calls return the first call's result. Callers must stop using the database before closing it (the server drains in-flight requests first, see server.Unmount).
func (*Database) CollectionForeignKeys ¶ added in v0.11.0
func (d *Database) CollectionForeignKeys(ctx context.Context, collection string) ([]dbschema.ForeignKeyDef, error)
CollectionForeignKeys returns foreign keys discovered by the storage provider. A provider without schema introspection contributes no keys; manifest-declared references are handled separately by the caller.
func (*Database) CollectionSpellings ¶ added in v0.11.12
CollectionSpellings returns every spelling of the collection that name designates, its canonical name first: a grant that scopes a capability to the collection holds under any of them. A name the database does not declare is the only spelling of itself. The caller owns the result.
func (*Database) Collections ¶
Collections lists the collections of the database, sorted. A document engine lists the collections its driver knows. On an engine whose adapter builds SQL the list is made of the declared collections only, by their canonical names (CanonicalCollection), each when the driver reports it: a table of the file that the manifest does not declare, and a table named with the quote characters of the quoted spelling of a declared key, are not listed. A declared name is matched with the reported one exactly, except on PostgreSQL and SQLite, where ASCII letters are compared without regard to case (see foldsIdentifiers); the declared spelling is the one listed. Every name listed is one the routes that take a collection accept.
func (*Database) Coordinator ¶ added in v0.5.0
func (d *Database) Coordinator() *access.EnforcementCoordinator
func (*Database) Engine ¶ added in v0.11.10
Engine returns the storage engine for routing decisions: the manifest's engine name, except that an inGitDB mount backed by GitHub is EngineInGitDBGitHub.
func (*Database) Execute ¶
Execute translates the wire query to dal.StructuredQuery and runs it on the driver. Result keys are full paths from the database root: records of a nested collection carry their parent key.
func (*Database) ExecuteDTQL ¶
ExecuteDTQL runs DTQL through the same secured DALgo handle as record reads.
func (*Database) ExecuteDTQLQuery ¶ added in v0.4.0
func (d *Database) ExecuteDTQLQuery(ctx context.Context, query dal.StructuredQuery) ([]Record, error)
ExecuteDTQLQuery executes an already parsed query after validating its shape.
func (*Database) Executor ¶ added in v0.11.10
func (d *Database) Executor() dal.QueryExecutor
Executor returns the database as a query executor with the request's access policies applied (it wraps the secured driver). The executor refuses with *QueryUnsupportedError whenever the database cannot be queried (CanQuery).
func (*Database) Exists ¶
Exists reports whether the record exists. Like Get, it refuses an undeclared collection on a SQL engine before the adapter is called, and gives the adapter the collection's canonical name.
func (*Database) Get ¶
Get returns record data or ErrNotFound. A collection the database does not declare is ErrNotFound on an engine whose adapter builds SQL, without an adapter call (GuardKey). The adapter is given the collection's canonical name (CanonicalCollection), whichever spelling the key carries.
func (*Database) GuardCanonicalCollection ¶ added in v0.11.15
GuardCanonicalCollection refuses, before any adapter call, a collection that is not named by its canonical name, when the database's adapter builds SQL (see GuardCollection): a name the database does not declare, and a spelling of a declared collection that is not its canonical name (the SQL-quoted key of a SQLite manifest). It is the rule of the routes that give the adapter, or the coordinator that reads it by key, the collection as the caller wrote it: a spelling that is not the canonical name would address the table of that literal name, which is a different table. Document engines keep their own rule and are not refused. The error wraps ErrNotFound and names the collection, clipped, as GuardCollection does; a name over the engine's limit is refused as GuardCollection refuses it.
func (*Database) GuardCollection ¶ added in v0.11.8
GuardCollection refuses, before any adapter call, a collection the database does not declare when its adapter builds SQL (sqlite, postgres, mysql, and any engine not known to be a document engine). dalgo2sql writes the collection name into the text of key reads and writes, and ValidateCollectionName is only a path-safety rule that accepts quotes, spaces and semicolons, so the set of collections the mount declared when it opened is the allow-list (see collectionNames: every spelling of a declared collection is accepted and has one canonical name). Names match exactly, case included. Document engines keep their own rule: any collection that passes ValidateCollectionName. The error wraps ErrNotFound. A collection name longer than the engine's server keeps in a name (63 bytes on PostgreSQL, see nameLimits) is refused first with an error that wraps ErrInvalidKey, declared or not.
func (*Database) GuardKey ¶ added in v0.11.8
GuardKey refuses, before any adapter call, a key the adapter of a SQL engine cannot address safely: a key with a parent, because a SQL mount has no subcollections (dalgo2sql maps such a key to a recordset named after the whole path, <leaf>_<parent>, that no mount registers and that is not the root collection the capability is checked on), and a collection the database does not declare (see GuardCollection). Document engines address nested keys natively, as a subcollection of the parent record, so they are not refused here and the capability stays scoped by the root collection. A nil key names nothing and is left to the caller. The error wraps ErrNotFound (HTTP 404 not_found).
func (*Database) HTTPProfile ¶ added in v0.23.0
HTTPProfile is captured when the mount opens; editing exported Manifest metadata cannot change the source profile used by server admission guards.
func (*Database) HasAccessPolicies ¶ added in v0.5.0
func (*Database) HasImmutableSQLiteKeys ¶ added in v0.14.0
HasImmutableSQLiteKeys reports whether every declared collection has a verified key and the SQLite handles have no automatic lock wait.
func (*Database) HasLicenseDeclarations ¶ added in v0.15.0
HasLicenseDeclarations reports the frozen authored declarations, never ACLs.
func (*Database) InferredSnapshot ¶
InferredSnapshot returns the inferred schema catalogue view, or nil for strict databases.
func (*Database) NativePostgresReadOnly ¶ added in v0.21.0
func (*Database) NativePostgresSource ¶ added in v0.21.0
func (d *Database) NativePostgresSource(id string) (schema.NativeCollectionSource, bool)
NativePostgresSource returns the original physical schema and relation name for a logical collection ID in a native PostgreSQL mount.
func (*Database) NoRetention ¶ added in v0.16.0
func (*Database) OnClose ¶ added in v0.6.0
OnClose registers fn to run when the database is closed, after resources registered later (reverse order). Mounts use it for resources the dal.DB driver does not own, e.g. a Firestore client.
func (*Database) PolicyLayers ¶ added in v0.5.0
func (d *Database) PolicyLayers(ctx context.Context) []PolicyLayer
func (*Database) PublishPolicies ¶ added in v0.5.0
func (d *Database) PublishPolicies(ctx context.Context, expected string, documents []access.DTQLDocument) (policystore.Snapshot, error)
func (*Database) ReadOnly ¶ added in v0.21.0
ReadOnly reports mounts that expose neither keyed record reads nor writes.
func (*Database) ReadOnlyHTTP ¶ added in v0.17.0
ReadOnlyHTTP reports the fixed source capability captured by Open. Such a source supports bounded queries, but not keyed reads, writes or DDL.
func (*Database) ReadTx ¶ added in v0.11.10
ReadTx runs fn in one read transaction of the secured driver. It returns *QueryUnsupportedError, without starting a transaction, when the database cannot be queried, and ErrProtectedReadTx when it has access policies. fn receives a guarded executor over the transaction, never the transaction itself. The error fn returns is returned as fn gave it: a driver that replaces it (SQL drivers wrap it with a rollback error that hides it from errors.Is once the context has expired) does not change what the caller sees. A transaction that fails by itself, because it cannot begin or cannot commit, is the failure of the driver and is returned as queryError builds it, so that on an engine reached through a connection string none of the driver's text (which can name the user, the database and the host of the connection) reaches a log. The transaction runs under a context that is cancelled when ReadTx returns, so the driver releases it on every exit, a panic in fn included.
func (*Database) ReloadPolicies ¶ added in v0.5.0
ReloadPolicies reloads this owner's committed generation. It is an embedded owner-administration API; no data endpoint grants this authority.
func (*Database) ResolveNativePostgresCollection ¶ added in v0.21.0
ResolveNativePostgresCollection resolves exact schema and relation names to the logical collection ID used by OVDB authorization and catalog routes.
func (*Database) Retention ¶ added in v0.16.0
Retention is fixed when Open accepts the source; callers cannot weaken it by changing the exposed manifest. Instances not opened by Open fail closed.
func (*Database) SelectAccessSample ¶ added in v0.5.0
func (d *Database) SelectAccessSample(ctx context.Context, query dal.StructuredQuery, n int, requester access.Principal) ([]Record, []dal.OrderExpression, error)
SelectAccessSample selects only the readable intersection. Its adapters use different key expressions; neither stored document id fields nor post-page sorting substitute for canonical record identity.
func (*Database) ServingKey ¶ added in v0.14.0
ServingKey returns the immutable, physically verified SQLite transport key.
func (*Database) SetAfterWrite ¶
SetAfterWrite registers a hook invoked after each successfully applied write batch. Used by pkg/mount to wire git push policies for inGitDB.
func (*Database) SourceRight ¶ added in v0.15.0
func (d *Database) SourceRight(serverID string, server *license.Declaration, collection string) (*license.SourceRight, error)
SourceRight resolves terms for an already authorized source. Callers must enforce access before disclosing the result. Core does not infer permission.
func (*Database) StreamDTQLSnapshot ¶ added in v0.8.0
func (d *Database) StreamDTQLSnapshot(ctx context.Context, query dal.StructuredQuery, emit func(Record) error) error
StreamDTQLSnapshot executes one complete query through one DALgo reader. Local OVDB writes cannot interleave with the capture. The caller must bound the emitted result and persist it before exposing any page token.
func (*Database) ValidateDataKeys ¶ added in v0.11.15
ValidateDataKeys checks the top-level keys of the data of an insert or a set, which an adapter that builds SQL writes as columns: each must be a plain name (ValidateFieldNames) and no longer than the engine's server keeps in a name (nameLimits), and on an engine that builds SQL (or one nobody classified) none may be the record's key column in a case other than "id", which is the same column (ErrKeyColumnCase). A document engine keeps the key outside the record's fields and is not refused here. No data is fine.
func (*Database) ValidateFieldPath ¶ added in v0.11.8
ValidateFieldPath checks the path of an update from a write body. The first segment is a field of the record, so it must be a plain name (ValidateFieldName) on every engine. The segments after it are map keys: on a SQL engine (or one nobody classified) they are held to the same rule, to fail closed; on a document engine they never reach SQL and are data (Sneat's linkage writes ["related", ext, collection, "id@spaceID"]), so only a segment that is blank (empty, or only white space) or carries a control character is refused: update.ByFieldPath panics on a blank segment inside the transaction. A path with no segment at all is refused too, and so is a segment longer than the engine's server keeps in a name (nameLimits). The error wraps ErrInvalidFieldName.
func (*Database) ValidateRetentionCache ¶ added in v0.16.0
ValidateRetentionCache rejects changed cache configuration at server admission. Enforcement still uses the immutable capability if the manifest later changes.
func (*Database) ValidateUpdatePath ¶ added in v0.11.15
ValidateUpdatePath checks the path of an update: ValidateFieldPath, and on an engine whose adapter builds SQL (or one nobody classified) the path must not name the record's key column, in any spelling of its case, as a field or as the head of a nested path. The error wraps ErrKeyUpdate, which wraps ErrInvalidFieldName. A document engine keeps the key outside the record's fields and is not refused here.
type Filter ¶
Filter is one field condition. Op is one of: ==, <, <=, >, >=, in, array-contains, array-contains-any.
type ModeCompatibilityError ¶
ModeCompatibilityError is the loud failure for a schema mode a driver does not support.
func (*ModeCompatibilityError) Error ¶
func (e *ModeCompatibilityError) Error() string
type Op ¶
type Op struct {
Op string `json:"op"` // set | insert | update | delete
Key *record.Key `json:"-"`
KeyPath string `json:"key"`
Data map[string]any `json:"data,omitempty"`
Updates []UpdateOp `json:"updates,omitempty"`
}
Op is one operation of a write batch, in wire format (see docs/api.md).
type PolicyLayer ¶ added in v0.5.0
PolicyLayer is a trusted in-process snapshot, never an HTTP DTO. Every enabled participant remains represented even if another participant denies. Hosts must separately authorize disclosure before exposing any of its facts.
type Profile ¶ added in v0.11.7
type Profile struct {
Kind ProfileKind
// Sources lists every collection read in the query, in document order,
// including reads inside derived sources and subquery expressions.
Sources []ProfileSource
// HasSubquery reports a derived source, scalar subquery, EXISTS predicate
// or query-valued comparison operand anywhere in the query.
HasSubquery bool
// HasAggregation reports GROUP BY, HAVING or an aggregate function in the
// query's own columns or ordering.
HasAggregation bool
}
Profile is the classification of a DTQL query.
func ClassifyDTQL ¶ added in v0.11.7
func ClassifyDTQL(query dal.StructuredQuery) (Profile, error)
ClassifyDTQL decides which profile query belongs to and refuses everything outside both. It is a security boundary: a shape it does not recognise is refused with ErrInvalidDTQL, never passed through.
The relational rules are checked for every document, single-collection ones included, over the whole query tree and the subqueries in it. A document that ParseDTQL accepts is therefore refused here when it carries a money configuration with a subquery, and, when it has a subquery in its WHERE (which ParseDTQL accepts), when that subquery nests deeper than the subquery cap, brings the query past the source cap, puts scan bounds on a nested source or carries a money configuration itself. A schema-qualified root, a scan root and a database on the root are refused by ParseDTQL as well. Names are checked next, with the query guard's rules (see validateRelationalNames), so a name that ParseDTQL refuses is not an accepted relational document either.
A query is single-collection only when validateDTQL accepts it and it also names no database and has no subquery anywhere (validateDTQL checks names inside conditions but does not refuse a subquery there, so a subquery in WHERE would otherwise hide a second source). Every other query is relational.
type ProfileBounds ¶ added in v0.12.0
type ProfileBounds struct {
// MaxSources is the most collection reads one document makes, subqueries
// included.
MaxSources int
// MaxSubqueryDepth is how many levels of subquery may sit below the outermost
// query.
MaxSubqueryDepth int
// MaxLimit and MaxOffset cap the outermost query only.
MaxLimit, MaxOffset int
}
ProfileBounds are the numeric bounds of the relational profile, as the classifier enforces them: discovery advertises these values and nothing else.
func RelationalBounds ¶ added in v0.12.0
func RelationalBounds() ProfileBounds
RelationalBounds returns the bounds the classifier applies to a relational document.
type ProfileKind ¶ added in v0.11.7
type ProfileKind string
ProfileKind names the DTQL profile a query belongs to.
const ( // ProfileSingleCollection is today's profile: one plain root collection // of the database the request is addressed to, accepted by validateDTQL. ProfileSingleCollection ProfileKind = "single-collection" // ProfileRelational is the bounded relational profile: joins, GROUP BY, // HAVING, aggregates, column aliases and subqueries over root collections. ProfileRelational ProfileKind = "relational" )
type ProfileSource ¶ added in v0.11.7
type ProfileSource struct {
// Database is the mounted database id the source names, or empty when the
// source does not name one.
Database string
// Collection is the root collection name.
Collection string
// Schema is present for a native PostgreSQL relation source. Collection is
// its stable logical ID, while Schema and Name retain its physical names.
Schema string
Name string
// Alias is the alias the query gives the source, or empty.
Alias string
}
ProfileSource is one collection read a query makes. A query that reads the same collection twice lists it twice, because each reference is a read.
type Query ¶
type Query struct {
Collection string `json:"collection"`
Parent string `json:"parent,omitempty"` // dal-escaped parent key path for scoped subcollection queries
Where []Filter `json:"where,omitempty"`
OrderBy []OrderBy `json:"orderBy,omitempty"`
Limit int `json:"limit,omitempty"`
KeysOnly bool `json:"keysOnly,omitempty"`
}
Query is a structured query in the JSON wire format (see docs/api.md). Filters are AND-ed. It translates 1:1 onto dal.StructuredQuery and executes natively on the DALgo driver — ovdb does not evaluate queries itself.
type QueryUnsupportedError ¶ added in v0.11.4
type QueryUnsupportedError struct {
// Engine is the storage engine of the mount, as written in its manifest.
Engine string
}
QueryUnsupportedError is the typed refusal of a structured query on an engine that is not yet cleared for queries.
func (*QueryUnsupportedError) Error ¶ added in v0.11.4
func (e *QueryUnsupportedError) Error() string
func (*QueryUnsupportedError) Is ¶ added in v0.11.4
func (e *QueryUnsupportedError) Is(target error) bool
Is makes errors.Is(err, ErrQueryUnsupported) true.
type UnreachableError ¶ added in v0.14.1
type UnreachableError struct {
// Database is the ID of the mount.
Database string
// Reason is the adapter's fixed sentence, with the SQLSTATE code of a server
// that answered.
Reason string
}
UnreachableError is the built error of a mount whose database server cannot be reached. It holds the ID of the mount and the adapter's fixed sentence for the failure (the adapter's own text of a *dalgo2postgres.ConnectionError, without the host, the port and the database name it may add). Nothing of the connection string and nothing of the driver's or the server's own text is in it, and it wraps no cause, so a log line or an answer that prints it cannot repeat one.
func (*UnreachableError) Error ¶ added in v0.14.1
func (e *UnreachableError) Error() string
func (*UnreachableError) Is ¶ added in v0.14.1
func (e *UnreachableError) Is(target error) bool
Is makes errors.Is(err, ErrDatabaseUnreachable) true.
type UpdateOp ¶
type UpdateOp struct {
FieldName string `json:"fieldName,omitempty"`
FieldPath []string `json:"fieldPath,omitempty"`
Value any `json:"value,omitempty"`
Delete bool `json:"delete,omitempty"`
Transform string `json:"transform,omitempty"`
ServerTimestamp bool `json:"serverTimestamp,omitempty"`
}
UpdateOp is one field-level update operation, in wire format.
Source Files
¶
- access_layers.go
- access_sample.go
- aggregate_functions.go
- collection_names.go
- core.go
- dtql_profile.go
- http.go
- infer.go
- join_source.go
- key.go
- licenses.go
- native_postgres.go
- preview_postgres.go
- provision_error.go
- query.go
- query_failure.go
- query_fields.go
- query_guard.go
- query_refusal.go
- query_sources.go
- query_unnamed.go
- retention.go
- unreachable.go
- updates.go
- write_guard.go