@@ -27,6 +27,7 @@ fn infer_sorts(query: SqlQuery, ctx: &mut Context) -> SqlQuery {
27
27
let mut s = SortingInference {
28
28
last_sorting : Vec :: new ( ) ,
29
29
ctes_sorting : HashMap :: new ( ) ,
30
+ main_relation : false ,
30
31
ctx,
31
32
} ;
32
33
@@ -36,12 +37,12 @@ fn infer_sorts(query: SqlQuery, ctx: &mut Context) -> SqlQuery {
36
37
struct SortingInference < ' a > {
37
38
last_sorting : Sorting ,
38
39
ctes_sorting : HashMap < TId , CteSorting > ,
40
+ main_relation : bool ,
39
41
ctx : & ' a mut Context ,
40
42
}
41
43
42
44
struct CteSorting {
43
45
sorting : Sorting ,
44
- has_been_used : bool ,
45
46
}
46
47
47
48
impl RqFold for SortingInference < ' _ > { }
@@ -50,51 +51,29 @@ impl PqFold for SortingInference<'_> {
50
51
fn fold_sql_query ( & mut self , query : SqlQuery ) -> Result < SqlQuery > {
51
52
let mut ctes = Vec :: with_capacity ( query. ctes . len ( ) ) ;
52
53
for cte in query. ctes {
54
+ log:: debug!( "infer_sorts: {0:?}" , cte. tid) ;
53
55
let cte = self . fold_cte ( cte) ?;
54
56
55
57
// store sorting to be used later in From references
56
58
let sorting = self . last_sorting . drain ( ..) . collect ( ) ;
57
- let sorting = CteSorting {
58
- sorting,
59
- has_been_used : false ,
60
- } ;
59
+ log:: debug!( "--- sorting {sorting:?}" ) ;
60
+ let sorting = CteSorting { sorting } ;
61
61
self . ctes_sorting . insert ( cte. tid , sorting) ;
62
62
63
63
ctes. push ( cte) ;
64
64
}
65
65
66
- // fold main_relation using a made-up tid
66
+ // fold main_relation
67
+ log:: debug!( "infer_sorts: main relation" ) ;
68
+ self . main_relation = true ;
67
69
let mut main_relation = self . fold_sql_relation ( query. main_relation ) ?;
70
+ log:: debug!( "--== last_sorting {0:?}" , self . last_sorting) ;
68
71
69
72
// push a sort at the back of the main pipeline
70
73
if let SqlRelation :: AtomicPipeline ( pipeline) = & mut main_relation {
71
74
pipeline. push ( SqlTransform :: Sort ( self . last_sorting . drain ( ..) . collect ( ) ) ) ;
72
75
}
73
76
74
- // make sure that all CTEs whose sorting was used actually SELECT it
75
- for cte in & mut ctes {
76
- let sorting = self . ctes_sorting . get ( & cte. tid ) . unwrap ( ) ;
77
- if !sorting. has_been_used {
78
- continue ;
79
- }
80
-
81
- let CteKind :: Normal ( sql_relation) = & mut cte. kind else {
82
- continue ;
83
- } ;
84
- let Some ( pipeline) = sql_relation. as_atomic_pipeline_mut ( ) else {
85
- continue ;
86
- } ;
87
- let select = pipeline. iter_mut ( ) . find_map ( |x| x. as_select_mut ( ) ) . unwrap ( ) ;
88
-
89
- for column_sort in & sorting. sorting {
90
- let cid = column_sort. column ;
91
- let is_selected = select. contains ( & cid) ;
92
- if !is_selected {
93
- select. push ( cid) ;
94
- }
95
- }
96
- }
97
-
98
77
Ok ( SqlQuery {
99
78
ctes,
100
79
main_relation,
@@ -116,6 +95,7 @@ impl PqMapper<RelationExpr, RelationExpr, (), ()> for SortingInference<'_> {
116
95
transforms : Vec < SqlTransform < RelationExpr , ( ) > > ,
117
96
) -> Result < Vec < SqlTransform < RelationExpr , ( ) > > > {
118
97
let mut sorting = Vec :: new ( ) ;
98
+ let mut has_sort_transform = false ;
119
99
120
100
let mut result = Vec :: with_capacity ( transforms. len ( ) + 1 ) ;
121
101
@@ -126,7 +106,6 @@ impl PqMapper<RelationExpr, RelationExpr, (), ()> for SortingInference<'_> {
126
106
RelationExprKind :: Ref ( ref tid) => {
127
107
// infer sorting from referenced pipeline
128
108
if let Some ( cte_sorting) = self . ctes_sorting . get_mut ( tid) {
129
- cte_sorting. has_been_used = true ;
130
109
sorting. clone_from ( & cte_sorting. sorting ) ;
131
110
} else {
132
111
sorting = Vec :: new ( ) ;
@@ -147,8 +126,9 @@ impl PqMapper<RelationExpr, RelationExpr, (), ()> for SortingInference<'_> {
147
126
}
148
127
149
128
// just store sorting and don't emit Sort
150
- SqlTransform :: Sort ( s) => {
151
- sorting. clone_from ( & s) ;
129
+ SqlTransform :: Sort ( expr) => {
130
+ sorting. clone_from ( & expr) ;
131
+ has_sort_transform = true ;
152
132
continue ;
153
133
}
154
134
@@ -166,6 +146,28 @@ impl PqMapper<RelationExpr, RelationExpr, (), ()> for SortingInference<'_> {
166
146
result. push ( transform)
167
147
}
168
148
149
+ if !self . main_relation {
150
+ // if this is a CTE, make sure that its SELECT includes the
151
+ // columns from the sort
152
+ let select = result. iter_mut ( ) . find_map ( |x| x. as_select_mut ( ) ) . unwrap ( ) ;
153
+ for column_sort in & sorting {
154
+ let cid = column_sort. column ;
155
+ let is_selected = select. contains ( & cid) ;
156
+ if !is_selected {
157
+ log:: debug!( "adding {cid:?} to {select:?}" ) ;
158
+ select. push ( cid) ;
159
+ }
160
+ }
161
+
162
+ if has_sort_transform {
163
+ // now revert the sort columns so that the output
164
+ // sorting reflects the input column cids, needed to
165
+ // ensure proper column reference lookup in the final
166
+ // steps
167
+ sorting = CidRedirector :: revert_sorts ( sorting, & mut self . ctx . anchor ) ;
168
+ }
169
+ }
170
+
169
171
// remember sorting for this pipeline
170
172
self . last_sorting = sorting;
171
173
0 commit comments