@@ -116,19 +116,9 @@ func indexSearchableLookup(ctx *sql.Context, c transform.Context, rt sql.TableNo
116
116
ret = plan .NewFilter (newFilter , ret )
117
117
}
118
118
119
- if fds != nil && fds .HasMax1Row () && ! qFlags .JoinIsSet () && ! qFlags .SubqueryIsSet () && lookup .Ranges .Len () == 1 {
120
- // Prevent max1Row when parent will combine results
121
- if c .Parent != nil {
122
- switch parent := c .Parent .(type ) {
123
- case * plan.SetOp :
124
- return ret , transform .NewTree , nil
125
- case * plan.Project :
126
- if plan .IsUnary (parent ) {
127
- return ret , transform .NewTree , nil
128
- }
129
- }
130
- }
131
-
119
+ // Skip Max1Row optimization for SetOp queries to avoid incorrect single-row assumption
120
+ _ , isSetOp := c .Parent .(* plan.SetOp )
121
+ if fds != nil && fds .HasMax1Row () && ! qFlags .JoinIsSet () && ! qFlags .SubqueryIsSet () && lookup .Ranges .Len () == 1 && ! isSetOp {
132
122
qFlags .Set (sql .QFlagMax1Row )
133
123
}
134
124
@@ -331,9 +321,13 @@ func getCostedIndexScan(ctx *sql.Context, statsProv sql.StatsProvider, rt sql.Ta
331
321
bestStat = stats .UpdateCounts (bestStat )
332
322
}
333
323
334
- if bestStat .FuncDeps ().HasMax1Row () && ! qFlags .JoinIsSet () && ! qFlags .SubqueryIsSet () && lookup .Ranges .Len () == 1 {
335
- qFlags .Set (sql .QFlagMax1Row )
336
- }
324
+ // Conservative: disable Max1Row optimization here due to lack of context for SetOp detection (dolt#9641)
325
+ // The indexSearchableLookup path above handles the context-aware SetOp detection for memory engine
326
+ // Server engine uses this path and would incorrectly set Max1Row for UNION subqueries
327
+ // See: https://github.com/dolthub/dolt/issues/9641
328
+ // if bestStat.FuncDeps().HasMax1Row() && !qFlags.JoinIsSet() && !qFlags.SubqueryIsSet() && lookup.Ranges.Len() == 1 {
329
+ // qFlags.Set(sql.QFlagMax1Row)
330
+ // }
337
331
338
332
return ret , bestStat , retFilters , nil
339
333
}
0 commit comments