Documentation
¶
Overview ¶
Package semantic resolves physical columns (a source + collection + set of scanned columns) to the entity fields a project's model says they mean.
Resolve is pure - no I/O, no mutation - so it can be called from anywhere that already has a project's entities in memory: the datatug-cli HTTP resolver behind GET /datatug/semantic/columns (REQ:semantic-resolution-endpoint in datatug/datatug's core-investigation-loop feature), the TUI, or a future `datatug context` verb. Placement note: the resolver lives here in datatug-core rather than in datatug-cli/pkg/semantic (as sketched in the Phase-1 plan's task 5) because datatug-cli currently vendors its own copy of this package's types and a separate stream is restoring its module dependency; the HTTP endpoint itself is still wired in datatug-cli. This is a planner decision, not a founder ruling - open to being moved once the module dependency lands.
Declared EntityField.Mappings always win over an EntityField.NamePatterns match; NamePatterns are tried only for a column with no declared mapping anywhere in the project, and the result is labelled Inferred. See Resolve for the full tie-break rule when more than one field could claim the same column.
RelatedLookups and Applicable build on the same SemanticValue shape a Resolution plus its cell value produces: the former finds every other collection reachable from a selected value (foreign keys in both directions, plus the same field mapped elsewhere); the latter matches the project's library queries against the values on hand and reports a human-readable resolution chain for each bound parameter.
Index ¶
- func Applicable(queries []*datatug.QueryDef, available []SemanticValue) (applicable []ApplicableQuery, notYet []NotYetApplicable)
- type ApplicableQuery
- type Binding
- type Column
- type Lookup
- type LookupKind
- type NotYetApplicable
- type Provenance
- type Resolution
- type SchemaKey
- type SemanticValue
- type TableSchema
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Applicable ¶ added in v0.19.0
func Applicable(queries []*datatug.QueryDef, available []SemanticValue) (applicable []ApplicableQuery, notYet []NotYetApplicable)
Applicable splits queries into those every required, Meta-tagged parameter of which can be bound from available, and those still missing at least one. A parameter with no Meta is never considered - it stays unbound and never blocks applicability, whether required or not. A Meta-tagged optional parameter (IsRequired == false) is bound when available can satisfy it, but its absence never blocks applicability either; only an unsatisfied *required* Meta-tagged parameter lands a query in notYet.
available is order-sensitive: when more than one entry shares the same Entity+Field (e.g. the Investigation Context holds a stale value and the user's current selection holds a newer one), the last entry for that Entity+Field wins - callers should append newer values after older ones.
Pure: no I/O.
Types ¶
type ApplicableQuery ¶ added in v0.19.0
type ApplicableQuery struct {
Query *datatug.QueryDef
Bindings []Binding
// Chain is the human-readable resolution chain, one entry per bound
// parameter: "<column> → <entity>.<field> (<declared|inferred>) →
// parameter <parameterID>".
Chain []string
}
ApplicableQuery is a query every required, semantically-tagged parameter of which could be bound from the available values.
type Binding ¶ added in v0.19.0
type Binding struct {
Parameter string
Value interface{}
From SemanticValue
}
Binding is one query parameter bound to a semantic value.
type Lookup ¶ added in v0.19.0
type Lookup struct {
Source string
Collection string
Column string
Kind LookupKind
Via string
}
Lookup is one related-record path reachable from a SemanticValue: the caller filters Lookup.Collection (in Lookup.Source) where Lookup.Column equals the selected value - RelatedLookups itself performs no such filter, it only says where to look (REQ:related-lookup-execution builds and runs that query server-side).
func RelatedLookups ¶ added in v0.19.0
func RelatedLookups(entities []*datatug.Entity, schemaByCollection map[SchemaKey]TableSchema, selected SemanticValue) []Lookup
RelatedLookups returns every other collection reachable from a selected semantic value: through declared foreign keys in both directions within selected's own source (schemaByCollection must carry that source's scanned schema for this to find anything), and through mappings of the same entity field (selected.Entity + selected.Field) in other sources or collections. A column that is neither part of a foreign-key relationship nor mapped anywhere else yields nothing.
The scanned-schema model does not record which column of a referenced table an outgoing foreign key targets, only the referencing table's own columns (datatug.ForeignKey has no "referenced column" field). Two heuristics fill that gap, both using the referenced table's primary key as the assumed join target - the common case, and the only information this model actually carries:
- LookupForeignKey: selected.Column matches one of the current table's own ForeignKey.Columns: this reports RefTable's primary key (its first column, when the schema for RefTable is known and single-column-keyed; the selected column's own name otherwise) as the join column.
- LookupReferencedBy: selected.Column must be part of the current table's own primary key for a "referenced by" lookup to fire at all, since that is this model's only signal that an incoming foreign key targets this exact column.
Order is deterministic: lookups in selected's own source come first, ordered by target Collection name (ties broken by Kind); then cross-source SameField lookups, ordered by Source then Collection name. Pure: no I/O.
type LookupKind ¶ added in v0.19.0
type LookupKind string
LookupKind identifies how a Lookup was derived.
const ( // LookupForeignKey means the selected value's own column is a foreign // key, pointing at Lookup.Collection. LookupForeignKey LookupKind = "foreignKey" // LookupReferencedBy means Lookup.Collection has a foreign key pointing // back at the selected value's table. LookupReferencedBy LookupKind = "referencedBy" // LookupSameField means Lookup.Collection maps the same semantic field // (the selected value's Entity + Field) in a different source or // collection. LookupSameField LookupKind = "sameField" )
type NotYetApplicable ¶ added in v0.19.0
type NotYetApplicable struct {
Query *datatug.QueryDef
// Missing lists each unsatisfied required parameter's semantic field, as
// "<entity>.<field>".
Missing []string
}
NotYetApplicable is a query with at least one required, semantically-tagged parameter the available values could not satisfy.
type Provenance ¶
type Provenance string
Provenance identifies how a Resolution was determined.
const ( // Declared means the column matched an EntityField's declared Mappings. Declared Provenance = "declared" // Inferred means the column matched an EntityField's NamePatterns, with // no declared mapping present for it. Inferred Provenance = "inferred" )
type Resolution ¶
type Resolution struct {
Column string
Entity string
Field string
Provenance Provenance
// Rule documents how the winner was chosen: which name pattern matched
// (for Inferred), and/or a tie-break note when more than one field
// resolved the same column at the same provenance level.
Rule string
// Err is set only when the column had NamePatterns candidates that could
// not be evaluated (e.g. an invalid regexp) and neither a declared
// mapping nor a valid inferred candidate resolved it. When Err is set,
// Entity, Field, Provenance and Rule are zero.
Err error
}
Resolution is what one Column resolved to.
func Resolve ¶
func Resolve(entities []*datatug.Entity, source, collection string, columns []Column) []Resolution
Resolve returns, for each Column, the entity field it maps to in the given source/collection (table): declared EntityField.Mappings win; absent a declared mapping, EntityField.NamePatterns are tried; a column matching neither is simply absent from the result (see REQ:field-mapping-model in datatug/datatug's core-investigation-loop feature).
When more than one field resolves the same column at the same provenance level, the field belonging to the lowest Entity.ID wins (Entity.ID, then EntityField.ID, ascending) and the tie is recorded in the winning Resolution's Rule. This keeps Resolve deterministic without requiring callers to pre-sort entities.
Resolve is pure: it performs no I/O and does not mutate entities. It never panics - a pattern that fails to evaluate (e.g. invalid regexp syntax) yields a Resolution with Err set instead, unless a declared mapping or another, valid pattern already resolved the column.
type SchemaKey ¶ added in v0.19.0
SchemaKey identifies one collection (table or view) within one source.
type SemanticValue ¶ added in v0.19.0
type SemanticValue struct {
Entity string
Field string
Value interface{}
Source string
Collection string
Column string
Provenance Provenance
}
SemanticValue is one resolved cell: a value in a physical column, and the semantic field a resolver (see Resolve) said it means. Provenance is a deliberate addition beyond the field-mapping-model REQ's own sketch of this type: it is needed to render the "(declared)"/"(inferred)" segment of an Applicable resolution Chain (REQ:applicable-queries), so a caller can build one SemanticValue directly from a Resolution and pass it to both RelatedLookups and Applicable.
type TableSchema ¶ added in v0.19.0
type TableSchema struct {
PrimaryKey *datatug.UniqueKey
ForeignKeys datatug.ForeignKeys
ReferencedBy datatug.ReferencedBys
}
TableSchema is the subset of a scanned table/view's metadata RelatedLookups needs: its primary key, and its foreign-key graph in both directions (datatug.ForeignKeys/datatug.ReferencedBys, as scanned by the DB driver).