STET

agent_patch

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

9911 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1526.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 ad59f07..c0a41ba 100644
--- a/tmp/agent-patch-flux-pr-1526.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
@@ -60,8 +60,8 @@ pub use self::query::{
     OrderBy, OrderByExpr, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
     RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
     SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table,
-    TableAlias, TableFactor, TableFunctionArgs, TableVersion, TableWithJoins, Top, TopQuantity,
-    ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
+    TableAlias, TableAliasColumn, TableFactor, TableFunctionArgs, TableVersion, TableWithJoins, Top,
+    TopQuantity, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
 };
 
 pub use self::trigger::{
diff --git a/tmp/agent-patch-flux-pr-1526.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/query.rs b/app/src/ast/query.rs
index 2160da0..9d7b048 100644
--- a/tmp/agent-patch-flux-pr-1526.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/query.rs
+++ b/app/src/ast/query.rs
@@ -1591,13 +1591,30 @@ impl fmt::Display for TableFactor {
         }
     }
 }
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct TableAliasColumn {
+    pub name: Ident,
+    pub data_type: Option<DataType>,
+}
+
+impl fmt::Display for TableAliasColumn {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.name)?;
+        if let Some(data_type) = &self.data_type {
+            write!(f, " {data_type}")?;
+        }
+        Ok(())
+    }
+}
 
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
 pub struct TableAlias {
     pub name: Ident,
-    pub columns: Vec<Ident>,
+    pub columns: Vec<TableAliasColumn>,
 }
 
 impl fmt::Display for TableAlias {
diff --git a/tmp/agent-patch-flux-pr-1526.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 0c82378..be0c17d 100644
--- a/tmp/agent-patch-flux-pr-1526.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
@@ -8270,7 +8270,7 @@ impl<'a> Parser<'a> {
     ) -> Result<Option<TableAlias>, ParserError> {
         match self.parse_optional_alias(reserved_kwds)? {
             Some(name) => {
-                let columns = self.parse_parenthesized_column_list(Optional, false)?;
+                let columns = self.parse_parenthesized_alias_column_list(Optional, false)?;
                 Ok(Some(TableAlias { name, columns }))
             }
             None => Ok(None),
@@ -8607,6 +8607,38 @@ impl<'a> Parser<'a> {
         }
     }
 
+    pub fn parse_parenthesized_alias_column_list(
+        &mut self,
+        optional: IsOptional,
+        allow_empty: bool,
+    ) -> Result<Vec<TableAliasColumn>, ParserError> {
+        if self.consume_token(&Token::LParen) {
+            if allow_empty && self.peek_token().token == Token::RParen {
+                self.next_token();
+                Ok(vec![])
+            } else {
+                let cols = self.parse_comma_separated(|p| {
+                    let name = p.parse_identifier(false)?;
+                    let data_type = if matches!(
+                        p.peek_token().token,
+                        Token::Comma | Token::RParen
+                    ) {
+                        None
+                    } else {
+                        Some(p.parse_data_type()?)
+                    };
+                    Ok(TableAliasColumn { name, data_type })
+                })?;
+                self.expect_token(&Token::RParen)?;
+                Ok(cols)
+            }
+        } else if optional == Optional {
+            Ok(vec![])
+        } else {
+            self.expected("a list of alias columns in parentheses", self.peek_token())
+        }
+    }
+
     pub fn parse_precision(&mut self) -> Result<u64, ParserError> {
         self.expect_token(&Token::LParen)?;
         let n = self.parse_literal_uint()?;
@@ -9174,7 +9206,7 @@ impl<'a> Parser<'a> {
                 materialized: is_materialized,
             }
         } else {
-            let columns = self.parse_parenthesized_column_list(Optional, false)?;
+            let columns = self.parse_parenthesized_alias_column_list(Optional, false)?;
             self.expect_keyword(Keyword::AS)?;
             let mut is_materialized = None;
             if dialect_of!(self is PostgreSqlDialect) {
diff --git a/tmp/agent-patch-flux-pr-1526.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/test_utils.rs b/app/src/test_utils.rs
index b35fc45..69e5faa 100644
--- a/tmp/agent-patch-flux-pr-1526.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/test_utils.rs
+++ b/app/src/test_utils.rs
@@ -336,6 +336,27 @@ pub fn table_alias(name: impl Into<String>) -> Option<TableAlias> {
     })
 }
 
+pub fn table_alias_column(name: impl Into<String>) -> TableAliasColumn {
+    TableAliasColumn {
+        name: Ident::new(name),
+        data_type: None,
+    }
+}
+
+pub fn table_alias_column_with_type(
+    name: impl Into<String>,
+    data_type: DataType,
+) -> TableAliasColumn {
+    TableAliasColumn {
+        name: Ident::new(name),
+        data_type: Some(data_type),
+    }
+}
+
+pub fn table_alias_columns(names: &[&str]) -> Vec<TableAliasColumn> {
+    names.iter().map(|name| table_alias_column(name)).collect()
+}
+
 pub fn table(name: impl Into<String>) -> TableFactor {
     TableFactor::Table {
         name: ObjectName(vec![Ident::new(name.into())]),
diff --git a/tmp/agent-patch-flux-pr-1526.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index 283071e..4aca5e2 100644
--- a/tmp/agent-patch-flux-pr-1526.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -39,7 +39,8 @@ use sqlparser::parser::{Parser, ParserError, ParserOptions};
 use sqlparser::tokenizer::Tokenizer;
 use test_utils::{
     all_dialects, all_dialects_where, alter_table_op, assert_eq_vec, call, expr_from_projection,
-    join, number, only, table, table_alias, TestedDialects,
+    join, number, only, table, table_alias, table_alias_column, table_alias_column_with_type,
+    table_alias_columns, TestedDialects,
 };
 
 #[macro_use]
@@ -553,7 +554,7 @@ fn parse_select_with_table_alias() {
                 name: ObjectName(vec![Ident::new("lineitem")]),
                 alias: Some(TableAlias {
                     name: Ident::new("l"),
-                    columns: vec![Ident::new("A"), Ident::new("B"), Ident::new("C"),],
+                    columns: table_alias_columns(&["A", "B", "C"]),
                 }),
                 args: None,
                 with_hints: vec![],
@@ -566,6 +567,24 @@ fn parse_select_with_table_alias() {
     );
 }
 
+#[test]
+fn parse_table_alias_columns_with_types() {
+    let sql = "SELECT * FROM generate_series(1, 2) AS numbers (n INT, s TEXT)";
+    let select = pg_and_generic().verified_only_select(sql);
+    match only(select.from).relation {
+        TableFactor::Table { alias: Some(alias), .. } => {
+            assert_eq!(
+                alias.columns,
+                vec![
+                    table_alias_column_with_type("n", DataType::Int(None)),
+                    table_alias_column_with_type("s", DataType::Text),
+                ]
+            );
+        }
+        _ => panic!("expected table factor with alias"),
+    }
+}
+
 #[test]
 fn parse_invalid_table_name() {
     let ast = all_dialects().run_parser_method("db.public..customer", |parser| {
@@ -6372,7 +6391,7 @@ fn parse_cte_renamed_columns() {
     let sql = "WITH cte (col1, col2) AS (SELECT foo, bar FROM baz) SELECT * FROM cte";
     let query = all_dialects().verified_query(sql);
     assert_eq!(
-        vec![Ident::new("col1"), Ident::new("col2")],
+        vec![table_alias_column("col1"), table_alias_column("col2")],
         query
             .with
             .unwrap()
@@ -6384,6 +6403,27 @@ fn parse_cte_renamed_columns() {
     );
 }
 
+#[test]
+fn parse_cte_columns_with_types() {
+    let sql = "WITH foo (id INT, name TEXT) AS (SELECT 1, 'a') SELECT * FROM foo";
+    let query = pg_and_generic().verified_query(sql);
+    let columns = &query
+        .with
+        .unwrap()
+        .cte_tables
+        .first()
+        .unwrap()
+        .alias
+        .columns;
+    assert_eq!(
+        columns,
+        &vec![
+            table_alias_column_with_type("id", DataType::Int(None)),
+            table_alias_column_with_type("name", DataType::Text),
+        ]
+    );
+}
+
 #[test]
 fn parse_recursive_cte() {
     let cte_query = "SELECT 1 UNION ALL SELECT val + 1 FROM nums WHERE val < 10".to_owned();
@@ -6401,10 +6441,7 @@ fn parse_recursive_cte() {
                 value: "nums".to_string(),
                 quote_style: None,
             },
-            columns: vec![Ident {
-                value: "val".to_string(),
-                quote_style: None,
-            }],
+            columns: vec![table_alias_column("val")],
         },
         query: Box::new(cte_query),
         from: None,
@@ -9347,7 +9384,7 @@ fn parse_pivot_table() {
                     value: "p".to_string(),
                     quote_style: None
                 },
-                columns: vec![Ident::new("c"), Ident::new("d")],
+                columns: table_alias_columns(&["c", "d"]),
             }),
         }
     );