@@ -238,14 +238,26 @@ bool HandleCustomColumnsForTableRename(THD &thd, const char *old_db,
238238 return false ;
239239}
240240
241- // Lazily allocate a TypeEncoder for field from TABLE::mem_root. The encoder
242- // is reused for all subsequent encodes on the same Field within the TABLE's
243- // lifetime.
241+ // Lazily allocate a TypeEncoder for field, reused for all subsequent encodes
242+ // within the table's lifetime.
243+ //
244+ // For any kind of tmp table, close_tmp_table() asserts TABLE::mem_root is
245+ // empty, so we use TABLE_SHARE::mem_root instead. This covers UNION result
246+ // tables and any other internal tmp table that may hold custom type fields
247+ // (e.g. when a string literal is unioned with a COMPLEX column and must be
248+ // encoded into the result tmp table's field).
249+ // free_tmp_table() frees the share's mem_root, cleaning up the encoder.
250+ //
251+ // For regular tables (NO_TMP_TABLE), TABLE::mem_root has the same lifetime as
252+ // the Field clone that caches the encoder pointer, so both are freed together
253+ // when the TABLE is evicted from the table open cache.
244254static TypeEncoder *GetTypeEncoderFor (Field *field) {
245255 TypeEncoder *encoder = field->get_type_encoder ();
246256 if (encoder == nullptr ) {
247- encoder = new (&field->table ->mem_root )
248- TypeEncoder (field->get_type_context (), field->table ->mem_root );
257+ MEM_ROOT &mem_root = (field->table ->s ->tmp_table == NO_TMP_TABLE)
258+ ? field->table ->mem_root
259+ : field->table ->s ->mem_root ;
260+ encoder = new (&mem_root) TypeEncoder (field->get_type_context (), mem_root);
249261 if (encoder == nullptr ) {
250262 my_error (ER_OUTOFMEMORY, MYF (ME_FATALERROR), sizeof (TypeEncoder));
251263 return nullptr ;
0 commit comments