STET

agent_patch

runs/2026-02-21__03-36-16__gpt-5-1-codex-mini/flux-pr-1747/flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/agent-logs/agent.patch

27391 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/dml.rs b/app/src/ast/dml.rs
index 9cdb1ca..5615250 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/dml.rs
+++ b/app/src/ast/dml.rs
@@ -36,8 +36,8 @@ use super::{
     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,
+    SqlOption, SqliteOnConflict, StorageSerializationPolicy, TableObject, TableWithJoins, Tag,
+    WrappedCollection,
 };
 
 /// Index column type.
@@ -146,19 +146,15 @@ 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>,
+    /// Table option blocks, e.g. `WITH`, `OPTIONS`, `TBLPROPERTIES`, or MySQL-style options.
+    pub 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/>
@@ -179,9 +175,6 @@ pub struct CreateTable {
     /// Hive: Table clustering column list.
     /// <https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable>
     pub clustered_by: Option<ClusteredBy>,
-    /// BigQuery: Table options list.
-    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
-    pub options: Option<Vec<SqlOption>>,
     /// Postgres `INHERITs` clause, which contains the list of tables from which
     /// the new table inherits.
     /// <https://www.postgresql.org/docs/current/ddl-inherit.html>
@@ -375,34 +368,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}")?;
-        }
-        if let Some(comment_def) = &self.comment {
-            match comment_def {
-                CommentDef::WithEq(comment) => {
-                    write!(f, " COMMENT = '{comment}'")?;
-                }
-                CommentDef::WithoutEq(comment) => {
-                    write!(f, " COMMENT '{comment}'")?;
-                }
-                // For CommentDef::AfterColumnDefsWithoutEq will be displayed after column definition
-                CommentDef::AfterColumnDefsWithoutEq(_) => (),
-            }
-        }
-
-        if let Some(auto_increment_offset) = self.auto_increment_offset {
-            write!(f, " AUTO_INCREMENT {auto_increment_offset}")?;
+        for option in &self.table_options {
+            write!(f, " {option}")?;
         }
         if let Some(primary_key) = &self.primary_key {
             write!(f, " PRIMARY KEY {}", primary_key)?;
@@ -420,14 +387,6 @@ impl Display for CreateTable {
             write!(f, " CLUSTER BY {cluster_by}")?;
         }
 
-        if let Some(options) = self.options.as_ref() {
-            write!(
-                f,
-                " OPTIONS({})",
-                display_comma_separated(options.as_slice())
-            )?;
-        }
-
         if let Some(external_volume) = self.external_volume.as_ref() {
             write!(f, " EXTERNAL_VOLUME = '{external_volume}'")?;
         }
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/helpers/stmt_create_table.rs b/app/src/ast/helpers/stmt_create_table.rs
index 1c50cb8..9a06df0 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/helpers/stmt_create_table.rs
+++ b/app/src/ast/helpers/stmt_create_table.rs
@@ -26,9 +26,9 @@ 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 +76,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 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>>,
@@ -96,7 +91,6 @@ pub struct CreateTableBuilder {
     pub partition_by: Option<Box<Expr>>,
     pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
     pub clustered_by: Option<ClusteredBy>,
-    pub options: Option<Vec<SqlOption>>,
     pub inherits: Option<Vec<ObjectName>>,
     pub strict: bool,
     pub copy_grants: bool,
@@ -131,8 +125,7 @@ impl CreateTableBuilder {
             constraints: vec![],
             hive_distribution: HiveDistributionStyle::NONE,
             hive_formats: None,
-            table_properties: vec![],
-            with_options: vec![],
+            table_options: vec![],
             file_format: None,
             location: None,
             query: None,
@@ -151,7 +144,6 @@ impl CreateTableBuilder {
             partition_by: None,
             cluster_by: None,
             clustered_by: None,
-            options: None,
             inherits: None,
             strict: false,
             copy_grants: false,
@@ -230,13 +222,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 table_options(mut self, table_options: Vec<CreateTableOptions>) -> Self {
+        self.table_options = table_options;
         self
     }
     pub fn file_format(mut self, file_format: Option<FileFormat>) -> Self {
@@ -268,11 +255,6 @@ 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
@@ -328,11 +310,6 @@ impl CreateTableBuilder {
         self
     }
 
-    pub fn options(mut self, options: Option<Vec<SqlOption>>) -> Self {
-        self.options = options;
-        self
-    }
-
     pub fn inherits(mut self, inherits: Option<Vec<ObjectName>>) -> Self {
         self.inherits = inherits;
         self
@@ -437,19 +414,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,
+            table_options: self.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,
@@ -457,7 +429,6 @@ impl CreateTableBuilder {
             partition_by: self.partition_by,
             cluster_by: self.cluster_by,
             clustered_by: self.clustered_by,
-            options: self.options,
             inherits: self.inherits,
             strict: self.strict,
             copy_grants: self.copy_grants,
@@ -499,19 +470,14 @@ impl TryFrom<Statement> for CreateTableBuilder {
                 constraints,
                 hive_distribution,
                 hive_formats,
-                table_properties,
-                with_options,
+                table_options,
                 file_format,
                 location,
                 query,
                 without_rowid,
                 like,
                 clone,
-                engine,
                 comment,
-                auto_increment_offset,
-                default_charset,
-                collation,
                 on_commit,
                 on_cluster,
                 primary_key,
@@ -519,7 +485,6 @@ impl TryFrom<Statement> for CreateTableBuilder {
                 partition_by,
                 cluster_by,
                 clustered_by,
-                options,
                 inherits,
                 strict,
                 copy_grants,
@@ -548,19 +513,14 @@ impl TryFrom<Statement> for CreateTableBuilder {
                 constraints,
                 hive_distribution,
                 hive_formats,
-                table_properties,
-                with_options,
+                table_options,
                 file_format,
                 location,
                 query,
                 without_rowid,
                 like,
                 clone,
-                engine,
                 comment,
-                auto_increment_offset,
-                default_charset,
-                collation,
                 on_commit,
                 on_cluster,
                 primary_key,
@@ -568,7 +528,6 @@ impl TryFrom<Statement> for CreateTableBuilder {
                 partition_by,
                 cluster_by,
                 clustered_by,
-                options,
                 inherits,
                 strict,
                 iceberg,
@@ -600,7 +559,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
 pub(crate) struct CreateTableConfiguration {
     pub partition_by: Option<Box<Expr>>,
     pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
-    pub options: Option<Vec<SqlOption>>,
+    pub table_options: Vec<CreateTableOptions>,
     pub inherits: Option<Vec<ObjectName>>,
 }
 
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/mod.rs b/app/src/ast/mod.rs
index 582922a..f819b94 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -2681,6 +2681,11 @@ pub enum CreateTableOptions {
     ///
     /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
     Options(Vec<SqlOption>),
+    /// MySQL-style options that are written in a space-separated sequence.
+    Plain(Vec<SqlOption>),
+    /// Options specified using the `TBLPROPERTIES` keyword.
+    /// e.g. `TBLPROPERTIES('classification' = 'parquet')`
+    TblProperties(Vec<SqlOption>),
 }
 
 impl fmt::Display for CreateTableOptions {
@@ -2692,6 +2697,12 @@ impl fmt::Display for CreateTableOptions {
             CreateTableOptions::Options(options) => {
                 write!(f, "OPTIONS({})", display_comma_separated(options))
             }
+            CreateTableOptions::TblProperties(props) => {
+                write!(f, "TBLPROPERTIES ({})", display_comma_separated(props))
+            }
+            CreateTableOptions::Plain(opts) => {
+                write!(f, "{}", display_separated(opts, " "))
+            }
             CreateTableOptions::None => Ok(()),
         }
     }
@@ -7548,7 +7559,16 @@ pub enum SqlOption {
     /// Any option that consists of a key value pair where the value is an expression. e.g.
     ///
     ///   WITH(DISTRIBUTION = ROUND_ROBIN)
-    KeyValue { key: Ident, value: Expr },
+    KeyValue { key: Vec<Ident>, value: Expr },
+    /// Engine clause, e.g. `ENGINE=InnoDB` or `ENGINE=SharedMergeTree(...)`.
+    Engine {
+        name: ObjectName,
+        parameters: Option<Vec<Expr>>,
+    },
+    /// `TABLESPACE foo` clause.
+    Tablespace(ObjectName),
+    /// `COMMENT 'foo'` clause.
+    Comment(String),
     /// One or more table partitions and represents which partition the boundary values belong to,
     /// e.g.
     ///
@@ -7570,8 +7590,27 @@ impl fmt::Display for SqlOption {
                 write!(f, "{}", ident)
             }
             SqlOption::KeyValue { key: name, value } => {
-                write!(f, "{} = {}", name, value)
+                for (idx, ident) in name.iter().enumerate() {
+                    if idx > 0 {
+                        write!(f, " ")?;
+                    }
+                    write!(f, "{}", ident)?;
+                }
+                write!(f, " = {value}")
+            }
+            SqlOption::Engine { name, parameters } => {
+                write!(f, "ENGINE={name}")?;
+                if let Some(params) = parameters {
+                    write!(f, "({})", display_separated(params, ", "))?;
+                }
+                Ok(())
             }
+            SqlOption::Tablespace(name) => write!(f, "TABLESPACE = {name}"),
+            SqlOption::Comment(comment) => write!(
+                f,
+                "COMMENT = '{}'",
+                value::escape_single_quote_string(comment)
+            ),
             SqlOption::Partition {
                 column_name,
                 range_direction,
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/spans.rs b/app/src/ast/spans.rs
index 836f229..f6d43c6 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/spans.rs
+++ b/app/src/ast/spans.rs
@@ -996,7 +996,24 @@ impl Spanned for SqlOption {
         match self {
             SqlOption::Clustered(table_options_clustered) => table_options_clustered.span(),
             SqlOption::Ident(ident) => ident.span,
-            SqlOption::KeyValue { key, value } => key.span.union(&value.span()),
+            SqlOption::KeyValue { key, value } => key
+                .iter()
+                .map(|ident| ident.span)
+                .fold(Span::empty(), |acc, span| acc.union(&span))
+                .union(&value.span()),
+            SqlOption::Engine { name, parameters } => {
+                let base_span = name.span();
+                if let Some(parameters) = parameters {
+                    union_spans(
+                        core::iter::once(base_span)
+                            .chain(parameters.iter().map(|expr| expr.span())),
+                    )
+                } else {
+                    base_span
+                }
+            }
+            SqlOption::Tablespace(name) => name.span(),
+            SqlOption::Comment(_) => Span::empty(),
             SqlOption::Partition {
                 column_name,
                 range_direction: _,
diff --git a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/parser/mod.rs b/app/src/parser/mod.rs
index cbd464c..36cd464 100644
--- a/tmp/agent-patch-flux-pr-1747.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -7062,36 +7062,17 @@ impl<'a> Parser<'a> {
         // 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
-        };
+        let mut table_options = Vec::new();
+        if !with_options.is_empty() {
+            table_options.push(CreateTableOptions::With(with_options));
+        }
+        if !table_properties.is_empty() {
+            table_options.push(CreateTableOptions::TblProperties(table_properties));
+        }
+        let plain_table_options = self.parse_plain_table_options()?;
+        if !plain_table_options.is_empty() {
+            table_options.push(CreateTableOptions::Plain(plain_table_options));
+        }
 
         // ClickHouse supports `PRIMARY KEY`, before `ORDER BY`
         // https://clickhouse.com/docs/en/sql-reference/statements/create/table#primary-key
@@ -7120,28 +7101,7 @@ 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
-        };
+        table_options.extend(create_table_config.table_options);
 
         let on_commit = if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT]) {
             Some(self.parse_create_table_on_commit()?)
@@ -7152,12 +7112,6 @@ impl<'a> Parser<'a> {
         let strict = self.parse_keyword(Keyword::STRICT);
 
         // Excludes Hive dialect here since it has been handled after table column definitions.
-        if !dialect_of!(self is HiveDialect) && self.parse_keyword(Keyword::COMMENT) {
-            // rewind the COMMENT keyword
-            self.prev_token();
-            comment = self.parse_optional_inline_comment()?
-        };
-
         // Parse optional `AS ( query )`
         let query = if self.parse_keyword(Keyword::AS) {
             Some(self.parse_query()?)
@@ -7174,8 +7128,7 @@ impl<'a> Parser<'a> {
             .temporary(temporary)
             .columns(columns)
             .constraints(constraints)
-            .with_options(with_options)
-            .table_properties(table_properties)
+            .table_options(table_options)
             .or_replace(or_replace)
             .if_not_exists(if_not_exists)
             .transient(transient)
@@ -7186,24 +7139,98 @@ 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)
             .partition_by(create_table_config.partition_by)
             .cluster_by(create_table_config.cluster_by)
-            .options(create_table_config.options)
             .inherits(create_table_config.inherits)
             .primary_key(primary_key)
             .strict(strict)
             .build())
     }
 
+    pub fn parse_plain_table_options(&mut self) -> Result<Vec<SqlOption>, ParserError> {
+        let mut options = Vec::new();
+
+        loop {
+            if self.parse_keyword(Keyword::ENGINE) {
+                self.expect_token(&Token::Eq)?;
+                let name = self.parse_object_name(false)?;
+                let parameters = if self.consume_token(&Token::LParen) {
+                    let args = if self.peek_token() != Token::RParen {
+                        self.parse_comma_separated(|p| p.parse_expr())?
+                    } else {
+                        vec![]
+                    };
+                    self.expect_token(&Token::RParen)?;
+                    Some(args)
+                } else {
+                    None
+                };
+                options.push(SqlOption::Engine { name, parameters });
+                continue;
+            }
+            if self.parse_keyword(Keyword::TABLESPACE) {
+                let _ = self.consume_token(&Token::Eq);
+                let tablespace = self.parse_object_name(false)?;
+                options.push(SqlOption::Tablespace(tablespace));
+                continue;
+            }
+            if self.parse_keyword(Keyword::COMMENT) {
+                let _ = self.consume_token(&Token::Eq);
+                let comment = self.parse_comment_value()?;
+                options.push(SqlOption::Comment(comment));
+                continue;
+            }
+            if self.parse_keyword(Keyword::AUTO_INCREMENT) {
+                let _ = self.consume_token(&Token::Eq);
+                let value = self.parse_expr()?;
+                options.push(SqlOption::KeyValue {
+                    key: vec![Ident::new("AUTO_INCREMENT")],
+                    value,
+                });
+                continue;
+            }
+            if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARSET]) {
+                let _ = self.consume_token(&Token::Eq);
+                let value = self.parse_expr()?;
+                options.push(SqlOption::KeyValue {
+                    key: vec![Ident::new("DEFAULT"), Ident::new("CHARSET")],
+                    value,
+                });
+                continue;
+            }
+            if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARACTER, Keyword::SET]) {
+                let _ = self.consume_token(&Token::Eq);
+                let value = self.parse_expr()?;
+                options.push(SqlOption::KeyValue {
+                    key: vec![
+                        Ident::new("DEFAULT"),
+                        Ident::new("CHARACTER"),
+                        Ident::new("SET"),
+                    ],
+                    value,
+                });
+                continue;
+            }
+            if self.parse_keyword(Keyword::COLLATE) {
+                let _ = self.consume_token(&Token::Eq);
+                let value = self.parse_expr()?;
+                options.push(SqlOption::KeyValue {
+                    key: vec![Ident::new("COLLATE")],
+                    value,
+                });
+                continue;
+            }
+            break;
+        }
+
+        Ok(options)
+    }
+
     pub(crate) fn parse_create_table_on_commit(&mut self) -> Result<OnCommit, ParserError> {
         if self.parse_keywords(&[Keyword::DELETE, Keyword::ROWS]) {
             Ok(OnCommit::DeleteRows)
@@ -7242,7 +7269,7 @@ impl<'a> Parser<'a> {
         };
 
         let mut cluster_by = None;
-        let mut options = None;
+        let mut table_options = Vec::new();
         if dialect_of!(self is BigQueryDialect | GenericDialect) {
             if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
                 cluster_by = Some(WrappedCollection::NoWrapping(
@@ -7252,7 +7279,10 @@ impl<'a> Parser<'a> {
 
             if let Token::Word(word) = self.peek_token().token {
                 if word.keyword == Keyword::OPTIONS {
-                    options = Some(self.parse_options(Keyword::OPTIONS)?);
+                    let opts = self.parse_options(Keyword::OPTIONS)?;
+                    if !opts.is_empty() {
+                        table_options.push(CreateTableOptions::Options(opts));
+                    }
                 }
             };
         }
@@ -7260,7 +7290,7 @@ impl<'a> Parser<'a> {
         Ok(CreateTableConfiguration {
             partition_by,
             cluster_by,
-            options,
+            table_options,
             inherits,
         })
     }
@@ -8061,13 +8091,16 @@ impl<'a> Parser<'a> {
             Token::Word(w) if w.keyword == Keyword::CLUSTERED && is_mssql => {
                 self.parse_option_clustered()
             }
-            _ => {
-                let name = self.parse_identifier()?;
-                self.expect_token(&Token::Eq)?;
-                let value = self.parse_expr()?;
+                _ => {
+                    let name = self.parse_identifier()?;
+                    self.expect_token(&Token::Eq)?;
+                    let value = self.parse_expr()?;
 
-                Ok(SqlOption::KeyValue { key: name, value })
-            }
+                    Ok(SqlOption::KeyValue {
+                        key: vec![name],
+                        value,
+                    })
+                }
         }
     }