Skip to content

Commit 7454087

Browse files
committed
Revert "bugfix: UPDATE and virtual BLOBs"
This reverts commit f73bdb6.
1 parent 1628a2a commit 7454087

File tree

6 files changed

+7
-156
lines changed

6 files changed

+7
-156
lines changed

sql/field.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3339,9 +3339,6 @@ class Field_blob :public Field_longstr {
33393339
uint max_packed_col_length(uint max_length);
33403340
void free() { value.free(); }
33413341
inline void clear_temporary() { bzero((uchar*) &value, sizeof(value)); }
3342-
inline bool owns_ptr(uchar* p) const { return p == (uchar*)value.ptr(); }
3343-
inline void own_value_ptr()
3344-
{ value.reset((char*)get_ptr(), get_length(), get_length(), value.charset()); }
33453342
uint size_of() const { return sizeof(*this); }
33463343
bool has_charset(void) const
33473344
{ return charset() == &my_charset_bin ? FALSE : TRUE; }

sql/sql_class.h

Lines changed: 2 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -201,99 +201,6 @@ typedef struct st_user_var_events
201201
bool unsigned_flag;
202202
} BINLOG_USER_VAR_EVENT;
203203

204-
205-
/*
206-
When updating a table with virtual BLOB columns, the following might happen:
207-
- an old record is read from the table, it has no vcol blob.
208-
- update_virtual_fields() is run, vcol blob gets its value into the
209-
record. But only a pointer to the value is in the table->record[0],
210-
the value is in Field_blob::value String (or, it can be elsewhere!)
211-
- store_record(table,record[1]), old record now is in record[1]
212-
- fill_record() prepares new values in record[0], vcol blob is updated,
213-
new value replaces the old one in the Field_blob::value
214-
- now both record[1] and record[0] have a pointer that points to the
215-
*new* vcol blob value. Or record[1] has a pointer to nowhere if
216-
Field_blob::value had to realloc.
217-
218-
To resolve this we unlink vcol blobs from the pointer to the
219-
data (in the record[1]). The orphan memory must be freed manually
220-
(but, again, only if it was owned by Field_blob::value String).
221-
222-
With REPLACE and INSERT ... ON DUP KEY UPATE it's even more complex.
223-
There is no store_record(table,record[1]), instead the row is read
224-
directly into record[1].
225-
*/
226-
struct BLOB_VALUE_ORPHANAGE {
227-
MY_BITMAP map;
228-
TABLE *table;
229-
BLOB_VALUE_ORPHANAGE() { map.bitmap= NULL; }
230-
~BLOB_VALUE_ORPHANAGE() { free(); }
231-
bool init(TABLE *table_arg)
232-
{
233-
table= table_arg;
234-
if (table->s->virtual_fields && table->s->blob_fields)
235-
return bitmap_init(&map, NULL, table->s->virtual_fields, FALSE);
236-
map.bitmap= NULL;
237-
return 0;
238-
}
239-
void free() { bitmap_free(&map); }
240-
241-
/** Remove blob's ownership from blob value memory
242-
243-
@note the memory becomes orphaned, it needs to be freed using
244-
free_orphans() or re-attached back to blobs using adopt_orphans()
245-
*/
246-
void make_orphans()
247-
{
248-
DBUG_ASSERT(!table || !table->s->virtual_fields || !table->s->blob_fields || map.bitmap);
249-
if (!map.bitmap)
250-
return;
251-
for (Field **ptr=table->vfield; *ptr; ptr++)
252-
{
253-
Field_blob *vb= (Field_blob*)(*ptr);
254-
if (!(vb->flags & BLOB_FLAG) || !vb->owns_ptr(vb->get_ptr()))
255-
continue;
256-
bitmap_set_bit(&map, ptr - table->vfield);
257-
vb->clear_temporary();
258-
}
259-
}
260-
261-
/** Frees orphaned blob values
262-
263-
@note It is assumed that value pointers are in table->record[1], while
264-
Field_blob::ptr's point to table->record[0] as usual
265-
*/
266-
void free_orphans()
267-
{
268-
DBUG_ASSERT(!table || !table->s->virtual_fields || !table->s->blob_fields || map.bitmap);
269-
if (!map.bitmap)
270-
return;
271-
for (Field **ptr=table->vfield; *ptr; ptr++)
272-
{
273-
Field_blob *vb= (Field_blob*)(*ptr);
274-
if (vb->flags & BLOB_FLAG && bitmap_fast_test_and_clear(&map, ptr - table->vfield))
275-
my_free(vb->get_ptr(table->s->rec_buff_length));
276-
}
277-
DBUG_ASSERT(bitmap_is_clear_all(&map));
278-
}
279-
280-
/** Restores blob's ownership over previously orphaned values */
281-
void adopt_orphans()
282-
{
283-
DBUG_ASSERT(!table || !table->s->virtual_fields || !table->s->blob_fields || map.bitmap);
284-
if (!map.bitmap)
285-
return;
286-
for (Field **ptr=table->vfield; *ptr; ptr++)
287-
{
288-
Field_blob *vb= (Field_blob*)(*ptr);
289-
if (vb->flags & BLOB_FLAG && bitmap_fast_test_and_clear(&map, ptr - table->vfield))
290-
vb->own_value_ptr();
291-
}
292-
DBUG_ASSERT(bitmap_is_clear_all(&map));
293-
}
294-
};
295-
296-
297204
/*
298205
The COPY_INFO structure is used by INSERT/REPLACE code.
299206
The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY
@@ -306,7 +213,7 @@ struct BLOB_VALUE_ORPHANAGE {
306213
of the INSERT ... ON DUPLICATE KEY UPDATE no matter whether the row
307214
was actually changed or not.
308215
*/
309-
struct COPY_INFO {
216+
typedef struct st_copy_info {
310217
ha_rows records; /**< Number of processed records */
311218
ha_rows deleted; /**< Number of deleted records */
312219
ha_rows updated; /**< Number of updated records */
@@ -322,8 +229,7 @@ struct COPY_INFO {
322229
/* for VIEW ... WITH CHECK OPTION */
323230
TABLE_LIST *view;
324231
TABLE_LIST *table_list; /* Normal table */
325-
BLOB_VALUE_ORPHANAGE vblobs0, vblobs1; // vcol blobs of record[0] and record[1]
326-
};
232+
} COPY_INFO;
327233

328234

329235
class Key_part_spec :public Sql_alloc {
@@ -5435,7 +5341,6 @@ class multi_update :public select_result_interceptor
54355341
TABLE_LIST *update_tables, *table_being_updated;
54365342
TABLE **tmp_tables, *main_table, *table_to_update;
54375343
TMP_TABLE_PARAM *tmp_table_param;
5438-
BLOB_VALUE_ORPHANAGE *vblobs;
54395344
ha_rows updated, found;
54405345
List <Item> *fields, *values;
54415346
List <Item> **fields_for_table, **values_for_table;

sql/sql_insert.cc

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
812812
info.update_values= &update_values;
813813
info.view= (table_list->view ? table_list : 0);
814814
info.table_list= table_list;
815-
if (duplic != DUP_ERROR)
816-
{
817-
info.vblobs0.init(table);
818-
info.vblobs1.init(table);
819-
}
820815

821816
/*
822817
Count warnings for all inserts.
@@ -1184,6 +1179,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
11841179
thd->lex->current_select->save_leaf_tables(thd);
11851180
thd->lex->current_select->first_cond_optimization= 0;
11861181
}
1182+
11871183
DBUG_RETURN(FALSE);
11881184

11891185
abort:
@@ -1695,12 +1691,9 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
16951691
}
16961692
if (table->vfield)
16971693
{
1698-
info->vblobs0.make_orphans();
16991694
table->move_fields(table->field, table->record[1], table->record[0]);
17001695
table->update_virtual_fields(VCOL_UPDATE_INDEXED);
1701-
info->vblobs1.make_orphans();
17021696
table->move_fields(table->field, table->record[0], table->record[1]);
1703-
info->vblobs0.adopt_orphans();
17041697
}
17051698
if (info->handle_duplicates == DUP_UPDATE)
17061699
{
@@ -1861,7 +1854,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
18611854
trg_error= 1;
18621855
goto ok_or_after_trg_err;
18631856
}
1864-
info->vblobs1.free_orphans();
18651857
/* Let us attempt do write_row() once more */
18661858
}
18671859
}
@@ -1912,7 +1904,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
19121904
my_safe_afree(key,table->s->max_unique_length);
19131905
if (!table->file->has_transactions())
19141906
thd->transaction.stmt.modified_non_trans_table= TRUE;
1915-
info->vblobs1.free_orphans();
19161907
DBUG_RETURN(trg_error);
19171908

19181909
err:
@@ -1924,7 +1915,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
19241915
if (key)
19251916
my_safe_afree(key, table->s->max_unique_length);
19261917
table->column_bitmaps_set(save_read_set, save_write_set);
1927-
info->vblobs1.free_orphans();
19281918
DBUG_RETURN(1);
19291919
}
19301920

@@ -3106,14 +3096,10 @@ static void free_delayed_insert_blobs(register TABLE *table)
31063096
{
31073097
for (Field **ptr=table->field ; *ptr ; ptr++)
31083098
{
3109-
Field_blob *f= (Field_blob*)(*ptr);
3110-
if (f->flags & BLOB_FLAG)
3099+
if ((*ptr)->flags & BLOB_FLAG)
31113100
{
3112-
if (f->vcol_info)
3113-
f->free();
3114-
else
3115-
my_free(f->get_ptr());
3116-
f->reset();
3101+
my_free(((Field_blob *) (*ptr))->get_ptr());
3102+
((Field_blob *) (*ptr))->reset();
31173103
}
31183104
}
31193105
}
@@ -3135,9 +3121,6 @@ bool Delayed_insert::handle_inserts(void)
31353121
table->next_number_field=table->found_next_number_field;
31363122
table->use_all_columns();
31373123

3138-
info.vblobs0.init(table);
3139-
info.vblobs1.init(table);
3140-
31413124
THD_STAGE_INFO(&thd, stage_upgrading_lock);
31423125
if (thr_upgrade_write_delay_lock(*thd.lock->locks, delayed_lock,
31433126
thd.variables.lock_wait_timeout))
@@ -3244,8 +3227,6 @@ bool Delayed_insert::handle_inserts(void)
32443227
if (info.handle_duplicates == DUP_UPDATE)
32453228
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
32463229
thd.clear_error(); // reset error for binlog
3247-
if (table->vfield)
3248-
table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE);
32493230
if (write_record(&thd, table, &info))
32503231
{
32513232
info.error_count++; // Ignore errors
@@ -3352,8 +3333,6 @@ bool Delayed_insert::handle_inserts(void)
33523333
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop"));
33533334
goto err;
33543335
}
3355-
info.vblobs0.free();
3356-
info.vblobs1.free();
33573336
query_cache_invalidate3(&thd, table, 1);
33583337
mysql_mutex_lock(&mutex);
33593338
DBUG_RETURN(0);
@@ -3362,8 +3341,6 @@ bool Delayed_insert::handle_inserts(void)
33623341
#ifndef DBUG_OFF
33633342
max_rows= 0; // For DBUG output
33643343
#endif
3365-
info.vblobs0.free();
3366-
info.vblobs1.free();
33673344
/* Remove all not used rows */
33683345
mysql_mutex_lock(&mutex);
33693346
while ((row=rows.get()))
@@ -3611,11 +3588,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
36113588
restore_record(table,s->default_values); // Get empty record
36123589
table->reset_default_fields();
36133590
table->next_number_field=table->found_next_number_field;
3614-
if (info.handle_duplicates != DUP_ERROR)
3615-
{
3616-
info.vblobs0.init(table);
3617-
info.vblobs1.init(table);
3618-
}
36193591

36203592
#ifdef HAVE_REPLICATION
36213593
if (thd->rgi_slave &&

sql/sql_insert.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
/* Instead of including sql_lex.h we add this typedef here */
2323
typedef List<Item> List_item;
24+
typedef struct st_copy_info COPY_INFO;
2425

2526
bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
2627
List<Item> &fields, List_item *values,

sql/sql_load.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -537,12 +537,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
537537
!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)))
538538
? (*escaped)[0] : INT_MAX;
539539

540-
if (handle_duplicates != DUP_ERROR)
541-
{
542-
info.vblobs0.init(table);
543-
info.vblobs1.init(table);
544-
}
545-
546540
READ_INFO read_info(thd, file, tot_length,
547541
ex->cs ? ex->cs : thd->variables.collation_database,
548542
*field_term,*ex->line_start, *ex->line_term, *enclosed,

sql/sql_update.cc

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ int mysql_update(THD *thd,
273273
SORT_INFO *file_sort= 0;
274274
READ_RECORD info;
275275
SELECT_LEX *select_lex= &thd->lex->select_lex;
276-
BLOB_VALUE_ORPHANAGE vblobs;
277276
ulonglong id;
278277
List<Item> all_fields;
279278
killed_state killed_status= NOT_KILLED;
@@ -725,8 +724,6 @@ int mysql_update(THD *thd,
725724

726725
table->reset_default_fields();
727726

728-
vblobs.init(table);
729-
730727
/*
731728
We can use compare_record() to optimize away updates if
732729
the table handler is returning all columns OR if
@@ -748,9 +745,6 @@ int mysql_update(THD *thd,
748745

749746
explain->tracker.on_record_after_where();
750747
store_record(table,record[1]);
751-
752-
vblobs.make_orphans();
753-
754748
if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
755749
TRG_EVENT_UPDATE))
756750
break; /* purecov: inspected */
@@ -910,9 +904,7 @@ int mysql_update(THD *thd,
910904
error= 1;
911905
break;
912906
}
913-
vblobs.free_orphans();
914907
}
915-
vblobs.free_orphans();
916908
ANALYZE_STOP_TRACKING(&explain->command_tracker);
917909
table->auto_increment_field_not_null= FALSE;
918910
dup_key_found= 0;
@@ -1760,8 +1752,6 @@ int multi_update::prepare(List<Item> &not_used_values,
17601752
table_count);
17611753
values_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
17621754
table_count);
1763-
vblobs= (BLOB_VALUE_ORPHANAGE *)thd->calloc(sizeof(*vblobs) * table_count);
1764-
17651755
if (thd->is_fatal_error)
17661756
DBUG_RETURN(1);
17671757
for (i=0 ; i < table_count ; i++)
@@ -1794,7 +1784,6 @@ int multi_update::prepare(List<Item> &not_used_values,
17941784
TABLE *table= ((Item_field*)(fields_for_table[i]->head()))->field->table;
17951785
switch_to_nullable_trigger_fields(*fields_for_table[i], table);
17961786
switch_to_nullable_trigger_fields(*values_for_table[i], table);
1797-
vblobs[i].init(table);
17981787
}
17991788
}
18001789
copy_field= new Copy_field[max_fields];
@@ -2076,8 +2065,6 @@ multi_update::~multi_update()
20762065
free_tmp_table(thd, tmp_tables[cnt]);
20772066
tmp_table_param[cnt].cleanup();
20782067
}
2079-
vblobs[cnt].free_orphans();
2080-
vblobs[cnt].free();
20812068
}
20822069
}
20832070
if (copy_field)
@@ -2123,9 +2110,7 @@ int multi_update::send_data(List<Item> &not_used_values)
21232110
can_compare_record= records_are_comparable(table);
21242111

21252112
table->status|= STATUS_UPDATED;
2126-
vblobs[offset].free_orphans();
21272113
store_record(table,record[1]);
2128-
vblobs[offset].make_orphans();
21292114
if (fill_record_n_invoke_before_triggers(thd, table,
21302115
*fields_for_table[offset],
21312116
*values_for_table[offset], 0,
@@ -2342,7 +2327,6 @@ int multi_update::do_updates()
23422327
goto err;
23432328
}
23442329
table->file->extra(HA_EXTRA_NO_CACHE);
2345-
empty_record(table);
23462330

23472331
check_opt_it.rewind();
23482332
while(TABLE *tbl= check_opt_it++)
@@ -2416,9 +2400,7 @@ int multi_update::do_updates()
24162400
goto err2;
24172401

24182402
table->status|= STATUS_UPDATED;
2419-
vblobs[offset].free_orphans();
24202403
store_record(table,record[1]);
2421-
vblobs[offset].make_orphans();
24222404

24232405
/* Copy data from temporary table to current table */
24242406
for (copy_field_ptr=copy_field;

0 commit comments

Comments
 (0)