Documentation
¶
Overview ¶
Package tugql provides TugQL query authoring, validation, resolution, formatting, and serialization for dal.StructuredQuery.
Decision: TugQL has been renamed to TugQL. TugQL is the canonical name of the SQL-like query language and TugQL.org is its canonical public home. TugQL.org is retained as a permanent redirect for backwards compatibility and discovery. TugQT (Tug Query Tree) is the intended name for the structured query-tree concept.
TugQL provides a human-friendly SQL-like authoring syntax with a versioned TugQLDocument/TugQLTree model: ParseTugQL creates a TugQLDocument and TugQLTree, ResolveTugQL validates and lowers supported constructs through the underlying query model, and FormatTugQL formats source text. For example:
doc, diagnostics := tugql.ParseTugQL("from Invoice as i\nselect i.Id\n")
if len(diagnostics) != 0 {
// show diagnostics to the author
}
resolved, diagnostics := tugql.ResolveTugQL(doc, context)
The existing Serialize and Deserialize APIs provide 1:1, lossless YAML serialization over dal.StructuredQuery (corresponding to the TugQT concept).
TugQL syntax, resolution, and formatting are described in spec/features/tugql/README.md. The YAML subset and node mapping are documented in tugql/README.md.
This package imports dal but adds no YAML dependency to dal.
Index ¶
- Constants
- func Deserialize(data []byte) (dal.StructuredQuery, error)
- func DeserializeTugQL(data []byte) (dal.StructuredQuery, error)
- func Equal(a, b dal.StructuredQuery) bool
- func ParseTugQL(source string) (TugQLDocument, []TugQLDiagnostic)
- func ResolveTugQL(doc TugQLDocument, context TugQLResolveContext) (TugQLResolved, []TugQLDiagnostic)
- func SchemaJSON() []byte
- func SchemaYAML() []byte
- func Serialize(q dal.StructuredQuery) ([]byte, error)
- func SerializeTugQL(q dal.StructuredQuery) ([]byte, error)
- type TugQLAuthorizedSchema
- type TugQLBinding
- type TugQLBody
- type TugQLComment
- type TugQLCommentGroup
- type TugQLComments
- type TugQLDatabase
- type TugQLDefinition
- type TugQLDependencyReceipt
- type TugQLDiagnostic
- type TugQLDocument
- type TugQLField
- type TugQLFormatOptions
- type TugQLMapping
- type TugQLOutputColumn
- type TugQLOutputLineage
- type TugQLParameter
- type TugQLPinnedImport
- type TugQLPosition
- type TugQLRelationEndpoint
- type TugQLRelationship
- type TugQLRelationshipExpansion
- type TugQLRelationshipPair
- type TugQLResolveContext
- type TugQLResolved
- type TugQLSourceMetadata
- type TugQLSpan
- type TugQLTable
- type TugQLTree
Constants ¶
const SchemaID = "https://dal-go.github.io/tugql/schema.json"
SchemaID is the canonical $id of the published TugQL JSON Schema.
Variables ¶
This section is empty.
Functions ¶
func Deserialize ¶
func Deserialize(data []byte) (dal.StructuredQuery, error)
Deserialize reconstructs a dal.StructuredQuery from a TugQL YAML document. Malformed or schema-invalid input — unknown keys, wrong value types, missing required fields, or an unknown operator — yields a descriptive error and no (partially-populated) query.
func DeserializeTugQL ¶
func DeserializeTugQL(data []byte) (dal.StructuredQuery, error)
DeserializeTugQL reconstructs a dal.StructuredQuery from a TugQL/TugQT-YAML document.
func Equal ¶
func Equal(a, b dal.StructuredQuery) bool
Equal reports whether two in-scope dal.StructuredQuery values are structurally equal across the TugQL-covered surface: From, Columns, the Where condition tree (including inline Constant/Array values), OrderBy, Limit and Offset. It compares via the dal accessor interface, so it is agnostic to the concrete query type (e.g. a builder query vs. a deserialized one). It is the equality mechanism behind the structural round-trip guarantee. The in-scope dal nodes are value types (Comparison, GroupCondition, FieldRef, Constant, Array), so the type switches handle the value forms.
func ParseTugQL ¶
func ParseTugQL(source string) (TugQLDocument, []TugQLDiagnostic)
ParseTugQL parses the complete version 1 source profile. On any diagnostic it returns the exact source and metadata without a semantic tree, preventing a partial parse from becoming executable.
func ResolveTugQL ¶
func ResolveTugQL(doc TugQLDocument, context TugQLResolveContext) (TugQLResolved, []TugQLDiagnostic)
ResolveTugQL validates caller-provided semantic trees against authorized schema and bindings, lowers supported authoring constructs, then delegates executable query validation to the existing TugQL deserializer.
func SchemaJSON ¶
func SchemaJSON() []byte
SchemaJSON renders the TugQL JSON Schema as canonical, indented JSON. The schema document holds only strings, bools, ints, slices and maps, so marshaling cannot fail.
func SchemaYAML ¶
func SchemaYAML() []byte
SchemaYAML renders the TugQL JSON Schema as canonical YAML (identical content).
func Serialize ¶
func Serialize(q dal.StructuredQuery) ([]byte, error)
Serialize converts an in-scope dal.StructuredQuery into a canonical TugQL YAML document. queryToDocument is the single validating pass: an out-of-scope query yields a descriptive error and no document.
func SerializeTugQL ¶
func SerializeTugQL(q dal.StructuredQuery) ([]byte, error)
SerializeTugQL converts an in-scope dal.StructuredQuery into a canonical TugQL/TugQT-YAML document.
Types ¶
type TugQLAuthorizedSchema ¶
type TugQLAuthorizedSchema struct {
Database string `json:"database,omitempty"`
Schema string `json:"schema,omitempty"`
Version string `json:"version"`
Tables []TugQLTable `json:"tables"`
}
TugQLAuthorizedSchema is a schema version ResolveTugQL may read. When the query source names a database or schema, the authorized schema must carry the same value, and Version is joined into the resolved schema version.
type TugQLBinding ¶
type TugQLBinding struct {
Name string `json:"name"`
Set bool `json:"set"`
Value any `json:"value,omitempty"`
}
TugQLBinding is a caller-supplied value for a declared parameter. When Set is false the binding is ignored and does not satisfy a required parameter.
type TugQLBody ¶
type TugQLBody struct {
Definitions []TugQLDefinition `json:"definitions,omitempty" yaml:"definitions,omitempty"`
Query map[string]any `json:"query" yaml:"-"`
}
TugQLBody is the body of a CTE or a scalar query. Definitions are optional and Query is required.
func (TugQLBody) MarshalYAML ¶
MarshalYAML requires Query, validates the body and its definitions, and returns the definitions and query.
type TugQLComment ¶
type TugQLComment struct {
Text string `json:"text"`
BlankBefore bool `json:"blankBefore,omitempty"`
}
TugQLComment is one source comment with its marker removed. In the TugQL text form a comment starts with `--` or `//` and runs to the end of the line; in the structured YAML form it is a `#` comment. Text drops the marker and one optional following space, so `-- note`, `--note` and `// note` all carry the text "note". BlankBefore records that at least one blank line separated this comment from the previous comment of the same group; it is never set on the first comment of a group.
type TugQLCommentGroup ¶
type TugQLCommentGroup struct {
Leading []TugQLComment `json:"leading,omitempty"`
Trailing *TugQLComment `json:"trailing,omitempty"`
}
TugQLCommentGroup holds the comments attached to one anchor: the comment lines above the anchor (Leading) and the comment on the anchor's own line (Trailing).
type TugQLComments ¶
type TugQLComments struct {
Anchors map[string]TugQLCommentGroup `json:"anchors,omitempty"`
End []TugQLComment `json:"end,omitempty"`
}
TugQLComments carries every comment of a TugQTree. Comments are not part of the query semantics: they live beside the tree, are ignored by resolution, and never reach `dal.StructuredQuery` or generated SQL.
Anchors maps a TugQTree path to the comments attached to the element at that path. The anchorable elements are the clause-level elements a person writes on one line of text:
databases the DATABASES block parameters the PARAMETERS block definitions[i] the i-th WITH definition query.from the FROM line query.from.joins[k] the k-th JOIN line query.from.joins[k].on[j] the j-th ON line of join k query.where query.groupBy query.having query.orderBy query.limit query.columns the SELECT clause
A comment with no clean anchor (inside a multi-line block, or in a position of the YAML form that is not an anchor) becomes a leading comment of the nearest following anchor. A comment after the last anchor is kept in End. A comment is never dropped.
type TugQLDatabase ¶ added in v0.102.0
type TugQLDatabase struct {
Name string `json:"name" yaml:"name"`
Target string `json:"target,omitempty" yaml:"target,omitempty"`
}
TugQLDatabase declares a database alias of a TugQTree, written in the text form as one line of the root DATABASES block. Name is an unquoted word that is not a reserved keyword; names are unique case-insensitively. Target is an optional opaque reference (for example `datatug://chinook/sales`) that must not carry a password; when it is empty the caller binds the alias. A source reads a declared database by carrying its Name as `database`.
type TugQLDefinition ¶
type TugQLDefinition struct {
Kind string `json:"kind" yaml:"kind"`
Name string `json:"name" yaml:"name"`
Query *TugQLBody `json:"query,omitempty" yaml:"query,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
Using []TugQLMapping `json:"using,omitempty" yaml:"using,omitempty"`
}
TugQLDefinition is a named CTE or import. Kind is cte or import. A CTE has Query and no Path or Using, and an import has Path and no Query.
type TugQLDependencyReceipt ¶
TugQLDependencyReceipt records the project path and revision of a saved-query import ResolveTugQL expanded.
type TugQLDiagnostic ¶
type TugQLDiagnostic struct {
Code string `json:"code"`
Message string `json:"message"`
Span TugQLSpan `json:"span"`
}
TugQLDiagnostic is one parse, format, or resolve finding. Code and Message describe it, and Span locates it in the source.
func FormatTugQL ¶
func FormatTugQL(doc TugQLDocument, options TugQLFormatOptions) (string, []TugQLDiagnostic)
FormatTugQL formats version 1 source while preserving comments and expressions. Lexically invalid source is returned unchanged with diagnostics so an editor can keep a repairable buffer.
func PrintTugQL ¶
func PrintTugQL(tree TugQLTree) (string, []TugQLDiagnostic)
PrintTugQL renders a TugQTree, including its comments, as TugQL source text.
func TugQLToYAML ¶
func TugQLToYAML(source string) ([]byte, []TugQLDiagnostic)
TugQLToYAML converts TugQL source text into the structured TugQL YAML form. Every `--` and `//` comment becomes a `#` comment: a comment on its own lines is the head comment above the clause it precedes, and a comment after code is the same-line comment of that clause. On any diagnostic no YAML is returned.
func YAMLToTugQL ¶
func YAMLToTugQL(data []byte) (string, []TugQLDiagnostic)
YAMLToTugQL converts the structured TugQL YAML form into TugQL source text. Every `#` comment becomes a `--` comment, so a `//` comment written in text comes back as `--` after a text, YAML, text round trip. The output uses the canonical lowercase, two-space layout. Constructs that have no text spelling fail closed with a diagnostic.
type TugQLDocument ¶
type TugQLDocument struct {
Source string `json:"source,omitempty"`
Tree *TugQLTree `json:"tree,omitempty"`
SourceMetadata TugQLSourceMetadata `json:"sourceMetadata"`
}
TugQLDocument keeps the original authoring source separate from its versioned semantic TugQTree. Source may be empty when the caller starts from TugQTree YAML alone.
func (*TugQLDocument) UnmarshalJSON ¶
func (doc *TugQLDocument) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects unknown public document fields so JSON input follows the same closed-shape boundary as TugQTree YAML.
type TugQLField ¶
type TugQLField struct {
Name string `json:"name"`
Type string `json:"type"`
Authorized bool `json:"authorized"`
}
TugQLField is one field of an authorized table. Authorized reports whether resolution may use the field.
type TugQLFormatOptions ¶
type TugQLFormatOptions struct {
KeywordCase string `json:"keywordCase,omitempty"` // explicit lowercase, uppercase, or preserve-existing
Indentation string `json:"indentation,omitempty"` // explicit two-spaces, tab, or preserve-existing
ProjectTeamKeywordCase string `json:"projectTeamKeywordCase,omitempty"`
UserKeywordCase string `json:"userKeywordCase,omitempty"`
DefaultKeywordCase string `json:"defaultKeywordCase,omitempty"`
ProjectTeamIndentation string `json:"projectTeamIndentation,omitempty"`
UserIndentation string `json:"userIndentation,omitempty"`
DefaultIndentation string `json:"defaultIndentation,omitempty"`
}
TugQLFormatOptions carries keyword-case and indentation preferences for FormatTugQL. An explicit value and the matching project-team value must be equal when both are set, and preserve-existing keeps the style already in the source. Keyword case is lowercase, uppercase, or preserve-existing, and indentation is two-spaces, tab, or preserve-existing.
type TugQLMapping ¶
type TugQLMapping struct {
Name string `json:"name" yaml:"name"`
Expression map[string]any `json:"expression" yaml:"expression"`
}
TugQLMapping pairs a parameter Name with an Expression in an import Using list.
type TugQLOutputColumn ¶
type TugQLOutputColumn struct {
Name string `json:"name"`
Type string `json:"type"`
Lineage []TugQLOutputLineage `json:"lineage"`
}
TugQLOutputColumn is one column reported by ResolveTugQL. Name is the output name, Type is the inferred type, and Lineage lists the source fields behind the column.
type TugQLOutputLineage ¶
TugQLOutputLineage names a source field that an output column comes from.
type TugQLParameter ¶
type TugQLParameter struct {
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
Default *any `json:"default,omitempty" yaml:"default,omitempty"`
}
TugQLParameter is a named parameter on a TugQTree. Name and Type are required, names are unique, and Type is integer, decimal, string, boolean, date, datetime, or timestamp. A required parameter cannot also have a default, and a default cannot be null.
type TugQLPinnedImport ¶
type TugQLPinnedImport struct {
Path string `json:"path"`
Revision string `json:"revision"`
Source string `json:"source"`
}
TugQLPinnedImport is the source text of a saved query at a project path and revision. ResolveTugQL parses Source when Path matches the import and Revision equals ProjectRevision.
type TugQLPosition ¶
TugQLPosition is a line and column in TugQL source. Both numbers start at 1.
type TugQLRelationEndpoint ¶
type TugQLRelationEndpoint struct {
Source string `json:"source,omitempty"`
Table string `json:"table"`
}
TugQLRelationEndpoint is one side of a relationship. Table matches a query source, and Source matches that source's alias when it is set.
type TugQLRelationship ¶
type TugQLRelationship struct {
ID string `json:"id"`
Version string `json:"version"`
From TugQLRelationEndpoint `json:"from"`
To TugQLRelationEndpoint `json:"to"`
Pairs []TugQLRelationshipPair `json:"pairs"`
ExactTypedEquality bool `json:"exactTypedEquality"`
}
TugQLRelationship is a join relationship supplied to ResolveTugQL. Resolution uses it only when ExactTypedEquality is set and each pair has the same authorized type on both ends.
type TugQLRelationshipExpansion ¶
type TugQLRelationshipExpansion struct {
ID string `json:"id"`
Version string `json:"version"`
FromSource string `json:"fromSource"`
ToSource string `json:"toSource"`
JoinType string `json:"joinType"`
Pairs []TugQLRelationshipPair `json:"pairs"`
}
TugQLRelationshipExpansion records a relationship ResolveTugQL applied to a join. It keeps the relationship id and version, the source aliases, the join type, and the field pairs.
type TugQLRelationshipPair ¶
type TugQLRelationshipPair struct {
FromField string `json:"fromField"`
ToField string `json:"toField"`
}
TugQLRelationshipPair names the FromField and ToField compared by a relationship.
type TugQLResolveContext ¶
type TugQLResolveContext struct {
AuthorizedSchemas []TugQLAuthorizedSchema `json:"authorizedSchemas,omitempty"`
Relationships []TugQLRelationship `json:"relationships,omitempty"`
ProjectRoot string `json:"projectRoot,omitempty"`
ImportingPath string `json:"importingPath,omitempty"`
ProjectRevision string `json:"projectRevision,omitempty"`
PinnedImports []TugQLPinnedImport `json:"pinnedImports,omitempty"`
Bindings []TugQLBinding `json:"bindings,omitempty"`
// contains filtered or unexported fields
}
TugQLResolveContext supplies the schemas, relationships, pinned imports, and bindings ResolveTugQL uses. Imports also require ProjectRoot, ImportingPath, and ProjectRevision.
type TugQLResolved ¶
type TugQLResolved struct {
Query dal.StructuredQuery `json:"query"`
Columns []TugQLOutputColumn `json:"columns"`
SchemaVersion string `json:"schemaVersion"`
Dependencies []TugQLDependencyReceipt `json:"dependencies,omitempty"`
Relationships []TugQLRelationshipExpansion `json:"relationships,omitempty"`
}
TugQLResolved is the value returned by ResolveTugQL. Query is the lowered dal.StructuredQuery and Columns describe its projection. SchemaVersion joins the matched schema versions with commas, and Dependencies and Relationships list the imports and joins that were applied.
type TugQLSourceMetadata ¶
TugQLSourceMetadata records the authoring format and version of a TugQLDocument. ResolveTugQL requires format "tugql" and version 1.
type TugQLSpan ¶
type TugQLSpan struct {
Start TugQLPosition `json:"start"`
End TugQLPosition `json:"end"`
}
TugQLSpan is the start and end of a range in TugQL source.
type TugQLTable ¶
type TugQLTable struct {
Name string `json:"name"`
Fields []TugQLField `json:"fields"`
}
TugQLTable is a named table and its fields in an authorized schema.
type TugQLTree ¶
type TugQLTree struct {
Format string `json:"format" yaml:"format"`
Version int `json:"version" yaml:"version"`
Databases []TugQLDatabase `json:"databases,omitempty" yaml:"databases,omitempty"`
Parameters []TugQLParameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
Definitions []TugQLDefinition `json:"definitions,omitempty" yaml:"definitions,omitempty"`
Query map[string]any `json:"query" yaml:"-"`
// Comments holds the author's comments. They are not semantics: resolution,
// authorization and SQL generation never read them.
Comments *TugQLComments `json:"comments,omitempty" yaml:"-"`
}
TugQLTree is a versioned semantic wrapper around the existing TugQL query document. Query maps use the same field names and discriminators as TugQL YAML.
func (TugQLTree) MarshalYAML ¶
MarshalYAML allows standard yaml.Marshal(tree) to emit the canonical versioned TugQTree form while retaining the legacy TugQL query field order.
func (*TugQLTree) UnmarshalYAML ¶
UnmarshalYAML validates the envelope shape but leaves query validation to ResolveTugQL, which also checks a caller-mutated public tree. It also reads the YAML comments into Comments. yaml.Unmarshal passes only the root mapping, so comments attached to the YAML document node (above a blank line at the top, or the document-end comments) are visible only through YAMLToTugQL.
Source Files
¶
- deserialize.go
- doc.go
- equal.go
- join_fields.go
- join_hints.go
- null_operand.go
- operators.go
- query.go
- schema.go
- serialize.go
- shapes.go
- tugql_api.go
- tugql_comments.go
- tugql_databases.go
- tugql_expression.go
- tugql_format.go
- tugql_lex.go
- tugql_parse.go
- tugql_path.go
- tugql_preflight.go
- tugql_print.go
- tugql_resolve.go
- tugql_semantics.go
- walk.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package authorization defines the portable TugQL authorization result wire contract.
|
Package authorization defines the portable TugQL authorization result wire contract. |