style

package
v1.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package style provides linting rules for SQL style and formatting conventions.

This package includes rules that enforce consistent style patterns across SQL code, including column alignment, comma placement, and aliasing conventions. These rules focus on readability and team coding standards rather than syntax.

Rules in this Package

L006: Column Alignment (no auto-fix)

  • Checks that SELECT columns are properly aligned
  • Detects misaligned columns in multi-line SELECT statements
  • Severity: Info
  • Requires manual formatting adjustment

L008: Comma Placement (no auto-fix)

  • Enforces consistent comma placement: trailing or leading
  • Configurable style: CommaTrailing or CommaLeading
  • Severity: Info
  • Requires manual restructuring

L009: Aliasing Consistency (no auto-fix)

  • Checks for consistent table and column alias usage
  • Detects mixed use of full names and aliases
  • Configurable: prefer explicit AS keyword or implicit aliases
  • Severity: Warning
  • Requires manual refactoring

Usage Examples

Column Alignment (L006):

import "github.com/ajitpratap0/GoSQLX/pkg/linter/rules/style"

rule := style.NewColumnAlignmentRule()
violations, _ := rule.Check(ctx)
// Detects:
// SELECT
//     column1,
//   column2,      <- Not aligned with column1
//     column3
// FROM table

Comma Placement - Trailing Style (L008):

rule := style.NewCommaPlacementRule(style.CommaTrailing)
violations, _ := rule.Check(ctx)
// Enforces:
// SELECT
//     column1,     <- Comma at end (trailing)
//     column2,
//     column3
// FROM table

Comma Placement - Leading Style (L008):

rule := style.NewCommaPlacementRule(style.CommaLeading)
violations, _ := rule.Check(ctx)
// Enforces:
// SELECT
//     column1
//     , column2    <- Comma at start (leading)
//     , column3
// FROM table

Aliasing Consistency with Explicit AS (L009):

rule := style.NewAliasingConsistencyRule(true)  // Prefer explicit AS
violations, _ := rule.Check(ctx)
// Enforces:
// SELECT u.name
// FROM users AS u              <- Explicit AS keyword
// JOIN orders AS o ON u.id = o.user_id

Aliasing Consistency with Implicit Aliases (L009):

rule := style.NewAliasingConsistencyRule(false)  // Allow implicit
violations, _ := rule.Check(ctx)
// Allows:
// SELECT u.name
// FROM users u                 <- Implicit alias (no AS)
// JOIN orders o ON u.id = o.user_id

Style Conventions

Column Alignment:

  • Improves readability in multi-line SELECT statements
  • Helps identify column relationships
  • Makes diffs cleaner in version control

Comma Placement:

  • Trailing (recommended for most teams):
  • Traditional SQL style
  • Easier to add columns at end
  • Matches most code formatters
  • Leading:
  • Makes it obvious when comma is forgotten
  • Easier to comment out last column
  • Preferred by some functional programming teams

Aliasing Consistency:

  • Explicit AS (recommended):
  • Clearer intent, no ambiguity
  • Easier for SQL beginners to understand
  • Matches most SQL documentation
  • Implicit (allowed in SQL standard):
  • More concise, less verbose
  • Common in ad-hoc queries
  • Preferred in some codebases for brevity

Rule Limitations

None of the style rules support auto-fixing because they require:

L006 (Column Alignment):

  • Complex indentation calculation
  • Semantic understanding of SELECT structure
  • Preservation of comments and formatting
  • Manual alignment is more reliable

L008 (Comma Placement):

  • Multi-line restructuring
  • Potential comment relocation
  • Context-sensitive placement decisions
  • Manual editing ensures correct results

L009 (Aliasing Consistency):

  • AST analysis of all table references
  • Renaming references throughout query
  • Risk of breaking query semantics
  • Manual refactoring is safer

These rules provide guidance and detect violations but require developer intervention to fix properly.

Configuration Recommendations

Standard enterprise style:

style.NewColumnAlignmentRule()                        // Enforce alignment
style.NewCommaPlacementRule(style.CommaTrailing)      // Traditional style
style.NewAliasingConsistencyRule(true)                // Explicit AS

Modern application style:

style.NewColumnAlignmentRule()                        // Still align columns
style.NewCommaPlacementRule(style.CommaLeading)       // Leading commas
style.NewAliasingConsistencyRule(false)               // Allow implicit

Relaxed style (minimal enforcement):

// Skip L006 if alignment not important
style.NewCommaPlacementRule(style.CommaTrailing)      // Just be consistent
// Skip L009 if aliasing flexibility desired

Legacy codebase (detection only):

// Enable all rules to detect inconsistencies
style.NewColumnAlignmentRule()
style.NewCommaPlacementRule(style.CommaTrailing)
style.NewAliasingConsistencyRule(true)
// Review violations, don't enforce immediately
// Gradually refactor hot paths first

Integration with Linter

Style rules integrate with the linter framework:

linter := linter.New(
    style.NewColumnAlignmentRule(),
    style.NewCommaPlacementRule(style.CommaTrailing),
    style.NewAliasingConsistencyRule(true),
    // other rules...
)
result := linter.LintFile("query.sql")

CLI usage:

# Check style
gosqlx lint query.sql

# Style rules don't support --fix
# Violations must be fixed manually

Configuration file (.gosqlx.yml):

linter:
  rules:
    - id: L006
      enabled: true
    - id: L008
      enabled: true
      config:
        comma_style: trailing  # or 'leading'
    - id: L009
      enabled: true
      config:
        prefer_explicit_as: true  # or false

AST vs Text-Based Analysis

L006 and L008 are text-based rules:

  • Analyze raw line content
  • Fast, no parsing required
  • Work even on syntactically invalid SQL
  • Pattern-based detection

L009 is hybrid (AST-preferred, text-fallback):

  • Prefers AST analysis for accuracy
  • Falls back to text analysis if parsing fails
  • More accurate violation detection with AST
  • Handles complex query structures

Performance Characteristics

All style rules are efficient with linear complexity:

L006 (Column Alignment):

  • Speed: 80,000+ lines/sec
  • Complexity: O(n) line scanning
  • Memory: Minimal state tracking

L008 (Comma Placement):

  • Speed: 100,000+ lines/sec
  • Complexity: O(n) line scanning
  • Memory: No allocation in check phase

L009 (Aliasing Consistency):

  • With AST: 50,000+ lines/sec (AST traversal)
  • Without AST: 80,000+ lines/sec (text analysis)
  • Complexity: O(n) nodes or lines
  • Memory: Maps for alias tracking

Thread Safety

All rule types in this package are stateless and thread-safe. Rule instances can be shared across goroutines safely.

Example Violations and Fixes

L006 - Column Alignment:

-- Bad (misaligned)
SELECT
    user_id,
  username,        <- Wrong indent
    email
FROM users

-- Good (aligned)
SELECT
    user_id,
    username,
    email
FROM users

L008 - Comma Placement (Trailing):

-- Bad (leading commas when trailing expected)
SELECT
    user_id
    , username       <- Comma at start
FROM users

-- Good (trailing)
SELECT
    user_id,
    username
FROM users

L009 - Aliasing Consistency:

-- Bad (mixing aliases and full names)
SELECT u.name, orders.total
FROM users u
JOIN orders ON users.id = orders.user_id
                ^^^^^^                      <- Using full table name instead of alias

-- Good (consistent aliases)
SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AliasStyle

type AliasStyle string

AliasStyle represents the preferred alias style for table and column aliases.

const (
	// AliasExplicit requires explicit AS keyword for clarity.
	// Example: FROM users AS u, orders AS o
	AliasExplicit AliasStyle = "explicit"

	// AliasImplicit allows implicit aliases for brevity.
	// Example: FROM users u, orders o
	AliasImplicit AliasStyle = "implicit"
)

type AliasingConsistencyRule

type AliasingConsistencyRule struct {
	linter.BaseRule
	// contains filtered or unexported fields
}

AliasingConsistencyRule (L009) checks for consistent use of table and column aliases.

Inconsistent aliasing reduces query readability and can indicate mixing of full table names with aliases throughout a query. This rule detects:

  1. Queries where some tables have aliases while others don't
  2. Queries that reference full table names when aliases are defined

Rule ID: L009 Severity: Warning Auto-fix: Not supported (requires semantic analysis and renaming)

Example violation:

SELECT u.name, orders.total    <- Mixed: alias 'u' and full name 'orders'
FROM users AS u
JOIN orders ON users.id = orders.user_id
                ^^^^^^                      <- Using full name when alias exists

Expected output:

SELECT u.name, o.total         <- Consistent: all aliases
FROM users AS u
JOIN orders AS o ON u.id = o.user_id

The rule uses AST analysis when available for accurate detection, falling back to text-based analysis for syntactically invalid SQL.

func NewAliasingConsistencyRule

func NewAliasingConsistencyRule(preferExplicitAS bool) *AliasingConsistencyRule

NewAliasingConsistencyRule creates a new L009 rule instance.

Parameters:

  • preferExplicitAS: If true, prefers explicit AS keyword in aliases (recommended)

Note: The preferExplicitAS parameter is currently informational. The rule focuses on consistency of alias usage rather than AS keyword presence.

Returns a configured AliasingConsistencyRule ready for use with the linter.

func (*AliasingConsistencyRule) Check

Check performs the aliasing consistency check on SQL content.

If AST is available, uses AST-based analysis to accurately detect aliasing issues by examining FROM and JOIN clauses. If AST is unavailable or parsing failed, falls back to text-based pattern matching.

Returns a slice of violations for inconsistent alias usage, and nil error.

func (*AliasingConsistencyRule) Fix

func (r *AliasingConsistencyRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is not supported for this rule as it requires semantic analysis and renaming.

Auto-fixing aliasing consistency would require:

  • Adding aliases to all tables (choosing appropriate short names)
  • Renaming all table references throughout the query
  • Handling qualified column references (table.column -> alias.column)
  • Preserving query semantics and avoiding name conflicts

These transformations risk breaking queries and are best done manually by developers who understand the query logic.

Returns the content unchanged with nil error.

type ColumnAlignmentRule

type ColumnAlignmentRule struct {
	linter.BaseRule
}

ColumnAlignmentRule (L006) checks for proper column alignment in multi-line SELECT statements.

Misaligned columns in SELECT lists reduce readability and make it harder to understand column relationships. This rule detects columns that don't align with the majority alignment pattern in each SELECT statement.

Rule ID: L006 Severity: Info Auto-fix: Not supported (requires complex formatting logic)

Example violation:

SELECT
    user_id,
  username,      <- Not aligned with user_id (violation)
    email,
    created_at
FROM users

Expected output:

SELECT
    user_id,
    username,      <- Now aligned
    email,
    created_at
FROM users

The rule finds the most common indentation level among columns and reports columns that deviate from this pattern.

func NewColumnAlignmentRule

func NewColumnAlignmentRule() *ColumnAlignmentRule

NewColumnAlignmentRule creates a new L006 rule instance.

Returns a configured ColumnAlignmentRule ready for use with the linter. The rule does not support auto-fix due to the complexity of preserving formatting while adjusting indentation.

func (*ColumnAlignmentRule) Check

Check performs the column alignment check on SQL content.

Scans through lines identifying SELECT statements and tracking column indentation in multi-line SELECT lists. Computes the most common (mode) indentation level among columns and reports any columns that don't match this alignment.

Only multi-line SELECT statements with 2+ columns are checked. Single-line SELECT and single-column SELECT statements don't have alignment issues.

Returns a slice of violations (one per misaligned column) and nil error.

func (*ColumnAlignmentRule) Fix

func (r *ColumnAlignmentRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is not supported for this rule as it requires complex formatting logic.

Auto-fixing column alignment would require:

  • Understanding SELECT clause structure
  • Preserving comments and inline formatting
  • Choosing appropriate indentation levels
  • Handling edge cases (subqueries, CASE expressions, etc.)

These decisions are best made by developers using a dedicated SQL formatter.

Returns the content unchanged with nil error.

type CommaPlacementRule

type CommaPlacementRule struct {
	linter.BaseRule
	// contains filtered or unexported fields
}

CommaPlacementRule (L008) enforces consistent comma placement style.

Inconsistent comma placement reduces readability and makes it harder to scan column lists or value lists. This rule detects commas that don't match the configured placement style.

Rule ID: L008 Severity: Info Auto-fix: Not supported (requires multi-line restructuring)

Example violation (CommaTrailing style):

SELECT
    user_id
    , username     <- Leading comma (violation)
    , email
FROM users

Expected output:

SELECT
    user_id,       <- Trailing comma
    username,
    email
FROM users

The rule checks commas in SELECT columns, INSERT value lists, and other comma-separated contexts.

func NewCommaPlacementRule

func NewCommaPlacementRule(preferredStyle CommaStyle) *CommaPlacementRule

NewCommaPlacementRule creates a new L008 rule instance.

Parameters:

  • preferredStyle: CommaTrailing or CommaLeading (defaults to CommaTrailing if empty)

Returns a configured CommaPlacementRule ready for use with the linter.

func (*CommaPlacementRule) Check

func (r *CommaPlacementRule) Check(ctx *linter.Context) ([]linter.Violation, error)

Check performs the comma placement check on SQL content.

Scans each line for leading or trailing commas and reports violations when they don't match the preferred style. Lines starting with SQL keywords (FROM, WHERE, etc.) are skipped as they indicate new clauses rather than continuation lines.

Returns a slice of violations (one per misplaced comma) and nil error.

func (*CommaPlacementRule) Fix

func (r *CommaPlacementRule) Fix(content string, violations []linter.Violation) (string, error)

Fix is not supported for this rule as it requires multi-line restructuring.

Auto-fixing comma placement would require:

  • Moving commas between lines while preserving formatting
  • Handling comments that may appear before/after commas
  • Understanding list context (SELECT columns vs INSERT values vs function args)
  • Adjusting whitespace appropriately

These transformations are complex and best performed by developers or dedicated SQL formatters that understand full query structure.

Returns the content unchanged with nil error.

type CommaStyle

type CommaStyle string

CommaStyle represents the preferred comma placement style in multi-line lists.

const (
	// CommaTrailing places commas at the end of lines (traditional style).
	// Example:
	//   SELECT
	//       column1,
	//       column2,
	//       column3
	//   FROM table
	CommaTrailing CommaStyle = "trailing"

	// CommaLeading places commas at the start of lines (modern style).
	// Example:
	//   SELECT
	//       column1
	//       , column2
	//       , column3
	//   FROM table
	CommaLeading CommaStyle = "leading"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL