STET

agent_patch

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

15274 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1900.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/ddl.rs b/app/src/ast/ddl.rs
index 059c619..f5a7a52 100644
--- a/tmp/agent-patch-flux-pr-1900.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/ddl.rs
+++ b/app/src/ast/ddl.rs
@@ -30,11 +30,10 @@ use sqlparser_derive::{Visit, VisitMut};
 
 use crate::ast::value::escape_single_quote_string;
 use crate::ast::{
-    display_comma_separated, display_separated, CommentDef, CreateFunctionBody,
-    CreateFunctionUsing, DataType, Expr, FunctionBehavior, FunctionCalledOnNull,
-    FunctionDeterminismSpecifier, FunctionParallel, Ident, MySQLColumnPosition, ObjectName,
-    OperateFunctionArg, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value,
-    ValueWithSpan,
+    display_comma_separated, display_separated, CommentDef, CreateFunctionBody, CreateFunctionUsing,
+    DataType, Expr, FunctionBehavior, FunctionCalledOnNull, FunctionDeterminismSpecifier,
+    FunctionParallel, Ident, IndexColumn, MySQLColumnPosition, ObjectName, OperateFunctionArg,
+    OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value, ValueWithSpan,
 };
 use crate::keywords::Keyword;
 use crate::tokenizer::Token;
@@ -978,8 +977,8 @@ pub enum TableConstraint {
         ///
         /// [1]: IndexType
         index_type: Option<IndexType>,
-        /// Identifiers of the columns that are unique.
-        columns: Vec<Ident>,
+        /// Index column definitions that are unique.
+        columns: Vec<IndexColumn>,
         index_options: Vec<IndexOption>,
         characteristics: Option<ConstraintCharacteristics>,
         /// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]`
@@ -1014,8 +1013,8 @@ pub enum TableConstraint {
         ///
         /// [1]: IndexType
         index_type: Option<IndexType>,
-        /// Identifiers of the columns that form the primary key.
-        columns: Vec<Ident>,
+        /// Index column definitions that form the primary key.
+        columns: Vec<IndexColumn>,
         index_options: Vec<IndexOption>,
         characteristics: Option<ConstraintCharacteristics>,
     },
@@ -1059,8 +1058,8 @@ pub enum TableConstraint {
         ///
         /// [1]: IndexType
         index_type: Option<IndexType>,
-        /// Referred column identifier list.
-        columns: Vec<Ident>,
+        /// Referred index column list.
+        columns: Vec<IndexColumn>,
     },
     /// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
     /// and MySQL displays both the same way, it is part of this definition as well.
@@ -1082,8 +1081,8 @@ pub enum TableConstraint {
         index_type_display: KeyOrIndexDisplay,
         /// Optional index name.
         opt_index_name: Option<Ident>,
-        /// Referred column identifier list.
-        columns: Vec<Ident>,
+        /// Referred index column list.
+        columns: Vec<IndexColumn>,
     },
 }
 
diff --git a/tmp/agent-patch-flux-pr-1900.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 292650c..bd69c9d 100644
--- a/tmp/agent-patch-flux-pr-1900.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
@@ -37,9 +37,9 @@ use super::{
     display_comma_separated, display_separated, query::InputFormatClause, Assignment, ClusteredBy,
     CommentDef, CreateTableOptions, Expr, FileFormat, FromTable, HiveDistributionStyle, HiveFormat,
     HiveIOFormat, HiveRowFormat, Ident, IndexType, InsertAliases, MysqlInsertPriority, ObjectName,
-    OnCommit, OnInsert, OneOrManyWithParens, OrderByExpr, Query, RowAccessPolicy, SelectItem,
-    Setting, SqliteOnConflict, StorageSerializationPolicy, TableObject, TableWithJoins, Tag,
-    WrappedCollection,
+    OnCommit, OnInsert, OneOrManyWithParens, OrderByExpr, OrderByOptions, Query, RowAccessPolicy,
+    SelectItem, Setting, SqliteOnConflict, StorageSerializationPolicy, TableObject, TableWithJoins,
+    Tag, WrappedCollection,
 };
 
 /// Index column type.
@@ -51,6 +51,37 @@ pub struct IndexColumn {
     pub operator_class: Option<Ident>,
 }
 
+impl IndexColumn {
+    /// Build an index column from an expression with default ordering options.
+    pub fn from_expr(expr: Expr) -> Self {
+        IndexColumn {
+            column: OrderByExpr {
+                expr,
+                options: OrderByOptions::default(),
+                with_fill: None,
+            },
+            operator_class: None,
+        }
+    }
+
+    /// Create an index column from a simple identifier.
+    pub fn from_ident(ident: Ident) -> Self {
+        Self::from_expr(Expr::Identifier(ident))
+    }
+}
+
+impl From<Expr> for IndexColumn {
+    fn from(expr: Expr) -> Self {
+        IndexColumn::from_expr(expr)
+    }
+}
+
+impl From<Ident> for IndexColumn {
+    fn from(ident: Ident) -> Self {
+        Expr::Identifier(ident).into()
+    }
+}
+
 impl Display for IndexColumn {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.column)?;
diff --git a/tmp/agent-patch-flux-pr-1900.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 1fb93b6..22f8ba5 100644
--- a/tmp/agent-patch-flux-pr-1900.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
@@ -2493,7 +2493,7 @@ impl fmt::Display for InterpolateExpr {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
 pub struct OrderByOptions {
diff --git a/tmp/agent-patch-flux-pr-1900.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 14664b4..d190581 100644
--- a/tmp/agent-patch-flux-pr-1900.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
@@ -32,7 +32,7 @@ use super::{
     InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView,
     LimitClause, MatchRecognizePattern, Measure, NamedParenthesizedList, NamedWindowDefinition,
     ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction, OnInsert, OpenStatement,
-    OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource, ProjectionSelect, Query,
+    OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource, IndexColumn, ProjectionSelect, Query,
     RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
     ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
     SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
@@ -717,6 +717,19 @@ impl Spanned for TableConstraint {
     }
 }
 
+impl Spanned for IndexColumn {
+    fn span(&self) -> Span {
+        let IndexColumn {
+            column,
+            operator_class,
+        } = self;
+
+        column
+            .span()
+            .union_opt(&operator_class.as_ref().map(|ident| ident.span))
+    }
+}
+
 impl Spanned for CreateIndex {
     fn span(&self) -> Span {
         let CreateIndex {
diff --git a/tmp/agent-patch-flux-pr-1900.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 44bf58d..84abb35 100644
--- a/tmp/agent-patch-flux-pr-1900.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
@@ -8070,7 +8070,7 @@ impl<'a> Parser<'a> {
                 let index_name = self.parse_optional_ident()?;
                 let index_type = self.parse_optional_using_then_index_type()?;
 
-                let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
+                let columns = self.parse_parenthesized_index_column_list(Mandatory, false)?;
                 let index_options = self.parse_index_options()?;
                 let characteristics = self.parse_constraint_characteristics()?;
                 Ok(Some(TableConstraint::Unique {
@@ -8092,7 +8092,8 @@ impl<'a> Parser<'a> {
                 let index_name = self.parse_optional_ident()?;
                 let index_type = self.parse_optional_using_then_index_type()?;
 
-                let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
+                let columns =
+                    self.parse_parenthesized_index_column_list(Mandatory, false)?;
                 let index_options = self.parse_index_options()?;
                 let characteristics = self.parse_constraint_characteristics()?;
                 Ok(Some(TableConstraint::PrimaryKey {
@@ -8107,7 +8108,8 @@ impl<'a> Parser<'a> {
             Token::Word(w) if w.keyword == Keyword::FOREIGN => {
                 self.expect_keyword_is(Keyword::KEY)?;
                 let index_name = self.parse_optional_ident()?;
-                let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
+                let columns =
+                    self.parse_parenthesized_column_list(Mandatory, false)?;
                 self.expect_keyword_is(Keyword::REFERENCES)?;
                 let foreign_table = self.parse_object_name(false)?;
                 let referred_columns = self.parse_parenthesized_column_list(Optional, false)?;
@@ -8170,7 +8172,8 @@ impl<'a> Parser<'a> {
                 };
 
                 let index_type = self.parse_optional_using_then_index_type()?;
-                let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
+                let columns =
+                    self.parse_parenthesized_index_column_list(Mandatory, false)?;
 
                 Ok(Some(TableConstraint::Index {
                     display_as_key,
@@ -8199,7 +8202,8 @@ impl<'a> Parser<'a> {
 
                 let opt_index_name = self.parse_optional_ident()?;
 
-                let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
+                let columns =
+                    self.parse_parenthesized_index_column_list(Mandatory, false)?;
 
                 Ok(Some(TableConstraint::FulltextOrSpatial {
                     fulltext,
@@ -10601,6 +10605,18 @@ impl<'a> Parser<'a> {
         self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier())
     }
 
+    pub fn parse_parenthesized_index_column_list(
+        &mut self,
+        optional: IsOptional,
+        allow_empty: bool,
+    ) -> Result<Vec<IndexColumn>, ParserError> {
+        self.parse_parenthesized_column_list_inner(
+            optional,
+            allow_empty,
+            |p| p.parse_create_index_expr(),
+        )
+    }
+
     /// Parses a parenthesized comma-separated list of qualified, possibly quoted identifiers.
     /// For example: `(db1.sc1.tbl1.col1, db1.sc1.tbl1."col 2", ...)`
     pub fn parse_parenthesized_qualified_column_list(
@@ -16537,7 +16553,7 @@ mod tests {
                 display_as_key: false,
                 name: None,
                 index_type: None,
-                columns: vec![Ident::new("c1")],
+                columns: vec![Ident::new("c1").into()],
             }
         );
 
@@ -16548,7 +16564,7 @@ mod tests {
                 display_as_key: true,
                 name: None,
                 index_type: None,
-                columns: vec![Ident::new("c1")],
+                columns: vec![Ident::new("c1").into()],
             }
         );
 
@@ -16559,7 +16575,10 @@ mod tests {
                 display_as_key: false,
                 name: Some(Ident::with_quote('\'', "index")),
                 index_type: None,
-                columns: vec![Ident::new("c1"), Ident::new("c2")],
+                columns: vec![
+                    Ident::new("c1").into(),
+                    Ident::new("c2").into()
+                ],
             }
         );
 
@@ -16570,7 +16589,7 @@ mod tests {
                 display_as_key: false,
                 name: None,
                 index_type: Some(IndexType::BTree),
-                columns: vec![Ident::new("c1")],
+                columns: vec![Ident::new("c1").into()],
             }
         );
 
@@ -16581,7 +16600,7 @@ mod tests {
                 display_as_key: false,
                 name: None,
                 index_type: Some(IndexType::Hash),
-                columns: vec![Ident::new("c1")],
+                columns: vec![Ident::new("c1").into()],
             }
         );
 
@@ -16592,7 +16611,7 @@ mod tests {
                 display_as_key: false,
                 name: Some(Ident::new("idx_name")),
                 index_type: Some(IndexType::BTree),
-                columns: vec![Ident::new("c1")],
+                columns: vec![Ident::new("c1").into()],
             }
         );
 
@@ -16603,7 +16622,7 @@ mod tests {
                 display_as_key: false,
                 name: Some(Ident::new("idx_name")),
                 index_type: Some(IndexType::Hash),
-                columns: vec![Ident::new("c1")],
+                columns: vec![Ident::new("c1").into()],
             }
         );
     }
diff --git a/tmp/agent-patch-flux-pr-1900.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_mysql.rs b/app/tests/sqlparser_mysql.rs
index 540348f..7c1c2f6 100644
--- a/tmp/agent-patch-flux-pr-1900.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_mysql.rs
+++ b/app/tests/sqlparser_mysql.rs
@@ -665,7 +665,7 @@ fn table_constraint_unique_primary_ctor(
     name: Option<Ident>,
     index_name: Option<Ident>,
     index_type: Option<IndexType>,
-    columns: Vec<Ident>,
+    columns: Vec<IndexColumn>,
     index_options: Vec<IndexOption>,
     characteristics: Option<ConstraintCharacteristics>,
     unique_index_type_display: Option<KeyOrIndexDisplay>,
@@ -713,7 +713,7 @@ fn parse_create_table_primary_and_unique_key() {
                     Some(Ident::new("bar_key")),
                     None,
                     None,
-                    vec![Ident::new("bar")],
+                    vec![Ident::new("bar").into()],
                     vec![],
                     None,
                     index_type_display,
@@ -776,7 +776,10 @@ fn parse_create_table_primary_and_unique_key_with_index_options() {
                     Some(Ident::new("constr")),
                     Some(Ident::new("index_name")),
                     None,
-                    vec![Ident::new("bar"), Ident::new("var")],
+                    vec![
+                        Ident::new("bar").into(),
+                        Ident::new("var").into()
+                    ],
                     vec![
                         IndexOption::Using(IndexType::Hash),
                         IndexOption::Comment("yes, ".into()),
@@ -814,7 +817,7 @@ fn parse_create_table_primary_and_unique_key_with_index_type() {
                     None,
                     Some(Ident::new("index_name")),
                     Some(IndexType::BTree),
-                    vec![Ident::new("bar")],
+                    vec![Ident::new("bar").into()],
                     vec![IndexOption::Using(IndexType::Hash)],
                     None,
                     index_type_display,