STET

agent_patch

runs/2026-02-28__18-27-22__gpt-5-1-codex-mini/flux-pr-1500/flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/agent-logs/agent.patch

7117 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/ast/mod.rs b/app/src/ast/mod.rs
index 505386f..c8ad0f8 100644
--- a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -561,6 +561,12 @@ pub enum Expr {
         expr: Box<Expr>,
         key: Ident,
     },
+    /// Method call on an expression, e.g. `(expr).value('x', 'y')`.
+    MethodCall {
+        expr: Box<Expr>,
+        method: Ident,
+        args: FunctionArgumentList,
+    },
     /// `IS FALSE` operator
     IsFalse(Box<Expr>),
     /// `IS NOT FALSE` operator
@@ -1630,6 +1636,9 @@ impl fmt::Display for Expr {
             Expr::CompositeAccess { expr, key } => {
                 write!(f, "{expr}.{key}")
             }
+            Expr::MethodCall { expr, method, args } => {
+                write!(f, "{expr}.{method}{args}")
+            }
             Expr::AtTimeZone {
                 timestamp,
                 time_zone,
diff --git a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/dialect/mod.rs b/app/src/dialect/mod.rs
index a732aa5..bc15e6c 100644
--- a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/dialect/mod.rs
+++ b/app/src/dialect/mod.rs
@@ -270,6 +270,11 @@ pub trait Dialect: Debug + Any {
         false
     }
 
+    /// Returns true if the dialect allows calling methods on expressions via `.method(...)`.
+    fn supports_expression_method_calls(&self) -> bool {
+        false
+    }
+
     /// Returns true if the dialect supports lambda functions, for example:
     ///
     /// ```sql
@@ -464,6 +469,15 @@ pub trait Dialect: Debug + Any {
             | Token::QuestionAnd
             | Token::QuestionPipe
             | Token::CustomBinaryOperator(_) => Ok(p!(PgOther)),
+            Token::Period if self.supports_expression_method_calls() => {
+                match (
+                    parser.peek_nth_token(1).token,
+                    parser.peek_nth_token(2).token,
+                ) {
+                    (Token::Word(_), Token::LParen) => Ok(p!(MemberAccess)),
+                    _ => Ok(self.prec_unknown()),
+                }
+            }
             _ => Ok(self.prec_unknown()),
         }
     }
@@ -496,6 +510,7 @@ pub trait Dialect: Debug + Any {
     /// Uses (APPROXIMATELY) <https://www.postgresql.org/docs/7.0/operators.htm#AEN2026> as a reference
     fn prec_value(&self, prec: Precedence) -> u8 {
         match prec {
+            Precedence::MemberAccess => 60,
             Precedence::DoubleColon => 50,
             Precedence::AtTz => 41,
             Precedence::MulDivModOp => 40,
@@ -645,6 +660,7 @@ pub trait Dialect: Debug + Any {
 /// higher number -> higher precedence
 #[derive(Debug, Clone, Copy)]
 pub enum Precedence {
+    MemberAccess,
     DoubleColon,
     AtTz,
     MulDivModOp,
diff --git a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/dialect/mssql.rs b/app/src/dialect/mssql.rs
index 8aab0bc..d42648e 100644
--- a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/dialect/mssql.rs
+++ b/app/src/dialect/mssql.rs
@@ -62,4 +62,8 @@ impl Dialect for MsSqlDialect {
     fn supports_boolean_literals(&self) -> bool {
         false
     }
+
+    fn supports_expression_method_calls(&self) -> bool {
+        true
+    }
 }
diff --git a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 4115bbc..2dbd946 100644
--- a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -2881,6 +2881,8 @@ impl<'a> Parser<'a> {
                 op: UnaryOperator::PGPostfixFactorial,
                 expr: Box::new(expr),
             })
+        } else if Token::Period == tok && self.dialect.supports_expression_method_calls() {
+            self.parse_method_call(expr)
         } else if Token::LBracket == tok {
             if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) {
                 self.parse_subscript(expr)
@@ -2902,6 +2904,17 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn parse_method_call(&mut self, expr: Expr) -> Result<Expr, ParserError> {
+        let method = self.parse_identifier(false)?;
+        self.expect_token(&Token::LParen)?;
+        let args = self.parse_function_argument_list()?;
+        Ok(Expr::MethodCall {
+            expr: Box::new(expr),
+            method,
+            args,
+        })
+    }
+
     /// Parse the `ESCAPE CHAR` portion of `LIKE`, `ILIKE`, and `SIMILAR TO`
     pub fn parse_escape_char(&mut self) -> Result<Option<String>, ParserError> {
         if self.parse_keyword(Keyword::ESCAPE) {
diff --git a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/tests/sqlparser_mssql.rs b/app/tests/sqlparser_mssql.rs
index c28f89e..8bad602 100644
--- a/tmp/agent-patch-flux-pr-1500.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -1445,6 +1445,51 @@ fn parse_true_false_as_identifiers() {
     );
 }
 
+#[test]
+fn parse_mssql_expression_method_calls() {
+    let expr = ms().verified_expr("CONVERT(XML, xmlcol).value('XQuery', 'SQL').query('/root')");
+
+    assert_eq!(
+        expr,
+        Expr::MethodCall {
+            expr: Box::new(Expr::MethodCall {
+                expr: Box::new(Expr::Convert {
+                    is_try: false,
+                    expr: Box::new(Expr::Identifier(Ident::new("xmlcol"))),
+                    data_type: Some(DataType::Custom(
+                        ObjectName(vec![Ident::new("XML")]),
+                        vec![]
+                    )),
+                    charset: None,
+                    target_before_value: true,
+                    styles: vec![],
+                }),
+                method: Ident::new("value"),
+                args: FunctionArgumentList {
+                    duplicate_treatment: None,
+                    args: vec![
+                        FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                            Value::SingleQuotedString("XQuery".to_string()),
+                        ))),
+                        FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                            Value::SingleQuotedString("SQL".to_string()),
+                        ))),
+                    ],
+                    clauses: vec![],
+                },
+            }),
+            method: Ident::new("query"),
+            args: FunctionArgumentList {
+                duplicate_treatment: None,
+                args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
+                    Value::SingleQuotedString("/root".to_string()),
+                )))],
+                clauses: vec![],
+            },
+        }
+    );
+}
+
 fn ms() -> TestedDialects {
     TestedDialects::new(vec![Box::new(MsSqlDialect {})])
 }