astgrep supports multi-dialect SQL analysis. Each dialect uses a specialized parser for accurate AST construction, enabling dialect-aware rule matching.
| Dialect | --dialect value |
Parser | Coverage |
|---|---|---|---|
| Standard SQL | standard (default) |
tree-sitter-sequel 0.3.11 | Generic SQL (ANSI) |
| GaussDB | gaussdb |
ogsql-parser v0.6.20 | Full GaussDB DML/DDL + PREDICT BY / TIMECAPSULE / SHRINK / Plan Hints |
| OpenGauss | opengauss |
ogsql-parser v0.6.20 | Shares GaussDB implementation |
| PolarDB-MySQL | polardb-mysql |
sqlparser-rs v0.62 (MySqlDialect) | MySQL DML/DDL + PolarDB keyword detection |
# GaussDB compatibility scan
astgrep analyze --dialect gaussdb --rules rules/gaussdb/ *.sql
# OpenGauss
astgrep analyze --dialect opengauss --rules rules/gaussdb/ *.sql
# PolarDB-MySQL
astgrep analyze --dialect polardb-mysql --rules rules/polardb/ *.sql
# Standard SQL (default, backward compatible)
astgrep analyze *.sqlRules can declare which dialects they apply to:
rules:
- id: gaussdb-no-on-conflict
name: "GaussDB does not support ON CONFLICT"
languages: [sql]
dialects: [gaussdb, opengauss] # only fires for these dialects
patterns:
- pattern: "ON CONFLICT"
message: "Use MERGE INTO instead"
severity: ERRORRules without dialects: apply to ALL dialects (backward compatible).
astgrep supports three pattern types for SQL:
Literal patterns (text-based, work across all parsers):
patterns:
- pattern: "VARCHAR2"Metavariable patterns (structural matching via tree-sitter):
patterns:
- pattern: "SELECT * FROM $TABLE"Structural patterns with negation (detect absence of clauses):
patterns:
- pattern: "UPDATE $T SET $S"
- pattern-not: "UPDATE $T SET $S WHERE $W"Located at tests/categories/rules/sql_dialects/gaussdb/:
| Rule ID | Category | Description |
|---|---|---|
| GAUSSDB-TYPE-001 | Type | VARCHAR2 Oracle-compat type |
| GAUSSDB-TYPE-002 | Type | NUMBER Oracle-compat type |
| GAUSSDB-CONFLICT-001 | Compat | ON CONFLICT not supported |
| GAUSSDB-STORE-001 | Storage | ustore/astore detection |
| GAUSSDB-PREDICT-001 | AI | PREDICT BY feature |
| GAUSSDB-TIMECAPSULE-001 | Compat | TIMECAPSULE flashback |
| GAUSSDB-SHRINK-001 | Compat | SHRINK TABLE/INDEX |
| GAUSSDB-SEC-001 | Security | SELECT * warning |
| GAUSSDB-SEC-002 | Security | UPDATE without WHERE |
| GAUSSDB-SEC-003 | Security | DELETE without WHERE |
| GAUSSDB-HINT-001 | Perf | Plan Hint usage |
| GAUSSDB-MERGE-001 | Semantic | MERGE DELETE not supported (validator) |
| GAUSSDB-MERGE-002 | Semantic | ON column updated (validator) |
| GAUSSDB-MERGE-003 | Semantic | DUAL table (validator) |
Located at tests/categories/rules/sql_dialects/polardb_mysql/:
| Rule ID | Category | Description |
|---|---|---|
| POLARDB-GSI-001 | Compat | GLOBAL INDEX syntax |
| POLARDB-SHARD-001 | Compat | DBPARTITION sharding |
| POLARDB-VERCOMMENT-001 | Compat | /*!99990 versioned comment |
| POLARDB-SEC-001 | Security | SELECT * warning |
| POLARDB-SEC-002 | Security | UPDATE without WHERE |
| POLARDB-SEC-003 | Security | DELETE without WHERE |
CLI (--dialect gaussdb)
→ AnalysisConfig.sql_dialect = Some(GaussDB)
→ analyze_with_rule_engine()
→ if SQL + non-Standard dialect:
dispatch(SqlDialect::GaussDB).parse(source) → UniversalNode
→ Rule engine (filters by dialects: field)
→ Pattern matching (literal + metavariable + pattern-not)
→ ogsql validators (GaussDB semantic checks)
| Dialect | Adapter | Underlying parser |
|---|---|---|
| Standard | SqlParser (existing) |
tree-sitter-sequel |
| GaussDB/OpenGauss | OgsqlAdapter |
ogsql-parser (hand-written Rust) |
| PolarDB-MySQL | SqlparserAdapter |
sqlparser-rs (Apache DataFusion) |
All adapters produce UniversalNode — the canonical AST type. Rule matching operates on UniversalNode regardless of source parser.
For GaussDB/OpenGauss, ogsql-parser's built-in semantic validators run after pattern matching:
validate_merge_semantics()— detects GaussDB-specific MERGE restrictions- Runs independently of rule files (always active for GaussDB dialect)
- Add variant to
SqlDialectenum incrates/astgrep-core/src/types.rs - Create adapter in
crates/astgrep-parser/src/adapter/{name}/mod.rs - Create dialect parser in
crates/astgrep-parser/src/dialect/{name}.rs - Wire into
dispatch()incrates/astgrep-parser/src/dialect/mod.rs - Apply
.with_text(source)in dialectparse()for metavariable support - Write rules with
dialects: [{name}]
Create YAML files under tests/categories/rules/sql_dialects/{dialect}/:
rules:
- id: {DIALECT}-{CATEGORY}-{NUM}
name: "Rule name"
languages: [sql]
dialects: [{dialect}]
patterns:
- pattern: "..."
message: "Description"
severity: WARNING # INFO | WARNING | ERROR | CRITICAL
confidence: HIGH # LOW | MEDIUM | HIGH