diff --git a/CLAUDE.md b/CLAUDE.md index 8c844162..14c2090f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,7 @@ GoSQLX is a **production-ready**, **race-free**, high-performance SQL parsing SD - Thread-safe with zero race conditions (20,000+ concurrent operations tested) - 1.38M+ ops/sec sustained, 1.5M peak with memory-efficient object pooling - ~80-85% SQL-99 compliance (window functions, CTEs, set operations, MERGE, etc.) -- Multi-dialect support: PostgreSQL, MySQL, SQL Server, Oracle, SQLite, ClickHouse +- Multi-dialect support: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, Snowflake, ClickHouse (8 dialects) ## Architecture diff --git a/README.md b/README.md index e8e3d6a2..7144fde7 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@
-| **1.38M+ ops/sec** | **<1渭s latency** | **85% SQL-99** | **7 dialects** | **0 race conditions** | +| **1.38M+ ops/sec** | **<1渭s latency** | **85% SQL-99** | **8 dialects** | **0 race conditions** | |:---:|:---:|:---:|:---:|:---:| @@ -48,7 +48,7 @@ ast, _ := gosqlx.Parse("SELECT u.name, COUNT(*) FROM users u JOIN orders o ON u. - **Not an ORM** - a parser. You get the AST, you decide what to do with it. - **Not slow** - zero-copy tokenization, sync.Pool recycling, no allocations on hot paths. -- **Not limited** - PostgreSQL, MySQL, SQL Server, Oracle, SQLite, Snowflake, ClickHouse. CTEs, window functions, MERGE, set operations. +- **Not limited** - PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, Snowflake, ClickHouse. CTEs, window functions, MERGE, set operations. - **Not just a library** - CLI, VS Code extension, GitHub Action, MCP server, WASM playground, Python bindings.
@@ -140,7 +140,7 @@ claude mcp add --transport http gosqlx \

馃敡 Tooling

AST-based formatter
Query transforms API
VS Code extension
GitHub Action -

馃寪 Multi-Dialect

PostgreSQL 路 MySQL
SQL Server 路 Oracle
SQLite 路 Snowflake +

馃寪 Multi-Dialect

PostgreSQL 路 MySQL 路 MariaDB
SQL Server 路 Oracle
SQLite 路 Snowflake 路 ClickHouse

馃 AI-Ready

MCP server (7 tools)
Public remote endpoint
Streamable HTTP

馃И Battle-Tested

20K+ concurrent ops
Zero race conditions
~85% SQL-99 compliance diff --git a/cmd/gosqlx/cmd/validate.go b/cmd/gosqlx/cmd/validate.go index 8284c73e..51153f26 100644 --- a/cmd/gosqlx/cmd/validate.go +++ b/cmd/gosqlx/cmd/validate.go @@ -89,7 +89,7 @@ func validateRun(cmd *cobra.Command, args []string) error { // Reject unknown dialect names early before any parsing. if validateDialect != "" && !keywords.IsValidDialect(validateDialect) { - return fmt.Errorf("unknown SQL dialect %q; valid dialects: postgresql, mysql, sqlserver, oracle, sqlite, snowflake, bigquery, redshift", validateDialect) + return fmt.Errorf("unknown SQL dialect %q; valid dialects: postgresql, mysql, mariadb, sqlserver, oracle, sqlite, snowflake, bigquery, redshift", validateDialect) } // Handle stdin input @@ -334,7 +334,7 @@ func init() { validateCmd.Flags().BoolVarP(&validateQuiet, "quiet", "q", false, "quiet mode (exit code only)") validateCmd.Flags().BoolVar(&validateQuiet, "check", false, "check mode (alias for --quiet): exit code only, no output") validateCmd.Flags().BoolVarP(&validateStats, "stats", "s", false, "show performance statistics") - validateCmd.Flags().StringVar(&validateDialect, "dialect", "", "SQL dialect: postgresql, mysql, sqlserver, oracle, sqlite (config: validate.dialect)") + validateCmd.Flags().StringVar(&validateDialect, "dialect", "", "SQL dialect: postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite (config: validate.dialect)") validateCmd.Flags().BoolVar(&validateStrict, "strict", false, "enable strict validation mode (config: validate.strict_mode)") validateCmd.Flags().StringVar(&validateOutputFormat, "output-format", "text", "output format: text, json, sarif") validateCmd.Flags().StringVar(&validateOutputFile, "output-file", "", "output file path (default: stdout)") diff --git a/cmd/gosqlx/internal/config/config.go b/cmd/gosqlx/internal/config/config.go index 686a9f85..d1665099 100644 --- a/cmd/gosqlx/internal/config/config.go +++ b/cmd/gosqlx/internal/config/config.go @@ -84,7 +84,7 @@ type FormatConfig struct { // Controls validation behavior including dialect selection and security limits. // // Fields: -// - Dialect: SQL dialect for validation (postgresql, mysql, sqlserver, oracle, sqlite, generic) +// - Dialect: SQL dialect for validation (postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite, generic) // - StrictMode: Enable strict validation rules (default: false) // - Recursive: Recursively process directories (default: false) // - Pattern: File pattern for recursive processing (default: "*.sql") @@ -345,7 +345,7 @@ func (c *Config) Validate() error { // Validate dialect (empty string means permissive/no dialect gates) if c.Validation.Dialect != "" { - validDialects := []string{"postgresql", "mysql", "sqlserver", "oracle", "sqlite", "generic"} + validDialects := []string{"postgresql", "mysql", "mariadb", "snowflake", "sqlserver", "oracle", "sqlite", "generic"} dialectValid := false for _, d := range validDialects { if c.Validation.Dialect == d { diff --git a/cmd/gosqlx/internal/config/doc.go b/cmd/gosqlx/internal/config/doc.go index b85fafa8..a991f043 100644 --- a/cmd/gosqlx/internal/config/doc.go +++ b/cmd/gosqlx/internal/config/doc.go @@ -152,7 +152,7 @@ // max_file_size: 10485760 # Maximum file size in bytes // // Fields: -// - Dialect: SQL dialect (postgresql, mysql, sqlserver, oracle, sqlite, generic) +// - Dialect: SQL dialect (postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite, generic) // - StrictMode: Enable strict validation rules (default: false) // - Recursive: Recursively process directories (default: false) // - Pattern: File pattern for recursive processing (default: "*.sql") @@ -195,7 +195,7 @@ // - MaxLineLength: 0-500 characters // // Validation validation: -// - Dialect: Must be one of: postgresql, mysql, sqlserver, oracle, sqlite, generic +// - Dialect: Must be one of: postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite, generic // // Output validation: // - Format: Must be one of: json, yaml, table, tree, auto diff --git a/cmd/gosqlx/internal/config/schema.go b/cmd/gosqlx/internal/config/schema.go index 0131dc27..d536667d 100644 --- a/cmd/gosqlx/internal/config/schema.go +++ b/cmd/gosqlx/internal/config/schema.go @@ -23,6 +23,8 @@ import ( var ValidDialects = []string{ "postgresql", "mysql", + "mariadb", + "snowflake", "sqlserver", "oracle", "sqlite", diff --git a/cmd/gosqlx/internal/config/schema_test.go b/cmd/gosqlx/internal/config/schema_test.go index d2dc734d..69457570 100644 --- a/cmd/gosqlx/internal/config/schema_test.go +++ b/cmd/gosqlx/internal/config/schema_test.go @@ -26,6 +26,8 @@ func TestValidateDialect(t *testing.T) { }{ {"valid postgresql", "postgresql", false}, {"valid mysql", "mysql", false}, + {"valid mariadb", "mariadb", false}, + {"valid snowflake", "snowflake", false}, {"valid sqlserver", "sqlserver", false}, {"valid oracle", "oracle", false}, {"valid sqlite", "sqlite", false}, @@ -225,7 +227,7 @@ func TestGetSchema(t *testing.T) { } func TestValidDialects(t *testing.T) { - expectedDialects := []string{"postgresql", "mysql", "sqlserver", "oracle", "sqlite", "generic"} + expectedDialects := []string{"postgresql", "mysql", "mariadb", "snowflake", "sqlserver", "oracle", "sqlite", "generic"} if len(ValidDialects) != len(expectedDialects) { t.Errorf("expected %d dialects, got %d", len(expectedDialects), len(ValidDialects)) diff --git a/docs/SQL_COMPATIBILITY.md b/docs/SQL_COMPATIBILITY.md index f62dcbf7..d3700db3 100644 --- a/docs/SQL_COMPATIBILITY.md +++ b/docs/SQL_COMPATIBILITY.md @@ -862,7 +862,7 @@ gosqlx format --dialect mysql query.sql 1. **ParseWithDialect()** - Parse SQL with dialect-specific syntax 2. **ValidateWithDialect()** - Validate with dialect awareness 3. **--dialect CLI flag** - Specify dialect for CLI commands -4. **6 Supported Dialects** - PostgreSQL, MySQL, SQL Server, Oracle, SQLite, Snowflake +4. **8 Supported Dialects** - PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, Snowflake, ClickHouse ### MySQL Syntax (11 Features) 1. **SHOW statements** - SHOW TABLES, DATABASES, CREATE TABLE diff --git a/pkg/config/config.go b/pkg/config/config.go index 68536fb0..7cca0d8a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -77,12 +77,12 @@ type FormatConfig struct { // ValidationConfig holds SQL validation options for the parser and validator. // // The Dialect field determines which SQL keywords and syntax are recognized. -// Supported values: "postgresql", "mysql", "sqlserver", "oracle", "sqlite". +// Supported values: "postgresql", "mysql", "mariadb", "snowflake", "sqlserver", "oracle", "sqlite". // // The Pattern field is used for recursive file validation and supports standard // glob patterns like "*.sql", "queries/**/*.sql", etc. type ValidationConfig struct { - Dialect string `yaml:"dialect" json:"dialect"` // SQL dialect: postgresql, mysql, sqlserver, oracle, sqlite (default: "postgresql") + Dialect string `yaml:"dialect" json:"dialect"` // SQL dialect: postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite (default: "postgresql") StrictMode *bool `yaml:"strict_mode" json:"strictMode"` // Enable strict validation mode (default: false) Recursive *bool `yaml:"recursive" json:"recursive"` // Recursively validate files in directories (default: false) Pattern string `yaml:"pattern" json:"pattern"` // File pattern for recursive validation (default: "*.sql") @@ -215,12 +215,14 @@ func (c *Config) Validate() error { validDialects := map[string]bool{ "postgresql": true, "mysql": true, + "mariadb": true, + "snowflake": true, "sqlserver": true, "oracle": true, "sqlite": true, } if c.Validation.Dialect != "" && !validDialects[c.Validation.Dialect] { - return fmt.Errorf("validation.dialect must be one of: postgresql, mysql, sqlserver, oracle, sqlite; got %q", c.Validation.Dialect) + return fmt.Errorf("validation.dialect must be one of: postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite; got %q", c.Validation.Dialect) } if c.Validation.Security.MaxFileSize < 0 { return fmt.Errorf("validation.security.max_file_size must be non-negative, got %d", c.Validation.Security.MaxFileSize) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 5fb10319..daff813d 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -231,7 +231,7 @@ func TestConfigMerge(t *testing.T) { } func TestConfigDialects(t *testing.T) { - validDialects := []string{"postgresql", "mysql", "sqlserver", "oracle", "sqlite"} + validDialects := []string{"postgresql", "mysql", "mariadb", "snowflake", "sqlserver", "oracle", "sqlite"} for _, dialect := range validDialects { t.Run(dialect, func(t *testing.T) { diff --git a/pkg/config/doc.go b/pkg/config/doc.go index aa4300fe..d2834f48 100644 --- a/pkg/config/doc.go +++ b/pkg/config/doc.go @@ -47,7 +47,7 @@ // // Validation: SQL validation and dialect settings // -// - dialect: Target SQL dialect - postgresql, mysql, sqlserver, oracle, sqlite (default: postgresql) +// - dialect: Target SQL dialect - postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite (default: postgresql) // - strict_mode: Enable strict validation mode (default: false) // - recursive: Recursively validate files in directories (default: false) // - pattern: File pattern for recursive validation (default: "*.sql") @@ -246,7 +246,7 @@ // Validation checks: // // - Format: Non-negative indent and max_line_length -// - Validation: Valid dialect (postgresql, mysql, sqlserver, oracle, sqlite) +// - Validation: Valid dialect (postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite) // - Output: Valid format (text, json, yaml) // - LSP: Non-negative rate limits, timeouts, and size limits // - LSP: Valid trace server level (off, messages, verbose) diff --git a/pkg/config/lsp.go b/pkg/config/lsp.go index c9564dd0..076e8a01 100644 --- a/pkg/config/lsp.go +++ b/pkg/config/lsp.go @@ -335,7 +335,7 @@ func GetLSPConfigSections() []LSPConfigSection { Description: "SQL validation options", DefaultValue: ToLSPSettings(defaults)["validation"], Properties: map[string]interface{}{ - "dialect": "SQL dialect (postgresql, mysql, sqlserver, oracle, sqlite)", + "dialect": "SQL dialect (postgresql, mysql, mariadb, snowflake, sqlserver, oracle, sqlite)", "strictMode": "Enable strict validation mode", }, }, diff --git a/wasm/main.go b/wasm/main.go index c19f94f2..9130306e 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -36,6 +36,8 @@ var dialectMap = map[string]sqlkeywords.SQLDialect{ "generic": sqlkeywords.DialectGeneric, "postgresql": sqlkeywords.DialectPostgreSQL, "mysql": sqlkeywords.DialectMySQL, + "mariadb": sqlkeywords.DialectMariaDB, + "clickhouse": sqlkeywords.DialectClickHouse, "sqlite": sqlkeywords.DialectSQLite, "sqlserver": sqlkeywords.DialectSQLServer, "oracle": sqlkeywords.DialectOracle, diff --git a/website/src/components/playground/Playground.tsx b/website/src/components/playground/Playground.tsx index 29f88d1c..5bd8f19e 100644 --- a/website/src/components/playground/Playground.tsx +++ b/website/src/components/playground/Playground.tsx @@ -22,9 +22,11 @@ const DIALECTS = [ { value: "generic", label: "Generic" }, { value: "postgresql", label: "PostgreSQL" }, { value: "mysql", label: "MySQL" }, + { value: "mariadb", label: "MariaDB" }, { value: "sqlite", label: "SQLite" }, { value: "sqlserver", label: "SQL Server" }, { value: "oracle", label: "Oracle" }, + { value: "snowflake", label: "Snowflake" }, { value: "clickhouse", label: "ClickHouse" }, ]; diff --git a/website/src/lib/constants.ts b/website/src/lib/constants.ts index 2780a43a..005a03a3 100644 --- a/website/src/lib/constants.ts +++ b/website/src/lib/constants.ts @@ -7,7 +7,7 @@ export const NAV_LINKS = [ ]; export const FEATURES = [ - { icon: 'globe', title: 'Multi-Dialect', description: 'PostgreSQL, MySQL, SQLite, SQL Server, Oracle, Snowflake, ClickHouse.', color: 'accent-purple' }, + { icon: 'globe', title: 'Multi-Dialect', description: 'PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, Snowflake, ClickHouse.', color: 'accent-purple' }, { icon: 'lock', title: 'Thread-Safe', description: 'Zero race conditions. 20,000+ concurrent ops tested.', color: 'accent-green' }, { icon: 'bolt', title: 'Zero-Copy', description: 'Direct byte slice operations. No unnecessary allocations.', color: 'accent-orange' }, { icon: 'recycle', title: 'Object Pooling', description: 'sync.Pool recycling for ASTs, tokenizers, expressions.', color: 'accent-indigo' },