Skip to content

Latest commit

 

History

History
323 lines (245 loc) · 10.2 KB

API_REFERENCE.md

File metadata and controls

323 lines (245 loc) · 10.2 KB

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
highlight pkg/highlight Dialect-aware SQL syntax highlighting as spans, ANSI, HTML and CSS
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.

Highlight Package

Moved to the highlight package reference. The guide with examples is Syntax Highlighting.

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/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 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
    lintResult, err := gosqlx.Lint(sql)
    if err != nil {
        log.Fatal(err)
    }

    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