agent_patch
runs/2026-02-28__18-27-22__gpt-5-3-codex/flux-pr-1747/flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/agent-logs/agent.patch
44850 bytes
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/dml.rs b/app/src/ast/dml.rs
index 9cdb1ca..665df4e 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/dml.rs
+++ b/app/src/ast/dml.rs
@@ -33,11 +33,11 @@ pub use super::ddl::{ColumnDef, TableConstraint};
use super::{
display_comma_separated, display_separated, query::InputFormatClause, Assignment, ClusteredBy,
- CommentDef, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat,
- HiveRowFormat, Ident, IndexType, InsertAliases, MysqlInsertPriority, ObjectName, OnCommit,
- OnInsert, OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem, Setting,
- SqlOption, SqliteOnConflict, StorageSerializationPolicy, TableEngine, TableObject,
- TableWithJoins, Tag, WrappedCollection,
+ CommentDef, CreateTableOptions, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat,
+ HiveIOFormat, HiveRowFormat, Ident, IndexType, InsertAliases, MysqlInsertPriority, ObjectName,
+ OnCommit, OnInsert, OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem,
+ Setting, SqlOption, SqliteOnConflict, StorageSerializationPolicy, TableObject, TableWithJoins,
+ Tag, WrappedCollection,
};
/// Index column type.
@@ -146,19 +146,14 @@ pub struct CreateTable {
pub constraints: Vec<TableConstraint>,
pub hive_distribution: HiveDistributionStyle,
pub hive_formats: Option<HiveFormat>,
- pub table_properties: Vec<SqlOption>,
- pub with_options: Vec<SqlOption>,
+ pub create_table_options: Vec<CreateTableOptions>,
pub file_format: Option<FileFormat>,
pub location: Option<String>,
pub query: Option<Box<Query>>,
pub without_rowid: bool,
pub like: Option<ObjectName>,
pub clone: Option<ObjectName>,
- pub engine: Option<TableEngine>,
pub comment: Option<CommentDef>,
- pub auto_increment_offset: Option<u32>,
- pub default_charset: Option<String>,
- pub collation: Option<String>,
pub on_commit: Option<OnCommit>,
/// ClickHouse "ON CLUSTER" clause:
/// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
@@ -375,18 +370,8 @@ impl Display for CreateTable {
}
write!(f, " LOCATION '{}'", self.location.as_ref().unwrap())?;
}
- if !self.table_properties.is_empty() {
- write!(
- f,
- " TBLPROPERTIES ({})",
- display_comma_separated(&self.table_properties)
- )?;
- }
- if !self.with_options.is_empty() {
- write!(f, " WITH ({})", display_comma_separated(&self.with_options))?;
- }
- if let Some(engine) = &self.engine {
- write!(f, " ENGINE={engine}")?;
+ for option in &self.create_table_options {
+ write!(f, " {option}")?;
}
if let Some(comment_def) = &self.comment {
match comment_def {
@@ -401,9 +386,6 @@ impl Display for CreateTable {
}
}
- if let Some(auto_increment_offset) = self.auto_increment_offset {
- write!(f, " AUTO_INCREMENT {auto_increment_offset}")?;
- }
if let Some(primary_key) = &self.primary_key {
write!(f, " PRIMARY KEY {}", primary_key)?;
}
@@ -503,13 +485,6 @@ impl Display for CreateTable {
write!(f, " WITH TAG ({})", display_comma_separated(tag.as_slice()))?;
}
- if let Some(default_charset) = &self.default_charset {
- write!(f, " DEFAULT CHARSET={default_charset}")?;
- }
- if let Some(collation) = &self.collation {
- write!(f, " COLLATE={collation}")?;
- }
-
if self.on_commit.is_some() {
let on_commit = match self.on_commit {
Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/helpers/stmt_create_table.rs b/app/src/ast/helpers/stmt_create_table.rs
index 1c50cb8..e03f845 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/helpers/stmt_create_table.rs
+++ b/app/src/ast/helpers/stmt_create_table.rs
@@ -26,9 +26,10 @@ use sqlparser_derive::{Visit, VisitMut};
use super::super::dml::CreateTable;
use crate::ast::{
- ClusteredBy, ColumnDef, CommentDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident,
- ObjectName, OnCommit, OneOrManyWithParens, Query, RowAccessPolicy, SqlOption, Statement,
- StorageSerializationPolicy, TableConstraint, TableEngine, Tag, WrappedCollection,
+ ClusteredBy, ColumnDef, CommentDef, CreateTableOptions, Expr, FileFormat,
+ HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit, OneOrManyWithParens, Query,
+ RowAccessPolicy, SqlOption, Statement, StorageSerializationPolicy, TableConstraint, Tag,
+ WrappedCollection,
};
use crate::parser::ParserError;
@@ -76,19 +77,14 @@ pub struct CreateTableBuilder {
pub constraints: Vec<TableConstraint>,
pub hive_distribution: HiveDistributionStyle,
pub hive_formats: Option<HiveFormat>,
- pub table_properties: Vec<SqlOption>,
- pub with_options: Vec<SqlOption>,
+ pub create_table_options: Vec<CreateTableOptions>,
pub file_format: Option<FileFormat>,
pub location: Option<String>,
pub query: Option<Box<Query>>,
pub without_rowid: bool,
pub like: Option<ObjectName>,
pub clone: Option<ObjectName>,
- pub engine: Option<TableEngine>,
pub comment: Option<CommentDef>,
- pub auto_increment_offset: Option<u32>,
- pub default_charset: Option<String>,
- pub collation: Option<String>,
pub on_commit: Option<OnCommit>,
pub on_cluster: Option<Ident>,
pub primary_key: Option<Box<Expr>>,
@@ -131,19 +127,14 @@ impl CreateTableBuilder {
constraints: vec![],
hive_distribution: HiveDistributionStyle::NONE,
hive_formats: None,
- table_properties: vec![],
- with_options: vec![],
+ create_table_options: vec![],
file_format: None,
location: None,
query: None,
without_rowid: false,
like: None,
clone: None,
- engine: None,
comment: None,
- auto_increment_offset: None,
- default_charset: None,
- collation: None,
on_commit: None,
on_cluster: None,
primary_key: None,
@@ -230,13 +221,8 @@ impl CreateTableBuilder {
self
}
- pub fn table_properties(mut self, table_properties: Vec<SqlOption>) -> Self {
- self.table_properties = table_properties;
- self
- }
-
- pub fn with_options(mut self, with_options: Vec<SqlOption>) -> Self {
- self.with_options = with_options;
+ pub fn create_table_options(mut self, create_table_options: Vec<CreateTableOptions>) -> Self {
+ self.create_table_options = create_table_options;
self
}
pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
@@ -268,31 +254,11 @@ impl CreateTableBuilder {
self
}
- pub fn engine(mut self, engine: Option<TableEngine>) -> Self {
- self.engine = engine;
- self
- }
-
pub fn comment(mut self, comment: Option<CommentDef>) -> Self {
self.comment = comment;
self
}
- pub fn auto_increment_offset(mut self, offset: Option<u32>) -> Self {
- self.auto_increment_offset = offset;
- self
- }
-
- pub fn default_charset(mut self, default_charset: Option<String>) -> Self {
- self.default_charset = default_charset;
- self
- }
-
- pub fn collation(mut self, collation: Option<String>) -> Self {
- self.collation = collation;
- self
- }
-
pub fn on_commit(mut self, on_commit: Option<OnCommit>) -> Self {
self.on_commit = on_commit;
self
@@ -437,19 +403,14 @@ impl CreateTableBuilder {
constraints: self.constraints,
hive_distribution: self.hive_distribution,
hive_formats: self.hive_formats,
- table_properties: self.table_properties,
- with_options: self.with_options,
+ create_table_options: self.create_table_options,
file_format: self.file_format,
location: self.location,
query: self.query,
without_rowid: self.without_rowid,
like: self.like,
clone: self.clone,
- engine: self.engine,
comment: self.comment,
- auto_increment_offset: self.auto_increment_offset,
- default_charset: self.default_charset,
- collation: self.collation,
on_commit: self.on_commit,
on_cluster: self.on_cluster,
primary_key: self.primary_key,
@@ -499,19 +460,14 @@ impl TryFrom<Statement> for CreateTableBuilder {
constraints,
hive_distribution,
hive_formats,
- table_properties,
- with_options,
+ create_table_options,
file_format,
location,
query,
without_rowid,
like,
clone,
- engine,
comment,
- auto_increment_offset,
- default_charset,
- collation,
on_commit,
on_cluster,
primary_key,
@@ -548,19 +504,14 @@ impl TryFrom<Statement> for CreateTableBuilder {
constraints,
hive_distribution,
hive_formats,
- table_properties,
- with_options,
+ create_table_options,
file_format,
location,
query,
without_rowid,
like,
clone,
- engine,
comment,
- auto_increment_offset,
- default_charset,
- collation,
on_commit,
on_cluster,
primary_key,
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/mod.rs b/app/src/ast/mod.rs
index 582922a..76a59a3 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -2662,6 +2662,12 @@ impl fmt::Display for Declare {
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CreateTableOptions {
None,
+ /// MySQL / ClickHouse-style options specified as a space-separated list.
+ /// e.g. `ENGINE=InnoDB AUTO_INCREMENT=1`
+ Plain(Vec<SqlOption>),
+ /// Hive-style options specified using the `TBLPROPERTIES` keyword.
+ /// e.g. `TBLPROPERTIES ('k'='v')`
+ TblProperties(Vec<SqlOption>),
/// Options specified using the `WITH` keyword.
/// e.g. `WITH (description = "123")`
///
@@ -2686,6 +2692,12 @@ pub enum CreateTableOptions {
impl fmt::Display for CreateTableOptions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
+ CreateTableOptions::Plain(options) => {
+ write!(f, "{}", display_separated(options, " "))
+ }
+ CreateTableOptions::TblProperties(table_properties) => {
+ write!(f, "TBLPROPERTIES ({})", display_comma_separated(table_properties))
+ }
CreateTableOptions::With(with_options) => {
write!(f, "WITH ({})", display_comma_separated(with_options))
}
@@ -7549,6 +7561,19 @@ pub enum SqlOption {
///
/// WITH(DISTRIBUTION = ROUND_ROBIN)
KeyValue { key: Ident, value: Expr },
+ /// Engine option for MySQL / ClickHouse.
+ /// e.g. `ENGINE=MergeTree(...)`
+ Engine(TableEngine),
+ /// MySQL `AUTO_INCREMENT [=] <value>`.
+ AutoIncrement(u32),
+ /// MySQL `DEFAULT CHARSET=<value>`.
+ DefaultCharset(String),
+ /// MySQL `COLLATE=<value>`.
+ Collate(String),
+ /// MySQL `TABLESPACE <value>`.
+ Tablespace(ObjectName),
+ /// COMMENT option. Used by dialects that model comment as a table option.
+ Comment(CommentDef),
/// One or more table partitions and represents which partition the boundary values belong to,
/// e.g.
///
@@ -7572,6 +7597,17 @@ impl fmt::Display for SqlOption {
SqlOption::KeyValue { key: name, value } => {
write!(f, "{} = {}", name, value)
}
+ SqlOption::Engine(engine) => write!(f, "ENGINE={engine}"),
+ SqlOption::AutoIncrement(value) => write!(f, "AUTO_INCREMENT {value}"),
+ SqlOption::DefaultCharset(charset) => write!(f, "DEFAULT CHARSET={charset}"),
+ SqlOption::Collate(collation) => write!(f, "COLLATE={collation}"),
+ SqlOption::Tablespace(tablespace) => write!(f, "TABLESPACE {tablespace}"),
+ SqlOption::Comment(comment) => match comment {
+ CommentDef::WithEq(comment) => write!(f, "COMMENT = '{comment}'"),
+ CommentDef::WithoutEq(comment) | CommentDef::AfterColumnDefsWithoutEq(comment) => {
+ write!(f, "COMMENT '{comment}'")
+ }
+ },
SqlOption::Partition {
column_name,
range_direction,
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/spans.rs b/app/src/ast/spans.rs
index 836f229..df6bb8a 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/spans.rs
+++ b/app/src/ast/spans.rs
@@ -567,19 +567,14 @@ impl Spanned for CreateTable {
constraints,
hive_distribution: _, // hive specific
hive_formats: _, // hive specific
- table_properties,
- with_options,
+ create_table_options,
file_format: _, // enum
location: _, // string, no span
query,
without_rowid: _, // bool
like,
clone,
- engine: _, // todo
comment: _, // todo, no span
- auto_increment_offset: _, // u32, no span
- default_charset: _, // string, no span
- collation: _, // string, no span
on_commit: _, // enum
on_cluster: _, // todo, clickhouse specific
primary_key: _, // todo, clickhouse specific
@@ -610,8 +605,7 @@ impl Spanned for CreateTable {
core::iter::once(name.span())
.chain(columns.iter().map(|i| i.span()))
.chain(constraints.iter().map(|i| i.span()))
- .chain(table_properties.iter().map(|i| i.span()))
- .chain(with_options.iter().map(|i| i.span()))
+ .chain(create_table_options.iter().map(|i| i.span()))
.chain(query.iter().map(|i| i.span()))
.chain(like.iter().map(|i| i.span()))
.chain(clone.iter().map(|i| i.span())),
@@ -997,6 +991,12 @@ impl Spanned for SqlOption {
SqlOption::Clustered(table_options_clustered) => table_options_clustered.span(),
SqlOption::Ident(ident) => ident.span,
SqlOption::KeyValue { key, value } => key.span.union(&value.span()),
+ SqlOption::Engine(_) => Span::empty(),
+ SqlOption::AutoIncrement(_) => Span::empty(),
+ SqlOption::DefaultCharset(_) => Span::empty(),
+ SqlOption::Collate(_) => Span::empty(),
+ SqlOption::Tablespace(object_name) => object_name.span(),
+ SqlOption::Comment(_) => Span::empty(),
SqlOption::Partition {
column_name,
range_direction: _,
@@ -1039,6 +1039,8 @@ impl Spanned for CreateTableOptions {
fn span(&self) -> Span {
match self {
CreateTableOptions::None => Span::empty(),
+ CreateTableOptions::Plain(vec) => union_spans(vec.iter().map(|i| i.span())),
+ CreateTableOptions::TblProperties(vec) => union_spans(vec.iter().map(|i| i.span())),
CreateTableOptions::With(vec) => union_spans(vec.iter().map(|i| i.span())),
CreateTableOptions::Options(vec) => union_spans(vec.iter().map(|i| i.span())),
}
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs b/app/src/parser/mod.rs
index cbd464c..7ed6c31 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -5524,12 +5524,16 @@ impl<'a> Parser<'a> {
};
let location = hive_formats.location.clone();
let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
+ let mut create_table_options = vec![];
+ if !table_properties.is_empty() {
+ create_table_options.push(CreateTableOptions::TblProperties(table_properties));
+ }
Ok(CreateTableBuilder::new(table_name)
.columns(columns)
.constraints(constraints)
.hive_distribution(hive_distribution)
.hive_formats(Some(hive_formats))
- .table_properties(table_properties)
+ .create_table_options(create_table_options)
.or_replace(or_replace)
.if_not_exists(if_not_exists)
.external(true)
@@ -7059,39 +7063,11 @@ impl<'a> Parser<'a> {
let hive_distribution = self.parse_hive_distribution()?;
let clustered_by = self.parse_optional_clustered_by()?;
let hive_formats = self.parse_hive_formats()?;
- // PostgreSQL supports `WITH ( options )`, before `AS`
- let with_options = self.parse_options(Keyword::WITH)?;
- let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
-
- let engine = if self.parse_keyword(Keyword::ENGINE) {
- self.expect_token(&Token::Eq)?;
- let next_token = self.next_token();
- match next_token.token {
- Token::Word(w) => {
- let name = w.value;
- let parameters = if self.peek_token() == Token::LParen {
- Some(self.parse_parenthesized_identifiers()?)
- } else {
- None
- };
- Some(TableEngine { name, parameters })
- }
- _ => self.expected("identifier", next_token)?,
- }
- } else {
- None
- };
-
- let auto_increment_offset = if self.parse_keyword(Keyword::AUTO_INCREMENT) {
- let _ = self.consume_token(&Token::Eq);
- let next_token = self.next_token();
- match next_token.token {
- Token::Number(s, _) => Some(Self::parse::<u32>(s, next_token.span.start)?),
- _ => self.expected("literal int", next_token)?,
- }
- } else {
- None
- };
+ // Parse table options in source order.
+ let mut create_table_options = vec![];
+ while let Some(option) = self.parse_optional_create_table_option()? {
+ create_table_options.push(option);
+ }
// ClickHouse supports `PRIMARY KEY`, before `ORDER BY`
// https://clickhouse.com/docs/en/sql-reference/statements/create/table#primary-key
@@ -7121,27 +7097,9 @@ impl<'a> Parser<'a> {
let create_table_config = self.parse_optional_create_table_config()?;
- let default_charset = if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARSET]) {
- self.expect_token(&Token::Eq)?;
- let next_token = self.next_token();
- match next_token.token {
- Token::Word(w) => Some(w.value),
- _ => self.expected("identifier", next_token)?,
- }
- } else {
- None
- };
-
- let collation = if self.parse_keywords(&[Keyword::COLLATE]) {
- self.expect_token(&Token::Eq)?;
- let next_token = self.next_token();
- match next_token.token {
- Token::Word(w) => Some(w.value),
- _ => self.expected("identifier", next_token)?,
- }
- } else {
- None
- };
+ while let Some(option) = self.parse_optional_create_table_option()? {
+ create_table_options.push(option);
+ }
let on_commit = if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT]) {
Some(self.parse_create_table_on_commit()?)
@@ -7174,8 +7132,7 @@ impl<'a> Parser<'a> {
.temporary(temporary)
.columns(columns)
.constraints(constraints)
- .with_options(with_options)
- .table_properties(table_properties)
+ .create_table_options(create_table_options)
.or_replace(or_replace)
.if_not_exists(if_not_exists)
.transient(transient)
@@ -7186,12 +7143,8 @@ impl<'a> Parser<'a> {
.without_rowid(without_rowid)
.like(like)
.clone_clause(clone)
- .engine(engine)
.comment(comment)
- .auto_increment_offset(auto_increment_offset)
.order_by(order_by)
- .default_charset(default_charset)
- .collation(collation)
.on_commit(on_commit)
.on_cluster(on_cluster)
.clustered_by(clustered_by)
@@ -7219,6 +7172,83 @@ impl<'a> Parser<'a> {
}
}
+ fn parse_optional_create_table_option(
+ &mut self,
+ ) -> Result<Option<CreateTableOptions>, ParserError> {
+ if let Some(with_options) = self.maybe_parse_options(Keyword::WITH)? {
+ return Ok(Some(CreateTableOptions::With(with_options)));
+ }
+ if let Some(table_properties) = self.maybe_parse_options(Keyword::TBLPROPERTIES)? {
+ return Ok(Some(CreateTableOptions::TblProperties(table_properties)));
+ }
+ if self.parse_keyword(Keyword::ENGINE) {
+ self.expect_token(&Token::Eq)?;
+ let next_token = self.next_token();
+ let engine = match next_token.token {
+ Token::Word(w) => {
+ let name = w.value;
+ let parameters = if self.peek_token() == Token::LParen {
+ Some(self.parse_parenthesized_identifiers()?)
+ } else {
+ None
+ };
+ TableEngine { name, parameters }
+ }
+ _ => self.expected("identifier", next_token)?,
+ };
+ return Ok(Some(CreateTableOptions::Plain(vec![SqlOption::Engine(engine)])));
+ }
+ if self.parse_keyword(Keyword::AUTO_INCREMENT) {
+ let _ = self.consume_token(&Token::Eq);
+ let next_token = self.next_token();
+ let value = match next_token.token {
+ Token::Number(s, _) => Self::parse::<u32>(s, next_token.span.start)?,
+ _ => self.expected("literal int", next_token)?,
+ };
+ return Ok(Some(CreateTableOptions::Plain(vec![
+ SqlOption::AutoIncrement(value),
+ ])));
+ }
+ if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARSET]) {
+ self.expect_token(&Token::Eq)?;
+ let next_token = self.next_token();
+ let value = match next_token.token {
+ Token::Word(w) => w.value,
+ _ => self.expected("identifier", next_token)?,
+ };
+ return Ok(Some(CreateTableOptions::Plain(vec![
+ SqlOption::DefaultCharset(value),
+ ])));
+ }
+ if self.parse_keyword(Keyword::COLLATE) {
+ self.expect_token(&Token::Eq)?;
+ let next_token = self.next_token();
+ let value = match next_token.token {
+ Token::Word(w) => w.value,
+ _ => self.expected("identifier", next_token)?,
+ };
+ return Ok(Some(CreateTableOptions::Plain(vec![SqlOption::Collate(value)])));
+ }
+ if dialect_of!(self is MySqlDialect | GenericDialect) && self.parse_keyword(Keyword::COMMENT)
+ {
+ self.prev_token();
+ if let Some(comment) = self.parse_optional_inline_comment()? {
+ return Ok(Some(CreateTableOptions::Plain(vec![SqlOption::Comment(
+ comment,
+ )])));
+ }
+ }
+ if let Token::Word(word) = self.peek_token().token {
+ if word.value.eq_ignore_ascii_case("TABLESPACE") {
+ self.next_token();
+ return Ok(Some(CreateTableOptions::Plain(vec![SqlOption::Tablespace(
+ self.parse_object_name(false)?,
+ )])));
+ }
+ }
+ Ok(None)
+ }
+
/// Parse configuration like inheritance, partitioning, clustering information during the table creation.
///
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_2)
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_clickhouse.rs b/app/tests/sqlparser_clickhouse.rs
index c56f988..b3fbb52 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_clickhouse.rs
+++ b/app/tests/sqlparser_clickhouse.rs
@@ -721,7 +721,7 @@ fn parse_create_table_with_primary_key() {
Statement::CreateTable(CreateTable {
name,
columns,
- engine,
+ create_table_options,
primary_key,
order_by,
..
@@ -743,14 +743,16 @@ fn parse_create_table_with_primary_key() {
columns
);
assert_eq!(
- engine,
- Some(TableEngine {
- name: "SharedMergeTree".to_string(),
- parameters: Some(vec![
- Ident::with_quote('\'', "/clickhouse/tables/{uuid}/{shard}"),
- Ident::with_quote('\'', "{replica}"),
- ]),
- })
+ create_table_options,
+ vec![CreateTableOptions::Plain(vec![SqlOption::Engine(
+ TableEngine {
+ name: "SharedMergeTree".to_string(),
+ parameters: Some(vec![
+ Ident::with_quote('\'', "/clickhouse/tables/{uuid}/{shard}"),
+ Ident::with_quote('\'', "{replica}"),
+ ]),
+ }
+ )])]
);
fn assert_function(actual: &Function, name: &str, arg: &str) -> bool {
assert_eq!(actual.name, ObjectName::from(vec![Ident::new(name)]));
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index 1ddf3f9..fe4c2a1 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -3657,7 +3657,7 @@ fn parse_create_table() {
name,
columns,
constraints,
- with_options,
+ create_table_options,
if_not_exists: false,
external: false,
file_format: None,
@@ -3795,7 +3795,7 @@ fn parse_create_table() {
},
]
);
- assert_eq!(with_options, vec![]);
+ assert_eq!(create_table_options, vec![]);
}
_ => unreachable!(),
}
@@ -3840,7 +3840,7 @@ fn parse_create_table_with_constraint_characteristics() {
name,
columns,
constraints,
- with_options,
+ create_table_options,
if_not_exists: false,
external: false,
file_format: None,
@@ -3934,7 +3934,7 @@ fn parse_create_table_with_constraint_characteristics() {
},
]
);
- assert_eq!(with_options, vec![]);
+ assert_eq!(create_table_options, vec![]);
}
_ => unreachable!(),
}
@@ -4421,9 +4421,12 @@ fn parse_create_table_with_options() {
let sql = "CREATE TABLE t (c INT) WITH (foo = 'bar', a = 123)";
match generic.verified_stmt(sql) {
- Statement::CreateTable(CreateTable { with_options, .. }) => {
+ Statement::CreateTable(CreateTable {
+ create_table_options,
+ ..
+ }) => {
assert_eq!(
- vec![
+ vec![CreateTableOptions::With(vec![
SqlOption::KeyValue {
key: "foo".into(),
value: Expr::Value(
@@ -4434,8 +4437,8 @@ fn parse_create_table_with_options() {
key: "a".into(),
value: Expr::value(number("123")),
},
- ],
- with_options
+ ])],
+ create_table_options
);
}
_ => unreachable!(),
@@ -4482,7 +4485,7 @@ fn parse_create_external_table() {
name,
columns,
constraints,
- with_options,
+ create_table_options,
if_not_exists,
external,
file_format,
@@ -4525,7 +4528,7 @@ fn parse_create_external_table() {
assert_eq!(FileFormat::TEXTFILE, file_format.unwrap());
assert_eq!("/tmp/example.csv", location.unwrap());
- assert_eq!(with_options, vec![]);
+ assert_eq!(create_table_options, vec![]);
assert!(!if_not_exists);
}
_ => unreachable!(),
@@ -4550,7 +4553,7 @@ fn parse_create_or_replace_external_table() {
name,
columns,
constraints,
- with_options,
+ create_table_options,
if_not_exists,
external,
file_format,
@@ -4579,7 +4582,7 @@ fn parse_create_or_replace_external_table() {
assert_eq!(FileFormat::TEXTFILE, file_format.unwrap());
assert_eq!("/tmp/example.csv", location.unwrap());
- assert_eq!(with_options, vec![]);
+ assert_eq!(create_table_options, vec![]);
assert!(!if_not_exists);
assert!(or_replace);
}
@@ -4784,12 +4787,12 @@ fn parse_alter_view() {
name,
columns,
query,
- with_options,
+ create_table_options,
} => {
assert_eq!("myschema.myview", name.to_string());
assert_eq!(Vec::<Ident>::new(), columns);
assert_eq!("SELECT foo FROM bar", query.to_string());
- assert_eq!(with_options, vec![]);
+ assert_eq!(create_table_options, vec![]);
}
_ => unreachable!(),
}
@@ -4828,12 +4831,12 @@ fn parse_alter_view_with_columns() {
name,
columns,
query,
- with_options,
+ create_table_options,
} => {
assert_eq!("v", name.to_string());
assert_eq!(columns, vec![Ident::new("has"), Ident::new("cols")]);
assert_eq!("SELECT 1, 2", query.to_string());
- assert_eq!(with_options, vec![]);
+ assert_eq!(create_table_options, vec![]);
}
_ => unreachable!(),
}
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_duckdb.rs b/app/tests/sqlparser_duckdb.rs
index 3205832..8220466 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_duckdb.rs
+++ b/app/tests/sqlparser_duckdb.rs
@@ -735,19 +735,14 @@ fn test_duckdb_union_datatype() {
storage: Default::default(),
location: Default::default()
}),
- table_properties: Default::default(),
- with_options: Default::default(),
+ create_table_options: Default::default(),
file_format: Default::default(),
location: Default::default(),
query: Default::default(),
without_rowid: Default::default(),
like: Default::default(),
clone: Default::default(),
- engine: Default::default(),
comment: Default::default(),
- auto_increment_offset: Default::default(),
- default_charset: Default::default(),
- collation: Default::default(),
on_commit: Default::default(),
on_cluster: Default::default(),
primary_key: Default::default(),
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs b/app/tests/sqlparser_mssql.rs
index 88e7a1f..4da0d1b 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -1747,19 +1747,14 @@ fn parse_create_table_with_valid_options() {
storage: None,
location: None,
},),
- table_properties: vec![],
- with_options,
+ create_table_options: vec![CreateTableOptions::With(with_options)],
file_format: None,
location: None,
query: None,
without_rowid: false,
like: None,
clone: None,
- engine: None,
comment: None,
- auto_increment_offset: None,
- default_charset: None,
- collation: None,
on_commit: None,
on_cluster: None,
primary_key: None,
@@ -1918,19 +1913,14 @@ fn parse_create_table_with_identity_column() {
storage: None,
location: None,
},),
- table_properties: vec![],
- with_options: vec![],
+ create_table_options: vec![],
file_format: None,
location: None,
query: None,
without_rowid: false,
like: None,
clone: None,
- engine: None,
comment: None,
- auto_increment_offset: None,
- default_charset: None,
- collation: None,
on_commit: None,
on_cluster: None,
primary_key: None,
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mysql.rs b/app/tests/sqlparser_mysql.rs
index 990107b..3497c7c 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mysql.rs
+++ b/app/tests/sqlparser_mysql.rs
@@ -848,9 +848,22 @@ fn parse_create_table_comment() {
for sql in [without_equal, with_equal] {
match mysql().verified_stmt(sql) {
- Statement::CreateTable(CreateTable { name, comment, .. }) => {
+ Statement::CreateTable(CreateTable {
+ name,
+ create_table_options,
+ ..
+ }) => {
assert_eq!(name.to_string(), "foo");
- assert_eq!(comment.expect("Should exist").to_string(), "baz");
+ assert_eq!(
+ create_table_options,
+ vec![CreateTableOptions::Plain(vec![SqlOption::Comment(
+ if sql.contains(" = ") {
+ CommentDef::WithEq("baz".to_string())
+ } else {
+ CommentDef::WithoutEq("baz".to_string())
+ }
+ )])]
+ );
}
_ => unreachable!(),
}
@@ -868,13 +881,19 @@ fn parse_create_table_auto_increment_offset() {
match mysql().one_statement_parses_to(sql, canonical) {
Statement::CreateTable(CreateTable {
name,
- auto_increment_offset,
+ create_table_options,
..
}) => {
assert_eq!(name.to_string(), "foo");
assert_eq!(
- auto_increment_offset.expect("Should exist").to_string(),
- "123"
+ create_table_options,
+ vec![
+ CreateTableOptions::Plain(vec![SqlOption::Engine(TableEngine {
+ name: "InnoDB".to_string(),
+ parameters: None,
+ })]),
+ CreateTableOptions::Plain(vec![SqlOption::AutoIncrement(123)]),
+ ]
);
}
_ => unreachable!(),
@@ -921,8 +940,7 @@ fn parse_create_table_engine_default_charset() {
Statement::CreateTable(CreateTable {
name,
columns,
- engine,
- default_charset,
+ create_table_options,
..
}) => {
assert_eq!(name.to_string(), "foo");
@@ -935,13 +953,17 @@ fn parse_create_table_engine_default_charset() {
columns
);
assert_eq!(
- engine,
- Some(TableEngine {
- name: "InnoDB".to_string(),
- parameters: None
- })
+ create_table_options,
+ vec![
+ CreateTableOptions::Plain(vec![SqlOption::Engine(TableEngine {
+ name: "InnoDB".to_string(),
+ parameters: None,
+ })]),
+ CreateTableOptions::Plain(vec![SqlOption::DefaultCharset(
+ "utf8mb3".to_string(),
+ )]),
+ ]
);
- assert_eq!(default_charset, Some("utf8mb3".to_string()));
}
_ => unreachable!(),
}
@@ -954,7 +976,7 @@ fn parse_create_table_collate() {
Statement::CreateTable(CreateTable {
name,
columns,
- collation,
+ create_table_options,
..
}) => {
assert_eq!(name.to_string(), "foo");
@@ -966,7 +988,12 @@ fn parse_create_table_collate() {
},],
columns
);
- assert_eq!(collation, Some("utf8mb4_0900_ai_ci".to_string()));
+ assert_eq!(
+ create_table_options,
+ vec![CreateTableOptions::Plain(vec![SqlOption::Collate(
+ "utf8mb4_0900_ai_ci".to_string()
+ )])]
+ );
}
_ => unreachable!(),
}
@@ -978,12 +1005,26 @@ fn parse_create_table_both_options_and_as_query() {
match mysql_and_generic().verified_stmt(sql) {
Statement::CreateTable(CreateTable {
name,
- collation,
+ create_table_options,
query,
..
}) => {
assert_eq!(name.to_string(), "foo");
- assert_eq!(collation, Some("utf8mb4_0900_ai_ci".to_string()));
+ assert_eq!(
+ create_table_options,
+ vec![
+ CreateTableOptions::Plain(vec![SqlOption::Engine(TableEngine {
+ name: "InnoDB".to_string(),
+ parameters: None,
+ })]),
+ CreateTableOptions::Plain(vec![SqlOption::DefaultCharset(
+ "utf8mb3".to_string(),
+ )]),
+ CreateTableOptions::Plain(vec![SqlOption::Collate(
+ "utf8mb4_0900_ai_ci".to_string(),
+ )]),
+ ]
+ );
assert_eq!(
query.unwrap().body.as_select().unwrap().projection,
vec![SelectItem::UnnamedExpr(Expr::Value(
@@ -1001,6 +1042,39 @@ fn parse_create_table_both_options_and_as_query() {
));
}
+#[test]
+fn parse_create_table_options_any_order() {
+ let sql = "CREATE TABLE foo (id INT) COLLATE=utf8mb4_0900_ai_ci DEFAULT CHARSET=utf8mb3 ENGINE=InnoDB COMMENT 'x' AUTO_INCREMENT=3";
+ let canonical = "CREATE TABLE foo (id INT) COLLATE=utf8mb4_0900_ai_ci DEFAULT CHARSET=utf8mb3 ENGINE=InnoDB COMMENT 'x' AUTO_INCREMENT 3";
+ match mysql().one_statement_parses_to(sql, canonical) {
+ Statement::CreateTable(CreateTable {
+ create_table_options,
+ ..
+ }) => {
+ assert_eq!(
+ create_table_options,
+ vec![
+ CreateTableOptions::Plain(vec![SqlOption::Collate(
+ "utf8mb4_0900_ai_ci".to_string(),
+ )]),
+ CreateTableOptions::Plain(vec![SqlOption::DefaultCharset(
+ "utf8mb3".to_string(),
+ )]),
+ CreateTableOptions::Plain(vec![SqlOption::Engine(TableEngine {
+ name: "InnoDB".to_string(),
+ parameters: None,
+ })]),
+ CreateTableOptions::Plain(vec![SqlOption::Comment(CommentDef::WithoutEq(
+ "x".to_string(),
+ ))]),
+ CreateTableOptions::Plain(vec![SqlOption::AutoIncrement(3)]),
+ ]
+ );
+ }
+ _ => unreachable!(),
+ }
+}
+
#[test]
fn parse_create_table_comment_character_set() {
let sql = "CREATE TABLE foo (s TEXT CHARACTER SET utf8mb4 COMMENT 'comment')";
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_postgres.rs b/app/tests/sqlparser_postgres.rs
index 6c008c8..3141ce4 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_postgres.rs
+++ b/app/tests/sqlparser_postgres.rs
@@ -4668,7 +4668,7 @@ fn parse_create_table_with_alias() {
name,
columns,
constraints,
- with_options: _with_options,
+ create_table_options: _create_table_options,
if_not_exists: false,
external: false,
file_format: None,
@@ -5078,9 +5078,12 @@ fn parse_at_time_zone() {
fn parse_create_table_with_options() {
let sql = "CREATE TABLE t (c INT) WITH (foo = 'bar', a = 123)";
match pg().verified_stmt(sql) {
- Statement::CreateTable(CreateTable { with_options, .. }) => {
+ Statement::CreateTable(CreateTable {
+ create_table_options,
+ ..
+ }) => {
assert_eq!(
- vec![
+ vec![CreateTableOptions::With(vec![
SqlOption::KeyValue {
key: "foo".into(),
value: Expr::Value(
@@ -5091,8 +5094,8 @@ fn parse_create_table_with_options() {
key: "a".into(),
value: Expr::value(number("123")),
},
- ],
- with_options
+ ])],
+ create_table_options
);
}
_ => unreachable!(),
@@ -5506,19 +5509,14 @@ fn parse_trigger_related_functions() {
storage: None,
location: None
}),
- table_properties: vec![],
- with_options: vec![],
+ create_table_options: vec![],
file_format: None,
location: None,
query: None,
without_rowid: false,
like: None,
clone: None,
- engine: None,
comment: None,
- auto_increment_offset: None,
- default_charset: None,
- collation: None,
on_commit: None,
on_cluster: None,
primary_key: None,