Documentation
¶
Overview ¶
Package engine defines the database engine interface the console drives, and the engine-independent types it returns: catalog descriptions, result sets and normalised query plans.
A Session is owned by the console. It never receives SQL from an agent without the classifier having seen it first, and its catalog methods only run SQL built by the engine itself.
Index ¶
- Constants
- Variables
- func CapBytes(b []byte) (out []byte, cut bool)
- func CapText(b []byte) (s string, cut bool)
- func ClientCertificate(certFile, keyFile string) (tls.Certificate, error)
- func CutAt(s string, n int) string
- func Names() []string
- func ProbeDial(ctx context.Context, p config.Profile, def int) (net.Conn, error)
- func ProbeHandshake(nc net.Conn, p config.Profile) ([]*x509.Certificate, error)
- func Register(name string, e Engine)
- func TLSConfig(p config.Profile) (*tls.Config, error)
- func TLSVerifyHint(err error, mode string) string
- type ColumnDesc
- type ColumnInfo
- type DialFunc
- type Engine
- type Flavor
- type IndexDesc
- type Noticer
- type Plan
- type PlanNode
- type Result
- type ResultColumn
- type Session
- type TLSProber
- type TableInfo
- type Transport
Constants ¶
const ( AccessFull = "full" // full table scan AccessIndex = "index" // full scan of an index AccessRange = "range" // index or key range AccessLookup = "lookup" // equality lookup on a key or index AccessUnknown = "unknown" // the engine did not say )
Access methods of a PlanNode.
const CutMark = "…"
CutMark ends a text value that was cut.
const MaxCellBytes = 64 << 10
MaxCellBytes is the most an engine keeps of one cell value. The engines apply it while reading, before a value is copied or converted (PostgreSQL on the wire, see the postgres capReader), so that a value of hundreds of megabytes built by the server (a numeric power, jsonb_pretty) never costs the console more. It equals the scan limit of the PII detectors: what is kept is what they read, and the renderer shows far less (max_cell_chars).
Variables ¶
var ErrConnLost = errors.New("connection lost")
ErrConnLost reports that the database connection is gone. The console reconnects (asking for the secret again if needed) instead of retrying.
var ErrNoServerTLS = errors.New("the server does not offer TLS")
ErrNoServerTLS reports a server that does not offer TLS.
Functions ¶
func CapText ¶ added in v0.5.0
CapText is the text of a value: b as is when it fits MaxCellBytes, else cut to at most MaxCellBytes bytes, CutMark included, and cut true. It copies no more of b than it keeps.
func ClientCertificate ¶ added in v0.5.0
func ClientCertificate(certFile, keyFile string) (tls.Certificate, error)
ClientCertificate loads the client certificate of tls_cert and its key from tls_key. The key must be readable by its owner only, as an ssh key. Errors name the files, never their content.
func CutAt ¶ added in v0.5.0
CutAt cuts s, which must be longer than n bytes, to at most n bytes followed by CutMark: at a rune boundary, then back over up to cutTail value-like characters, so that a value the cut splits (a partial e-mail address or number, which no detector would recognise) is dropped rather than shown in part.
func ProbeDial ¶ added in v0.5.0
ProbeDial opens the TCP connection of a probe to the profile's host and port (def when the profile has none), bounded by ctx.
func ProbeHandshake ¶ added in v0.5.0
ProbeHandshake makes the TLS client handshake of a probe on nc and returns the server's certificates. A server that then refuses the handshake for want of a client certificate has already shown its own: they are returned with the error.
func Register ¶
Register makes an engine available under a config engine name. Engine packages call it from init; it panics on a duplicate or empty name.
func TLSConfig ¶ added in v0.5.0
TLSConfig builds the client TLS configuration of a network profile's tls mode, as libpq's sslmode: nil for disable and for a Unix socket; prefer and require encrypt without verifying, except require with tls_ca, which is verify-ca as in libpq; verify-ca checks the chain against tls_ca (or the system roots); verify-full checks the chain and that the certificate names host (or tls_server_name). "" is prefer, the mode of policies approved before the setting existed. tls_cert and tls_key, when set, are the client certificate presented to a server that asks for one.
func TLSVerifyHint ¶ added in v0.5.0
TLSVerifyHint is the way out of a connection refused because the server's certificate did not verify, as a private or self-signed one does since verify-full became the default of a remote host; "" for any other error.
Types ¶
type ColumnDesc ¶
type ColumnDesc struct {
Name string `json:"name"`
Type string `json:"type"`
Nullable bool `json:"nullable"`
PrimaryKey bool `json:"primary_key,omitempty"`
// Default is the column default as the catalog spells it, nil when none.
Default *string `json:"default,omitempty"`
}
ColumnDesc describes one column for catalog.describe.
type ColumnInfo ¶
type ColumnInfo struct {
DB string `json:"db"`
Table string `json:"table"`
Column string `json:"column"`
Type string `json:"type"`
// View is set for a column of a view (or a materialized view or a
// foreign table): its base columns are unknown.
View bool `json:"view,omitempty"`
}
ColumnInfo is one column of a table, as used for PII detection.
type DialFunc ¶ added in v0.5.0
DialFunc opens the network connection to the database server. nil is a direct TCP or Unix socket connection.
type Engine ¶
type Engine interface {
Connect(ctx context.Context, p config.Profile, secret []byte, dial DialFunc) (Session, error)
}
Engine opens sessions for one engine name. secret is the password, or nil when the engine needs none; it is never stored past Connect. dial, when not nil, opens every network connection of the session (main, control and cancel connections).
type IndexDesc ¶
type IndexDesc struct {
Name string `json:"name"`
Columns []string `json:"columns"`
Unique bool `json:"unique,omitempty"`
Primary bool `json:"primary,omitempty"`
}
IndexDesc describes one index for catalog.describe.
type Noticer ¶
type Noticer interface {
Notices() []string
}
Noticer is implemented by sessions with something the human must know about the connection itself, such as a fallback to no encryption. The console prints and audits each notice after connecting.
type Plan ¶
type Plan struct {
Root PlanNode `json:"root"`
// Cost is the engine's total cost estimate for the statement, in its
// own units (PostgreSQL Total Cost, MySQL query_cost, MariaDB cost), or
// -1 when the engine gives none.
Cost float64 `json:"cost"`
Raw json.RawMessage `json:"raw"`
}
Plan is a normalised plan plus the engine's raw plan, kept for the audit log and for debugging.
type PlanNode ¶
type PlanNode struct {
Table string `json:"table,omitempty"`
// Access is one of the Access* constants for a table node, "" for a group.
Access string `json:"access,omitempty"`
// EstRows is the engine's estimate of rows examined per execution of the
// node, or -1 when the engine has none.
EstRows int64 `json:"est_rows"`
// Sort and Temp report a sort or a temporary table. On a group they apply
// to the output of the group's pipeline.
Sort bool `json:"sort,omitempty"`
Temp bool `json:"temp,omitempty"`
Correlated bool `json:"correlated,omitempty"`
// NoJoinCond marks a table joined without a usable join condition, so
// that every outer row reads all of it.
NoJoinCond bool `json:"no_join_cond,omitempty"`
// Recursive marks the group of a recursive CTE: how many times it
// iterates is unknown to the planner, so its row estimate is a guess.
Recursive bool `json:"recursive,omitempty"`
// Detail is the engine's own label for the node, for display only.
Detail string `json:"detail,omitempty"`
Children []PlanNode `json:"children,omitempty"`
}
PlanNode is one node of a normalised plan.
A node with a Table is a table access. A node without one is a group: the plan root, a subquery, a derived table, a compound arm and so on, with Detail naming it. The table children of a group form, in order, one nested-loop pipeline: the rows examined are the product of their EstRows. The group children are subqueries and materialisations: their cost adds to the group, multiplied by the outer rows when Correlated.
type Result ¶
type Result struct {
Columns []ResultColumn `json:"columns"`
Rows [][]any `json:"rows"`
// Truncated is set when the statement produced more than maxRows rows.
Truncated bool `json:"truncated"`
// Affected is the number of rows changed by a write-class statement.
Affected int64 `json:"affected"`
// CutCells lists the cells, as [row, column] indexes of Rows, whose
// value was longer than MaxCellBytes and was cut while it was read.
CutCells [][2]int `json:"cut_cells,omitempty"`
}
Result is the outcome of Run. Rows hold driver values (nil, int64, float64, string, []byte, time.Time, ...); rendering and masking happen later, in the console.
func (*Result) CutSet ¶ added in v0.5.0
CutSet is CutCells as a set, for lookups over a whole result.
type ResultColumn ¶
type ResultColumn struct {
Label string `json:"label"`
OriginDB string `json:"origin_db,omitempty"`
OriginTable string `json:"origin_table,omitempty"`
OriginColumn string `json:"origin_column,omitempty"`
}
ResultColumn is one result column: its label, and the base column it comes from when the engine reports it. The origin fields are all empty when the origin is unknown or not trustworthy.
func (ResultColumn) HasOrigin ¶
func (c ResultColumn) HasOrigin() bool
HasOrigin reports whether the column carries an origin.
type Session ¶
type Session interface {
ServerVersion() string
Flavor() Flavor
// OriginColumns reports whether Run fills in result column origins.
OriginColumns() bool
// ExtraPrivileges lists the warnings about what the connection could do
// beyond the profile tier.
ExtraPrivileges(ctx context.Context, tier config.Tier) ([]string, error)
Databases(ctx context.Context) ([]string, error)
Tables(ctx context.Context, db string) ([]string, error)
Describe(ctx context.Context, db, table string) (TableInfo, error)
Columns(ctx context.Context, db string) ([]ColumnInfo, error)
Explain(ctx context.Context, db, sql string) (Plan, error)
// Run executes one classified statement. Write classes run in a
// transaction and report Affected. Rows are capped at maxRows (no cap
// when maxRows <= 0) and Truncated says whether more were available.
Run(ctx context.Context, db string, st sqlclass.Statement, maxRows int) (Result, error)
Ping(ctx context.Context) error
Close() error
}
Session is one open connection with its policy-relevant settings applied (read-only mode for tier read, timeouts).
type TLSProber ¶ added in v0.5.0
type TLSProber interface {
ProbeTLS(ctx context.Context, p config.Profile) ([]*x509.Certificate, error)
}
TLSProber is implemented by the engines whose protocol starts TLS before authentication. ProbeTLS connects to the profile's server directly (not through an ssh tunnel), starts TLS as the engine does and returns the certificates the server presents, leaf first, verifying nothing. It sends no user name and no secret, and presents no client certificate: locksql doctor uses it from an account that holds none.
type TableInfo ¶
type TableInfo struct {
DB string `json:"db"`
Table string `json:"table"`
Columns []ColumnDesc `json:"columns"`
Indexes []IndexDesc `json:"indexes,omitempty"`
// EstRows is the engine's row estimate, or -1 when it has none.
EstRows int64 `json:"est_rows"`
}
TableInfo is the catalog description of one table or view.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package mysql is the MariaDB and MySQL engine, on the go-mysql-org client (chosen because it reports each result column's origin schema, table and column).
|
Package mysql is the MariaDB and MySQL engine, on the go-mysql-org client (chosen because it reports each result column's origin schema, table and column). |
|
Package postgres is the PostgreSQL engine, on pgx v5.
|
Package postgres is the PostgreSQL engine, on pgx v5. |
|
Package sqlite is the SQLite engine, on the pure-Go modernc.org/sqlite driver.
|
Package sqlite is the SQLite engine, on the pure-Go modernc.org/sqlite driver. |