STET

agent_patch

runs/2026-02-28__18-27-22__gpt-5-3-codex/flux-pr-2172/flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/agent-logs/agent.patch

29227 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/query.rs b/app/src/ast/query.rs
index 08448ca..3076f47 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/query.rs
+++ b/app/src/ast/query.rs
@@ -350,6 +350,9 @@ pub struct Select {
     pub optimizer_hint: Option<OptimizerHint>,
     /// `SELECT [DISTINCT] ...`
     pub distinct: Option<Distinct>,
+    /// `SELECT` modifiers, including duplicate-row options and MySQL-specific hints.
+    #[cfg_attr(feature = "serde", serde(default))]
+    pub select_modifiers: Vec<SelectModifier>,
     /// MSSQL syntax: `TOP (<N>) [ PERCENT ] [ WITH TIES ]`
     pub top: Option<Top>,
     /// Whether the top was located before `ALL`/`DISTINCT`
@@ -431,9 +434,16 @@ impl fmt::Display for Select {
                 top.fmt(f)?;
             }
         }
-        if let Some(ref distinct) = self.distinct {
-            f.write_str(" ")?;
-            distinct.fmt(f)?;
+        if self.select_modifiers.is_empty() {
+            if let Some(ref distinct) = self.distinct {
+                f.write_str(" ")?;
+                distinct.fmt(f)?;
+            }
+        } else {
+            for select_modifier in &self.select_modifiers {
+                f.write_str(" ")?;
+                select_modifier.fmt(f)?;
+            }
         }
         if let Some(ref top) = self.top {
             if !self.top_before_distinct {
@@ -3372,6 +3382,56 @@ impl fmt::Display for Distinct {
     }
 }
 
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+/// `SELECT` modifiers such as `ALL`, `DISTINCTROW`, and MySQL-specific hints.
+pub enum SelectModifier {
+    /// `ALL` (do not remove duplicate rows)
+    All,
+    /// `DISTINCT` (remove duplicate rows)
+    Distinct,
+    /// `DISTINCT ON (...)` (Postgres extension)
+    DistinctOn(Vec<Expr>),
+    /// `DISTINCTROW` (MySQL synonym for `DISTINCT`)
+    DistinctRow,
+    /// MySQL `HIGH_PRIORITY`
+    HighPriority,
+    /// MySQL `STRAIGHT_JOIN`
+    StraightJoin,
+    /// MySQL `SQL_SMALL_RESULT`
+    SqlSmallResult,
+    /// MySQL `SQL_BIG_RESULT`
+    SqlBigResult,
+    /// MySQL `SQL_BUFFER_RESULT`
+    SqlBufferResult,
+    /// MySQL `SQL_NO_CACHE`
+    SqlNoCache,
+    /// MySQL `SQL_CALC_FOUND_ROWS`
+    SqlCalcFoundRows,
+}
+
+impl fmt::Display for SelectModifier {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            SelectModifier::All => write!(f, "ALL"),
+            SelectModifier::Distinct => write!(f, "DISTINCT"),
+            SelectModifier::DistinctOn(col_names) => {
+                let col_names = display_comma_separated(col_names);
+                write!(f, "DISTINCT ON ({col_names})")
+            }
+            SelectModifier::DistinctRow => write!(f, "DISTINCTROW"),
+            SelectModifier::HighPriority => write!(f, "HIGH_PRIORITY"),
+            SelectModifier::StraightJoin => write!(f, "STRAIGHT_JOIN"),
+            SelectModifier::SqlSmallResult => write!(f, "SQL_SMALL_RESULT"),
+            SelectModifier::SqlBigResult => write!(f, "SQL_BIG_RESULT"),
+            SelectModifier::SqlBufferResult => write!(f, "SQL_BUFFER_RESULT"),
+            SelectModifier::SqlNoCache => write!(f, "SQL_NO_CACHE"),
+            SelectModifier::SqlCalcFoundRows => write!(f, "SQL_CALC_FOUND_ROWS"),
+        }
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/spans.rs b/app/src/ast/spans.rs
index 60c983f..18c0c2e 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/spans.rs
+++ b/app/src/ast/spans.rs
@@ -2238,6 +2238,7 @@ impl Spanned for Select {
             select_token,
             optimizer_hint: _,
             distinct: _, // todo
+            select_modifiers: _,
             top: _,      // todo, mysql specific
             projection,
             exclude: _,
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/keywords.rs b/app/src/keywords.rs
index 964e4b3..2e26bda 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/keywords.rs
+++ b/app/src/keywords.rs
@@ -333,6 +333,7 @@ define_keywords!(
     DISCARD,
     DISCONNECT,
     DISTINCT,
+    DISTINCTROW,
     DISTRIBUTE,
     DIV,
     DO,
@@ -956,6 +957,11 @@ define_keywords!(
     SQLEXCEPTION,
     SQLSTATE,
     SQLWARNING,
+    SQL_BIG_RESULT,
+    SQL_BUFFER_RESULT,
+    SQL_CALC_FOUND_ROWS,
+    SQL_NO_CACHE,
+    SQL_SMALL_RESULT,
     SQRT,
     SRID,
     STABLE,
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 5fa224f..a576f8e 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -4951,6 +4951,144 @@ impl<'a> Parser<'a> {
         Ok(Some(Distinct::On(col_names)))
     }
 
+    /// Parse repeated `SELECT` modifiers in any order.
+    ///
+    /// This includes duplicate-row modifiers (`ALL`, `DISTINCT`, `DISTINCT ON`, `DISTINCTROW`)
+    /// and MySQL-specific modifiers (`HIGH_PRIORITY`, `STRAIGHT_JOIN`, `SQL_*`).
+    pub fn parse_select_modifiers(&mut self) -> Result<Vec<SelectModifier>, ParserError> {
+        let mut modifiers = vec![];
+        let mut has_all = false;
+        let mut has_distinct = false;
+        let mut has_high_priority = false;
+        let mut has_straight_join = false;
+        let mut has_sql_small_result = false;
+        let mut has_sql_big_result = false;
+        let mut has_sql_buffer_result = false;
+        let mut has_sql_no_cache = false;
+        let mut has_sql_calc_found_rows = false;
+        let is_mysql = dialect_of!(self is MySqlDialect | GenericDialect);
+
+        loop {
+            let loc = self.peek_token().span.start;
+            if self.parse_keyword(Keyword::ALL) {
+                if has_distinct {
+                    return parser_err!("Cannot specify both ALL and DISTINCT".to_string(), loc);
+                }
+                if has_all {
+                    return parser_err!("Cannot specify ALL more than once".to_string(), loc);
+                }
+                has_all = true;
+                modifiers.push(SelectModifier::All);
+            } else if self.parse_keyword(Keyword::DISTINCT) {
+                if has_all {
+                    return parser_err!("Cannot specify both ALL and DISTINCT".to_string(), loc);
+                }
+                if has_distinct {
+                    return parser_err!("Cannot specify DISTINCT more than once".to_string(), loc);
+                }
+                has_distinct = true;
+                if self.parse_keyword(Keyword::ON) {
+                    self.expect_token(&Token::LParen)?;
+                    let col_names = if self.consume_token(&Token::RParen) {
+                        self.prev_token();
+                        Vec::new()
+                    } else {
+                        self.parse_comma_separated(Parser::parse_expr)?
+                    };
+                    self.expect_token(&Token::RParen)?;
+                    modifiers.push(SelectModifier::DistinctOn(col_names));
+                } else {
+                    modifiers.push(SelectModifier::Distinct);
+                }
+            } else if is_mysql && self.parse_keyword(Keyword::DISTINCTROW) {
+                if has_all {
+                    return parser_err!("Cannot specify both ALL and DISTINCT".to_string(), loc);
+                }
+                if has_distinct {
+                    return parser_err!("Cannot specify DISTINCT more than once".to_string(), loc);
+                }
+                has_distinct = true;
+                modifiers.push(SelectModifier::DistinctRow);
+            } else if is_mysql && self.parse_keyword(Keyword::HIGH_PRIORITY) {
+                if has_high_priority {
+                    return parser_err!(
+                        "Cannot specify HIGH_PRIORITY more than once".to_string(),
+                        loc
+                    );
+                }
+                has_high_priority = true;
+                modifiers.push(SelectModifier::HighPriority);
+            } else if is_mysql && self.parse_keyword(Keyword::STRAIGHT_JOIN) {
+                if has_straight_join {
+                    return parser_err!(
+                        "Cannot specify STRAIGHT_JOIN more than once".to_string(),
+                        loc
+                    );
+                }
+                has_straight_join = true;
+                modifiers.push(SelectModifier::StraightJoin);
+            } else if is_mysql && self.parse_keyword(Keyword::SQL_SMALL_RESULT) {
+                if has_sql_small_result {
+                    return parser_err!(
+                        "Cannot specify SQL_SMALL_RESULT more than once".to_string(),
+                        loc
+                    );
+                }
+                has_sql_small_result = true;
+                modifiers.push(SelectModifier::SqlSmallResult);
+            } else if is_mysql && self.parse_keyword(Keyword::SQL_BIG_RESULT) {
+                if has_sql_big_result {
+                    return parser_err!(
+                        "Cannot specify SQL_BIG_RESULT more than once".to_string(),
+                        loc
+                    );
+                }
+                has_sql_big_result = true;
+                modifiers.push(SelectModifier::SqlBigResult);
+            } else if is_mysql && self.parse_keyword(Keyword::SQL_BUFFER_RESULT) {
+                if has_sql_buffer_result {
+                    return parser_err!(
+                        "Cannot specify SQL_BUFFER_RESULT more than once".to_string(),
+                        loc
+                    );
+                }
+                has_sql_buffer_result = true;
+                modifiers.push(SelectModifier::SqlBufferResult);
+            } else if is_mysql && self.parse_keyword(Keyword::SQL_NO_CACHE) {
+                if has_sql_no_cache {
+                    return parser_err!(
+                        "Cannot specify SQL_NO_CACHE more than once".to_string(),
+                        loc
+                    );
+                }
+                has_sql_no_cache = true;
+                modifiers.push(SelectModifier::SqlNoCache);
+            } else if is_mysql && self.parse_keyword(Keyword::SQL_CALC_FOUND_ROWS) {
+                if has_sql_calc_found_rows {
+                    return parser_err!(
+                        "Cannot specify SQL_CALC_FOUND_ROWS more than once".to_string(),
+                        loc
+                    );
+                }
+                has_sql_calc_found_rows = true;
+                modifiers.push(SelectModifier::SqlCalcFoundRows);
+            } else {
+                break;
+            }
+        }
+
+        Ok(modifiers)
+    }
+
+    fn distinct_from_select_modifiers(select_modifiers: &[SelectModifier]) -> Option<Distinct> {
+        select_modifiers.iter().find_map(|modifier| match modifier {
+            SelectModifier::Distinct => Some(Distinct::Distinct),
+            SelectModifier::DistinctOn(col_names) => Some(Distinct::On(col_names.clone())),
+            SelectModifier::DistinctRow => Some(Distinct::Distinct),
+            _ => None,
+        })
+    }
+
     /// Parse a SQL CREATE statement
     pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
         let or_replace = self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]);
@@ -13861,6 +13999,7 @@ impl<'a> Parser<'a> {
                     select_token: AttachedToken(from_token),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![],
@@ -13896,7 +14035,8 @@ impl<'a> Parser<'a> {
             top = Some(self.parse_top()?);
             top_before_distinct = true;
         }
-        let distinct = self.parse_all_or_distinct()?;
+        let select_modifiers = self.parse_select_modifiers()?;
+        let distinct = Self::distinct_from_select_modifiers(&select_modifiers);
         if !self.dialect.supports_top_before_distinct() && self.parse_keyword(Keyword::TOP) {
             top = Some(self.parse_top()?);
         }
@@ -14044,6 +14184,7 @@ impl<'a> Parser<'a> {
             select_token: AttachedToken(select_token),
             optimizer_hint,
             distinct,
+            select_modifiers,
             top,
             top_before_distinct,
             projection,
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_bigquery.rs b/app/tests/sqlparser_bigquery.rs
index fb28b4d..30271f2 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_bigquery.rs
+++ b/app/tests/sqlparser_bigquery.rs
@@ -2683,6 +2683,7 @@ fn test_export_data() {
                     )),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![
@@ -2788,6 +2789,7 @@ fn test_export_data() {
                     )),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_clickhouse.rs b/app/tests/sqlparser_clickhouse.rs
index ac31a27..04821e7 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_clickhouse.rs
+++ b/app/tests/sqlparser_clickhouse.rs
@@ -41,6 +41,7 @@ fn parse_map_access_expr() {
     assert_eq!(
         Select {
             distinct: None,
+            select_modifiers: vec![],
             optimizer_hint: None,
             select_token: AttachedToken::empty(),
             top: None,
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index e6a48c7..ed5f267 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -473,6 +473,7 @@ fn parse_update_set_from() {
                             select_token: AttachedToken::empty(),
                             optimizer_hint: None,
                             distinct: None,
+                            select_modifiers: vec![],
                             top: None,
                             top_before_distinct: false,
                             projection: vec![
@@ -1074,7 +1075,7 @@ fn parse_select_distinct_missing_paren() {
 
 #[test]
 fn parse_select_all() {
-    one_statement_parses_to("SELECT ALL name FROM customer", "SELECT name FROM customer");
+    one_statement_parses_to("SELECT ALL name FROM customer", "SELECT ALL name FROM customer");
 }
 
 #[test]
@@ -5809,6 +5810,7 @@ fn test_parse_named_window() {
         select_token: AttachedToken::empty(),
         optimizer_hint: None,
         distinct: None,
+        select_modifiers: vec![],
         top: None,
         top_before_distinct: false,
         projection: vec![
@@ -6540,6 +6542,7 @@ fn parse_interval_and_or_xor() {
             select_token: AttachedToken::empty(),
             optimizer_hint: None,
             distinct: None,
+            select_modifiers: vec![],
             top: None,
             top_before_distinct: false,
             projection: vec![UnnamedExpr(Expr::Identifier(Ident {
@@ -8917,6 +8920,7 @@ fn lateral_function() {
         select_token: AttachedToken::empty(),
         optimizer_hint: None,
         distinct: None,
+        select_modifiers: vec![],
         top: None,
         projection: vec![SelectItem::Wildcard(WildcardAdditionalOptions::default())],
         exclude: None,
@@ -9919,6 +9923,7 @@ fn parse_merge() {
                             select_token: AttachedToken::empty(),
                             optimizer_hint: None,
                             distinct: None,
+                            select_modifiers: vec![],
                             top: None,
                             top_before_distinct: false,
                             projection: vec![SelectItem::Wildcard(
@@ -12323,6 +12328,7 @@ fn parse_unload() {
                     select_token: AttachedToken::empty(),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![UnnamedExpr(Expr::Identifier(Ident::new("cola"))),],
@@ -12632,6 +12638,7 @@ fn parse_connect_by() {
         select_token: AttachedToken::empty(),
         optimizer_hint: None,
         distinct: None,
+        select_modifiers: vec![],
         top: None,
         top_before_distinct: false,
         projection: vec![
@@ -12715,6 +12722,7 @@ fn parse_connect_by() {
             select_token: AttachedToken::empty(),
             optimizer_hint: None,
             distinct: None,
+            select_modifiers: vec![],
             top: None,
             top_before_distinct: false,
             projection: vec![
@@ -13649,6 +13657,7 @@ fn test_extract_seconds_ok() {
             select_token: AttachedToken::empty(),
             optimizer_hint: None,
             distinct: None,
+            select_modifiers: vec![],
             top: None,
             top_before_distinct: false,
             projection: vec![UnnamedExpr(Expr::Extract {
@@ -14830,9 +14839,9 @@ fn test_load_extension() {
 #[test]
 fn test_select_top() {
     let dialects = all_dialects_where(|d| d.supports_top_before_distinct());
-    dialects.one_statement_parses_to("SELECT ALL * FROM tbl", "SELECT * FROM tbl");
+    dialects.one_statement_parses_to("SELECT ALL * FROM tbl", "SELECT ALL * FROM tbl");
     dialects.verified_stmt("SELECT TOP 3 * FROM tbl");
-    dialects.one_statement_parses_to("SELECT TOP 3 ALL * FROM tbl", "SELECT TOP 3 * FROM tbl");
+    dialects.one_statement_parses_to("SELECT TOP 3 ALL * FROM tbl", "SELECT TOP 3 ALL * FROM tbl");
     dialects.verified_stmt("SELECT TOP 3 DISTINCT * FROM tbl");
     dialects.verified_stmt("SELECT TOP 3 DISTINCT a, b, c FROM tbl");
 }
@@ -15789,6 +15798,7 @@ fn test_select_from_first() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 projection,
                 exclude: None,
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_duckdb.rs b/app/tests/sqlparser_duckdb.rs
index 7cc710d..e2e52b9 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_duckdb.rs
+++ b/app/tests/sqlparser_duckdb.rs
@@ -268,6 +268,7 @@ fn test_select_union_by_name() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 projection: vec![SelectItem::Wildcard(WildcardAdditionalOptions::default())],
                 exclude: None,
@@ -300,6 +301,7 @@ fn test_select_union_by_name() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 projection: vec![SelectItem::Wildcard(WildcardAdditionalOptions::default())],
                 exclude: None,
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs b/app/tests/sqlparser_mssql.rs
index d770008..606831e 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -143,6 +143,7 @@ fn parse_create_procedure() {
                         select_token: AttachedToken::empty(),
                         optimizer_hint: None,
                         distinct: None,
+                        select_modifiers: vec![],
                         top: None,
                         top_before_distinct: false,
                         projection: vec![SelectItem::UnnamedExpr(Expr::Value(
@@ -1351,6 +1352,7 @@ fn parse_substring_in_select() {
                         select_token: AttachedToken::empty(),
                         optimizer_hint: None,
                         distinct: Some(Distinct::Distinct),
+                        select_modifiers: vec![SelectModifier::Distinct],
                         top: None,
                         top_before_distinct: false,
                         projection: vec![SelectItem::UnnamedExpr(Expr::Substring {
@@ -1509,6 +1511,7 @@ fn parse_mssql_declare() {
                     select_token: AttachedToken::empty(),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![SelectItem::UnnamedExpr(Expr::BinaryOp {
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mysql.rs b/app/tests/sqlparser_mysql.rs
index 2c94279..746d2df 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mysql.rs
+++ b/app/tests/sqlparser_mysql.rs
@@ -1437,6 +1437,7 @@ fn parse_escaped_quote_identifiers_with_escape() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 top_before_distinct: false,
                 projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
@@ -1493,6 +1494,7 @@ fn parse_escaped_quote_identifiers_with_no_escape() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 top_before_distinct: false,
                 projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
@@ -1541,6 +1543,7 @@ fn parse_escaped_backticks_with_escape() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 top_before_distinct: false,
                 projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
@@ -1593,6 +1596,7 @@ fn parse_escaped_backticks_with_no_escape() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 top_before_distinct: false,
                 projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
@@ -2413,6 +2417,7 @@ fn parse_select_with_numeric_prefix_column_name() {
                     select_token: AttachedToken::empty(),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident::new(
@@ -2588,6 +2593,7 @@ fn parse_select_with_concatenation_of_exp_number_and_numeric_prefix_column() {
                     select_token: AttachedToken::empty(),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![
@@ -3222,6 +3228,7 @@ fn parse_substring_in_select() {
                         select_token: AttachedToken::empty(),
                         optimizer_hint: None,
                         distinct: Some(Distinct::Distinct),
+                        select_modifiers: vec![SelectModifier::Distinct],
                         top: None,
                         top_before_distinct: false,
                         projection: vec![SelectItem::UnnamedExpr(Expr::Substring {
@@ -3280,6 +3287,55 @@ fn parse_substring_in_select() {
     }
 }
 
+#[test]
+fn parse_mysql_select_modifiers() {
+    let sql = "SELECT HIGH_PRIORITY STRAIGHT_JOIN SQL_SMALL_RESULT SQL_BIG_RESULT SQL_BUFFER_RESULT SQL_NO_CACHE SQL_CALC_FOUND_ROWS 1";
+    let select = mysql_and_generic().verified_only_select(sql);
+    assert_eq!(
+        select.select_modifiers,
+        vec![
+            SelectModifier::HighPriority,
+            SelectModifier::StraightJoin,
+            SelectModifier::SqlSmallResult,
+            SelectModifier::SqlBigResult,
+            SelectModifier::SqlBufferResult,
+            SelectModifier::SqlNoCache,
+            SelectModifier::SqlCalcFoundRows,
+        ]
+    );
+}
+
+#[test]
+fn parse_mysql_select_modifiers_interleaved_with_distinct() {
+    let sql = "SELECT SQL_NO_CACHE DISTINCT HIGH_PRIORITY SQL_BUFFER_RESULT STRAIGHT_JOIN SQL_SMALL_RESULT SQL_BIG_RESULT SQL_CALC_FOUND_ROWS 1";
+    let select = mysql_and_generic().verified_only_select(sql);
+    assert_eq!(
+        select.select_modifiers,
+        vec![
+            SelectModifier::SqlNoCache,
+            SelectModifier::Distinct,
+            SelectModifier::HighPriority,
+            SelectModifier::SqlBufferResult,
+            SelectModifier::StraightJoin,
+            SelectModifier::SqlSmallResult,
+            SelectModifier::SqlBigResult,
+            SelectModifier::SqlCalcFoundRows,
+        ]
+    );
+    assert_eq!(select.distinct, Some(Distinct::Distinct));
+}
+
+#[test]
+fn parse_mysql_select_distinctrow_and_all_modifiers() {
+    let distinctrow = mysql_and_generic().verified_only_select("SELECT DISTINCTROW 1");
+    assert_eq!(distinctrow.select_modifiers, vec![SelectModifier::DistinctRow]);
+    assert_eq!(distinctrow.distinct, Some(Distinct::Distinct));
+
+    let all = mysql_and_generic().verified_only_select("SELECT ALL 1");
+    assert_eq!(all.select_modifiers, vec![SelectModifier::All]);
+    assert_eq!(all.distinct, None);
+}
+
 #[test]
 fn parse_show_variables() {
     mysql_and_generic().verified_stmt("SHOW VARIABLES");
@@ -3546,6 +3602,7 @@ fn parse_hex_string_introducer() {
                 select_token: AttachedToken::empty(),
                 optimizer_hint: None,
                 distinct: None,
+                select_modifiers: vec![],
                 top: None,
                 top_before_distinct: false,
                 projection: vec![SelectItem::UnnamedExpr(Expr::Prefixed {
diff --git a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_postgres.rs b/app/tests/sqlparser_postgres.rs
index 1f91bff..d6cb35e 100644
--- a/tmp/agent-patch-flux-pr-2172.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_postgres.rs
+++ b/app/tests/sqlparser_postgres.rs
@@ -1293,6 +1293,7 @@ fn parse_copy_to() {
                     select_token: AttachedToken::empty(),
                     optimizer_hint: None,
                     distinct: None,
+                    select_modifiers: vec![],
                     top: None,
                     top_before_distinct: false,
                     projection: vec![
@@ -3074,6 +3075,7 @@ fn parse_array_subquery_expr() {
                         select_token: AttachedToken::empty(),
                         optimizer_hint: None,
                         distinct: None,
+                        select_modifiers: vec![],
                         top: None,
                         top_before_distinct: false,
                         projection: vec![SelectItem::UnnamedExpr(Expr::Value(
@@ -3101,6 +3103,7 @@ fn parse_array_subquery_expr() {
                         select_token: AttachedToken::empty(),
                         optimizer_hint: None,
                         distinct: None,
+                        select_modifiers: vec![],
                         top: None,
                         top_before_distinct: false,
                         projection: vec![SelectItem::UnnamedExpr(Expr::Value(