Documentation
¶
Overview ¶
Package sqlcomplete suggests what to type next in a SQL buffer: the columns, tables and join conditions the connection's schema holds, and the dialect's keywords, functions and types. Both UIs ask it — the TUI's editor popup and dbc web's Monaco suggest widget — so the rules for what is offered where exist once, in Go, rather than as a JavaScript copy that would drift from the terminal's.
How a request is answered ¶
buffer + caret ─► the statement under the caret (sqlsplit, the run's splitter)
│
├─► tokens (sqlsplit.Lex for strings/comments/quoted names)
│
├─► scope: FROM/JOIN/UPDATE/INTO refs and their aliases,
│ CTEs with the columns their SELECT lists name
│
└─► context: what the token before the caret asks for
│
┌──────────┬────────┴──────┬────────────┬──────────┐
start tables expression qualified clause …
(SELECT…) (FROM ▮) (WHERE ▮, =▮) (o.▮) (FROM t ▮)
│
candidates ─► filtered by the typed prefix ─► ranked ─► capped
Lexical, not a parse ¶
Like the splitter and the highlighter this is a scanner with a few rules, not a SQL grammar. It knows which keyword precedes the caret and which tables the statement names; it does not know that a subquery's columns are out of scope outside it. Every table the statement names is therefore in scope everywhere in it. Offering a column one subquery too early costs a line in a list; a grammar for four dialects would cost far more and still fail on the half-typed statement a completion request always sees.
Offsets ¶
Every offset in and out is a byte offset into the buffer. dbc web converts to and from the UTF-16 units the browser counts (web/api.go byteOffset), the TUI from its rune positions.
Index ¶
Constants ¶
const MaxItems = 400
MaxItems caps a result. A catalog of thousands of columns answered in full would be a long list nobody scrolls and a large response per keystroke; the first few hundred, best first, are the useful ones, and Incomplete tells the client to ask again as the prefix narrows it.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Edit ¶ added in v0.7.0
Edit replaces [From, To) of the buffer with Text.
func Rename ¶ added in v0.7.0
Rename is the edits that rename the symbol under caret to name, quoted as driver's dialect needs (a capital on Postgres, a reserved word, a space). A name the user quoted already is used as written. The error is a sentence for the user: nothing renamable is under the caret, the symbol is a table, or the name is taken in the same query.
type Item ¶
type Item struct {
Label string `json:"label"` // what the list shows
Kind Kind `json:"kind"` // see Kind
Detail string `json:"detail,omitempty"` // one line beside the label: a type, a signature
Doc string `json:"doc,omitempty"` // longer text: a table's DDL, a function's description
Insert string `json:"insert"` // what replaces [From, To) when picked
// Filter is the text the typed prefix is matched against when it is
// not the label — a column offered qualified ("o.id") still matches
// "id". Empty means the label.
Filter string `json:"filter,omitempty"`
// Cursor is where the caret lands inside Insert after the pick, as a
// byte offset into Insert; -1 means after it. A function lands
// between its parentheses.
Cursor int `json:"cursor"`
Sort string `json:"sort"` // ascending sort key; the order Items is already in
}
Item is one suggestion.
type Kind ¶
type Kind string
Kind classifies a suggestion, for its icon and its place in the order.
const ( KindColumn Kind = "column" KindTable Kind = "table" KindView Kind = "view" KindSchema Kind = "schema" KindAlias Kind = "alias" // a table reference's alias, or a CTE KindJoin Kind = "join" // a whole join clause or ON condition from a foreign key KindKeyword Kind = "keyword" KindFunction Kind = "function" KindType Kind = "type" )
type Request ¶
type Request struct {
// Schema is the connection's tables, columns and keys (the ERD's
// reading of the catalog); nil offers only the dialect's vocabulary.
Schema *erd.Schema
// Driver is the connection's driver as configured (postgres, pg,
// mysql, sqlite, bytdb …), for the dialect's vocabulary and quoting.
Driver string
// Focus is the schema the user is browsing (the sidebar's), whose
// tables are ranked first; "" when there is none.
Focus string
// SearchPath is the schemas a bare table name resolves through, in
// order (Postgres's current_schemas); nil means the dialect's default
// (public on Postgres and bytdb). A table in one of them is inserted
// bare unless a schema earlier on the path has a table of that name.
SearchPath []string
// Buffer is the whole editor text and Caret a byte offset into it.
Buffer string
Caret int
}
Request is one completion request.
type Result ¶
type Result struct {
From, To int // the byte range a picked item replaces: the word being typed
Prefix string // buffer[From:To], what was matched against
Items []Item
// Incomplete reports that Items was cut at MaxItems: a longer prefix
// may surface items not listed now, so a client should ask again as
// the prefix grows rather than filter this list itself.
Incomplete bool
}
Result is the answer to a request.
type Span ¶ added in v0.7.0
Span is a byte range of the buffer, a token's: a quoted name's quotes included.
type Symbol ¶ added in v0.7.0
type Symbol struct {
Kind SymbolKind `json:"kind"`
Name string `json:"name"` // as declared, without quotes
At Span `json:"at"` // the occurrence under the caret
Def Span `json:"def"` // where it is declared
Uses []Span `json:"uses"` // every occurrence, Def included, in buffer order
// Fixed says why the name cannot be renamed here; "" when it can.
Fixed string `json:"fixed,omitempty"`
}
Symbol is the answer to Resolve. A zero Kind means the caret is on nothing the resolver knows: a column, a keyword, blank space.
type SymbolKind ¶ added in v0.7.0
type SymbolKind string
SymbolKind is what a resolved name is.
const ( SymAlias SymbolKind = "alias" // a table reference's alias SymCTE SymbolKind = "cte" // a WITH query's name SymTable SymbolKind = "table" // a table referenced without an alias )