GoSQLX API Reference
GoSQLX is split into small packages with a one-way dependency chain. Most programs only need the high-level gosqlx package; the lower-level packages are there when you need control over pooling, tokens or individual AST nodes.
Each package has its own reference page. Signatures on pkg.go.dev are generated from the source and are authoritative when the two disagree.
New to GoSQLX? Start with Getting Started, then pick a task guide such as Parse PostgreSQL in Go or Extract table names from SQL in Go.
Packages
| Package | Import path | Use it for |
|---|---|---|
| gosqlx | pkg/gosqlx | Parsing, validation, formatting, linting and metadata extraction with pooling handled for you |
| tokenizer | pkg/sql/tokenizer | Zero-copy lexing of SQL bytes into tokens |
| parser | pkg/sql/parser | Building an AST from tokens |
| ast | pkg/sql/ast | Statement and expression node types, pools and visitors |
| keywords | pkg/sql/keywords | Keyword tables and dialect identifiers |
| models | pkg/models | Tokens, spans and source locations |
| errors | pkg/errors | Structured errors with codes, positions and hints |
| metrics | pkg/metrics | Production counters and timings |
| security | pkg/sql/security | SQL injection pattern detection |
| linter | pkg/linter | The lint engine and its rules |
| lsp | pkg/lsp | The Language Server Protocol server |
| mcp | pkg/mcp | The Model Context Protocol server |
| config | pkg/config | Configuration loading for the CLI, LSP and library |
All import paths are relative to github.com/ajitpratap0/GoSQLX/.
High-Level API
Moved to the gosqlx package reference.
Tokenizer API
Moved to the tokenizer package reference.
Parser API
Moved to the parser package reference.
AST API
Moved to the ast package reference.
Keywords Package
Moved to the keywords package reference.
Models
Moved to the models package reference.
Error Handling
Moved to the errors package reference. Every error code is listed in Error Codes.
Metrics Package
Moved to the metrics package reference.
Security Package
Moved to the security package reference.
Linter Package
Moved to the linter package reference. Every rule is listed in Linting Rules.
LSP Package
Moved to the lsp package reference.
MCP Package
Moved to the mcp package reference.
Configuration Package
Moved to the config package reference.
Performance Considerations
Object Pooling
Always use defer with pool return functions:
// Tokenizer
tkz := tokenizer.GetTokenizer()
defer tokenizer.PutTokenizer(tkz)
// Parser
p := parser.NewParser()
defer p.Release()
// AST
astObj := ast.NewAST()
defer ast.ReleaseAST(astObj)
// Statements
stmt := ast.NewSelectStatement()
defer ast.ReleaseSelectStatement(stmt)
Batch Processing
Use batch functions for multiple queries:
// Reuses pooled objects across the batch
asts, err := gosqlx.ParseMultiple(queries)
// More efficient validation
err := gosqlx.ValidateMultiple(queries)
Context and Timeouts
Use context for long-running operations:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
astNode, err := gosqlx.ParseWithContext(ctx, complexSQL)
For measured throughput and latency, see the benchmarks page, which labels every number with its stage, hardware and Go version.
Complete Example
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/ajitpratap0/GoSQLX/pkg/gosqlx"
"github.com/ajitpratap0/GoSQLX/pkg/sql/ast"
"github.com/ajitpratap0/GoSQLX/pkg/sql/security"
"github.com/ajitpratap0/GoSQLX/pkg/linter"
"github.com/ajitpratap0/GoSQLX/pkg/linter/rules"
"github.com/ajitpratap0/GoSQLX/pkg/metrics"
"github.com/ajitpratap0/GoSQLX/pkg/config"
)
func main() {
// Load configuration
cfg, _ := config.Load(".gosqlx.yml")
// Enable metrics
metrics.Enable()
defer func() {
snapshot := metrics.GetSnapshot()
fmt.Printf("Processed %d queries with %.2f%% success rate\n",
snapshot.TotalQueries, snapshot.SuccessRate)
}()
sql := `
-- PostgreSQL v1.6.0 features demonstration
WITH RECURSIVE active_users AS (
SELECT id, name, manager_id, 1 as level
FROM employees
WHERE active = true AND manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, au.level + 1
FROM employees e
INNER JOIN active_users au ON e.manager_id = au.id
WHERE au.level < 10
)
SELECT DISTINCT ON (dept_id)
u.id,
u.name,
COUNT(o.id) FILTER (WHERE o.status = 'completed') as completed_orders,
STRING_AGG(o.product, ', ' ORDER BY o.date DESC NULLS LAST) as recent_products,
ROW_NUMBER() OVER (PARTITION BY u.dept_id ORDER BY COUNT(o.id) DESC) as dept_rank,
u.metadata->>'email' as email,
u.metadata->'address'->>'city' as city
FROM active_users u
LEFT JOIN LATERAL (
SELECT * FROM orders
WHERE user_id = u.id
ORDER BY order_date DESC
LIMIT 5
) o ON true
WHERE u.created_at >= '2024-01-01'
GROUP BY u.id, u.name, u.dept_id, u.metadata
HAVING COUNT(o.id) > 5
ORDER BY dept_id, completed_orders DESC NULLS LAST
FETCH FIRST 10 ROWS WITH TIES
RETURNING u.id, u.name, completed_orders
`
// Parse SQL with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
astNode, err := gosqlx.ParseWithContext(ctx, sql)
if err != nil {
log.Fatal("Parse error:", err)
}
defer ast.ReleaseAST(astNode)
// Security scan
scanner := security.NewScanner()
secResults := scanner.Scan(astNode)
if secResults.HasCritical() {
fmt.Println("CRITICAL SECURITY ISSUES FOUND:")
for _, f := range secResults.Findings {
if f.Severity == security.SeverityCritical {
fmt.Printf(" - [%s] %s: %s\n", f.Severity, f.Pattern, f.Description)
}
}
} else {
fmt.Println("Security scan: CLEAN")
}
// Lint SQL
linter := linter.New(rules.AllRules()...)
lintResult := linter.LintString(sql, "demo.sql")
if len(lintResult.Violations) > 0 {
fmt.Printf("\nLinting violations: %d\n", len(lintResult.Violations))
for _, v := range lintResult.Violations {
fmt.Printf(" [%s] %s at line %d\n", v.Rule, v.Message, v.Location.Line)
}
} else {
fmt.Println("Linting: PASSED")
}
// Analyze AST structure
if len(astNode.Statements) > 0 {
if stmt, ok := astNode.Statements[0].(*ast.SelectStatement); ok {
fmt.Printf("\nQuery Analysis:\n")
fmt.Printf(" Columns: %d\n", len(stmt.Columns))
fmt.Printf(" DISTINCT ON: %v\n", len(stmt.DistinctOn) > 0)
if stmt.With != nil {
fmt.Printf(" CTEs: %d (Recursive: %v)\n",
len(stmt.With.CTEs), stmt.With.Recursive)
}
if len(stmt.Windows) > 0 {
fmt.Printf(" Window Functions: %d\n", len(stmt.Windows))
}
// Check for PostgreSQL features
hasLateral := false
for _, from := range stmt.From {
if from.Lateral {
hasLateral = true
break
}
}
fmt.Printf(" LATERAL JOIN: %v\n", hasLateral)
// Check for FILTER clause
hasFilter := false
for _, col := range stmt.Columns {
if fc, ok := col.(*ast.FunctionCall); ok && fc.Filter != nil {
hasFilter = true
break
}
}
fmt.Printf(" FILTER Clause: %v\n", hasFilter)
if stmt.FetchClause != nil {
fmt.Printf(" FETCH FIRST: %v rows (WITH TIES: %v)\n",
*stmt.FetchClause.Count, stmt.FetchClause.WithTies)
}
if len(stmt.Returning) > 0 {
fmt.Printf(" RETURNING: %d columns\n", len(stmt.Returning))
}
}
}
fmt.Println("\nSQL parsed, validated, and analyzed successfully!")
}
Output:
Security scan: CLEAN
Linting violations: 2
[L003] Multiple consecutive blank lines at line 11
[L005] Line length exceeds 120 characters at line 17
Query Analysis:
Columns: 7
DISTINCT ON: true
CTEs: 1 (Recursive: true)
Window Functions: 1
LATERAL JOIN: true
FILTER Clause: true
FETCH FIRST: 10 rows (WITH TIES: true)
RETURNING: 3 columns
SQL parsed, validated, and analyzed successfully!
Processed 1 queries with 100.00% success rate
Additional Resources
- Getting Started: install and parse your first query
- Usage Guide: patterns for services and batch jobs
- SQL Compatibility: dialect and feature coverage
- Error Codes: every error code with causes and fixes
- Linting Rules: all built-in lint rules
- Configuration: the
.gosqlx.ymlfile - Benchmarks: measured performance with stage, hardware and Go version
- Examples: runnable programs