Skip to content

feat: Rewrite GitHub Action shell scripts in Go (#251)#310

Merged
ajitpratap0 merged 3 commits intomainfrom
feat/251-go-action-entrypoint
Feb 16, 2026
Merged

feat: Rewrite GitHub Action shell scripts in Go (#251)#310
ajitpratap0 merged 3 commits intomainfrom
feat/251-go-action-entrypoint

Conversation

@ajitpratap0
Copy link
Copy Markdown
Owner

Closes #251

Replaces bash entrypoint with Go subcommand for better error handling and maintainability.

Changes

  • New gosqlx action subcommand (cmd/gosqlx/cmd/action.go) that replicates all shell script logic:
    • SQL file discovery by glob pattern
    • Validation with per-file timeout
    • Linting with standard rules
    • GitHub Actions annotations (::error::, ::warning::, ::notice::)
    • Step summary markdown output
    • Severity-based exit codes
    • Support for env vars: SQL_FILES, RULES, SEVERITY, CONFIG, TIMEOUT
  • Simplified action/entrypoint.sh to a thin wrapper that calls gosqlx action

@claude
Copy link
Copy Markdown

claude bot commented Feb 16, 2026

Claude finished @ajitpratap0's task —— View job


Code Review Complete ✅

Reviewing PR #310: Rewrite GitHub Action shell scripts in Go

Todo List:

  • Read and analyze the new Go action command implementation
  • Review the simplified shell script entrypoint
  • Check code quality and Go best practices
  • Identify potential bugs and edge cases
  • Evaluate security considerations
  • Assess performance implications
  • Review error handling patterns
  • Check test coverage needs
  • Provide comprehensive feedback

Code Review Summary

This is a solid refactoring that moves GitHub Action logic from bash to Go. The implementation is well-structured and maintains all original functionality while improving maintainability. However, there are several areas for improvement.

✅ Strengths

Architecture & Design:

  • Clean separation of concerns with dedicated functions
  • Good use of cobra command structure following project patterns
  • Proper environment variable handling with flag fallbacks
  • Maintains backward compatibility with all environment variables

Error Handling:

  • Comprehensive error handling throughout the codebase
  • Proper timeout implementation for validation
  • Structured error reporting with GitHub Actions annotations

Code Quality:

  • Follows Go conventions and project patterns
  • Good function decomposition and readability
  • Proper defer usage for file cleanup

⚠️ Issues & Concerns

Critical Issues

1. Missing Test Coverage - cmd/gosqlx/cmd/action.go:1-376

  • No tests exist for the new action subcommand
  • High-risk functions like file discovery, timeout handling, and annotation formatting are untested
  • All other commands in cmd/gosqlx/cmd/ have corresponding *_test.go files
  • Recommendation: Add action_test.go with comprehensive test coverage

2. Unused Parameter in lintFile - cmd/gosqlx/cmd/action.go:307

func lintFile(filePath string, _ []string) []lintViolation {
  • Rules parameter is parsed but never used
  • Could break functionality if users expect custom rule configuration
  • Fix: Either implement rule filtering or remove the parameter

Security Considerations

3. File Path Validation - cmd/gosqlx/cmd/action.go:231-287

  • findSQLFiles() doesn't validate file paths for directory traversal
  • Could potentially access files outside intended directories
  • Recommendation: Add path validation to prevent ../ traversal

4. File Permissions - cmd/gosqlx/cmd/action.go:356

f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o600)
  • Good: Uses restrictive file permissions (0o600)

Performance & Reliability

5. Timeout Implementation - cmd/gosqlx/cmd/action.go:330-352

  • Goroutine leak potential: timeout goroutine continues even after completion
  • Fix: Add proper goroutine cleanup or use context.WithTimeout
// Suggested improvement
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// Use ctx in parser.ValidateBytes

6. Error Parsing Fragility - cmd/gosqlx/cmd/action.go:144-152

  • String-based error parsing for line numbers is brittle
  • Assumes specific error message format
  • Recommendation: Use structured errors from the parser if available

Code Quality Issues

7. Hardcoded Linter Rules - cmd/gosqlx/cmd/action.go:297-304

func defaultLinter() *linter.Linter {
    return linter.New(
        whitespace.NewTrailingWhitespaceRule(),
        whitespace.NewMixedIndentationRule(),
        keywords.NewKeywordCaseRule(keywords.CaseUpper),
        style.NewColumnAlignmentRule(),
    )
}
  • Limited to 4 rules when the project has 10 lint rules (L001-L010 per CLAUDE.md)
  • Should use configurable rule set or all available rules

8. GitHub Actions Annotation Format - cmd/gosqlx/cmd/action.go:214

fmt.Printf("::%s %s::%s\n", level, params, msg)
  • Missing space before params could cause malformed annotations
  • Fix: fmt.Printf("::%s %s::%s\n", level, params, msg) → ensure proper formatting

Minor Issues

9. String Comparison Case Sensitivity - cmd/gosqlx/cmd/action.go:191-196

  • Uses strings.EqualFold inconsistently in violation processing but not in severity comparison
  • Recommendation: Standardize case-insensitive comparisons

10. Magic Numbers - cmd/gosqlx/cmd/action.go:84

  • Default timeout of 600 seconds is hardcoded
  • Consider making it a named constant

📋 Recommendations

Immediate Actions

  1. Add comprehensive test coverage - Create action_test.go
  2. Fix unused rules parameter - Implement or remove rule filtering
  3. Add path validation - Prevent directory traversal in file discovery

Enhancement Opportunities

  1. Use all available linter rules - Match the 10 rules (L001-L010) mentioned in project docs
  2. Improve timeout implementation - Use context for better resource management
  3. Add configuration validation - Validate severity levels and other parameters
  4. Structure error handling - Use project's error handling patterns from pkg/errors/

📈 Performance Impact

  • Positive: Eliminates shell subprocess overhead
  • Neutral: File processing remains the same
  • Risk: Potential goroutine leak in timeout implementation

🔒 Security Assessment

  • Good: Restrictive file permissions for step summary
  • Concern: File path validation missing
  • Good: No direct command execution or injection risks

📊 Test Coverage Gap

This PR adds 375 lines of untested code, significantly impacting the project's test coverage. Given the project's emphasis on quality (76%+ coverage across packages), tests are essential before merging.


@claude
Copy link
Copy Markdown

claude bot commented Feb 16, 2026

Claude finished @ajitpratap0's task —— View job


Code Review Complete ✅

Reviewing PR #310: Rewrite GitHub Action shell scripts in Go

Todo List:

  • Read and analyze the new Go action command implementation
  • Review the simplified shell script entrypoint
  • Check code quality and Go best practices
  • Identify potential bugs and edge cases
  • Evaluate security considerations (including GitHub Security alerts)
  • Assess performance implications
  • Review error handling patterns
  • Check test coverage needs
  • Provide comprehensive feedback

Summary

This is a well-executed refactoring that successfully migrates GitHub Action logic from bash to Go. The implementation maintains all original functionality while improving maintainability and error handling. However, there are several critical issues that should be addressed before merging.

✅ Strengths

Architecture & Design

  • Clean separation of concerns with well-structured functions (findSQLFiles, lintFile, validateFileWithTimeout)
  • Proper command structure following existing cobra patterns in the project
  • Comprehensive environment variable support with sensible flag fallbacks
  • Maintains backward compatibility with all existing environment variables

Error Handling & Output

  • Structured GitHub Actions annotations with proper file/line references
  • Timeout implementation prevents hanging on problematic files
  • Step summary markdown output provides clear CI feedback
  • Severity-based exit codes allow flexible CI configurations

⚠️ Critical Issues

1. Missing Test Coverage - cmd/gosqlx/cmd/action.go:1-376

Severity: High

The new action subcommand has zero test coverage, adding 376 lines of untested code. All other commands in cmd/gosqlx/cmd/ have corresponding test files.

Required: Add action_test.go with comprehensive coverage for:

  • File discovery patterns and edge cases
  • Timeout behavior
  • GitHub annotation formatting
  • Error handling scenarios
  • Environment variable processing

2. Security: File Path Validation Missing - cmd/gosqlx/cmd/action.go:231-287

Severity: High (Addresses GitHub Security alerts)

The findSQLFiles() function lacks path validation, potentially allowing directory traversal attacks:

// VULNERABLE: No validation against ../../../etc/passwd patterns
files = append(files, path)

Fix: Add path sanitization:

cleanPath := filepath.Clean(path)
if strings.Contains(cleanPath, "..") {
    return nil // Skip traversal attempts
}

3. Incomplete Linter Rules - cmd/gosqlx/cmd/action.go:297-304

Severity: Medium

The defaultLinter() only uses 4 rules, but the project has 10 linting rules (L001-L010) as documented. Missing rules:

  • L003 (Consecutive Blank Lines)
  • L004 (Indentation Depth)
  • L005 (Long Lines)
  • L008 (Comma Placement)
  • L009 (Aliasing Consistency)
  • L010 (Redundant Whitespace)

Fix: Use all available rules or make it configurable.

4. Unused Parameter in lintFile - cmd/gosqlx/cmd/action.go:307

Severity: Medium

func lintFile(filePath string, _ []string) []lintViolation {

Rules parameter is parsed but ignored, breaking user expectations for custom rule filtering.

Fix: Either implement rule filtering or remove the unused parameter.

🔒 Security Assessment

GitHub Security Alerts Analysis

The two "Potential file inclusion via variable" alerts likely relate to:

  1. Line 338: os.ReadFile(filepath.Clean(filePath)) - Good use of filepath.Clean()
  2. Line 356: os.OpenFile(filepath.Clean(path), ...) - Good use of filepath.Clean()

Both use filepath.Clean() correctly, but the file discovery logic needs additional traversal protection.

Security Strengths

  • Restrictive file permissions (0o600) for step summary
  • No command injection risks (pure Go implementation)
  • Proper file path cleaning where file operations occur

Security Concerns

  • Missing directory traversal validation in file discovery
  • No input validation on severity/config parameters

🐛 Additional Issues

Performance & Reliability

Goroutine Leak Risk - cmd/gosqlx/cmd/action.go:330-352

go func() {
    // This goroutine may continue even after timeout
    ch <- result{err: parser.ValidateBytes(data)}
}()

Fix: Use context.WithTimeout() for proper cancellation.

Error Message Parsing - cmd/gosqlx/cmd/action.go:149

lineno := extractLineNumber(lineRe, line) // Fragile regex parsing

Risk: Brittle string parsing may miss line numbers if error format changes.

Code Quality

GitHub Annotation Format - cmd/gosqlx/cmd/action.go:214

fmt.Printf("::%s %s::%s\n", level, params, msg)
//                ^-- Missing space could cause malformed annotations

Magic Numbers - cmd/gosqlx/cmd/action.go:84

timeoutSec = 600 // Should be a named constant

📊 Performance Impact

  • ✅ Positive: Eliminates shell subprocess overhead (~10-50ms per call)
  • ➖ Neutral: Core file processing performance unchanged
  • ⚠️ Risk: Potential goroutine leak in timeout implementation

📋 Recommendations

Before Merge (Required)

  1. Add comprehensive test coverage (action_test.go)
  2. Fix security: Add path traversal validation
  3. Include all 10 linter rules or make configurable
  4. Fix unused rules parameter in lintFile()

Post-Merge Improvements

  1. Improve timeout implementation using context.WithTimeout()
  2. Add input validation for severity levels and config paths
  3. Use structured error handling from pkg/errors/
  4. Add configuration validation

📈 Test Coverage Impact

This PR significantly impacts test coverage by adding 376 untested lines. Given the project's emphasis on quality (76%+ coverage per CLAUDE.md), comprehensive tests are essential.

Suggested Test Structure:

func TestActionCmd_FileDiscovery(t *testing.T) { /* ... */ }
func TestActionCmd_TimeoutHandling(t *testing.T) { /* ... */ }  
func TestActionCmd_GitHubAnnotations(t *testing.T) { /* ... */ }
func TestActionCmd_SecurityValidation(t *testing.T) { /* ... */ }

🎯 Overall Assessment

This is a solid architectural improvement that successfully modernizes the GitHub Action implementation. The Go rewrite provides better maintainability, error handling, and integration with the existing codebase.

However, the security vulnerabilities and missing test coverage are blocking issues that must be resolved before merge. Once addressed, this will be a significant improvement to the project's CI/CD capabilities.


@claude
Copy link
Copy Markdown

claude bot commented Feb 16, 2026

Claude finished @ajitpratap0's task —— View job


Code Review Complete ✅

Reviewing PR #310: Rewrite GitHub Action shell scripts in Go

Todo List:

  • Read and analyze the new Go action command implementation
  • Review the simplified shell script entrypoint
  • Check code quality and Go best practices
  • Identify potential bugs and edge cases
  • Evaluate security considerations (including GitHub Security alerts)
  • Assess performance implications
  • Review error handling patterns
  • Check test coverage needs
  • Provide comprehensive feedback

Summary

This PR successfully refactors the GitHub Action from bash to Go, providing better maintainability and error handling. The implementation is well-structured and maintains backward compatibility. However, there are several critical issues that need to be addressed before merging.

✅ Strengths

Architecture & Design

  • Clean separation of concerns with well-organized functions (findSQLFiles, validateFileWithTimeout, lintFile)
  • Proper cobra command integration following existing project patterns
  • Comprehensive environment variable handling with sensible flag fallbacks
  • Maintains full backward compatibility with all existing environment variables

Error Handling & GitHub Integration

  • Structured GitHub Actions annotations with proper file/line references
  • Timeout implementation prevents hanging on problematic files
  • Step summary markdown output provides clear CI feedback
  • Severity-based exit codes allow flexible CI configurations

Code Quality

  • Good Go conventions with proper imports, error handling patterns
  • Clean function decomposition and readable code structure
  • Proper use of filepath.Clean() in file operations

⚠️ Critical Issues

1. Missing Test Coverage - cmd/gosqlx/cmd/action.go:1-376

Severity: Critical

The new action command has zero test coverage, adding 376 lines of untested code. All other commands in cmd/gosqlx/cmd/ have comprehensive test files.

Required: Create cmd/gosqlx/cmd/action_test.go with tests for:

  • File discovery patterns and edge cases
  • Timeout behavior and cancellation
  • GitHub annotation formatting
  • Error handling scenarios
  • Environment variable processing

2. Security: Directory Traversal Risk - cmd/gosqlx/cmd/action.go:241,276

Severity: High (Related to GitHub Security alerts)

The file discovery logic lacks validation against directory traversal attacks:

// Lines 241, 276: No validation against ../../../etc/passwd patterns
files = append(files, path)

Fix needed: Add path validation to prevent traversal:

cleanPath := filepath.Clean(path)
if strings.Contains(cleanPath, "..") {
    continue // Skip potential traversal attempts
}

3. Incomplete Linter Rules - cmd/gosqlx/cmd/action.go:297-304

Severity: Medium

The defaultLinter() only implements 4 of the project's 10 available linting rules (L001-L010):

Currently implemented:

  • L001: Trailing Whitespace
  • L002: Mixed Indentation
  • L007: Keyword Case Consistency
  • L006: Column Alignment

Missing rules:

  • L003: Consecutive Blank Lines
  • L004: Indentation Depth
  • L005: Long Lines
  • L008: Comma Placement
  • L009: Aliasing Consistency
  • L010: Redundant Whitespace

Fix: Include all available rules or make it configurable.

4. Unused Parameter Bug - cmd/gosqlx/cmd/action.go:307

Severity: Medium

func lintFile(filePath string, _ []string) []lintViolation {

The rules parameter is parsed from environment/flags but completely ignored, breaking user expectations for custom rule filtering.

Fix: Either implement rule filtering or remove the unused parameter entirely.

🔒 Security Assessment

GitHub Security Alerts

The "Potential file inclusion via variable" alerts appear to be false positives for:

  • Line 338: os.ReadFile(filepath.Clean(filePath)) - ✅ Uses filepath.Clean()
  • Line 356: os.OpenFile(filepath.Clean(path), ...) - ✅ Uses filepath.Clean()

However, the file discovery logic needs additional security measures.

Security Strengths

  • Restrictive file permissions (0o600) for step summary file
  • No command injection risks (pure Go implementation)
  • Proper path cleaning in file operations

Security Concerns

  • Directory traversal vulnerability in file discovery
  • Missing input validation on severity/config parameters

🐛 Additional Issues

Performance & Reliability

Potential Goroutine Leak - cmd/gosqlx/cmd/action.go:330-352

go func() {
    // This goroutine continues even after timeout
    data, err := os.ReadFile(filepath.Clean(filePath))
    // ...
}()

Impact: Resource leak in timeout scenarios
Fix: Use context.WithTimeout() for proper cancellation

Fragile Error Parsing - cmd/gosqlx/cmd/action.go:149

lineno := extractLineNumber(lineRe, line)

Risk: Regex-based line number extraction may fail if parser error format changes

Code Quality Issues

GitHub Annotation Spacing - cmd/gosqlx/cmd/action.go:214

fmt.Printf("::%s %s::%s\n", level, params, msg)
//               ^-- Space missing could cause malformed annotations

Magic Numbers - cmd/gosqlx/cmd/action.go:84

timeoutSec = 600 // Should be a named constant

Inconsistent Case Handling - cmd/gosqlx/cmd/action.go:191-196
Uses strings.EqualFold for severity comparison but not consistently throughout.

📊 Performance Impact

  • ✅ Positive: Eliminates shell subprocess overhead (~10-50ms per file)
  • ➖ Neutral: Core file processing performance unchanged
  • ⚠️ Risk: Potential goroutine leak in timeout implementation

📋 Recommendations

Before Merge (Required)

  1. Add comprehensive test coverage - Create action_test.go
  2. Fix security vulnerability - Add directory traversal validation
  3. Implement all 10 linter rules or make rule selection configurable
  4. Fix unused rules parameter - Either implement or remove

Post-Merge Improvements

  1. Improve timeout implementation - Use context.WithTimeout()
  2. Add input validation - Validate severity levels, config paths
  3. Use structured error handling - Leverage pkg/errors/ patterns
  4. Extract magic numbers - Define named constants

📈 Test Coverage Impact

This PR adds 376 lines of untested code, significantly impacting the project's test coverage. Given the project's emphasis on quality (76%+ coverage per CLAUDE.md), comprehensive tests are essential.

Suggested Test Structure:

func TestActionCmd_FileDiscovery(t *testing.T) { /* ... */ }
func TestActionCmd_TimeoutHandling(t *testing.T) { /* ... */ }
func TestActionCmd_GitHubAnnotations(t *testing.T) { /* ... */ }
func TestActionCmd_SecurityValidation(t *testing.T) { /* ... */ }

🎯 Overall Assessment

This is a solid architectural improvement that modernizes the GitHub Action implementation. The Go rewrite provides significantly better maintainability, error handling, and integration with the existing codebase compared to the original bash implementation.

However, the missing test coverage and security vulnerabilities are blocking issues that must be resolved before merge. The incomplete linter rule implementation also reduces the feature's effectiveness.

Once these issues are addressed, this will be a significant improvement to the project's CI/CD capabilities and developer experience.


@ajitpratap0 ajitpratap0 merged commit 838d0e1 into main Feb 16, 2026
20 checks passed
ajitpratap0 pushed a commit that referenced this pull request Mar 22, 2026
… React error #310

useState(copied) and useCallback(handleCopy) were declared after the
if (loading) and if (error) early returns, violating the Rules of Hooks.

When the WASM binary was a 404, the component always hit the error branch
so both renders exited with the same hook count. After committing the WASM
binary (#423), the component now successfully transitions loading→ready,
causing React to see 11 hooks instead of 9 on the second render → #310.

Fix: move both hooks above all conditional returns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ajitpratap0 pushed a commit that referenced this pull request Mar 22, 2026
… React error #310

useState(copied) and useCallback(handleCopy) were declared after the
if (loading) and if (error) early returns, violating the Rules of Hooks.

When the WASM binary was a 404, the component always hit the error branch
so both renders exited with the same hook count. After committing the WASM
binary (#423), the component now successfully transitions loading→ready,
causing React to see 11 hooks instead of 9 on the second render → #310.

Fix: move both hooks above all conditional returns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ajitpratap0 added a commit that referenced this pull request Mar 22, 2026
… React error #310 (#429)

Hooks (useState for copied, useCallback for handleCopy) were placed after conditional early returns for loading/error states, violating React Rules of Hooks. Moved both hooks above the early returns so all 11 hooks are called unconditionally on every render.

Root cause: the hooks violation was previously masked because the WASM binary was missing (404), so the component always stayed in the error branch. Once the WASM binary was committed (#423), the loading→ready transition exposed the hook count mismatch, triggering React error #310.

Fixes #427
ajitpratap0 added a commit that referenced this pull request Mar 24, 2026
…, and CONNECT BY (#431)

* fix(playground): move useState/useCallback above early returns to fix React error #310

useState(copied) and useCallback(handleCopy) were declared after the
if (loading) and if (error) early returns, violating the Rules of Hooks.

When the WASM binary was a 404, the component always hit the error branch
so both renders exited with the same hook count. After committing the WASM
binary (#423), the component now successfully transitions loading→ready,
causing React to see 11 hooks instead of 9 on the second render → #310.

Fix: move both hooks above all conditional returns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(dialect): add DialectMariaDB constant to keyword dialect system

* fix(dialect): return MYSQL_SPECIFIC for DialectMariaDB and add to validDialects test

* fix(dialect): wire DialectMariaDB into keywords.New() to load MYSQL_SPECIFIC keywords

* test(dialect): add TestDialectMariaDB_InheritsMySQL to guard MySQL keyword inheritance

* feat(dialect): add MARIADB_SPECIFIC keyword list extending MySQL dialect

* feat(dialect): add MariaDB auto-detection hints (SEQUENCE, VERSIONING, CONNECT BY)

* fix(dialect): remove over-broad START WITH hint and complete DetectDialect doc comment

* fix(dialect): restore MariaDB CONNECT BY hint and add accumulation test

* feat(ast): add CreateSequenceStatement, DropSequenceStatement, AlterSequenceStatement nodes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ast): nil guard in sequence ToSQL, split Restart field, add sequence tests

- Guard s.Name nil dereference in CreateSequenceStatement.ToSQL,
  DropSequenceStatement.ToSQL, and AlterSequenceStatement.ToSQL
- Split SequenceOptions.Restart (*LiteralValue) into two fields:
  Restart bool (bare RESTART) and RestartWith *LiteralValue (RESTART WITH n)
- Update writeSequenceOptions to emit bare RESTART or RESTART WITH n accordingly
- Add ast_sequence_test.go with full ToSQL table-driven tests and pool round-trip test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ast): add ForSystemTimeClause, PeriodDefinition, temporal table fields

- Add SystemTimeClauseType enum with AS OF, BETWEEN, FROM/TO, ALL variants
- Add ForSystemTimeClause struct for MariaDB FOR SYSTEM_TIME temporal queries
- Add PeriodDefinition struct for PERIOD FOR clauses in CREATE TABLE
- Extend TableReference with ForSystemTime field (MariaDB 10.3.4+)
- Extend CreateTableStatement with WithSystemVersioning and PeriodDefinitions fields
- Add ForSystemTimeClause.ToSQL() and tableRefSQL integration in sql.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ast): add SQL() methods to temporal/CONNECT BY types and fix SelectStatement field order

Add SQL() methods to ForSystemTimeClause, ConnectByClause, and PeriodDefinition
(all implement expressionNode()) so they satisfy the Expression interface fully
without silently degrading via the exprSQL() fallback. Move StartWith and
ConnectBy fields in SelectStatement to directly follow Having, matching logical
SQL clause ordering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement CREATE/DROP/ALTER SEQUENCE parsing for MariaDB dialect

Add parseCreateSequenceStatement, parseDropSequenceStatement, and
parseAlterSequenceStatement to mariadb.go with full option parsing
(START WITH, INCREMENT BY, MINVALUE, MAXVALUE, CYCLE, CACHE, RESTART WITH).
Wire dispatch into parseStatement() for DROP/ALTER and into parseCreateStatement()
for CREATE. Gate all paths behind isMariaDB() so MySQL and other dialects
are unaffected. Add six passing parser tests in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement temporal table parsing (FOR SYSTEM_TIME, WITH SYSTEM VERSIONING, PERIOD FOR)

Add parseForSystemTimeClause and parseTemporalPointExpression to mariadb.go
supporting AS OF, BETWEEN, FROM/TO, and ALL variants. Hook into
parseFromTableReference in select_subquery.go (after alias, before SQL Server
hints) with a peek-ahead guard so FOR is only consumed when followed by
SYSTEM_TIME. Add WITH SYSTEM VERSIONING parsing to parseCreateTable (after
closing paren, before PARTITION BY) and PERIOD FOR column parsing to the
column loop in ddl.go. Add four passing tests for temporal queries and
system versioning in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement CONNECT BY hierarchical query parsing for MariaDB dialect

Add parseConnectByCondition to mariadb.go which handles the PRIOR prefix
operator by wrapping the referenced column in a FunctionCall node and
building a BinaryExpression for the full PRIOR col = parent_col pattern.
Wire START WITH and CONNECT BY [NOCYCLE] parsing into parseSelectStatement
in select.go after the HAVING clause. Guard CONNECT and START from being
consumed as table aliases in parseFromTableReference via a peek-ahead check
in select_subquery.go. Add three passing tests covering basic, NOCYCLE, and
no-START-WITH variants in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(parser): add bare RESTART test and nil guard for CONNECT BY condition

* test(parser): add MariaDB SQL test data files and file-based integration test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add MariaDB dialect to SQL_COMPATIBILITY.md and CHANGELOG.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address code review issues across AST, keywords, and parser

AST layer:
- Add `Prior` UnaryOperator constant for CONNECT BY PRIOR expressions
- Add `NoCache bool` to SequenceOptions (NOCACHE was previously a silent no-op)
- Add `Pos models.Location` to all 6 new MariaDB AST nodes (CreateSequence,
  DropSequence, AlterSequence, ForSystemTimeClause, ConnectByClause, PeriodDefinition)
- Add `NewDropSequenceStatement()` / `ReleaseDropSequenceStatement()` pool funcs
  to match Create/Alter sequence pooling consistency
- Emit NOCACHE in writeSequenceOptions when NoCache=true

Keywords:
- Remove duplicate MINVALUE, MAXVALUE, INCREMENT, RESTART, NOCACHE entries
  from MARIADB_SPECIFIC (already covered by base/Oracle keyword lists)

Parser:
- Fix PRIOR operator: switch from FunctionCall to UnaryExpression{Operator: Prior}
- Fix PRIOR on RHS: CONNECT BY col = PRIOR col now parsed correctly
- Fix parseJoinedTableRef: add isMariaDBClauseKeyword guard to prevent CONNECT/START
  from being consumed as table aliases (same guard already in parseFromTableReference)
- Fix parseJoinedTableRef: add FOR SYSTEM_TIME temporal clause support on JOIN refs
- Fix DROP SEQUENCE: support IF NOT EXISTS in addition to IF EXISTS
- Fix DROP SEQUENCE: use NewDropSequenceStatement() for pool consistency
- Fix parseSequenceOptions: set opts.NoCache=true for NOCACHE keyword
- Add comment in parseTemporalPointExpression explaining quote-stripping behaviour

Tests:
- Add TestMariaDB_ConnectBy_PriorOnRight
- Add TestMariaDB_DropSequence_IfNotExists
- Add TestMariaDB_Sequence_NoCache
- Expand testdata SQL files with NO MINVALUE/MAXVALUE forms, PRIOR-on-right cases,
  IF NOT EXISTS on DROP, and multi-table temporal JOIN query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address second code review pass — Pos, NO CACHE, CONNECT BY, dedup

Parser dispatch (parser.go, ddl.go, select.go):
- Populate Pos on CreateSequenceStatement (at SEQUENCE token in ddl.go)
- Populate Pos on DropSequenceStatement (at DROP token in parser.go)
- Populate Pos on AlterSequenceStatement (at ALTER token in parser.go)
- Populate Pos on ConnectByClause (at CONNECT token in select.go)
- Populate Pos on PeriodDefinition (at PERIOD token in ddl.go)

mariadb.go:
- Fix NO CACHE (two-token) to also set opts.NoCache=true, matching NOCACHE
- Fix parseConnectByCondition to handle complex AND/OR chains:
  CONNECT BY PRIOR id = parent_id AND active = 1 now fully parsed
- Extract isMariaDBClauseStart() method (was duplicated closure in two functions)
- Populate Pos on ForSystemTimeClause (at SYSTEM_TIME token)
- Add comment clarifying IF NOT EXISTS is a non-standard permissive extension

select_subquery.go:
- Remove both isMariaDBClauseKeyword closures, replace with p.isMariaDBClauseStart()

ast.go:
- Update DropSequenceStatement doc to show [IF EXISTS | IF NOT EXISTS]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): correct START WITH/CONNECT BY SQL order and implement PeriodDefinition.SQL()

- Move START WITH / CONNECT BY emission to after HAVING, before ORDER BY
- Implement PeriodDefinition.SQL() — was silently returning empty string
- Add round-trip tests for both fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): code review fixes — pool comments, expressionNode docs, PERIOD FOR SYSTEM_TIME test

- Add '// zero all fields' comment to ReleaseCreateSequenceStatement and ReleaseAlterSequenceStatement
- Add design-choice comments on expressionNode() for ForSystemTimeClause, ConnectByClause, PeriodDefinition
- Add TestMariaDB_CreateTable_PeriodForSystemTime to cover PERIOD FOR SYSTEM_TIME parsing
- Fix parsePeriodDefinition to use parseColumnName so SYSTEM_TIME (reserved keyword) is accepted as period name
- Add GENERATED ALWAYS AS ROW START/END column constraint parsing in parseColumnConstraint (MariaDB system-versioned columns)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(dialect): reduce MariaDB CONNECT BY hint weight to 2 so Oracle wins pure CONNECT BY queries

Oracle's CONNECT BY weight is 3; MariaDB's was also 3, causing a tie broken
by non-deterministic map iteration. Reducing MariaDB to weight 2 ensures
Oracle wins when CONNECT BY is the only hint. MariaDB is still correctly
detected when its unique high-weight hints (NEXTVAL, FOR SYSTEM_TIME, etc.)
are present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address code review — CycleOption enum, CACHE validation, structured errors

- Replace Cycle bool + NoCycle bool with CycleOption enum to prevent
  invalid state where both could be true simultaneously
- Add validation in parseSequenceOptions for contradictory CACHE/NOCACHE
- Replace fmt.Errorf with p.expectedError() for consistent error style

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* bench(mariadb): add MariaDB-specific parsing benchmarks

17 benchmarks across 4 groups:
- BenchmarkMariaDB_Sequence: CREATE/ALTER/DROP SEQUENCE (5 cases)
- BenchmarkMariaDB_ForSystemTime: temporal table queries (5 cases)
- BenchmarkMariaDB_ConnectBy: hierarchical queries with PRIOR (4 cases)
- BenchmarkMariaDB_Mixed: combined features — CTE+temporal, CTE+CONNECT BY,
  CREATE TABLE WITH SYSTEM VERSIONING (3 cases)

Baseline (M2): 398–3001 ns/op, 984–6763 B/op

---------

Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini-2655.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
ajitpratap0 added a commit that referenced this pull request Mar 25, 2026
…tMap, unify config validation (#432)

* fix(playground): move useState/useCallback above early returns to fix React error #310

useState(copied) and useCallback(handleCopy) were declared after the
if (loading) and if (error) early returns, violating the Rules of Hooks.

When the WASM binary was a 404, the component always hit the error branch
so both renders exited with the same hook count. After committing the WASM
binary (#423), the component now successfully transitions loading→ready,
causing React to see 11 hooks instead of 9 on the second render → #310.

Fix: move both hooks above all conditional returns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(dialect): add DialectMariaDB constant to keyword dialect system

* fix(dialect): return MYSQL_SPECIFIC for DialectMariaDB and add to validDialects test

* fix(dialect): wire DialectMariaDB into keywords.New() to load MYSQL_SPECIFIC keywords

* test(dialect): add TestDialectMariaDB_InheritsMySQL to guard MySQL keyword inheritance

* feat(dialect): add MARIADB_SPECIFIC keyword list extending MySQL dialect

* feat(dialect): add MariaDB auto-detection hints (SEQUENCE, VERSIONING, CONNECT BY)

* fix(dialect): remove over-broad START WITH hint and complete DetectDialect doc comment

* fix(dialect): restore MariaDB CONNECT BY hint and add accumulation test

* feat(ast): add CreateSequenceStatement, DropSequenceStatement, AlterSequenceStatement nodes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ast): nil guard in sequence ToSQL, split Restart field, add sequence tests

- Guard s.Name nil dereference in CreateSequenceStatement.ToSQL,
  DropSequenceStatement.ToSQL, and AlterSequenceStatement.ToSQL
- Split SequenceOptions.Restart (*LiteralValue) into two fields:
  Restart bool (bare RESTART) and RestartWith *LiteralValue (RESTART WITH n)
- Update writeSequenceOptions to emit bare RESTART or RESTART WITH n accordingly
- Add ast_sequence_test.go with full ToSQL table-driven tests and pool round-trip test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ast): add ForSystemTimeClause, PeriodDefinition, temporal table fields

- Add SystemTimeClauseType enum with AS OF, BETWEEN, FROM/TO, ALL variants
- Add ForSystemTimeClause struct for MariaDB FOR SYSTEM_TIME temporal queries
- Add PeriodDefinition struct for PERIOD FOR clauses in CREATE TABLE
- Extend TableReference with ForSystemTime field (MariaDB 10.3.4+)
- Extend CreateTableStatement with WithSystemVersioning and PeriodDefinitions fields
- Add ForSystemTimeClause.ToSQL() and tableRefSQL integration in sql.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ast): add SQL() methods to temporal/CONNECT BY types and fix SelectStatement field order

Add SQL() methods to ForSystemTimeClause, ConnectByClause, and PeriodDefinition
(all implement expressionNode()) so they satisfy the Expression interface fully
without silently degrading via the exprSQL() fallback. Move StartWith and
ConnectBy fields in SelectStatement to directly follow Having, matching logical
SQL clause ordering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement CREATE/DROP/ALTER SEQUENCE parsing for MariaDB dialect

Add parseCreateSequenceStatement, parseDropSequenceStatement, and
parseAlterSequenceStatement to mariadb.go with full option parsing
(START WITH, INCREMENT BY, MINVALUE, MAXVALUE, CYCLE, CACHE, RESTART WITH).
Wire dispatch into parseStatement() for DROP/ALTER and into parseCreateStatement()
for CREATE. Gate all paths behind isMariaDB() so MySQL and other dialects
are unaffected. Add six passing parser tests in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement temporal table parsing (FOR SYSTEM_TIME, WITH SYSTEM VERSIONING, PERIOD FOR)

Add parseForSystemTimeClause and parseTemporalPointExpression to mariadb.go
supporting AS OF, BETWEEN, FROM/TO, and ALL variants. Hook into
parseFromTableReference in select_subquery.go (after alias, before SQL Server
hints) with a peek-ahead guard so FOR is only consumed when followed by
SYSTEM_TIME. Add WITH SYSTEM VERSIONING parsing to parseCreateTable (after
closing paren, before PARTITION BY) and PERIOD FOR column parsing to the
column loop in ddl.go. Add four passing tests for temporal queries and
system versioning in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement CONNECT BY hierarchical query parsing for MariaDB dialect

Add parseConnectByCondition to mariadb.go which handles the PRIOR prefix
operator by wrapping the referenced column in a FunctionCall node and
building a BinaryExpression for the full PRIOR col = parent_col pattern.
Wire START WITH and CONNECT BY [NOCYCLE] parsing into parseSelectStatement
in select.go after the HAVING clause. Guard CONNECT and START from being
consumed as table aliases in parseFromTableReference via a peek-ahead check
in select_subquery.go. Add three passing tests covering basic, NOCYCLE, and
no-START-WITH variants in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(parser): add bare RESTART test and nil guard for CONNECT BY condition

* test(parser): add MariaDB SQL test data files and file-based integration test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add MariaDB dialect to SQL_COMPATIBILITY.md and CHANGELOG.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address code review issues across AST, keywords, and parser

AST layer:
- Add `Prior` UnaryOperator constant for CONNECT BY PRIOR expressions
- Add `NoCache bool` to SequenceOptions (NOCACHE was previously a silent no-op)
- Add `Pos models.Location` to all 6 new MariaDB AST nodes (CreateSequence,
  DropSequence, AlterSequence, ForSystemTimeClause, ConnectByClause, PeriodDefinition)
- Add `NewDropSequenceStatement()` / `ReleaseDropSequenceStatement()` pool funcs
  to match Create/Alter sequence pooling consistency
- Emit NOCACHE in writeSequenceOptions when NoCache=true

Keywords:
- Remove duplicate MINVALUE, MAXVALUE, INCREMENT, RESTART, NOCACHE entries
  from MARIADB_SPECIFIC (already covered by base/Oracle keyword lists)

Parser:
- Fix PRIOR operator: switch from FunctionCall to UnaryExpression{Operator: Prior}
- Fix PRIOR on RHS: CONNECT BY col = PRIOR col now parsed correctly
- Fix parseJoinedTableRef: add isMariaDBClauseKeyword guard to prevent CONNECT/START
  from being consumed as table aliases (same guard already in parseFromTableReference)
- Fix parseJoinedTableRef: add FOR SYSTEM_TIME temporal clause support on JOIN refs
- Fix DROP SEQUENCE: support IF NOT EXISTS in addition to IF EXISTS
- Fix DROP SEQUENCE: use NewDropSequenceStatement() for pool consistency
- Fix parseSequenceOptions: set opts.NoCache=true for NOCACHE keyword
- Add comment in parseTemporalPointExpression explaining quote-stripping behaviour

Tests:
- Add TestMariaDB_ConnectBy_PriorOnRight
- Add TestMariaDB_DropSequence_IfNotExists
- Add TestMariaDB_Sequence_NoCache
- Expand testdata SQL files with NO MINVALUE/MAXVALUE forms, PRIOR-on-right cases,
  IF NOT EXISTS on DROP, and multi-table temporal JOIN query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address second code review pass — Pos, NO CACHE, CONNECT BY, dedup

Parser dispatch (parser.go, ddl.go, select.go):
- Populate Pos on CreateSequenceStatement (at SEQUENCE token in ddl.go)
- Populate Pos on DropSequenceStatement (at DROP token in parser.go)
- Populate Pos on AlterSequenceStatement (at ALTER token in parser.go)
- Populate Pos on ConnectByClause (at CONNECT token in select.go)
- Populate Pos on PeriodDefinition (at PERIOD token in ddl.go)

mariadb.go:
- Fix NO CACHE (two-token) to also set opts.NoCache=true, matching NOCACHE
- Fix parseConnectByCondition to handle complex AND/OR chains:
  CONNECT BY PRIOR id = parent_id AND active = 1 now fully parsed
- Extract isMariaDBClauseStart() method (was duplicated closure in two functions)
- Populate Pos on ForSystemTimeClause (at SYSTEM_TIME token)
- Add comment clarifying IF NOT EXISTS is a non-standard permissive extension

select_subquery.go:
- Remove both isMariaDBClauseKeyword closures, replace with p.isMariaDBClauseStart()

ast.go:
- Update DropSequenceStatement doc to show [IF EXISTS | IF NOT EXISTS]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): correct START WITH/CONNECT BY SQL order and implement PeriodDefinition.SQL()

- Move START WITH / CONNECT BY emission to after HAVING, before ORDER BY
- Implement PeriodDefinition.SQL() — was silently returning empty string
- Add round-trip tests for both fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): code review fixes — pool comments, expressionNode docs, PERIOD FOR SYSTEM_TIME test

- Add '// zero all fields' comment to ReleaseCreateSequenceStatement and ReleaseAlterSequenceStatement
- Add design-choice comments on expressionNode() for ForSystemTimeClause, ConnectByClause, PeriodDefinition
- Add TestMariaDB_CreateTable_PeriodForSystemTime to cover PERIOD FOR SYSTEM_TIME parsing
- Fix parsePeriodDefinition to use parseColumnName so SYSTEM_TIME (reserved keyword) is accepted as period name
- Add GENERATED ALWAYS AS ROW START/END column constraint parsing in parseColumnConstraint (MariaDB system-versioned columns)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(dialect): reduce MariaDB CONNECT BY hint weight to 2 so Oracle wins pure CONNECT BY queries

Oracle's CONNECT BY weight is 3; MariaDB's was also 3, causing a tie broken
by non-deterministic map iteration. Reducing MariaDB to weight 2 ensures
Oracle wins when CONNECT BY is the only hint. MariaDB is still correctly
detected when its unique high-weight hints (NEXTVAL, FOR SYSTEM_TIME, etc.)
are present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address code review — CycleOption enum, CACHE validation, structured errors

- Replace Cycle bool + NoCycle bool with CycleOption enum to prevent
  invalid state where both could be true simultaneously
- Add validation in parseSequenceOptions for contradictory CACHE/NOCACHE
- Replace fmt.Errorf with p.expectedError() for consistent error style

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* bench(mariadb): add MariaDB-specific parsing benchmarks

17 benchmarks across 4 groups:
- BenchmarkMariaDB_Sequence: CREATE/ALTER/DROP SEQUENCE (5 cases)
- BenchmarkMariaDB_ForSystemTime: temporal table queries (5 cases)
- BenchmarkMariaDB_ConnectBy: hierarchical queries with PRIOR (4 cases)
- BenchmarkMariaDB_Mixed: combined features — CTE+temporal, CTE+CONNECT BY,
  CREATE TABLE WITH SYSTEM VERSIONING (3 cases)

Baseline (M2): 398–3001 ns/op, 984–6763 B/op

* feat(playground): add Snowflake and MariaDB to dialect dropdown

Closes #428 — Snowflake was missing despite full keyword support.
Closes #426 (partial) — MariaDB playground integration complete.
Playground now exposes all 8 named dialects + Generic (9 total).

* fix(wasm): add mariadb to dialectMap so playground selection takes effect

Without this, selecting MariaDB in the dropdown silently fell back to
generic dialect parsing. The UI entry was a no-op at the parser layer.

* fix(wasm): add clickhouse to dialectMap (pre-existing silent fallback bug)

* fix(config): add snowflake to validDialects and update help text

snowflake was accepted by --dialect flag but rejected when set in
YAML config. Both layers are now consistent.

Part of #428.

* fix(config): add snowflake+mariadb to internal ValidDialects, tests, and doc comments

Add "snowflake" and "mariadb" to the ValidDialects slice and inline
validDialects list in cmd/gosqlx/internal/config, update corresponding
tests, and sync doc comments in pkg/config to reflect all supported
dialects including the two new ones.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(config): update remaining dialect doc strings and LSP runtime description

* docs: update dialect counts 7→8 and add MariaDB to all doc lists

- CLAUDE.md: add Snowflake + MariaDB (was missing both)
- README.md: 7→8 dialects in stats bar, add MariaDB to feature lists
- SQL_COMPATIBILITY.md: 6→8 Supported Dialects (add ClickHouse + MariaDB)
- website/src/lib/constants.ts: add MariaDB to feature description

Resolves #426 (docs integration)
Resolves #428 (count sync)

* docs: update dialect counts in publishing drafts (7→8, add MariaDB)

* chore: remove plan files from PR (internal docs)

---------

Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini-2655.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
ajitpratap0 added a commit that referenced this pull request Mar 25, 2026
* fix(playground): move useState/useCallback above early returns to fix React error #310

useState(copied) and useCallback(handleCopy) were declared after the
if (loading) and if (error) early returns, violating the Rules of Hooks.

When the WASM binary was a 404, the component always hit the error branch
so both renders exited with the same hook count. After committing the WASM
binary (#423), the component now successfully transitions loading→ready,
causing React to see 11 hooks instead of 9 on the second render → #310.

Fix: move both hooks above all conditional returns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(dialect): add DialectMariaDB constant to keyword dialect system

* fix(dialect): return MYSQL_SPECIFIC for DialectMariaDB and add to validDialects test

* fix(dialect): wire DialectMariaDB into keywords.New() to load MYSQL_SPECIFIC keywords

* test(dialect): add TestDialectMariaDB_InheritsMySQL to guard MySQL keyword inheritance

* feat(dialect): add MARIADB_SPECIFIC keyword list extending MySQL dialect

* feat(dialect): add MariaDB auto-detection hints (SEQUENCE, VERSIONING, CONNECT BY)

* fix(dialect): remove over-broad START WITH hint and complete DetectDialect doc comment

* fix(dialect): restore MariaDB CONNECT BY hint and add accumulation test

* feat(ast): add CreateSequenceStatement, DropSequenceStatement, AlterSequenceStatement nodes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ast): nil guard in sequence ToSQL, split Restart field, add sequence tests

- Guard s.Name nil dereference in CreateSequenceStatement.ToSQL,
  DropSequenceStatement.ToSQL, and AlterSequenceStatement.ToSQL
- Split SequenceOptions.Restart (*LiteralValue) into two fields:
  Restart bool (bare RESTART) and RestartWith *LiteralValue (RESTART WITH n)
- Update writeSequenceOptions to emit bare RESTART or RESTART WITH n accordingly
- Add ast_sequence_test.go with full ToSQL table-driven tests and pool round-trip test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(ast): add ForSystemTimeClause, PeriodDefinition, temporal table fields

- Add SystemTimeClauseType enum with AS OF, BETWEEN, FROM/TO, ALL variants
- Add ForSystemTimeClause struct for MariaDB FOR SYSTEM_TIME temporal queries
- Add PeriodDefinition struct for PERIOD FOR clauses in CREATE TABLE
- Extend TableReference with ForSystemTime field (MariaDB 10.3.4+)
- Extend CreateTableStatement with WithSystemVersioning and PeriodDefinitions fields
- Add ForSystemTimeClause.ToSQL() and tableRefSQL integration in sql.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ast): add SQL() methods to temporal/CONNECT BY types and fix SelectStatement field order

Add SQL() methods to ForSystemTimeClause, ConnectByClause, and PeriodDefinition
(all implement expressionNode()) so they satisfy the Expression interface fully
without silently degrading via the exprSQL() fallback. Move StartWith and
ConnectBy fields in SelectStatement to directly follow Having, matching logical
SQL clause ordering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement CREATE/DROP/ALTER SEQUENCE parsing for MariaDB dialect

Add parseCreateSequenceStatement, parseDropSequenceStatement, and
parseAlterSequenceStatement to mariadb.go with full option parsing
(START WITH, INCREMENT BY, MINVALUE, MAXVALUE, CYCLE, CACHE, RESTART WITH).
Wire dispatch into parseStatement() for DROP/ALTER and into parseCreateStatement()
for CREATE. Gate all paths behind isMariaDB() so MySQL and other dialects
are unaffected. Add six passing parser tests in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement temporal table parsing (FOR SYSTEM_TIME, WITH SYSTEM VERSIONING, PERIOD FOR)

Add parseForSystemTimeClause and parseTemporalPointExpression to mariadb.go
supporting AS OF, BETWEEN, FROM/TO, and ALL variants. Hook into
parseFromTableReference in select_subquery.go (after alias, before SQL Server
hints) with a peek-ahead guard so FOR is only consumed when followed by
SYSTEM_TIME. Add WITH SYSTEM VERSIONING parsing to parseCreateTable (after
closing paren, before PARTITION BY) and PERIOD FOR column parsing to the
column loop in ddl.go. Add four passing tests for temporal queries and
system versioning in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(parser): implement CONNECT BY hierarchical query parsing for MariaDB dialect

Add parseConnectByCondition to mariadb.go which handles the PRIOR prefix
operator by wrapping the referenced column in a FunctionCall node and
building a BinaryExpression for the full PRIOR col = parent_col pattern.
Wire START WITH and CONNECT BY [NOCYCLE] parsing into parseSelectStatement
in select.go after the HAVING clause. Guard CONNECT and START from being
consumed as table aliases in parseFromTableReference via a peek-ahead check
in select_subquery.go. Add three passing tests covering basic, NOCYCLE, and
no-START-WITH variants in mariadb_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(parser): add bare RESTART test and nil guard for CONNECT BY condition

* test(parser): add MariaDB SQL test data files and file-based integration test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add MariaDB dialect to SQL_COMPATIBILITY.md and CHANGELOG.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address code review issues across AST, keywords, and parser

AST layer:
- Add `Prior` UnaryOperator constant for CONNECT BY PRIOR expressions
- Add `NoCache bool` to SequenceOptions (NOCACHE was previously a silent no-op)
- Add `Pos models.Location` to all 6 new MariaDB AST nodes (CreateSequence,
  DropSequence, AlterSequence, ForSystemTimeClause, ConnectByClause, PeriodDefinition)
- Add `NewDropSequenceStatement()` / `ReleaseDropSequenceStatement()` pool funcs
  to match Create/Alter sequence pooling consistency
- Emit NOCACHE in writeSequenceOptions when NoCache=true

Keywords:
- Remove duplicate MINVALUE, MAXVALUE, INCREMENT, RESTART, NOCACHE entries
  from MARIADB_SPECIFIC (already covered by base/Oracle keyword lists)

Parser:
- Fix PRIOR operator: switch from FunctionCall to UnaryExpression{Operator: Prior}
- Fix PRIOR on RHS: CONNECT BY col = PRIOR col now parsed correctly
- Fix parseJoinedTableRef: add isMariaDBClauseKeyword guard to prevent CONNECT/START
  from being consumed as table aliases (same guard already in parseFromTableReference)
- Fix parseJoinedTableRef: add FOR SYSTEM_TIME temporal clause support on JOIN refs
- Fix DROP SEQUENCE: support IF NOT EXISTS in addition to IF EXISTS
- Fix DROP SEQUENCE: use NewDropSequenceStatement() for pool consistency
- Fix parseSequenceOptions: set opts.NoCache=true for NOCACHE keyword
- Add comment in parseTemporalPointExpression explaining quote-stripping behaviour

Tests:
- Add TestMariaDB_ConnectBy_PriorOnRight
- Add TestMariaDB_DropSequence_IfNotExists
- Add TestMariaDB_Sequence_NoCache
- Expand testdata SQL files with NO MINVALUE/MAXVALUE forms, PRIOR-on-right cases,
  IF NOT EXISTS on DROP, and multi-table temporal JOIN query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address second code review pass — Pos, NO CACHE, CONNECT BY, dedup

Parser dispatch (parser.go, ddl.go, select.go):
- Populate Pos on CreateSequenceStatement (at SEQUENCE token in ddl.go)
- Populate Pos on DropSequenceStatement (at DROP token in parser.go)
- Populate Pos on AlterSequenceStatement (at ALTER token in parser.go)
- Populate Pos on ConnectByClause (at CONNECT token in select.go)
- Populate Pos on PeriodDefinition (at PERIOD token in ddl.go)

mariadb.go:
- Fix NO CACHE (two-token) to also set opts.NoCache=true, matching NOCACHE
- Fix parseConnectByCondition to handle complex AND/OR chains:
  CONNECT BY PRIOR id = parent_id AND active = 1 now fully parsed
- Extract isMariaDBClauseStart() method (was duplicated closure in two functions)
- Populate Pos on ForSystemTimeClause (at SYSTEM_TIME token)
- Add comment clarifying IF NOT EXISTS is a non-standard permissive extension

select_subquery.go:
- Remove both isMariaDBClauseKeyword closures, replace with p.isMariaDBClauseStart()

ast.go:
- Update DropSequenceStatement doc to show [IF EXISTS | IF NOT EXISTS]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): correct START WITH/CONNECT BY SQL order and implement PeriodDefinition.SQL()

- Move START WITH / CONNECT BY emission to after HAVING, before ORDER BY
- Implement PeriodDefinition.SQL() — was silently returning empty string
- Add round-trip tests for both fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): code review fixes — pool comments, expressionNode docs, PERIOD FOR SYSTEM_TIME test

- Add '// zero all fields' comment to ReleaseCreateSequenceStatement and ReleaseAlterSequenceStatement
- Add design-choice comments on expressionNode() for ForSystemTimeClause, ConnectByClause, PeriodDefinition
- Add TestMariaDB_CreateTable_PeriodForSystemTime to cover PERIOD FOR SYSTEM_TIME parsing
- Fix parsePeriodDefinition to use parseColumnName so SYSTEM_TIME (reserved keyword) is accepted as period name
- Add GENERATED ALWAYS AS ROW START/END column constraint parsing in parseColumnConstraint (MariaDB system-versioned columns)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(dialect): reduce MariaDB CONNECT BY hint weight to 2 so Oracle wins pure CONNECT BY queries

Oracle's CONNECT BY weight is 3; MariaDB's was also 3, causing a tie broken
by non-deterministic map iteration. Reducing MariaDB to weight 2 ensures
Oracle wins when CONNECT BY is the only hint. MariaDB is still correctly
detected when its unique high-weight hints (NEXTVAL, FOR SYSTEM_TIME, etc.)
are present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(mariadb): address code review — CycleOption enum, CACHE validation, structured errors

- Replace Cycle bool + NoCycle bool with CycleOption enum to prevent
  invalid state where both could be true simultaneously
- Add validation in parseSequenceOptions for contradictory CACHE/NOCACHE
- Replace fmt.Errorf with p.expectedError() for consistent error style

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* bench(mariadb): add MariaDB-specific parsing benchmarks

17 benchmarks across 4 groups:
- BenchmarkMariaDB_Sequence: CREATE/ALTER/DROP SEQUENCE (5 cases)
- BenchmarkMariaDB_ForSystemTime: temporal table queries (5 cases)
- BenchmarkMariaDB_ConnectBy: hierarchical queries with PRIOR (4 cases)
- BenchmarkMariaDB_Mixed: combined features — CTE+temporal, CTE+CONNECT BY,
  CREATE TABLE WITH SYSTEM VERSIONING (3 cases)

Baseline (M2): 398–3001 ns/op, 984–6763 B/op

* feat(playground): add Snowflake and MariaDB to dialect dropdown

Closes #428 — Snowflake was missing despite full keyword support.
Closes #426 (partial) — MariaDB playground integration complete.
Playground now exposes all 8 named dialects + Generic (9 total).

* fix(wasm): add mariadb to dialectMap so playground selection takes effect

Without this, selecting MariaDB in the dropdown silently fell back to
generic dialect parsing. The UI entry was a no-op at the parser layer.

* fix(wasm): add clickhouse to dialectMap (pre-existing silent fallback bug)

* fix(config): add snowflake to validDialects and update help text

snowflake was accepted by --dialect flag but rejected when set in
YAML config. Both layers are now consistent.

Part of #428.

* fix(config): add snowflake+mariadb to internal ValidDialects, tests, and doc comments

Add "snowflake" and "mariadb" to the ValidDialects slice and inline
validDialects list in cmd/gosqlx/internal/config, update corresponding
tests, and sync doc comments in pkg/config to reflect all supported
dialects including the two new ones.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(config): update remaining dialect doc strings and LSP runtime description

* docs: update dialect counts 7→8 and add MariaDB to all doc lists

- CLAUDE.md: add Snowflake + MariaDB (was missing both)
- README.md: 7→8 dialects in stats bar, add MariaDB to feature lists
- SQL_COMPATIBILITY.md: 6→8 Supported Dialects (add ClickHouse + MariaDB)
- website/src/lib/constants.ts: add MariaDB to feature description

Resolves #426 (docs integration)
Resolves #428 (count sync)

* docs: update dialect counts in publishing drafts (7→8, add MariaDB)

* chore: remove plan files from PR (internal docs)

* fix(analytics): add missing Analytics component to layout

@vercel/analytics was installed but <Analytics /> was never rendered,
causing 0 data collection. Adds the component from @vercel/analytics/next
for App Router compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(website): add Speed Insights, fix Analytics CSP

- Add @vercel/speed-insights package
- Render <SpeedInsights /> in root layout alongside <Analytics />
- Add vitals.vercel-insights.com to connect-src CSP so Speed
  Insights beacons are not blocked by the security policy

Both Web Analytics and Speed Insights were silently broken:
Analytics had no component rendered; Speed Insights was not
installed; and the CSP would have blocked beacon requests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini-2655.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P2-5: Rewrite GitHub Action Shell Scripts in Go

2 participants