STET

agent_patch

runs/2026-02-28__18-27-22__gpt-5-4/flux-pr-1891/flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/agent-logs/agent.patch

11744 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/ddl.rs b/app/src/ast/ddl.rs
index f81c6fc..401e00e 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/ddl.rs
+++ b/app/src/ast/ddl.rs
@@ -1408,9 +1408,11 @@ impl fmt::Display for ColumnDef {
 ///
 /// Syntax
 /// ```markdown
-/// <name> [data_type][OPTIONS(option, ...)]
+/// <name> [data_type] [column_option [separator column_option ...]]
 ///
-/// option: <name> = <value>
+/// separator:
+///   - `,` for comma-separated view column options
+///   - ` ` for space-separated view column options
 /// ```
 ///
 /// Examples:
@@ -1418,8 +1420,17 @@ impl fmt::Display for ColumnDef {
 /// name
 /// age OPTIONS(description = "age column", tag = "prod")
 /// amount COMMENT 'The total amount for the order line'
+/// amount COMMENT 'masked' MASKING POLICY policy_name
 /// created_at DateTime64
 /// ```
+#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum ViewColumnOptionSeparator {
+    Comma,
+    Space,
+}
+
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -1427,6 +1438,7 @@ pub struct ViewColumnDef {
     pub name: Ident,
     pub data_type: Option<DataType>,
     pub options: Option<Vec<ColumnOption>>,
+    pub options_separator: ViewColumnOptionSeparator,
 }
 
 impl fmt::Display for ViewColumnDef {
@@ -1436,7 +1448,14 @@ impl fmt::Display for ViewColumnDef {
             write!(f, " {}", data_type)?;
         }
         if let Some(options) = self.options.as_ref() {
-            write!(f, " {}", display_comma_separated(options.as_slice()))?;
+            match self.options_separator {
+                ViewColumnOptionSeparator::Comma => {
+                    write!(f, " {}", display_comma_separated(options.as_slice()))?;
+                }
+                ViewColumnOptionSeparator::Space => {
+                    write!(f, " {}", display_separated(options.as_slice(), " "))?;
+                }
+            }
         }
         Ok(())
     }
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/mod.rs b/app/src/ast/mod.rs
index ef0c4dc..d331218 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -68,6 +68,7 @@ pub use self::ddl::{
     IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
     ProcedureParam, ReferentialAction, ReplicaIdentity, TableConstraint, TagsColumnOption,
     UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
+    ViewColumnOptionSeparator,
 };
 pub use self::dml::{CreateIndex, CreateTable, Delete, IndexColumn, Insert};
 pub use self::operator::{BinaryOperator, UnaryOperator};
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/spans.rs b/app/src/ast/spans.rs
index ca321cc..f4bc3ac 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/spans.rs
+++ b/app/src/ast/spans.rs
@@ -989,6 +989,7 @@ impl Spanned for ViewColumnDef {
             name,
             data_type: _, // todo, DataType
             options,
+            options_separator: _,
         } = self;
 
         union_spans(
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/parser/mod.rs b/app/src/parser/mod.rs
index ca658d7..35ca369 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -10579,26 +10579,53 @@ impl<'a> Parser<'a> {
     /// Parses a column definition within a view.
     fn parse_view_column(&mut self) -> Result<ViewColumnDef, ParserError> {
         let name = self.parse_identifier()?;
-        let options = if (dialect_of!(self is BigQueryDialect | GenericDialect)
-            && self.parse_keyword(Keyword::OPTIONS))
-            || (dialect_of!(self is SnowflakeDialect | GenericDialect)
-                && self.parse_keyword(Keyword::COMMENT))
-        {
-            self.prev_token();
-            self.parse_optional_column_option()?
-                .map(|option| vec![option])
-        } else {
-            None
-        };
         let data_type = if dialect_of!(self is ClickHouseDialect) {
             Some(self.parse_data_type()?)
         } else {
             None
         };
+        let (options, options_separator) = if dialect_of!(self is BigQueryDialect | GenericDialect)
+            && self.parse_keyword(Keyword::OPTIONS)
+        {
+            self.prev_token();
+            let mut options = vec![
+                self.parse_optional_column_option()?
+                    .expect("view column option should exist after a matched option keyword"),
+            ];
+            while let Some(option) = self.parse_optional_column_option()? {
+                options.push(option);
+            }
+            (Some(options), ViewColumnOptionSeparator::Comma)
+        } else if (dialect_of!(self is SnowflakeDialect | GenericDialect)
+            && self.parse_keyword(Keyword::COMMENT))
+            || (dialect_of!(self is SnowflakeDialect)
+                && matches!(
+                    self.parse_one_of_keywords(&[
+                        Keyword::WITH,
+                        Keyword::MASKING,
+                        Keyword::PROJECTION,
+                        Keyword::TAG,
+                    ]),
+                    Some(_)
+                ))
+        {
+            self.prev_token();
+            let mut options = vec![
+                self.parse_optional_column_option()?
+                    .expect("view column option should exist after a matched option keyword"),
+            ];
+            while let Some(option) = self.parse_optional_column_option()? {
+                options.push(option);
+            }
+            (Some(options), ViewColumnOptionSeparator::Space)
+        } else {
+            (None, ViewColumnOptionSeparator::Comma)
+        };
         Ok(ViewColumnDef {
             name,
             data_type,
             options,
+            options_separator,
         })
     }
 
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_bigquery.rs b/app/tests/sqlparser_bigquery.rs
index 0de0b12..4ce3464 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_bigquery.rs
+++ b/app/tests/sqlparser_bigquery.rs
@@ -351,6 +351,7 @@ fn parse_create_view_with_options() {
                         name: Ident::new("name"),
                         data_type: None,
                         options: None,
+                        options_separator: ViewColumnOptionSeparator::Comma,
                     },
                     ViewColumnDef {
                         name: Ident::new("age"),
@@ -363,6 +364,7 @@ fn parse_create_view_with_options() {
                                 )
                             ),
                         }])]),
+                        options_separator: ViewColumnOptionSeparator::Comma,
                     },
                 ],
                 columns
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_clickhouse.rs b/app/tests/sqlparser_clickhouse.rs
index 93b4c4f..935a375 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_clickhouse.rs
+++ b/app/tests/sqlparser_clickhouse.rs
@@ -914,7 +914,8 @@ fn parse_create_view_with_fields_data_types() {
                             }]),
                             vec![]
                         )),
-                        options: None
+                        options: None,
+                        options_separator: ViewColumnOptionSeparator::Comma,
                     },
                     ViewColumnDef {
                         name: "f".into(),
@@ -926,7 +927,8 @@ fn parse_create_view_with_fields_data_types() {
                             }]),
                             vec![]
                         )),
-                        options: None
+                        options: None,
+                        options_separator: ViewColumnOptionSeparator::Comma,
                     },
                 ]
             );
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index d45da69..5248468 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -7990,7 +7990,8 @@ fn parse_create_view_with_columns() {
                     .map(|name| ViewColumnDef {
                         name,
                         data_type: None,
-                        options: None
+                        options: None,
+                        options_separator: ViewColumnOptionSeparator::Comma,
                     })
                     .collect::<Vec<_>>()
             );
diff --git a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_snowflake.rs b/app/tests/sqlparser_snowflake.rs
index 7dc00f9..98117f1 100644
--- a/tmp/agent-patch-flux-pr-1891.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_snowflake.rs
+++ b/app/tests/sqlparser_snowflake.rs
@@ -3143,11 +3143,51 @@ fn parse_view_column_descriptions() {
                         name: Ident::new("a"),
                         data_type: None,
                         options: Some(vec![ColumnOption::Comment("Comment".to_string())]),
+                        options_separator: ViewColumnOptionSeparator::Space,
                     },
                     ViewColumnDef {
                         name: Ident::new("b"),
                         data_type: None,
                         options: None,
+                        options_separator: ViewColumnOptionSeparator::Comma,
+                    }
+                ]
+            );
+        }
+        _ => unreachable!(),
+    };
+}
+
+#[test]
+fn parse_view_column_multiple_options() {
+    let sql = "CREATE OR REPLACE VIEW v (a COMMENT 'Comment' MASKING POLICY p, b) AS SELECT a, b FROM table1";
+
+    match snowflake().verified_stmt(sql) {
+        Statement::CreateView { name, columns, .. } => {
+            assert_eq!(name.to_string(), "v");
+            assert_eq!(
+                columns,
+                vec![
+                    ViewColumnDef {
+                        name: Ident::new("a"),
+                        data_type: None,
+                        options: Some(vec![
+                            ColumnOption::Comment("Comment".to_string()),
+                            ColumnOption::Policy(ColumnPolicy::MaskingPolicy(
+                                ColumnPolicyProperty {
+                                    with: false,
+                                    policy_name: Ident::new("p"),
+                                    using_columns: None,
+                                }
+                            )),
+                        ]),
+                        options_separator: ViewColumnOptionSeparator::Space,
+                    },
+                    ViewColumnDef {
+                        name: Ident::new("b"),
+                        data_type: None,
+                        options: None,
+                        options_separator: ViewColumnOptionSeparator::Comma,
                     }
                 ]
             );