@@ -5839,6 +5839,7 @@ static bool replace_aggregate_in_list(Item::Aggregate_replacement &info,
58395839 new_item->update_used_tables ();
58405840 if (new_item != select_expr) {
58415841 new_item->hidden = was_hidden;
5842+ new_item->increment_ref_count ();
58425843 *lii = new_item;
58435844 for (size_t i = 0 ; i < list->size (); i++) {
58445845 if ((*ref_item_array)[i] == select_expr)
@@ -6464,6 +6465,8 @@ bool Query_block::transform_grouped_to_derived(THD *thd, bool *break_off) {
64646465 // now that replaces_field has inherited the upper context
64656466 pair.second ->context = &new_derived->context ;
64666467
6468+ replaces_field->increment_ref_count ();
6469+
64676470 for (const auto &[expr, was_hidden] : contrib_exprs) {
64686471 Item_field *replacement = replaces_field;
64696472 // If this expression was hidden, we need to make a copy of the derived
@@ -6830,6 +6833,7 @@ bool Query_block::decorrelate_derived_scalar_subquery_pre(
68306833 lifted_fields->m_field_positions .push_back (fields.size () -
68316834 hidden_fields);
68326835 fields.push_back (inner_field);
6836+ inner_field->increment_ref_count ();
68336837 // We have added to fields; master_query_expression->types must
68346838 // always be equal to it;
68356839 master_query_expression ()->types .push_back (inner_field);
@@ -6883,11 +6887,12 @@ bool Query_block::decorrelate_derived_scalar_subquery_pre(
68836887 // added to group by above.
68846888 if (!selected_field_in_group_by &&
68856889 !fields[first_non_hidden]->has_aggregation ()) {
6886- Item *func_any =
6887- new (thd->mem_root ) Item_func_any_value (fields[first_non_hidden] );
6890+ Item *const old_field = fields[first_non_hidden];
6891+ Item *func_any = new (thd->mem_root ) Item_func_any_value (old_field );
68886892 if (func_any == nullptr ) return true ;
68896893 if (func_any->fix_fields (thd, &func_any)) return true ;
68906894 fields[first_non_hidden] = func_any;
6895+ replace_referenced_item (old_field, func_any);
68916896 }
68926897
68936898 if (!m_agg_func_used) {
@@ -6921,6 +6926,7 @@ bool Query_block::decorrelate_derived_scalar_subquery_pre(
69216926 base_ref_items[fields.size ()] = cnt;
69226927 lifted_fields->m_field_positions .push_back (fields.size () - hidden_fields);
69236928 fields.push_back (cnt);
6929+ cnt->increment_ref_count ();
69246930 m_agg_func_used = true ;
69256931 // Add a new column to the derived table's query expression
69266932 derived->derived_query_expression ()->types .push_back (cnt);
@@ -7002,6 +7008,31 @@ bool Query_block::decorrelate_derived_scalar_subquery_post(
70027008 return false ;
70037009}
70047010
7011+ /* *
7012+ Replace item in select list and preserve its reference count.
7013+
7014+ @param old_item Item to be replaced.
7015+ @param new_item Item to replace the old item.
7016+
7017+ If old item is present in base_ref_items, make sure it is replaced there.
7018+
7019+ Also make sure that reference count for old item is preserved in new item.
7020+ */
7021+ void Query_block::replace_referenced_item (Item *const old_item,
7022+ Item *const new_item) {
7023+ for (size_t i = 0 ; i < fields.size (); i++) {
7024+ if (base_ref_items[i] == old_item) {
7025+ base_ref_items[i] = new_item;
7026+ break ;
7027+ }
7028+ }
7029+ // Keep the same number of references as for the old expression:
7030+ new_item->increment_ref_count ();
7031+ while (old_item->decrement_ref_count () > 0 ) {
7032+ new_item->increment_ref_count ();
7033+ }
7034+ }
7035+
70057036/* *
70067037 Converts a subquery to a derived table and inserts it into the FROM
70077038 clause of the owning query block
@@ -7691,15 +7722,7 @@ bool Query_block::transform_scalar_subqueries_to_join_with_derived(THD *thd) {
76917722 return true ;
76927723 Item *unwrapped_select_expr = unwrap_rollup_group (select_expr);
76937724 if (unwrapped_select_expr != prev_value) {
7694- // If we replace a subquery in the select field list, possibly
7695- // hidden inside a rollup wrapper, replace corresponding item
7696- // in base_ref_items
7697- for (size_t i = 0 ; i < fields.size (); i++) {
7698- if (base_ref_items[i] == prev_value)
7699- base_ref_items[i] = unwrapped_select_expr;
7700- }
7701- // All items in select list must have a positive ref count.
7702- unwrapped_select_expr->increment_ref_count ();
7725+ replace_referenced_item (prev_value, unwrapped_select_expr);
77037726 }
77047727 if (fields.size () != old_size) {
77057728 // The (implicit) iterator over fields has been invalidated,
0 commit comments