@@ -7,6 +7,7 @@ use crate::{
77} ;
88use anyhow:: { bail, Context , Result } ;
99use chrono:: { DateTime , NaiveDateTime , TimeZone , Utc } ;
10+ use indexmap:: IndexMap ;
1011use itertools:: multizip;
1112use serde:: { Deserialize , Serialize } ;
1213use serde_json:: Value ;
@@ -171,7 +172,12 @@ pub fn get_members(
171172 alias_to_member_name_map : & HashMap < String , String > ,
172173 annotation : & HashMap < String , ConfigItem > ,
173174) -> Result < ( MembersMap , Vec < String > ) > {
174- let mut members_map: MembersMap = HashMap :: new ( ) ;
175+ let mut members_map: MembersMap = IndexMap :: new ( ) ;
176+ // IndexMap maintains insertion order, ensuring deterministic column ordering.
177+ // The order comes from db_data.columns which now preserves the database result order
178+ // (since JsRawData uses IndexMap instead of HashMap).
179+ // Not sure if it solves the original comment below.
180+ // Original Comment:
175181 // Hashmaps don't guarantee the order of the elements while iterating
176182 // this fires in get_compact_row because members map doesn't hold the members for
177183 // date range queries, which are added later and thus columns in final recordset are not
@@ -267,13 +273,13 @@ pub fn get_members(
267273
268274/// Convert DB response object to the compact output format.
269275pub fn get_compact_row (
270- members_to_alias_map : & HashMap < String , String > ,
276+ members_to_alias_map : & IndexMap < String , String > ,
271277 annotation : & HashMap < String , ConfigItem > ,
272278 query_type : & QueryType ,
273279 members : & [ String ] ,
274280 time_dimensions : Option < & Vec < QueryTimeDimension > > ,
275281 db_row : & [ DBResponseValue ] ,
276- columns_pos : & HashMap < String , usize > ,
282+ columns_pos : & IndexMap < String , usize > ,
277283) -> Result < Vec < DBResponsePrimitive > > {
278284 let mut row: Vec < DBResponsePrimitive > = Vec :: with_capacity ( members. len ( ) ) ;
279285
@@ -322,9 +328,9 @@ pub fn get_vanilla_row(
322328 query_type : & QueryType ,
323329 query : & NormalizedQuery ,
324330 db_row : & [ DBResponseValue ] ,
325- columns_pos : & HashMap < String , usize > ,
326- ) -> Result < HashMap < String , DBResponsePrimitive > > {
327- let mut row = HashMap :: new ( ) ;
331+ columns_pos : & IndexMap < String , usize > ,
332+ ) -> Result < IndexMap < String , DBResponsePrimitive > > {
333+ let mut row = IndexMap :: new ( ) ;
328334
329335 // FIXME: For now custom granularities are not supported, only common ones.
330336 // There is no granularity type/class implementation in rust yet.
@@ -527,7 +533,7 @@ pub enum TransformedData {
527533 members : Vec < String > ,
528534 dataset : Vec < Vec < DBResponsePrimitive > > ,
529535 } ,
530- Vanilla ( Vec < HashMap < String , DBResponsePrimitive > > ) ,
536+ Vanilla ( Vec < IndexMap < String , DBResponsePrimitive > > ) ,
531537}
532538
533539impl TransformedData {
@@ -2180,7 +2186,7 @@ mod tests {
21802186 & QueryResult {
21812187 columns : vec ! [ ] ,
21822188 rows : vec ! [ ] ,
2183- columns_pos : HashMap :: new ( ) ,
2189+ columns_pos : IndexMap :: new ( ) ,
21842190 } ,
21852191 alias_to_member_name_map,
21862192 annotation,
@@ -2209,7 +2215,7 @@ mod tests {
22092215 alias_to_member_name_map,
22102216 annotation,
22112217 ) ?;
2212- let members_map_expected: MembersMap = HashMap :: from ( [
2218+ let members_map_expected: MembersMap = IndexMap :: from ( [
22132219 (
22142220 "ECommerceRecordsUs2021.postalCode" . to_string ( ) ,
22152221 "e_commerce_records_us2021__postal_code" . to_string ( ) ,
@@ -2241,7 +2247,7 @@ mod tests {
22412247 & QueryResult {
22422248 columns : vec ! [ ] ,
22432249 rows : vec ! [ ] ,
2244- columns_pos : HashMap :: new ( ) ,
2250+ columns_pos : IndexMap :: new ( ) ,
22452251 } ,
22462252 alias_to_member_name_map,
22472253 annotation,
@@ -2270,7 +2276,7 @@ mod tests {
22702276 alias_to_member_name_map,
22712277 annotation,
22722278 ) ?;
2273- let members_map_expected: MembersMap = HashMap :: from ( [
2279+ let members_map_expected: MembersMap = IndexMap :: from ( [
22742280 (
22752281 "ECommerceRecordsUs2021.orderDate.day" . to_string ( ) ,
22762282 "e_commerce_records_us2021__order_date_day" . to_string ( ) ,
@@ -2313,7 +2319,7 @@ mod tests {
23132319 & QueryResult {
23142320 columns : vec ! [ ] ,
23152321 rows : vec ! [ ] ,
2316- columns_pos : HashMap :: new ( ) ,
2322+ columns_pos : IndexMap :: new ( ) ,
23172323 } ,
23182324 alias_to_member_name_map,
23192325 annotation,
@@ -2345,7 +2351,7 @@ mod tests {
23452351 alias_to_member_name_map,
23462352 annotation,
23472353 ) ?;
2348- let members_map_expected: HashMap < String , String > = HashMap :: from ( [
2354+ let members_map_expected: MembersMap = IndexMap :: from ( [
23492355 (
23502356 "ECommerceRecordsUs2021.orderDate.month" . to_string ( ) ,
23512357 "e_commerce_records_us2021__order_date_month" . to_string ( ) ,
@@ -2640,7 +2646,7 @@ mod tests {
26402646 & raw_data. rows [ 0 ] ,
26412647 & raw_data. columns_pos ,
26422648 ) ?;
2643- let expected = HashMap :: from ( [
2649+ let expected = IndexMap :: from ( [
26442650 (
26452651 "ECommerceRecordsUs2021.city" . to_string ( ) ,
26462652 DBResponsePrimitive :: String ( "Missouri City" . to_string ( ) ) ,
0 commit comments