Documentation
¶
Overview ¶
Package lens classifies SQL statements and counts their output columns, fully offline, for BigQuery (GoogleSQL), Snowflake, and Databricks (Spark SQL).
The behavior contract is pinned by the test suite and the oracle-verified corpora under testdata/ (see docs/regenerate-ground-truth.md).
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Bucket ¶
type Bucket int
Bucket is the coarse routing category of a statement.
const ( ReadOnly Bucket = iota + 1 // SELECT and friends: WITH…SELECT, (SELECT), pipe FROM, VALUES DML // INSERT, UPDATE, DELETE, MERGE (TRUNCATE per dialect) DDL // CREATE / ALTER / DROP / UNDROP … DCL // GRANT, REVOKE Script // ≥2 statements or a procedural-only construct Transaction // BEGIN/START TRANSACTION, COMMIT, ROLLBACK DataMovement // COPY INTO, LOAD DATA, EXPORT …, PUT/GET/LIST/REMOVE Auxiliary // SHOW, DESCRIBE, EXPLAIN, USE, SET, CALL, ASSERT, OPTIMIZE, VACUUM … )
type Classification ¶
Classification is the tier-1 result: what the statement is.
func (Classification) Header ¶
func (c Classification) Header() Classification
Header returns the classification itself, satisfying Result.
type Kind ¶
type Kind string
Kind is sql-lens's own fine-grained, dialect-neutral statement vocabulary (no vendor publishes a complete one). DDL kinds compose as VERB_OBJECT (e.g. "CREATE_TABLE", "ALTER_MATERIALIZED_VIEW"), so the set is open; the constants below name the fixed, non-composed kinds.
const ( KindSelect Kind = "SELECT" KindValues Kind = "VALUES" KindGraphQuery Kind = "GRAPH_QUERY" KindInsert Kind = "INSERT" KindUpdate Kind = "UPDATE" KindDelete Kind = "DELETE" KindMerge Kind = "MERGE" KindTruncateTable Kind = "TRUNCATE_TABLE" KindGrant Kind = "GRANT" KindRevoke Kind = "REVOKE" KindScript Kind = "SCRIPT" KindBeginTransaction Kind = "BEGIN_TRANSACTION" KindCommit Kind = "COMMIT" KindRollback Kind = "ROLLBACK" KindCall Kind = "CALL" KindExecuteImmediate Kind = "EXECUTE_IMMEDIATE" KindAssert Kind = "ASSERT" KindShow Kind = "SHOW" KindDescribe Kind = "DESCRIBE" KindExplain Kind = "EXPLAIN" KindUse Kind = "USE" KindSet Kind = "SET" KindUnset Kind = "UNSET" KindCopyInto Kind = "COPY_INTO" KindLoadData Kind = "LOAD_DATA" KindExportData Kind = "EXPORT_DATA" KindExportModel Kind = "EXPORT_MODEL" KindPut Kind = "PUT" KindGet Kind = "GET" KindList Kind = "LIST" KindRemove Kind = "REMOVE" KindOptimize Kind = "OPTIMIZE" KindVacuum Kind = "VACUUM" KindAnalyzeTable Kind = "ANALYZE_TABLE" KindMsckRepair Kind = "MSCK_REPAIR" KindCache Kind = "CACHE" KindUncache Kind = "UNCACHE" KindRefresh Kind = "REFRESH" KindDeclareVariable Kind = "DECLARE_VARIABLE" KindExecuteTask Kind = "EXECUTE_TASK" )
type Lens ¶
type Lens struct {
// contains filtered or unexported fields
}
Lens analyzes SQL for one dialect. Zero-value is invalid; use New.
func (*Lens) Analyze ¶
Analyze classifies the statement and, for ReadOnly statements, counts its output columns.
Example ¶
package main
import (
"fmt"
lens "github.com/akshaysangma/sql-lens"
)
func main() {
l, _ := lens.New(lens.BigQuery)
r, _ := l.Analyze("WITH t AS (SELECT 1 AS a, 2 AS b) SELECT * FROM t")
q := r.(*lens.QueryResult)
fmt.Println(q.Bucket, q.Kind, q.ColumnCount)
}
Output: ReadOnly SELECT 2
Example (ResultShapes) ¶
Result is a sealed sum type: a type switch over the three shapes is exhaustive.
package main
import (
"fmt"
lens "github.com/akshaysangma/sql-lens"
)
func main() {
l, _ := lens.New(lens.Databricks)
for _, sql := range []string{
"SELECT a, b FROM t",
"BEGIN SELECT 1; SELECT 2; END",
"OPTIMIZE events ZORDER BY (ts)",
} {
r, _ := l.Analyze(sql)
switch v := r.(type) {
case *lens.QueryResult:
fmt.Println("query with", v.ColumnCount, "columns")
case *lens.ScriptResult:
fmt.Println("script")
case *lens.StatementResult:
fmt.Println(v.Bucket, v.Kind)
}
}
}
Output: query with 2 columns script Auxiliary OPTIMIZE
Example (SchemaDependent) ¶
A star over a base table is schema-dependent: the count is -1, never a guess.
package main
import (
"fmt"
lens "github.com/akshaysangma/sql-lens"
)
func main() {
l, _ := lens.New(lens.Snowflake)
r, _ := l.Analyze("SELECT * FROM prod.sales.orders")
fmt.Println(r.(*lens.QueryResult).ColumnCount)
}
Output: -1
func (*Lens) Classify ¶
func (l *Lens) Classify(sql string) (Classification, error)
Classify returns the statement's classification without counting columns.
Example ¶
package main
import (
"fmt"
lens "github.com/akshaysangma/sql-lens"
)
func main() {
l, _ := lens.New(lens.BigQuery)
c, _ := l.Classify("MERGE t USING s ON t.id = s.id WHEN MATCHED THEN DELETE")
fmt.Println(c.Bucket, c.Kind)
}
Output: DML MERGE
type ParseError ¶
ParseError is the only error kind Analyze and Classify return for bad or unrecognized SQL.
Example ¶
Statements that don't exist in the selected dialect are rejected with a typed *ParseError.
package main
import (
"fmt"
lens "github.com/akshaysangma/sql-lens"
)
func main() {
l, _ := lens.New(lens.BigQuery)
_, err := l.Analyze("SHOW TABLES") // SHOW is not BigQuery syntax
fmt.Println(err)
}
Output: sql-lens (bigquery): unrecognized statement "SHOW"
func (*ParseError) Error ¶
func (e *ParseError) Error() string
type QueryResult ¶
type QueryResult struct {
Classification
ColumnCount int
}
QueryResult is the Analyze result for ReadOnly statements. ColumnCount is exact when the select list is resolvable from the SQL text alone (including stars over same-query CTEs); -1 when a star makes it schema-dependent.
type Result ¶
type Result interface {
Header() Classification
// contains filtered or unexported methods
}
Result is the sealed outcome of Analyze. Exactly three shapes exist: *QueryResult (ReadOnly — carries ColumnCount), *ScriptResult, and *StatementResult (everything else). A type switch over these is exhaustive.
type ScriptResult ¶
type ScriptResult struct {
Classification
}
ScriptResult is the Analyze result for scripts. It never carries column info — scripts are detected and flagged only.
type StatementResult ¶
type StatementResult struct {
Classification
}
StatementResult is the Analyze result for every non-ReadOnly, non-Script statement (DML, DDL, DCL, Transaction, DataMovement, Auxiliary).