STET

agent_patch

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

11359 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/dml.rs b/app/src/ast/dml.rs
index d68a227..a159d9a 100644
--- a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/dml.rs
+++ b/app/src/ast/dml.rs
@@ -33,10 +33,10 @@ pub use super::ddl::{ColumnDef, TableConstraint};
 
 use super::{
     display_comma_separated, display_separated, Assignment, ClusteredBy, CommentDef, Expr,
-    FileFormat, FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, Ident,
-    InsertAliases, MysqlInsertPriority, ObjectName, OnCommit, OnInsert, OneOrManyWithParens,
-    OrderByExpr, Query, RowAccessPolicy, SelectItem, SqlOption, SqliteOnConflict, TableEngine,
-    TableObject, TableWithJoins, Tag, WrappedCollection,
+    FileFormat, FormatClause, FromTable, HiveDistributionStyle, HiveFormat, HiveIOFormat,
+    HiveRowFormat, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnCommit, OnInsert,
+    OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem, Setting, SqlOption,
+    SqliteOnConflict, TableEngine, TableObject, TableWithJoins, Tag, WrappedCollection,
 };
 
 /// CREATE INDEX statement.
@@ -479,6 +479,12 @@ pub struct Insert {
     pub overwrite: bool,
     /// A SQL query that specifies what to insert
     pub source: Option<Box<Query>>,
+    /// ClickHouse `SETTINGS` clause on `INSERT`
+    pub settings: Option<Vec<Setting>>,
+    /// ClickHouse `FORMAT <name>` clause on `INSERT`
+    pub format_clause: Option<FormatClause>,
+    /// Raw payload that follows a ClickHouse `FORMAT` clause
+    pub format_data: Option<String>,
     /// MySQL `INSERT INTO ... SET`
     /// See: <https://dev.mysql.com/doc/refman/8.4/en/insert.html>
     pub assignments: Vec<Assignment>,
@@ -544,9 +550,17 @@ impl Display for Insert {
         if !self.after_columns.is_empty() {
             write!(f, "({}) ", display_comma_separated(&self.after_columns))?;
         }
+        if let Some(ref settings) = self.settings {
+            write!(f, "SETTINGS {} ", display_comma_separated(settings))?;
+        }
 
         if let Some(source) = &self.source {
             write!(f, "{source}")?;
+        } else if let Some(format_clause) = &self.format_clause {
+            write!(f, "{format_clause}")?;
+            if let Some(format_data) = &self.format_data {
+                write!(f, "{format_data}")?;
+            }
         } else if !self.assignments.is_empty() {
             write!(f, "SET ")?;
             write!(f, "{}", display_comma_separated(&self.assignments))?;
diff --git a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/spans.rs b/app/src/ast/spans.rs
index 8a27c4a..d226eeb 100644
--- a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/spans.rs
+++ b/app/src/ast/spans.rs
@@ -1147,6 +1147,9 @@ impl Spanned for Insert {
             columns,
             overwrite: _, // bool
             source,
+            settings: _,
+            format_clause: _,
+            format_data: _,
             partitioned,
             after_columns,
             has_table_keyword: _, // bool
diff --git a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/parser/mod.rs b/app/src/parser/mod.rs
index b6e3fd1..7508852 100644
--- a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -12033,9 +12033,18 @@ impl<'a> Parser<'a> {
 
             let is_mysql = dialect_of!(self is MySqlDialect);
 
-            let (columns, partitioned, after_columns, source, assignments) =
+            let (
+                columns,
+                partitioned,
+                after_columns,
+                source,
+                settings,
+                format_clause,
+                format_data,
+                assignments,
+            ) =
                 if self.parse_keywords(&[Keyword::DEFAULT, Keyword::VALUES]) {
-                    (vec![], None, vec![], None, vec![])
+                    (vec![], None, vec![], None, None, None, None, vec![])
                 } else {
                     let (columns, partitioned, after_columns) = if !self.peek_subquery_start() {
                         let columns = self.parse_parenthesized_column_list(Optional, is_mysql)?;
@@ -12052,14 +12061,34 @@ impl<'a> Parser<'a> {
                         Default::default()
                     };
 
-                    let (source, assignments) =
-                        if self.dialect.supports_insert_set() && self.parse_keyword(Keyword::SET) {
-                            (None, self.parse_comma_separated(Parser::parse_assignment)?)
+                    let settings = self.parse_settings()?;
+
+                    let (source, format_clause, format_data, assignments) = if dialect_of!(self is ClickHouseDialect | GenericDialect)
+                        && self.parse_keyword(Keyword::FORMAT)
+                    {
+                        let format_clause = if self.parse_keyword(Keyword::NULL) {
+                            FormatClause::Null
                         } else {
-                            (Some(self.parse_query()?), vec![])
+                            FormatClause::Identifier(self.parse_identifier()?)
                         };
+                        let format_data = self.parse_statement_tail_as_string();
+                        (None, Some(format_clause), format_data, vec![])
+                    } else if self.dialect.supports_insert_set() && self.parse_keyword(Keyword::SET) {
+                        (None, None, None, self.parse_comma_separated(Parser::parse_assignment)?)
+                    } else {
+                        (Some(self.parse_query()?), None, None, vec![])
+                    };
 
-                    (columns, partitioned, after_columns, source, assignments)
+                    (
+                        columns,
+                        partitioned,
+                        after_columns,
+                        source,
+                        settings,
+                        format_clause,
+                        format_data,
+                        assignments,
+                    )
                 };
 
             let insert_alias = if dialect_of!(self is MySqlDialect | GenericDialect)
@@ -12139,6 +12168,9 @@ impl<'a> Parser<'a> {
                 columns,
                 after_columns,
                 source,
+                settings,
+                format_clause,
+                format_data,
                 assignments,
                 has_table_keyword: table,
                 on,
@@ -12187,6 +12219,17 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn parse_statement_tail_as_string(&mut self) -> Option<String> {
+        let mut tail = String::new();
+        while !matches!(self.peek_token_no_skip().token, Token::EOF | Token::SemiColon) {
+            let Some(token) = self.next_token_no_skip() else {
+                break;
+            };
+            tail.push_str(&token.to_string());
+        }
+        if tail.is_empty() { None } else { Some(tail) }
+    }
+
     pub fn parse_load_data_table_format(
         &mut self,
     ) -> Result<Option<HiveLoadDataFormat>, ParserError> {
diff --git a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_clickhouse.rs b/app/tests/sqlparser_clickhouse.rs
index 4fa657b..c1af847 100644
--- a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_clickhouse.rs
+++ b/app/tests/sqlparser_clickhouse.rs
@@ -228,6 +228,69 @@ fn parse_insert_into_function() {
     clickhouse().verified_stmt(r#"INSERT INTO FUNCTION remote('localhost', default.simple_table) VALUES (100, 'inserted via remote()')"#);
 }
 
+#[test]
+fn parse_insert_with_settings_and_format() {
+    let sql =
+        r#"INSERT INTO tbl SETTINGS input_format_skip_unknown_fields = 1 FORMAT JSONEachRow {"id":1}"#;
+
+    match clickhouse_and_generic().verified_stmt(sql) {
+        Statement::Insert(Insert {
+            table,
+            settings,
+            format_clause,
+            format_data,
+            source,
+            ..
+        }) => {
+            assert_eq!(table, TableObject::TableName(ObjectName(vec![Ident::new("tbl")])));
+            assert_eq!(
+                settings,
+                Some(vec![Setting {
+                    key: Ident::new("input_format_skip_unknown_fields"),
+                    value: Value::Number("1".to_string(), false),
+                }])
+            );
+            assert_eq!(
+                format_clause,
+                Some(FormatClause::Identifier(Ident::new("JSONEachRow")))
+            );
+            assert_eq!(format_data, Some(r#" {"id":1}"#.to_string()));
+            assert_eq!(source, None);
+        }
+        _ => unreachable!(),
+    }
+}
+
+#[test]
+fn parse_insert_with_settings_and_values() {
+    let sql = "INSERT INTO tbl SETTINGS async_insert = 1 VALUES (1)";
+
+    match clickhouse_and_generic().verified_stmt(sql) {
+        Statement::Insert(Insert {
+            settings,
+            source,
+            format_clause,
+            format_data,
+            ..
+        }) => {
+            assert_eq!(
+                settings,
+                Some(vec![Setting {
+                    key: Ident::new("async_insert"),
+                    value: Value::Number("1".to_string(), false),
+                }])
+            );
+            let source = source.expect("expected VALUES source");
+            assert!(matches!(source.body.as_ref(), SetExpr::Values(_)));
+            assert_eq!(source.settings, None);
+            assert_eq!(source.format_clause, None);
+            assert_eq!(format_clause, None);
+            assert_eq!(format_data, None);
+        }
+        _ => unreachable!(),
+    }
+}
+
 #[test]
 fn parse_alter_table_attach_and_detach_partition() {
     for operation in &["ATTACH", "DETACH"] {
diff --git a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_postgres.rs b/app/tests/sqlparser_postgres.rs
index ce31a06..6f8650f 100644
--- a/tmp/agent-patch-flux-pr-1628.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_postgres.rs
+++ b/app/tests/sqlparser_postgres.rs
@@ -4423,6 +4423,9 @@ fn test_simple_postgres_insert_with_alias() {
                 settings: None,
                 format_clause: None,
             })),
+            settings: None,
+            format_clause: None,
+            format_data: None,
             assignments: vec![],
             partitioned: None,
             after_columns: vec![],
@@ -4494,6 +4497,9 @@ fn test_simple_postgres_insert_with_alias() {
                 settings: None,
                 format_clause: None,
             })),
+            settings: None,
+            format_clause: None,
+            format_data: None,
             assignments: vec![],
             partitioned: None,
             after_columns: vec![],
@@ -4561,6 +4567,9 @@ fn test_simple_insert_with_quoted_alias() {
                 settings: None,
                 format_clause: None,
             })),
+            settings: None,
+            format_clause: None,
+            format_data: None,
             assignments: vec![],
             partitioned: None,
             after_columns: vec![],