Documentation
¶
Overview ¶
Package sqlclass is locksql's first gate: a conservative, dialect-aware lexer and statement classifier. It does not build an AST. It refuses anything it cannot classify with certainty, and it never rewrites SQL.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ForbiddenFunction ¶ added in v0.5.0
ForbiddenFunction reports whether name (folded) is on the list of functions refused at every tier, by exact name (not by prefix).
func RedactLiterals ¶ added in v0.5.0
RedactLiterals returns sql with every string, number and quoted identifier replaced by '<redacted>', for the record of a statement that may carry a secret. Text that does not lex is replaced whole.
Types ¶
type Class ¶
type Class int
Class is the privilege class of a statement. Its order matches the profile tiers: Read < Write < DDL < Admin.
type Dialect ¶
type Dialect int
Dialect selects the lexing and classification rules.
func DialectFor ¶
DialectFor maps a config engine name ("mariadb", "mysql", "postgres", "sqlite") to its dialect.
type Refusal ¶
Refusal is the error Classify and Lex return for a refused statement: a code, a reason and, when known, the offset of the token refused in the text checked (the input without its surrounding blanks). Reason never quotes literal values from the statement.
type Statement ¶
type Statement struct {
Class Class
// Kind is the lower-cased leading keyword ("select", "show", "describe",
// "pragma", "insert", "create", "set", ...). SELECT, WITH, VALUES and
// TABLE reads are "select"; a WITH that modifies data takes the kind of
// its first data-modifying keyword ("delete", ...).
Kind string
// SQL is the statement as it will run: the input without surrounding
// blanks and without one trailing ';'. It is never otherwise rewritten.
SQL string
// Limit is the row count of the top-level LIMIT/FETCH of a READ select,
// or -1 when the statement has none (SHOW, DESCRIBE, PRAGMA, writes...).
Limit int
}
Statement is a classified statement, ready for the policy checks.
func Classify ¶
Classify lexes and classifies one statement. A READ select must end with a top-level LIMIT (or PostgreSQL FETCH FIRST) of at most maxRows rows; a maxRows of 0 or less only requires the LIMIT. Classify does not know the profile tier: FORBIDDEN constructs are refused whatever the tier. The error, if any, is a *Refusal.
type TokKind ¶
type TokKind int
TokKind is the lexical kind of a token.
const ( TokWord TokKind = iota // keyword or unquoted identifier; Text is upper-cased TokNumber // numeric literal (or a MySQL identifier starting with a digit); Text is upper-cased TokString // string literal, E” string or $tag$ body; Text is the raw source with quotes TokQuotedIdent // quoted identifier: "x" (PG, SQLite), `x` (MySQL, SQLite), [x] (SQLite); Text is raw TokPunct // a single punctuation or operator character )
Token kinds.
type Token ¶
type Token struct {
Kind TokKind
Text string
Depth int
// Pos and End are the byte offsets of the token in the lexed text.
Pos, End int
}
Token is one lexical unit. Depth is the parenthesis depth: an opening parenthesis carries the depth it opens, a closing one the depth it returns to, so a top-level token has Depth 0.
func Lex ¶
Lex splits sql into tokens using the quoting rules of the dialect. It refuses (with a *Refusal) comments, variables, assignments, bind parameters, backslashes outside PostgreSQL E” strings, unterminated quotes, unbalanced parentheses and control characters other than blanks (\t \n \v \f \r): SQLite stops reading a statement at a NUL, so what runs could differ from what was classified and approved.