From 30fd5211418c13d1e32fc534d6116b03e17eb05b Mon Sep 17 00:00:00 2001 From: Selase Krakani Date: Wed, 4 Jun 2025 21:39:51 +0000 Subject: [PATCH] FIX: Stop silently dropping first two rows during `load_mapping` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the first two rows returned by `DiscourseDB#query_array` are silently dropped during the column size check in `DiscourseDB#load_mapping`. This happens because the rows object, while an enumerator, isn't fully compliant, it doesn't rewind during introspection. As a result, calls like `#first`, `#peek`, or `#any?` advance the iterator. Ideally, we’d fix this by updating the `query_array` enumeration implementation. However, customizing the enumerator to be fully compliant would likely introduce unnecessary perf overhead for all use cases. So, this fix works around that limitation by building the map a little differently. --- migrations/lib/importer/shared_data.rb | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/migrations/lib/importer/shared_data.rb b/migrations/lib/importer/shared_data.rb index 763d553163c6e..7896bdedbb20a 100644 --- a/migrations/lib/importer/shared_data.rb +++ b/migrations/lib/importer/shared_data.rb @@ -13,11 +13,23 @@ def load_set(sql) def load_mapping(sql) rows = @discourse_db.query_array(sql) - if rows.first && rows.first.size > 2 - rows.to_h { |key, *values| [key, *values] } - else - rows.to_h - end + # While rows is an enumerator, it's not fully compliant, it does not + # rewind on #first, #peek, #any?, etc. + # So we need to hold on to first_row for use later + first_row = rows.first + + return {} if first_row.nil? + + has_multiple_values = first_row.size > 2 + result = + if has_multiple_values + rows.to_h { |key, *values| [key, values] } + else + rows.to_h + end + + result[first_row[0]] = has_multiple_values ? first_row[1..] : first_row[1] + result end def load(type)