Documentation
¶
Overview ¶
Package source defines the data-source abstraction. A Connector represents one external system (registered under a SQL schema name, e.g. "github") and exposes one or more tables. Each table is loaded into the per-request SQLite database; the engine pushes as much of the query as it safely can into the connector's Scan so the source returns less data.
Index ¶
- Variables
- func EnvFirst(vars ...string) func() string
- func IntParam(v any) (int, bool)
- func StringList(params map[string]any, key string) []string
- type Column
- type Connector
- type Credential
- type CredentialFunc
- type Factory
- type Filter
- type ListOptions
- type Operator
- type OrderTerm
- type Registry
- type Rows
- type ScanRequest
- type SchemaDescriber
- type TableLister
- type TableSchema
Constants ¶
This section is empty.
Variables ¶
var ErrNotImplemented = errors.New("not implemented")
ErrNotImplemented is returned by connectors that are not yet wired up.
Functions ¶
func EnvFirst ¶
EnvFirst returns a closure over the environment that yields the first non-empty variable among vars, or "" when none is set. It is the env source for the common bare-value case; connectors that shape the value (a "Bearer " prefix, a Basic pair) write their own closure.
func IntParam ¶
IntParam coerces a YAML/JSON numeric param to int (YAML may decode as int, int64, or float64). The second result is false when the value is absent or not numeric.
func StringList ¶
StringList reads params[key] as a list of strings, tolerating the shapes YAML produces: a []string, a []any of strings, or a single string. It returns nil when the key is absent or not string-like. Dynamic connectors use it for the scoping convention (e.g. params["schemas"], params["tables"]).
Types ¶
type Column ¶
type Column struct {
// Name is the column name as it appears in the SQLite table.
Name string
// Type is the SQLite type affinity (e.g. "TEXT", "INTEGER", "REAL").
Type string
}
Column describes a single column of a connector table.
type Connector ¶
type Connector interface {
// Tables returns the schemas of every table this connector serves. A dynamic
// connector may return an empty slice and rely on SchemaDescriber instead.
Tables() []TableSchema
// Scan fetches rows for one table, pushing down what it can from req. It
// calls emit once per chunk (e.g. per API page) so the engine can load each
// chunk as it arrives instead of buffering the whole result; emit returns an
// error to abort the scan early, which Scan should propagate.
Scan(ctx context.Context, req ScanRequest, emit func(*Rows) error) error
}
Connector exposes the tables of one external system.
A connector with a small, fixed set of tables returns them all from Tables(). A dynamic source (a SQL warehouse with thousands of tables) instead returns an empty or curated Tables() and implements the optional SchemaDescriber and TableLister interfaces below, so the engine resolves only the referenced tables per query and discovery stays lazy.
type Credential ¶
type Credential struct {
// contains filtered or unexported fields
}
Credential resolves one connector secret lazily, once, race-safely, from up to four sources with fixed precedence:
- a static param value (params["<staticKey>"], e.g. postgres's "dsn"),
- the environment (via the env closure — read at first Get, not at construction),
- a caller-supplied Go function (params["<name>_func"]),
- an executed command (params["<name>_command"] — an argv list run directly without a shell, 5s timeout, stdout's trailing CR/LF trimmed).
Connectors are built eagerly for every query (engine.New), so resolution is deferred to first use to avoid shelling out (or calling a func) on queries that never touch the connector. A mutex serializes resolution — the engine scans a connector's tables concurrently, so the func/command runs at most once at a time and a successful value is written before any other goroutine reads it. Success is cached for the connector's lifetime; a failure is returned to that caller but NOT cached, so the next Get retries — a canceled first query or a transient secrets-manager hiccup doesn't poison a long-lived process. The resolving caller's ctx governs the func call / command timeout.
An empty value with a nil error means nothing is configured (or the env var is unset); each connector decides whether that is an error or an unauthenticated request. A configured func or command that yields an empty value is an error, not an empty credential — silently proceeding unauthenticated would mask a broken secrets source — and like any failure it is retried on the next Get rather than cached.
func NewCredential ¶
func NewCredential(connector, name string, params map[string]any, staticKey string, env func() string) (*Credential, error)
NewCredential builds a Credential for the param base name: it reads params[name+"_func"] (which must be a source.CredentialFunc) and params[name+"_command"] (an argv list of strings). staticKey, when non-empty, names a plain string param holding the value directly (e.g. "dsn"). env, when non-nil, reads the environment at resolve time; use EnvFirst for the common first-non-empty-var case. connector prefixes parse errors (e.g. "github: token_command must be a list of strings").
func (*Credential) Get ¶
func (c *Credential) Get(ctx context.Context) (string, error)
Get resolves the credential on first successful call and returns the cached value on every later call. A failed resolution is returned without being cached, so a later Get retries. See the Credential doc for precedence and concurrency semantics.
type CredentialFunc ¶
CredentialFunc lazily supplies a credential value — a token, a header value, or a DSN. Passed through params (e.g. params["token_func"]) by programs that build their config in Go; YAML config cannot express it. It is an alias, so a bare func literal in a params map satisfies it without conversion.
type Filter ¶
Filter is a structured WHERE conjunct the engine offers for push-down. Value holds the typed literal for single-value operators (string/int64/float64/ bool/[]byte/nil); Values holds the list for IN / the [low, high] pair for BETWEEN. Bind parameters are not pushed down.
type ListOptions ¶
type ListOptions struct {
// Filter is a case-insensitive substring matched against the table name;
// empty matches all.
Filter string
// Limit caps the number of names returned; 0 means no limit.
Limit int
}
ListOptions filters a TableLister.ListTables call.
type Operator ¶
type Operator int
Operator is a comparison operator in a structured predicate. It is an enum so downstream consumers (e.g. a push-down planner) handle the full closed set via an exhaustive switch rather than matching operator strings. The zero value, OpNone, means the predicate is not a structured comparison (only Raw applies).
const ( OpNone Operator = iota // not a structured comparison OpEq // = OpNotEq // <> OpLt // < OpLte // <= OpGt // > OpGte // >= OpLike // LIKE OpNotLike // NOT LIKE OpGlob // GLOB OpNotGlob // NOT GLOB OpRegexp // REGEXP OpNotRegexp // NOT REGEXP OpMatch // MATCH OpNotMatch // NOT MATCH OpIs // IS OpIsNot // IS NOT OpIsDistinctFrom // IS DISTINCT FROM OpIsNotDistinctFrom // IS NOT DISTINCT FROM OpIsNull // IS NULL OpIsNotNull // IS NOT NULL OpBetween // BETWEEN (Values = [low, high]) OpNotBetween // NOT BETWEEN (Values = [low, high]) OpIn // IN (Values = list) OpNotIn // NOT IN (Values = list) )
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry maps connector type names to their factories.
func (*Registry) Merge ¶
Merge copies every factory from other into r, overwriting r's entry when both registries define the same type name. Unlike Register it never panics: merging is deliberate composition (e.g. layering a custom registry over the default set), so the later registry wins. A nil other is a no-op.
type Rows ¶
type Rows struct {
Columns []string
Rows [][]any
// Warnings carries non-fatal notices about this result, e.g. that the
// connector truncated at a cap or applied a narrowing default, so the result
// may be incomplete. The engine collects these across all emitted chunks and
// surfaces them to the user. A chunk may carry only Warnings (no rows).
Warnings []string
}
Rows is the result of a Scan: column names plus rows whose values are ordered to match Columns.
type ScanRequest ¶
type ScanRequest struct {
Table string
Columns []string // requested columns; empty means all
Filters []Filter
OrderBy []OrderTerm
Limit *int
Offset *int
}
ScanRequest carries the pushed-down portion of a query for one table. A connector may honor as little or as much as it can; the engine re-applies the full query in SQLite, so returning a superset is always correct.
type SchemaDescriber ¶
type SchemaDescriber interface {
DescribeTable(ctx context.Context, table string) (ts TableSchema, found bool, err error)
}
SchemaDescriber is an optional capability: a connector that resolves one table's columns on demand rather than enumerating every table up front. The engine prefers DescribeTable over the Tables() lookup when a connector implements it, so a dynamic source only introspects the referenced tables. found is false (with a nil error) when the table does not exist.
type TableLister ¶
type TableLister interface {
ListTables(ctx context.Context, opts ListOptions) ([]string, error)
}
TableLister is an optional capability for discovery: it lists table names (without columns) so `dfetch tables <schema>` can browse a large catalog without loading every column. A connector that implements it need not return those tables from Tables().
type TableSchema ¶
TableSchema describes one table a connector serves.
func (TableSchema) ColumnNames ¶
func (t TableSchema) ColumnNames() []string
ColumnNames returns the schema's column names in order.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ckan is a dfetch Connector backed by a CKAN portal's Action API (https://docs.ckan.org/en/latest/api/).
|
Package ckan is a dfetch Connector backed by a CKAN portal's Action API (https://docs.ckan.org/en/latest/api/). |
|
Package docker is a dfetch Connector backed by the Docker Engine API.
|
Package docker is a dfetch Connector backed by the Docker Engine API. |
|
Package git is a dfetch Connector that serves a local git repository as tables — commit history, branches, tags, working-tree status, and tracked files — so repo questions become SQL (and join against github/jira sources) instead of `git log --format | awk` pipelines.
|
Package git is a dfetch Connector that serves a local git repository as tables — commit history, branches, tags, working-tree status, and tracked files — so repo questions become SQL (and join against github/jira sources) instead of `git log --format | awk` pipelines. |
|
Package github is a dfetch Connector backed by the GitHub REST API.
|
Package github is a dfetch Connector backed by the GitHub REST API. |
|
Package jaeger is a dfetch Connector backed by Jaeger's api_v3 query service.
|
Package jaeger is a dfetch Connector backed by Jaeger's api_v3 query service. |
|
Package jira is a dfetch Connector backed by the Jira Cloud REST API (https://developer.atlassian.com/cloud/jira/platform/rest/v3/).
|
Package jira is a dfetch Connector backed by the Jira Cloud REST API (https://developer.atlassian.com/cloud/jira/platform/rest/v3/). |
|
Package newrelic is a dfetch Connector backed by New Relic's NerdGraph GraphQL API (https://docs.newrelic.com/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph/).
|
Package newrelic is a dfetch Connector backed by New Relic's NerdGraph GraphQL API (https://docs.newrelic.com/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph/). |
|
Package postgres is a dfetch Connector backed by a PostgreSQL database over database/sql (jackc/pgx).
|
Package postgres is a dfetch Connector backed by a PostgreSQL database over database/sql (jackc/pgx). |
|
Package slack is a dfetch Connector backed by the Slack Web API.
|
Package slack is a dfetch Connector backed by the Slack Web API. |