Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ node scripts/compare-corpus-reports.js target/corpus-report.json target/corpus-r
- Handles panics and stack overflows gracefully
- Same binary used in GitHub Actions (`.github/workflows/corpus.yml`)
- Can be used for profiling (same workload as tests)
- `customer_*` dialect prefixes automatically stripped (customer_bigquery → bigquery)
- `customer_*` and `synq_*` dialect prefixes automatically stripped (customer_bigquery → bigquery, synq_clickhouse → clickhouse)
- **Cannot run corpus-runner on subdirectories** — dialect is extracted from first path component relative to corpus root
- **Corpus files are symlinked** from `kernel-cll-corpus` repo — commit corpus changes there, not in sqlparser-rs
- Analyze failures: parse `target/corpus-report.json` with Python to filter/group `test_results` by dialect or error pattern

**Development workflow:**
- Use corpus-runner for fast feedback (6.7s vs 2+ hours)
Expand Down Expand Up @@ -245,6 +248,11 @@ Semantic analysis varies drastically between SQL dialects and is left to consume
3. **Add Tests**: Write dialect-specific tests in appropriate test file
4. **Consider Dialect**: Use `dialect_of!` if syntax is dialect-specific

#### Adding New Keywords
Keywords in `src/keywords.rs` MUST be in strict alphabetical order — `ALL_KEYWORDS` uses binary search.
If a keyword is out of order, the tokenizer silently fails to recognize it (maps to `Keyword::NoKeyword`).
Verify ordering carefully: e.g., `EXCHANGE` < `EXCLUDE` < `EXEC` (compare character by character).

#### AST Change Workflow
When adding fields to AST structs, you must update ALL pattern matches:
1. Add field to struct definition (e.g., `src/ast/mod.rs`, `src/ast/query.rs`)
Expand Down
80 changes: 78 additions & 2 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use sqlparser_derive::{Visit, VisitMut};

use crate::ast::value::escape_single_quote_string;
use crate::ast::{
display_comma_separated, display_separated, DataType, Expr, Ident, ObjectName, OrderBy, Select,
SequenceOptions,
display_comma_separated, display_separated, Assignment, DataType, Expr, Ident, ObjectName,
OrderBy, Select, SequenceOptions,
};
use crate::tokenizer::Token;

Expand Down Expand Up @@ -158,6 +158,45 @@ pub enum AlterTableOperation {
/// Note: this is a ClickHouse-specific operation
/// <https://clickhouse.com/docs/sql-reference/statements/alter/projection>
DropProjection { if_exists: bool, name: Ident },

/// `MODIFY COLUMN <column_name> <data_type> [<options>]`
///
/// Note: this is a ClickHouse-specific operation
/// <https://clickhouse.com/docs/en/sql-reference/statements/alter/column#modify-column>
ModifyColumn {
column_name: Ident,
/// Data type is optional (e.g., `MODIFY COLUMN x REMOVE DEFAULT` has no type)
column_type: Option<DataType>,
/// Optional column options (e.g., DEFAULT, REMOVE DEFAULT, etc.)
options: Vec<ColumnOption>,
},

/// `MATERIALIZE COLUMN <column_name>`
///
/// Note: this is a ClickHouse-specific operation
/// <https://clickhouse.com/docs/en/sql-reference/statements/alter/column#materialize-column>
MaterializeColumn { column_name: Ident },

/// `MATERIALIZE PROJECTION <projection_name>`
///
/// Note: this is a ClickHouse-specific operation
/// <https://clickhouse.com/docs/sql-reference/statements/alter/projection>
MaterializeProjection { name: Ident },

/// `DROP INDEX [IF EXISTS] <index_name>`
///
/// Note: this is a ClickHouse-specific operation
/// <https://clickhouse.com/docs/en/sql-reference/statements/alter/index#drop-index>
DropIndex { if_exists: bool, name: Ident },

/// `UPDATE <column> = <expr> [, ...] WHERE <condition>`
///
/// Note: this is a ClickHouse-specific operation (lightweight mutation)
/// <https://clickhouse.com/docs/en/sql-reference/statements/alter/update>
UpdateData {
assignments: Vec<Assignment>,
selection: Option<Expr>,
},
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
Expand Down Expand Up @@ -314,6 +353,43 @@ impl fmt::Display for AlterTableOperation {
}
write!(f, " {name}")
}
AlterTableOperation::ModifyColumn {
column_name,
column_type,
options,
} => {
write!(f, "MODIFY COLUMN {column_name}")?;
if let Some(dt) = column_type {
write!(f, " {dt}")?;
}
for option in options {
write!(f, " {option}")?;
}
Ok(())
}
AlterTableOperation::MaterializeColumn { column_name } => {
write!(f, "MATERIALIZE COLUMN {column_name}")
}
AlterTableOperation::MaterializeProjection { name } => {
write!(f, "MATERIALIZE PROJECTION {name}")
}
AlterTableOperation::DropIndex { if_exists, name } => {
write!(f, "DROP INDEX")?;
if *if_exists {
write!(f, " IF EXISTS")?;
}
write!(f, " {name}")
}
AlterTableOperation::UpdateData {
assignments,
selection,
} => {
write!(f, "UPDATE {}", display_comma_separated(assignments))?;
if let Some(predicate) = selection {
write!(f, " WHERE {predicate}")?;
}
Ok(())
}
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,16 @@ pub enum Statement {
name: Ident,
operation: AlterRoleOperation,
},
/// `EXCHANGE TABLES <table1> AND <table2>`
///
/// Note: this is a ClickHouse-specific statement
/// <https://clickhouse.com/docs/en/sql-reference/statements/exchange>
ExchangeTables {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
first: ObjectName,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
second: ObjectName,
},
/// DROP
Drop {
/// The type of the object to drop: TABLE, VIEW, etc.
Expand Down Expand Up @@ -3539,6 +3549,9 @@ impl fmt::Display for Statement {
operations = display_comma_separated(operations)
)
}
Statement::ExchangeTables { first, second } => {
write!(f, "EXCHANGE TABLES {first} AND {second}")
}
Statement::AlterIndex { name, operation } => {
write!(f, "ALTER INDEX {name} {operation}")
}
Expand Down
4 changes: 4 additions & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ define_keywords!(
EVENT,
EVERY,
EXCEPT,
EXCHANGE,
EXCLUDE,
EXEC,
EXECUTE,
Expand Down Expand Up @@ -437,6 +438,7 @@ define_keywords!(
MATCHED,
MATCH_CONDITION,
MATCH_RECOGNIZE,
MATERIALIZE,
MATERIALIZED,
MAX,
MAXVALUE,
Expand All @@ -460,6 +462,7 @@ define_keywords!(
MODE,
MODEL,
MODIFIES,
MODIFY,
MODULE,
MONTH,
MONTHS,
Expand Down Expand Up @@ -595,6 +598,7 @@ define_keywords!(
RELATIVE,
RELEASE,
RELY,
REMOVE,
RENAME,
REORG,
REPAIR,
Expand Down
Loading