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 ¶
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:
- Queries where some tables have aliases while others don't
- 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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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" )