1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2006 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
||
17 |
/*
|
|
18 |
Single table and multi table updates of tables.
|
|
19 |
Multi-table updates were introduced by Sinisa & Monty
|
|
20 |
*/
|
|
243.1.17
by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.) |
21 |
#include <drizzled/server_includes.h> |
22 |
#include <drizzled/sql_select.h> |
|
549
by Monty Taylor
Took gettext.h out of header files. |
23 |
#include <drizzled/error.h> |
520.7.1
by Monty Taylor
Moved hash.c to drizzled. |
24 |
#include <drizzled/probes.h> |
584.1.15
by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes. |
25 |
#include <drizzled/sql_base.h> |
584.5.1
by Monty Taylor
Removed field includes from field.h. |
26 |
#include <drizzled/field/timestamp.h> |
1
by brian
clean slate |
27 |
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
28 |
#include <list> |
982.1.3
by Padraig O'Sullivan
Various small cleanups to numerous files to now have calls to the correct |
29 |
|
30 |
using namespace std; |
|
31 |
||
1
by brian
clean slate |
32 |
/*
|
33 |
check that all fields are real fields
|
|
34 |
||
35 |
SYNOPSIS
|
|
36 |
check_fields()
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
37 |
session thread handler
|
1
by brian
clean slate |
38 |
items Items for check
|
39 |
||
40 |
RETURN
|
|
56
by brian
Next pass of true/false update. |
41 |
true Items can't be used in UPDATE
|
42 |
false Items are OK
|
|
1
by brian
clean slate |
43 |
*/
|
44 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
45 |
static bool check_fields(Session *session, List<Item> &items) |
1
by brian
clean slate |
46 |
{
|
47 |
List_iterator<Item> it(items); |
|
48 |
Item *item; |
|
49 |
Item_field *field; |
|
50 |
||
51 |
while ((item= it++)) |
|
52 |
{
|
|
53 |
if (!(field= item->filed_for_view_update())) |
|
54 |
{
|
|
55 |
/* item has name, because it comes from VIEW SELECT list */
|
|
56 |
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); |
|
56
by brian
Next pass of true/false update. |
57 |
return true; |
1
by brian
clean slate |
58 |
}
|
59 |
/*
|
|
60 |
we make temporary copy of Item_field, to avoid influence of changing
|
|
61 |
result_field on Item_ref which refer on this field
|
|
62 |
*/
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
63 |
session->change_item_tree(it.ref(), new Item_field(session, field)); |
1
by brian
clean slate |
64 |
}
|
56
by brian
Next pass of true/false update. |
65 |
return false; |
1
by brian
clean slate |
66 |
}
|
67 |
||
1005.2.3
by Monty Taylor
Further reversion of P. |
68 |
|
1
by brian
clean slate |
69 |
/**
|
70 |
Re-read record if more columns are needed for error message.
|
|
71 |
||
72 |
If we got a duplicate key error, we want to write an error
|
|
73 |
message containing the value of the duplicate key. If we do not have
|
|
74 |
all fields of the key value in record[0], we need to re-read the
|
|
75 |
record with a proper read_set.
|
|
76 |
||
77 |
@param[in] error error number
|
|
78 |
@param[in] table table
|
|
79 |
*/
|
|
80 |
||
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
81 |
static void prepare_record_for_error_message(int error, Table *table) |
1
by brian
clean slate |
82 |
{
|
83 |
Field **field_p; |
|
84 |
Field *field; |
|
482
by Brian Aker
Remove uint. |
85 |
uint32_t keynr; |
1005.2.3
by Monty Taylor
Further reversion of P. |
86 |
MY_BITMAP unique_map; /* Fields in offended unique. */ |
87 |
my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)]; |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
88 |
|
1
by brian
clean slate |
89 |
/*
|
90 |
Only duplicate key errors print the key value.
|
|
91 |
If storage engine does always read all columns, we have the value alraedy.
|
|
92 |
*/
|
|
93 |
if ((error != HA_ERR_FOUND_DUPP_KEY) || |
|
94 |
!(table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
95 |
return; |
1
by brian
clean slate |
96 |
|
97 |
/*
|
|
98 |
Get the number of the offended index.
|
|
99 |
We will see MAX_KEY if the engine cannot determine the affected index.
|
|
100 |
*/
|
|
101 |
if ((keynr= table->file->get_dup_key(error)) >= MAX_KEY) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
102 |
return; |
1
by brian
clean slate |
103 |
|
104 |
/* Create unique_map with all fields used by that index. */
|
|
1005.2.3
by Monty Taylor
Further reversion of P. |
105 |
bitmap_init(&unique_map, unique_map_buf, table->s->fields, false); |
1
by brian
clean slate |
106 |
table->mark_columns_used_by_index_no_reset(keynr, &unique_map); |
107 |
||
108 |
/* Subtract read_set and write_set. */
|
|
1005.2.3
by Monty Taylor
Further reversion of P. |
109 |
bitmap_subtract(&unique_map, table->read_set); |
110 |
bitmap_subtract(&unique_map, table->write_set); |
|
1
by brian
clean slate |
111 |
|
112 |
/*
|
|
113 |
If the unique index uses columns that are neither in read_set
|
|
114 |
nor in write_set, we must re-read the record.
|
|
115 |
Otherwise no need to do anything.
|
|
116 |
*/
|
|
1005.2.3
by Monty Taylor
Further reversion of P. |
117 |
if (bitmap_is_clear_all(&unique_map)) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
118 |
return; |
1
by brian
clean slate |
119 |
|
120 |
/* Get identifier of last read record into table->file->ref. */
|
|
121 |
table->file->position(table->record[0]); |
|
122 |
/* Add all fields used by unique index to read_set. */
|
|
1005.2.3
by Monty Taylor
Further reversion of P. |
123 |
bitmap_union(table->read_set, &unique_map); |
1
by brian
clean slate |
124 |
/* Read record that is identified by table->file->ref. */
|
125 |
(void) table->file->rnd_pos(table->record[1], table->file->ref); |
|
126 |
/* Copy the newly read columns into the new record. */
|
|
127 |
for (field_p= table->field; (field= *field_p); field_p++) |
|
1005.2.3
by Monty Taylor
Further reversion of P. |
128 |
if (bitmap_is_set(&unique_map, field->field_index)) |
1
by brian
clean slate |
129 |
field->copy_from_tmp(table->s->rec_buff_length); |
130 |
||
51.2.2
by Patrick Galbraith
Removed DBUGs from |
131 |
return; |
1
by brian
clean slate |
132 |
}
|
133 |
||
134 |
||
135 |
/*
|
|
136 |
Process usual UPDATE
|
|
137 |
||
138 |
SYNOPSIS
|
|
139 |
mysql_update()
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
140 |
session thread handler
|
1
by brian
clean slate |
141 |
fields fields for update
|
142 |
values values of fields for update
|
|
143 |
conds WHERE clause expression
|
|
327.2.3
by Brian Aker
Refactoring of class Table |
144 |
order_num number of elemen in order_st BY clause
|
145 |
order order_st BY clause list
|
|
1
by brian
clean slate |
146 |
limit limit clause
|
147 |
handle_duplicates how to handle duplicates
|
|
148 |
||
149 |
RETURN
|
|
150 |
0 - OK
|
|
151 |
1 - error
|
|
152 |
*/
|
|
153 |
||
575.1.2
by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead. |
154 |
int mysql_update(Session *session, TableList *table_list, |
155 |
List<Item> &fields, List<Item> &values, COND *conds, |
|
482
by Brian Aker
Remove uint. |
156 |
uint32_t order_num, order_st *order, |
575.1.2
by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead. |
157 |
ha_rows limit, enum enum_duplicates, |
77.1.45
by Monty Taylor
Warning fixes. |
158 |
bool ignore) |
1
by brian
clean slate |
159 |
{
|
160 |
bool using_limit= limit != HA_POS_ERROR; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
161 |
bool safe_update= test(session->options & OPTION_SAFE_UPDATES); |
1
by brian
clean slate |
162 |
bool used_key_is_modified, transactional_table, will_batch; |
163 |
bool can_compare_record; |
|
164 |
int error, loc_error; |
|
165 |
uint used_index= MAX_KEY, dup_key_found; |
|
56
by brian
Next pass of true/false update. |
166 |
bool need_sort= true; |
482
by Brian Aker
Remove uint. |
167 |
uint32_t table_count= 0; |
1
by brian
clean slate |
168 |
ha_rows updated, found; |
169 |
key_map old_covering_keys; |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
170 |
Table *table; |
1
by brian
clean slate |
171 |
SQL_SELECT *select; |
172 |
READ_RECORD info; |
|
846
by Brian Aker
Removing on typedeffed class. |
173 |
Select_Lex *select_lex= &session->lex->select_lex; |
1
by brian
clean slate |
174 |
bool need_reopen; |
151
by Brian Aker
Ulonglong to uint64_t |
175 |
uint64_t id; |
1
by brian
clean slate |
176 |
List<Item> all_fields; |
520.1.21
by Brian Aker
THD -> Session rename |
177 |
Session::killed_state killed_status= Session::NOT_KILLED; |
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
178 |
|
1
by brian
clean slate |
179 |
for ( ; ; ) |
180 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
181 |
if (open_tables(session, &table_list, &table_count, 0)) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
182 |
return(1); |
1
by brian
clean slate |
183 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
184 |
if (!lock_tables(session, table_list, table_count, &need_reopen)) |
1
by brian
clean slate |
185 |
break; |
186 |
if (!need_reopen) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
187 |
return(1); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
188 |
close_tables_for_reopen(session, &table_list); |
1
by brian
clean slate |
189 |
}
|
190 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
191 |
if (mysql_handle_derived(session->lex, &mysql_derived_prepare) || |
192 |
(session->fill_derived_tables() && |
|
193 |
mysql_handle_derived(session->lex, &mysql_derived_filling))) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
194 |
return(1); |
1
by brian
clean slate |
195 |
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
196 |
DRIZZLE_UPDATE_START(); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
197 |
session->set_proc_info("init"); |
1
by brian
clean slate |
198 |
table= table_list->table; |
199 |
||
200 |
/* Calculate "table->covering_keys" based on the WHERE */
|
|
201 |
table->covering_keys= table->s->keys_in_use; |
|
1005.2.6
by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<> |
202 |
table->quick_keys.reset(); |
1
by brian
clean slate |
203 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
204 |
if (mysql_prepare_update(session, table_list, &conds, order_num, order)) |
1
by brian
clean slate |
205 |
goto abort; |
206 |
||
207 |
old_covering_keys= table->covering_keys; // Keys used in WHERE |
|
208 |
/* Check the fields we are going to modify */
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
209 |
if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0)) |
1
by brian
clean slate |
210 |
goto abort; /* purecov: inspected */ |
211 |
if (table->timestamp_field) |
|
212 |
{
|
|
213 |
// Don't set timestamp column if this is modified
|
|
1009
by Brian Aker
Merge of Monty |
214 |
if (table->timestamp_field->isWriteSet()) |
1
by brian
clean slate |
215 |
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; |
216 |
else
|
|
217 |
{
|
|
218 |
if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE || |
|
219 |
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) |
|
1005.2.12
by Monty Taylor
Moved some things to the API. |
220 |
table->setWriteSet(table->timestamp_field->field_index); |
1
by brian
clean slate |
221 |
}
|
222 |
}
|
|
223 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
224 |
if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0)) |
1
by brian
clean slate |
225 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
226 |
free_underlaid_joins(session, select_lex); |
1
by brian
clean slate |
227 |
goto abort; /* purecov: inspected */ |
228 |
}
|
|
229 |
||
230 |
if (select_lex->inner_refs_list.elements && |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
231 |
fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array)) |
1
by brian
clean slate |
232 |
{
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
233 |
DRIZZLE_UPDATE_END(); |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
234 |
return(-1); |
1
by brian
clean slate |
235 |
}
|
236 |
||
237 |
if (conds) |
|
238 |
{
|
|
239 |
Item::cond_result cond_value; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
240 |
conds= remove_eq_conds(session, conds, &cond_value); |
1
by brian
clean slate |
241 |
if (cond_value == Item::COND_FALSE) |
242 |
limit= 0; // Impossible WHERE |
|
243 |
}
|
|
244 |
||
245 |
/*
|
|
246 |
If a timestamp field settable on UPDATE is present then to avoid wrong
|
|
247 |
update force the table handler to retrieve write-only fields to be able
|
|
248 |
to compare records and detect data change.
|
|
249 |
*/
|
|
250 |
if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ && |
|
251 |
table->timestamp_field && |
|
252 |
(table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE || |
|
253 |
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)) |
|
1005.2.3
by Monty Taylor
Further reversion of P. |
254 |
bitmap_union(table->read_set, table->write_set); |
1
by brian
clean slate |
255 |
// Don't count on usage of 'only index' when calculating which key to use
|
1005.2.6
by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<> |
256 |
table->covering_keys.reset(); |
1
by brian
clean slate |
257 |
|
258 |
/* Update the table->file->stats.records number */
|
|
259 |
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); |
|
260 |
||
261 |
select= make_select(table, 0, 0, conds, 0, &error); |
|
262 |
if (error || !limit || |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
263 |
(select && select->check_quick(session, safe_update, limit))) |
1
by brian
clean slate |
264 |
{
|
265 |
delete select; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
266 |
free_underlaid_joins(session, select_lex); |
1
by brian
clean slate |
267 |
if (error) |
268 |
goto abort; // Error in where |
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
269 |
DRIZZLE_UPDATE_END(); |
836
by Brian Aker
Fixed session call from function to method. |
270 |
session->my_ok(); // No matching records |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
271 |
return(0); |
1
by brian
clean slate |
272 |
}
|
273 |
if (!select && limit != HA_POS_ERROR) |
|
274 |
{
|
|
275 |
if ((used_index= get_index_for_order(table, order, limit)) != MAX_KEY) |
|
56
by brian
Next pass of true/false update. |
276 |
need_sort= false; |
1
by brian
clean slate |
277 |
}
|
278 |
/* If running in safe sql mode, don't allow updates without keys */
|
|
1005.2.6
by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<> |
279 |
if (table->quick_keys.none()) |
1
by brian
clean slate |
280 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
281 |
session->server_status|=SERVER_QUERY_NO_INDEX_USED; |
1
by brian
clean slate |
282 |
if (safe_update && !using_limit) |
283 |
{
|
|
284 |
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, |
|
285 |
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0)); |
|
286 |
goto err; |
|
287 |
}
|
|
288 |
}
|
|
289 |
||
290 |
table->mark_columns_needed_for_update(); |
|
291 |
||
292 |
/* Check if we are modifying a key that we are used to search with */
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
293 |
|
1
by brian
clean slate |
294 |
if (select && select->quick) |
295 |
{
|
|
296 |
used_index= select->quick->index; |
|
297 |
used_key_is_modified= (!select->quick->unique_key_range() && |
|
298 |
select->quick->is_keys_used(table->write_set)); |
|
299 |
}
|
|
300 |
else
|
|
301 |
{
|
|
302 |
used_key_is_modified= 0; |
|
303 |
if (used_index == MAX_KEY) // no index for sort order |
|
304 |
used_index= table->file->key_used_on_scan; |
|
305 |
if (used_index != MAX_KEY) |
|
306 |
used_key_is_modified= is_key_used(table, used_index, table->write_set); |
|
307 |
}
|
|
308 |
||
309 |
||
310 |
if (used_key_is_modified || order) |
|
311 |
{
|
|
312 |
/*
|
|
313 |
We can't update table directly; We must first search after all
|
|
314 |
matching rows before updating the table!
|
|
315 |
*/
|
|
1005.2.6
by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<> |
316 |
if (used_index < MAX_KEY && old_covering_keys.test(used_index)) |
1
by brian
clean slate |
317 |
{
|
318 |
table->key_read=1; |
|
319 |
table->mark_columns_used_by_index(used_index); |
|
320 |
}
|
|
321 |
else
|
|
322 |
{
|
|
323 |
table->use_all_columns(); |
|
324 |
}
|
|
325 |
||
326 |
/* note: We avoid sorting avoid if we sort on the used index */
|
|
327 |
if (order && (need_sort || used_key_is_modified)) |
|
328 |
{
|
|
329 |
/*
|
|
327.2.3
by Brian Aker
Refactoring of class Table |
330 |
Doing an order_st BY; Let filesort find and sort the rows we are going
|
1
by brian
clean slate |
331 |
to update
|
332 |
NOTE: filesort will call table->prepare_for_position()
|
|
333 |
*/
|
|
482
by Brian Aker
Remove uint. |
334 |
uint32_t length= 0; |
1
by brian
clean slate |
335 |
SORT_FIELD *sortorder; |
336 |
ha_rows examined_rows; |
|
337 |
||
684
by Brian Aker
Mass cleanup for casting. |
338 |
table->sort.io_cache = new IO_CACHE; |
641.3.8
by Monty Taylor
Removed my_malloc from drizzled. |
339 |
memset(table->sort.io_cache, 0, sizeof(IO_CACHE)); |
340 |
||
1
by brian
clean slate |
341 |
if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) || |
520.1.22
by Brian Aker
Second pass of thd cleanup |
342 |
(table->sort.found_records= filesort(session, table, sortorder, length, |
1
by brian
clean slate |
343 |
select, limit, 1, |
344 |
&examined_rows)) |
|
345 |
== HA_POS_ERROR) |
|
346 |
{
|
|
347 |
goto err; |
|
348 |
}
|
|
349 |
/*
|
|
350 |
Filesort has already found and selected the rows we want to update,
|
|
351 |
so we don't need the where clause
|
|
352 |
*/
|
|
353 |
delete select; |
|
354 |
select= 0; |
|
355 |
}
|
|
356 |
else
|
|
357 |
{
|
|
358 |
/*
|
|
359 |
We are doing a search on a key that is updated. In this case
|
|
360 |
we go trough the matching rows, save a pointer to them and
|
|
361 |
update these in a separate loop based on the pointer.
|
|
362 |
*/
|
|
363 |
||
364 |
IO_CACHE tempfile; |
|
575.4.3
by ysano
Rename mysql to drizzle. |
365 |
if (open_cached_file(&tempfile, drizzle_tmpdir,TEMP_PREFIX, |
1
by brian
clean slate |
366 |
DISK_BUFFER_SIZE, MYF(MY_WME))) |
367 |
goto err; |
|
368 |
||
369 |
/* If quick select is used, initialize it before retrieving rows. */
|
|
370 |
if (select && select->quick && select->quick->reset()) |
|
371 |
goto err; |
|
372 |
table->file->try_semi_consistent_read(1); |
|
373 |
||
374 |
/*
|
|
375 |
When we get here, we have one of the following options:
|
|
376 |
A. used_index == MAX_KEY
|
|
377 |
This means we should use full table scan, and start it with
|
|
378 |
init_read_record call
|
|
379 |
B. used_index != MAX_KEY
|
|
380 |
B.1 quick select is used, start the scan with init_read_record
|
|
381 |
B.2 quick select is not used, this is full index scan (with LIMIT)
|
|
382 |
Full index scan must be started with init_read_record_idx
|
|
383 |
*/
|
|
384 |
||
385 |
if (used_index == MAX_KEY || (select && select->quick)) |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
386 |
init_read_record(&info,session,table,select,0,1); |
1
by brian
clean slate |
387 |
else
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
388 |
init_read_record_idx(&info, session, table, 1, used_index); |
1
by brian
clean slate |
389 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
390 |
session->set_proc_info("Searching rows for update"); |
1
by brian
clean slate |
391 |
ha_rows tmp_limit= limit; |
392 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
393 |
while (!(error=info.read_record(&info)) && !session->killed) |
1
by brian
clean slate |
394 |
{
|
395 |
if (!(select && select->skip_record())) |
|
396 |
{
|
|
397 |
if (table->file->was_semi_consistent_read()) |
|
398 |
continue; /* repeat the read of the same row if it still exists */ |
|
399 |
||
400 |
table->file->position(table->record[0]); |
|
401 |
if (my_b_write(&tempfile,table->file->ref, |
|
402 |
table->file->ref_length)) |
|
403 |
{
|
|
404 |
error=1; /* purecov: inspected */ |
|
405 |
break; /* purecov: inspected */ |
|
406 |
}
|
|
407 |
if (!--limit && using_limit) |
|
408 |
{
|
|
409 |
error= -1; |
|
410 |
break; |
|
411 |
}
|
|
412 |
}
|
|
413 |
else
|
|
414 |
table->file->unlock_row(); |
|
415 |
}
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
416 |
if (session->killed && !error) |
1
by brian
clean slate |
417 |
error= 1; // Aborted |
418 |
limit= tmp_limit; |
|
419 |
table->file->try_semi_consistent_read(0); |
|
420 |
end_read_record(&info); |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
421 |
|
1
by brian
clean slate |
422 |
/* Change select to use tempfile */
|
423 |
if (select) |
|
424 |
{
|
|
425 |
delete select->quick; |
|
426 |
if (select->free_cond) |
|
427 |
delete select->cond; |
|
428 |
select->quick=0; |
|
429 |
select->cond=0; |
|
430 |
}
|
|
431 |
else
|
|
432 |
{
|
|
433 |
select= new SQL_SELECT; |
|
434 |
select->head=table; |
|
435 |
}
|
|
436 |
if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) |
|
437 |
error=1; /* purecov: inspected */ |
|
438 |
select->file=tempfile; // Read row ptrs from this file |
|
439 |
if (error >= 0) |
|
440 |
goto err; |
|
441 |
}
|
|
442 |
if (table->key_read) |
|
443 |
table->restore_column_maps_after_mark_index(); |
|
444 |
}
|
|
445 |
||
446 |
if (ignore) |
|
447 |
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
448 |
|
1
by brian
clean slate |
449 |
if (select && select->quick && select->quick->reset()) |
450 |
goto err; |
|
451 |
table->file->try_semi_consistent_read(1); |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
452 |
init_read_record(&info,session,table,select,0,1); |
1
by brian
clean slate |
453 |
|
454 |
updated= found= 0; |
|
685.4.1
by Jay Pipes
Enabled the null.test. |
455 |
/*
|
456 |
* Per the SQL standard, inserting NULL into a NOT NULL
|
|
457 |
* field requires an error to be thrown.
|
|
458 |
*
|
|
459 |
* @NOTE
|
|
460 |
*
|
|
461 |
* NULL check and handling occurs in field_conv.cc
|
|
462 |
*/
|
|
463 |
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; |
|
464 |
session->cuted_fields= 0L; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
465 |
session->set_proc_info("Updating"); |
1
by brian
clean slate |
466 |
|
467 |
transactional_table= table->file->has_transactions(); |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
468 |
session->abort_on_warning= test(!ignore); |
1
by brian
clean slate |
469 |
will_batch= !table->file->start_bulk_update(); |
470 |
||
471 |
/*
|
|
472 |
Assure that we can use position()
|
|
473 |
if we need to create an error message.
|
|
474 |
*/
|
|
475 |
if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) |
|
476 |
table->prepare_for_position(); |
|
477 |
||
478 |
/*
|
|
479 |
We can use compare_record() to optimize away updates if
|
|
480 |
the table handler is returning all columns OR if
|
|
481 |
if all updated columns are read
|
|
482 |
*/
|
|
483 |
can_compare_record= (!(table->file->ha_table_flags() & |
|
484 |
HA_PARTIAL_COLUMN_READ) || |
|
1005.2.3
by Monty Taylor
Further reversion of P. |
485 |
bitmap_is_subset(table->write_set, table->read_set)); |
1
by brian
clean slate |
486 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
487 |
while (!(error=info.read_record(&info)) && !session->killed) |
1
by brian
clean slate |
488 |
{
|
489 |
if (!(select && select->skip_record())) |
|
490 |
{
|
|
491 |
if (table->file->was_semi_consistent_read()) |
|
492 |
continue; /* repeat the read of the same row if it still exists */ |
|
493 |
||
997.5.1
by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record |
494 |
table->storeRecord(); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
495 |
if (fill_record(session, fields, values, 0)) |
1
by brian
clean slate |
496 |
break; /* purecov: inspected */ |
497 |
||
498 |
found++; |
|
499 |
||
355
by Brian Aker
More Table cleanup |
500 |
if (!can_compare_record || table->compare_record()) |
1
by brian
clean slate |
501 |
{
|
502 |
if (will_batch) |
|
503 |
{
|
|
504 |
/*
|
|
505 |
Typically a batched handler can execute the batched jobs when:
|
|
506 |
1) When specifically told to do so
|
|
507 |
2) When it is not a good idea to batch anymore
|
|
508 |
3) When it is necessary to send batch for other reasons
|
|
509 |
(One such reason is when READ's must be performed)
|
|
510 |
||
511 |
1) is covered by exec_bulk_update calls.
|
|
512 |
2) and 3) is handled by the bulk_update_row method.
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
513 |
|
1
by brian
clean slate |
514 |
bulk_update_row can execute the updates including the one
|
515 |
defined in the bulk_update_row or not including the row
|
|
516 |
in the call. This is up to the handler implementation and can
|
|
517 |
vary from call to call.
|
|
518 |
||
519 |
The dup_key_found reports the number of duplicate keys found
|
|
520 |
in those updates actually executed. It only reports those if
|
|
521 |
the extra call with HA_EXTRA_IGNORE_DUP_KEY have been issued.
|
|
522 |
If this hasn't been issued it returns an error code and can
|
|
523 |
ignore this number. Thus any handler that implements batching
|
|
524 |
for UPDATE IGNORE must also handle this extra call properly.
|
|
525 |
||
526 |
If a duplicate key is found on the record included in this
|
|
527 |
call then it should be included in the count of dup_key_found
|
|
528 |
and error should be set to 0 (only if these errors are ignored).
|
|
529 |
*/
|
|
530 |
error= table->file->ha_bulk_update_row(table->record[1], |
|
531 |
table->record[0], |
|
532 |
&dup_key_found); |
|
533 |
limit+= dup_key_found; |
|
534 |
updated-= dup_key_found; |
|
535 |
}
|
|
536 |
else
|
|
537 |
{
|
|
538 |
/* Non-batched update */
|
|
539 |
error= table->file->ha_update_row(table->record[1], |
|
540 |
table->record[0]); |
|
541 |
}
|
|
542 |
if (!error || error == HA_ERR_RECORD_IS_THE_SAME) |
|
543 |
{
|
|
544 |
if (error != HA_ERR_RECORD_IS_THE_SAME) |
|
545 |
updated++; |
|
546 |
else
|
|
547 |
error= 0; |
|
548 |
}
|
|
549 |
else if (!ignore || |
|
550 |
table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) |
|
551 |
{
|
|
552 |
/*
|
|
553 |
If (ignore && error is ignorable) we don't have to
|
|
554 |
do anything; otherwise...
|
|
555 |
*/
|
|
556 |
myf flags= 0; |
|
557 |
||
558 |
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) |
|
559 |
flags|= ME_FATALERROR; /* Other handler errors are fatal */ |
|
560 |
||
561 |
prepare_record_for_error_message(error, table); |
|
562 |
table->file->print_error(error,MYF(flags)); |
|
563 |
error= 1; |
|
564 |
break; |
|
565 |
}
|
|
566 |
}
|
|
567 |
||
568 |
if (!--limit && using_limit) |
|
569 |
{
|
|
570 |
/*
|
|
571 |
We have reached end-of-file in most common situations where no
|
|
572 |
batching has occurred and if batching was supposed to occur but
|
|
573 |
no updates were made and finally when the batch execution was
|
|
574 |
performed without error and without finding any duplicate keys.
|
|
575 |
If the batched updates were performed with errors we need to
|
|
576 |
check and if no error but duplicate key's found we need to
|
|
577 |
continue since those are not counted for in limit.
|
|
578 |
*/
|
|
579 |
if (will_batch && |
|
580 |
((error= table->file->exec_bulk_update(&dup_key_found)) || |
|
581 |
dup_key_found)) |
|
582 |
{
|
|
583 |
if (error) |
|
584 |
{
|
|
585 |
/* purecov: begin inspected */
|
|
586 |
/*
|
|
587 |
The handler should not report error of duplicate keys if they
|
|
588 |
are ignored. This is a requirement on batching handlers.
|
|
589 |
*/
|
|
590 |
prepare_record_for_error_message(error, table); |
|
591 |
table->file->print_error(error,MYF(0)); |
|
592 |
error= 1; |
|
593 |
break; |
|
594 |
/* purecov: end */
|
|
595 |
}
|
|
596 |
/*
|
|
597 |
Either an error was found and we are ignoring errors or there
|
|
598 |
were duplicate keys found. In both cases we need to correct
|
|
599 |
the counters and continue the loop.
|
|
600 |
*/
|
|
601 |
limit= dup_key_found; //limit is 0 when we get here so need to + |
|
602 |
updated-= dup_key_found; |
|
603 |
}
|
|
604 |
else
|
|
605 |
{
|
|
606 |
error= -1; // Simulate end of file |
|
607 |
break; |
|
608 |
}
|
|
609 |
}
|
|
610 |
}
|
|
611 |
else
|
|
612 |
table->file->unlock_row(); |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
613 |
session->row_count++; |
1
by brian
clean slate |
614 |
}
|
615 |
dup_key_found= 0; |
|
616 |
/*
|
|
617 |
Caching the killed status to pass as the arg to query event constuctor;
|
|
618 |
The cached value can not change whereas the killed status can
|
|
619 |
(externally) since this point and change of the latter won't affect
|
|
620 |
binlogging.
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
621 |
It's assumed that if an error was set in combination with an effective
|
1
by brian
clean slate |
622 |
killed status then the error is due to killing.
|
623 |
*/
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
624 |
killed_status= session->killed; // get the status of the volatile |
1
by brian
clean slate |
625 |
// simulated killing after the loop must be ineffective for binlogging
|
520.1.21
by Brian Aker
THD -> Session rename |
626 |
error= (killed_status == Session::NOT_KILLED)? error : 1; |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
627 |
|
1
by brian
clean slate |
628 |
if (error && |
629 |
will_batch && |
|
630 |
(loc_error= table->file->exec_bulk_update(&dup_key_found))) |
|
631 |
/*
|
|
632 |
An error has occurred when a batched update was performed and returned
|
|
633 |
an error indication. It cannot be an allowed duplicate key error since
|
|
634 |
we require the batching handler to treat this as a normal behavior.
|
|
635 |
||
636 |
Otherwise we simply remove the number of duplicate keys records found
|
|
637 |
in the batched update.
|
|
638 |
*/
|
|
639 |
{
|
|
640 |
/* purecov: begin inspected */
|
|
641 |
prepare_record_for_error_message(loc_error, table); |
|
642 |
table->file->print_error(loc_error,MYF(ME_FATALERROR)); |
|
643 |
error= 1; |
|
644 |
/* purecov: end */
|
|
645 |
}
|
|
646 |
else
|
|
647 |
updated-= dup_key_found; |
|
648 |
if (will_batch) |
|
649 |
table->file->end_bulk_update(); |
|
650 |
table->file->try_semi_consistent_read(0); |
|
651 |
||
652 |
if (!transactional_table && updated > 0) |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
653 |
session->transaction.stmt.modified_non_trans_table= true; |
1
by brian
clean slate |
654 |
|
655 |
end_read_record(&info); |
|
656 |
delete select; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
657 |
session->set_proc_info("end"); |
398.1.10
by Monty Taylor
Actually removed VOID() this time. |
658 |
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); |
1
by brian
clean slate |
659 |
|
660 |
/*
|
|
661 |
error < 0 means really no error at all: we processed all rows until the
|
|
662 |
last one without error. error > 0 means an error (e.g. unique key
|
|
663 |
violation and no IGNORE or REPLACE). error == 0 is also an error (if
|
|
664 |
preparing the record or invoking before triggers fails). See
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
665 |
ha_autocommit_or_rollback(error>=0) and return(error>=0) below.
|
1
by brian
clean slate |
666 |
Sometimes we want to binlog even if we updated no rows, in case user used
|
667 |
it to be sure master and slave are in same state.
|
|
668 |
*/
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
669 |
if ((error < 0) || session->transaction.stmt.modified_non_trans_table) |
1
by brian
clean slate |
670 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
671 |
if (session->transaction.stmt.modified_non_trans_table) |
672 |
session->transaction.all.modified_non_trans_table= true; |
|
1
by brian
clean slate |
673 |
}
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
674 |
assert(transactional_table || !updated || session->transaction.stmt.modified_non_trans_table); |
675 |
free_underlaid_joins(session, select_lex); |
|
1
by brian
clean slate |
676 |
|
677 |
/* If LAST_INSERT_ID(X) was used, report X */
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
678 |
id= session->arg_of_last_insert_id_function ? |
679 |
session->first_successful_insert_id_in_prev_stmt : 0; |
|
1
by brian
clean slate |
680 |
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
681 |
DRIZZLE_UPDATE_END(); |
1
by brian
clean slate |
682 |
if (error < 0) |
683 |
{
|
|
684 |
char buff[STRING_BUFFER_USUAL_SIZE]; |
|
685 |
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
686 |
(ulong) session->cuted_fields); |
687 |
session->row_count_func= |
|
688 |
(session->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; |
|
836
by Brian Aker
Fixed session call from function to method. |
689 |
session->my_ok((ulong) session->row_count_func, id, buff); |
1
by brian
clean slate |
690 |
}
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
691 |
session->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ |
692 |
session->abort_on_warning= 0; |
|
693 |
return((error >= 0 || session->is_error()) ? 1 : 0); |
|
1
by brian
clean slate |
694 |
|
695 |
err: |
|
696 |
delete select; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
697 |
free_underlaid_joins(session, select_lex); |
1
by brian
clean slate |
698 |
if (table->key_read) |
699 |
{
|
|
700 |
table->key_read=0; |
|
701 |
table->file->extra(HA_EXTRA_NO_KEYREAD); |
|
702 |
}
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
703 |
session->abort_on_warning= 0; |
1
by brian
clean slate |
704 |
|
705 |
abort: |
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
706 |
DRIZZLE_UPDATE_END(); |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
707 |
return(1); |
1
by brian
clean slate |
708 |
}
|
709 |
||
710 |
/*
|
|
711 |
Prepare items in UPDATE statement
|
|
712 |
||
713 |
SYNOPSIS
|
|
714 |
mysql_prepare_update()
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
715 |
session - thread handler
|
1
by brian
clean slate |
716 |
table_list - global/local table list
|
717 |
conds - conditions
|
|
327.2.3
by Brian Aker
Refactoring of class Table |
718 |
order_num - number of order_st BY list entries
|
719 |
order - order_st BY clause list
|
|
1
by brian
clean slate |
720 |
|
721 |
RETURN VALUE
|
|
56
by brian
Next pass of true/false update. |
722 |
false OK
|
723 |
true error
|
|
1
by brian
clean slate |
724 |
*/
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
725 |
bool mysql_prepare_update(Session *session, TableList *table_list, |
482
by Brian Aker
Remove uint. |
726 |
Item **conds, uint32_t order_num, order_st *order) |
1
by brian
clean slate |
727 |
{
|
728 |
List<Item> all_fields; |
|
846
by Brian Aker
Removing on typedeffed class. |
729 |
Select_Lex *select_lex= &session->lex->select_lex; |
1
by brian
clean slate |
730 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
731 |
session->lex->allow_sum_func= 0; |
1
by brian
clean slate |
732 |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
733 |
if (setup_tables_and_check_access(session, &select_lex->context, |
1
by brian
clean slate |
734 |
&select_lex->top_join_list, |
735 |
table_list, |
|
736 |
&select_lex->leaf_tables, |
|
737 |
false) || |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
738 |
setup_conds(session, table_list, select_lex->leaf_tables, conds) || |
739 |
select_lex->setup_ref_array(session, order_num) || |
|
740 |
setup_order(session, select_lex->ref_pointer_array, |
|
1
by brian
clean slate |
741 |
table_list, all_fields, all_fields, order)) |
836
by Brian Aker
Fixed session call from function to method. |
742 |
return true; |
1
by brian
clean slate |
743 |
|
744 |
/* Check that we are not using table that we are updating in a sub select */
|
|
745 |
{
|
|
327.2.4
by Brian Aker
Refactoring table.h |
746 |
TableList *duplicate; |
520.1.22
by Brian Aker
Second pass of thd cleanup |
747 |
if ((duplicate= unique_table(session, table_list, table_list->next_global, 0))) |
1
by brian
clean slate |
748 |
{
|
749 |
update_non_unique_table_error(table_list, "UPDATE", duplicate); |
|
750 |
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name); |
|
836
by Brian Aker
Fixed session call from function to method. |
751 |
return true; |
1
by brian
clean slate |
752 |
}
|
753 |
}
|
|
177.1.1
by brian
Removed dead code around prep. |
754 |
|
836
by Brian Aker
Fixed session call from function to method. |
755 |
return false; |
1
by brian
clean slate |
756 |
}
|
757 |
||
758 |
||
759 |
/***************************************************************************
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
760 |
Update multiple tables from join
|
1
by brian
clean slate |
761 |
***************************************************************************/
|
762 |
||
763 |
/*
|
|
764 |
Get table map for list of Item_field
|
|
765 |
*/
|
|
766 |
||
767 |
static table_map get_table_map(List<Item> *items) |
|
768 |
{
|
|
769 |
List_iterator_fast<Item> item_it(*items); |
|
770 |
Item_field *item; |
|
771 |
table_map map= 0; |
|
772 |
||
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
773 |
while ((item= (Item_field *) item_it++)) |
1
by brian
clean slate |
774 |
map|= item->used_tables(); |
775 |
return map; |
|
776 |
}
|
|
777 |
||
778 |
||
779 |
/*
|
|
780 |
make update specific preparation and checks after opening tables
|
|
781 |
||
782 |
SYNOPSIS
|
|
783 |
mysql_multi_update_prepare()
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
784 |
session thread handler
|
1
by brian
clean slate |
785 |
|
786 |
RETURN
|
|
56
by brian
Next pass of true/false update. |
787 |
false OK
|
788 |
true Error
|
|
1
by brian
clean slate |
789 |
*/
|
790 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
791 |
int mysql_multi_update_prepare(Session *session) |
1
by brian
clean slate |
792 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
793 |
LEX *lex= session->lex; |
327.2.4
by Brian Aker
Refactoring table.h |
794 |
TableList *table_list= lex->query_tables; |
795 |
TableList *tl, *leaves; |
|
1
by brian
clean slate |
796 |
List<Item> *fields= &lex->select_lex.item_list; |
797 |
table_map tables_for_update; |
|
798 |
bool update_view= 0; |
|
799 |
/*
|
|
800 |
if this multi-update was converted from usual update, here is table
|
|
801 |
counter else junk will be assigned here, but then replaced with real
|
|
802 |
count in open_tables()
|
|
803 |
*/
|
|
482
by Brian Aker
Remove uint. |
804 |
uint32_t table_count= lex->table_count; |
520.1.22
by Brian Aker
Second pass of thd cleanup |
805 |
const bool using_lock_tables= session->locked_tables != 0; |
806 |
bool original_multiupdate= (session->lex->sql_command == SQLCOM_UPDATE_MULTI); |
|
56
by brian
Next pass of true/false update. |
807 |
bool need_reopen= false; |
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
808 |
|
1
by brian
clean slate |
809 |
|
810 |
/* following need for prepared statements, to run next time multi-update */
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
811 |
session->lex->sql_command= SQLCOM_UPDATE_MULTI; |
1
by brian
clean slate |
812 |
|
813 |
reopen_tables: |
|
814 |
||
815 |
/* open tables and create derived ones, but do not lock and fill them */
|
|
816 |
if (((original_multiupdate || need_reopen) && |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
817 |
open_tables(session, &table_list, &table_count, 0)) || |
1
by brian
clean slate |
818 |
mysql_handle_derived(lex, &mysql_derived_prepare)) |
836
by Brian Aker
Fixed session call from function to method. |
819 |
return true; |
1
by brian
clean slate |
820 |
/*
|
821 |
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
|
|
822 |
second time, but this call will do nothing (there are check for second
|
|
823 |
call in setup_tables()).
|
|
824 |
*/
|
|
825 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
826 |
if (setup_tables_and_check_access(session, &lex->select_lex.context, |
1
by brian
clean slate |
827 |
&lex->select_lex.top_join_list, |
828 |
table_list, |
|
829 |
&lex->select_lex.leaf_tables, false)) |
|
836
by Brian Aker
Fixed session call from function to method. |
830 |
return true; |
1
by brian
clean slate |
831 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
832 |
if (setup_fields_with_no_wrap(session, 0, *fields, MARK_COLUMNS_WRITE, 0, 0)) |
836
by Brian Aker
Fixed session call from function to method. |
833 |
return true; |
1
by brian
clean slate |
834 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
835 |
if (update_view && check_fields(session, *fields)) |
1
by brian
clean slate |
836 |
{
|
836
by Brian Aker
Fixed session call from function to method. |
837 |
return true; |
1
by brian
clean slate |
838 |
}
|
839 |
||
840 |
tables_for_update= get_table_map(fields); |
|
841 |
||
842 |
/*
|
|
843 |
Setup timestamp handling and locking mode
|
|
844 |
*/
|
|
845 |
leaves= lex->select_lex.leaf_tables; |
|
846 |
for (tl= leaves; tl; tl= tl->next_leaf) |
|
847 |
{
|
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
848 |
Table *table= tl->table; |
1
by brian
clean slate |
849 |
/* Only set timestamp column if this is not modified */
|
1009
by Brian Aker
Merge of Monty |
850 |
if (table->timestamp_field && table->timestamp_field->isWriteSet()) |
1
by brian
clean slate |
851 |
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; |
852 |
||
853 |
/* if table will be updated then check that it is unique */
|
|
854 |
if (table->map & tables_for_update) |
|
855 |
{
|
|
856 |
table->mark_columns_needed_for_update(); |
|
857 |
/*
|
|
858 |
If table will be updated we should not downgrade lock for it and
|
|
859 |
leave it as is.
|
|
860 |
*/
|
|
861 |
}
|
|
862 |
else
|
|
863 |
{
|
|
864 |
/*
|
|
865 |
If we are using the binary log, we need TL_READ_NO_INSERT to get
|
|
866 |
correct order of statements. Otherwise, we use a TL_READ lock to
|
|
867 |
improve performance.
|
|
868 |
*/
|
|
604
by Brian Aker
Remove lock condition needed (we do row based replication, so... lock is |
869 |
tl->lock_type= TL_READ; |
1
by brian
clean slate |
870 |
tl->updating= 0; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
871 |
/* Update Table::lock_type accordingly. */
|
1
by brian
clean slate |
872 |
if (!tl->placeholder() && !using_lock_tables) |
873 |
tl->table->reginfo.lock_type= tl->lock_type; |
|
874 |
}
|
|
875 |
}
|
|
876 |
||
877 |
/* now lock and fill tables */
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
878 |
if (lock_tables(session, table_list, table_count, &need_reopen)) |
1
by brian
clean slate |
879 |
{
|
880 |
if (!need_reopen) |
|
836
by Brian Aker
Fixed session call from function to method. |
881 |
return true; |
1
by brian
clean slate |
882 |
|
883 |
/*
|
|
884 |
We have to reopen tables since some of them were altered or dropped
|
|
885 |
during lock_tables() or something was done with their triggers.
|
|
886 |
Let us do some cleanups to be able do setup_table() and setup_fields()
|
|
887 |
once again.
|
|
888 |
*/
|
|
889 |
List_iterator_fast<Item> it(*fields); |
|
890 |
Item *item; |
|
891 |
while ((item= it++)) |
|
892 |
item->cleanup(); |
|
893 |
||
894 |
/* We have to cleanup translation tables of views. */
|
|
327.2.4
by Brian Aker
Refactoring table.h |
895 |
for (TableList *tbl= table_list; tbl; tbl= tbl->next_global) |
1
by brian
clean slate |
896 |
tbl->cleanup_items(); |
897 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
898 |
close_tables_for_reopen(session, &table_list); |
1
by brian
clean slate |
899 |
goto reopen_tables; |
900 |
}
|
|
901 |
||
902 |
/*
|
|
903 |
Check that we are not using table that we are updating, but we should
|
|
904 |
skip all tables of UPDATE SELECT itself
|
|
905 |
*/
|
|
56
by brian
Next pass of true/false update. |
906 |
lex->select_lex.exclude_from_table_unique_test= true; |
1
by brian
clean slate |
907 |
/* We only need SELECT privilege for columns in the values list */
|
908 |
for (tl= leaves; tl; tl= tl->next_leaf) |
|
909 |
{
|
|
910 |
if (tl->lock_type != TL_READ && |
|
911 |
tl->lock_type != TL_READ_NO_INSERT) |
|
912 |
{
|
|
327.2.4
by Brian Aker
Refactoring table.h |
913 |
TableList *duplicate; |
520.1.22
by Brian Aker
Second pass of thd cleanup |
914 |
if ((duplicate= unique_table(session, tl, table_list, 0))) |
1
by brian
clean slate |
915 |
{
|
916 |
update_non_unique_table_error(table_list, "UPDATE", duplicate); |
|
836
by Brian Aker
Fixed session call from function to method. |
917 |
return true; |
1
by brian
clean slate |
918 |
}
|
919 |
}
|
|
920 |
}
|
|
921 |
/*
|
|
56
by brian
Next pass of true/false update. |
922 |
Set exclude_from_table_unique_test value back to false. It is needed for
|
1
by brian
clean slate |
923 |
further check in multi_update::prepare whether to use record cache.
|
924 |
*/
|
|
56
by brian
Next pass of true/false update. |
925 |
lex->select_lex.exclude_from_table_unique_test= false; |
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
926 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
927 |
if (session->fill_derived_tables() && |
1
by brian
clean slate |
928 |
mysql_handle_derived(lex, &mysql_derived_filling)) |
836
by Brian Aker
Fixed session call from function to method. |
929 |
return true; |
1
by brian
clean slate |
930 |
|
51.1.8
by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false |
931 |
return (false); |
1
by brian
clean slate |
932 |
}
|
933 |
||
934 |
||
935 |
/*
|
|
936 |
Setup multi-update handling and call SELECT to do the join
|
|
937 |
*/
|
|
938 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
939 |
bool mysql_multi_update(Session *session, |
327.2.4
by Brian Aker
Refactoring table.h |
940 |
TableList *table_list, |
1
by brian
clean slate |
941 |
List<Item> *fields, |
942 |
List<Item> *values, |
|
943 |
COND *conds, |
|
151
by Brian Aker
Ulonglong to uint64_t |
944 |
uint64_t options, |
1
by brian
clean slate |
945 |
enum enum_duplicates handle_duplicates, bool ignore, |
848
by Brian Aker
typdef class removal (just... use the name of the class). |
946 |
Select_Lex_Unit *unit, Select_Lex *select_lex) |
1
by brian
clean slate |
947 |
{
|
948 |
multi_update *result; |
|
949 |
bool res; |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
950 |
|
1
by brian
clean slate |
951 |
if (!(result= new multi_update(table_list, |
520.1.22
by Brian Aker
Second pass of thd cleanup |
952 |
session->lex->select_lex.leaf_tables, |
1
by brian
clean slate |
953 |
fields, values, |
954 |
handle_duplicates, ignore))) |
|
836
by Brian Aker
Fixed session call from function to method. |
955 |
return true; |
1
by brian
clean slate |
956 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
957 |
session->abort_on_warning= true; |
1
by brian
clean slate |
958 |
|
959 |
List<Item> total_list; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
960 |
res= mysql_select(session, &select_lex->ref_pointer_array, |
1
by brian
clean slate |
961 |
table_list, select_lex->with_wild, |
962 |
total_list, |
|
327.2.3
by Brian Aker
Refactoring of class Table |
963 |
conds, 0, (order_st *) NULL, (order_st *)NULL, (Item *) NULL, |
1
by brian
clean slate |
964 |
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | |
965 |
OPTION_SETUP_TABLES_DONE, |
|
966 |
result, unit, select_lex); |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
967 |
res|= session->is_error(); |
1
by brian
clean slate |
968 |
if (unlikely(res)) |
969 |
{
|
|
970 |
/* If we had a another error reported earlier then this will be ignored */
|
|
971 |
result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR)); |
|
972 |
result->abort(); |
|
973 |
}
|
|
974 |
delete result; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
975 |
session->abort_on_warning= 0; |
836
by Brian Aker
Fixed session call from function to method. |
976 |
return false; |
1
by brian
clean slate |
977 |
}
|
978 |
||
979 |
||
327.2.4
by Brian Aker
Refactoring table.h |
980 |
multi_update::multi_update(TableList *table_list, |
981 |
TableList *leaves_list, |
|
1
by brian
clean slate |
982 |
List<Item> *field_list, List<Item> *value_list, |
983 |
enum enum_duplicates handle_duplicates_arg, |
|
984 |
bool ignore_arg) |
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
985 |
:all_tables(table_list), leaves(leaves_list), |
1
by brian
clean slate |
986 |
tmp_tables(0), updated(0), found(0), fields(field_list), |
987 |
values(value_list), table_count(0), copy_field(0), |
|
988 |
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1), |
|
989 |
transactional_tables(0), ignore(ignore_arg), error_handled(0) |
|
990 |
{}
|
|
991 |
||
992 |
||
993 |
/*
|
|
994 |
Connect fields with tables and create list of tables that are updated
|
|
995 |
*/
|
|
996 |
||
575.1.2
by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead. |
997 |
int multi_update::prepare(List<Item> &, |
848
by Brian Aker
typdef class removal (just... use the name of the class). |
998 |
Select_Lex_Unit *) |
1
by brian
clean slate |
999 |
{
|
327.2.4
by Brian Aker
Refactoring table.h |
1000 |
TableList *table_ref; |
1
by brian
clean slate |
1001 |
table_map tables_to_update; |
1002 |
Item_field *item; |
|
1003 |
List_iterator_fast<Item> field_it(*fields); |
|
1004 |
List_iterator_fast<Item> value_it(*values); |
|
482
by Brian Aker
Remove uint. |
1005 |
uint32_t i, max_fields; |
1006 |
uint32_t leaf_table_count= 0; |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1007 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1008 |
session->count_cuted_fields= CHECK_FIELD_WARN; |
1009 |
session->cuted_fields=0L; |
|
1010 |
session->set_proc_info("updating main table"); |
|
1
by brian
clean slate |
1011 |
|
1012 |
tables_to_update= get_table_map(fields); |
|
1013 |
||
1014 |
if (!tables_to_update) |
|
1015 |
{
|
|
1016 |
my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0)); |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1017 |
return(1); |
1
by brian
clean slate |
1018 |
}
|
1019 |
||
1020 |
/*
|
|
1021 |
We have to check values after setup_tables to get covering_keys right in
|
|
1022 |
reference tables
|
|
1023 |
*/
|
|
1024 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1025 |
if (setup_fields(session, 0, *values, MARK_COLUMNS_READ, 0, 0)) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1026 |
return(1); |
1
by brian
clean slate |
1027 |
|
1028 |
/*
|
|
1029 |
Save tables beeing updated in update_tables
|
|
1030 |
update_table->shared is position for table
|
|
1031 |
Don't use key read on tables that are updated
|
|
1032 |
*/
|
|
1033 |
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf) |
|
1034 |
{
|
|
1035 |
/* TODO: add support of view of join support */
|
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1036 |
Table *table=table_ref->table; |
1
by brian
clean slate |
1037 |
leaf_table_count++; |
1038 |
if (tables_to_update & table->map) |
|
1039 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1040 |
TableList *tl= (TableList*) session->memdup((char*) table_ref, |
1
by brian
clean slate |
1041 |
sizeof(*tl)); |
1042 |
if (!tl) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1043 |
return(1); |
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1044 |
update_tables.push_back(tl); |
1
by brian
clean slate |
1045 |
tl->shared= table_count++; |
1046 |
table->no_keyread=1; |
|
1005.2.6
by Monty Taylor
Re-added bitset<> as a replacement for Bitmap<> |
1047 |
table->covering_keys.reset(); |
1
by brian
clean slate |
1048 |
table->pos_in_table_list= tl; |
1049 |
}
|
|
1050 |
}
|
|
1051 |
||
1052 |
||
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1053 |
table_count= update_tables.size(); |
1
by brian
clean slate |
1054 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1055 |
tmp_tables = (Table**) session->calloc(sizeof(Table *) * table_count); |
851
by Brian Aker
Class rewrite of Session (aka get all of the junk out) |
1056 |
tmp_table_param = (Tmp_Table_Param*) session->calloc(sizeof(Tmp_Table_Param) * |
1
by brian
clean slate |
1057 |
table_count); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1058 |
fields_for_table= (List_item **) session->alloc(sizeof(List_item *) * |
1059 |
table_count); |
|
1060 |
values_for_table= (List_item **) session->alloc(sizeof(List_item *) * |
|
1061 |
table_count); |
|
1062 |
if (session->is_fatal_error) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1063 |
return(1); |
1
by brian
clean slate |
1064 |
for (i=0 ; i < table_count ; i++) |
1065 |
{
|
|
1066 |
fields_for_table[i]= new List_item; |
|
1067 |
values_for_table[i]= new List_item; |
|
1068 |
}
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1069 |
if (session->is_fatal_error) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1070 |
return(1); |
1
by brian
clean slate |
1071 |
|
1072 |
/* Split fields into fields_for_table[] and values_by_table[] */
|
|
1073 |
||
1074 |
while ((item= (Item_field *) field_it++)) |
|
1075 |
{
|
|
1076 |
Item *value= value_it++; |
|
482
by Brian Aker
Remove uint. |
1077 |
uint32_t offset= item->field->table->pos_in_table_list->shared; |
1
by brian
clean slate |
1078 |
fields_for_table[offset]->push_back(item); |
1079 |
values_for_table[offset]->push_back(value); |
|
1080 |
}
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1081 |
if (session->is_fatal_error) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1082 |
return(1); |
1
by brian
clean slate |
1083 |
|
1084 |
/* Allocate copy fields */
|
|
1085 |
max_fields=0; |
|
1086 |
for (i=0 ; i < table_count ; i++) |
|
1087 |
set_if_bigger(max_fields, fields_for_table[i]->elements + leaf_table_count); |
|
1088 |
copy_field= new Copy_field[max_fields]; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1089 |
return(session->is_fatal_error != 0); |
1
by brian
clean slate |
1090 |
}
|
1091 |
||
1092 |
||
1093 |
/*
|
|
1094 |
Check if table is safe to update on fly
|
|
1095 |
||
1096 |
SYNOPSIS
|
|
1097 |
safe_update_on_fly()
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1098 |
session Thread handler
|
1
by brian
clean slate |
1099 |
join_tab How table is used in join
|
1100 |
all_tables List of tables
|
|
1101 |
||
1102 |
NOTES
|
|
1103 |
We can update the first table in join on the fly if we know that
|
|
1104 |
a row in this table will never be read twice. This is true under
|
|
1105 |
the following conditions:
|
|
1106 |
||
1107 |
- We are doing a table scan and the data is in a separate file (MyISAM) or
|
|
1108 |
if we don't update a clustered key.
|
|
1109 |
||
1110 |
- We are doing a range scan and we don't update the scan key or
|
|
1111 |
the primary key for a clustered table handler.
|
|
1112 |
||
1113 |
- Table is not joined to itself.
|
|
1114 |
||
1115 |
This function gets information about fields to be updated from
|
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1116 |
the Table::write_set bitmap.
|
1
by brian
clean slate |
1117 |
|
1118 |
WARNING
|
|
1119 |
This code is a bit dependent of how make_join_readinfo() works.
|
|
1120 |
||
1121 |
RETURN
|
|
1122 |
0 Not safe to update
|
|
1123 |
1 Safe to update
|
|
1124 |
*/
|
|
1125 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1126 |
static bool safe_update_on_fly(Session *session, JOIN_TAB *join_tab, |
327.2.4
by Brian Aker
Refactoring table.h |
1127 |
TableList *table_ref, TableList *all_tables) |
1
by brian
clean slate |
1128 |
{
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1129 |
Table *table= join_tab->table; |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1130 |
if (unique_table(session, table_ref, all_tables, 0)) |
1
by brian
clean slate |
1131 |
return 0; |
1132 |
switch (join_tab->type) { |
|
1133 |
case JT_SYSTEM: |
|
1134 |
case JT_CONST: |
|
1135 |
case JT_EQ_REF: |
|
56
by brian
Next pass of true/false update. |
1136 |
return true; // At most one matching row |
1
by brian
clean slate |
1137 |
case JT_REF: |
1138 |
case JT_REF_OR_NULL: |
|
1139 |
return !is_key_used(table, join_tab->ref.key, table->write_set); |
|
1140 |
case JT_ALL: |
|
1141 |
/* If range search on index */
|
|
1142 |
if (join_tab->quick) |
|
1143 |
return !join_tab->quick->is_keys_used(table->write_set); |
|
1144 |
/* If scanning in clustered key */
|
|
1145 |
if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && |
|
1146 |
table->s->primary_key < MAX_KEY) |
|
1147 |
return !is_key_used(table, table->s->primary_key, table->write_set); |
|
56
by brian
Next pass of true/false update. |
1148 |
return true; |
1
by brian
clean slate |
1149 |
default: |
1150 |
break; // Avoid compler warning |
|
1151 |
}
|
|
56
by brian
Next pass of true/false update. |
1152 |
return false; |
1
by brian
clean slate |
1153 |
|
1154 |
}
|
|
1155 |
||
1156 |
||
1157 |
/*
|
|
1158 |
Initialize table for multi table
|
|
1159 |
||
1160 |
IMPLEMENTATION
|
|
1161 |
- Update first table in join on the fly, if possible
|
|
1162 |
- Create temporary tables to store changed values for all other tables
|
|
1163 |
that are updated (and main_table if the above doesn't hold).
|
|
1164 |
*/
|
|
1165 |
||
1166 |
bool
|
|
1167 |
multi_update::initialize_tables(JOIN *join) |
|
1168 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1169 |
if ((session->options & OPTION_SAFE_UPDATES) && error_if_full_join(join)) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1170 |
return(1); |
1
by brian
clean slate |
1171 |
main_table=join->join_tab->table; |
1172 |
table_to_update= 0; |
|
1173 |
||
1174 |
/* Any update has at least one pair (field, value) */
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1175 |
assert(fields->elements); |
1
by brian
clean slate |
1176 |
|
1177 |
/* Create a temporary table for keys to all tables, except main table */
|
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1178 |
for (list<TableList*>::iterator it= update_tables.begin(); |
1179 |
it != update_tables.end(); |
|
1180 |
++it) |
|
1
by brian
clean slate |
1181 |
{
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1182 |
Table *table= (*it)->table; |
1183 |
uint32_t cnt= (*it)->shared; |
|
1
by brian
clean slate |
1184 |
List<Item> temp_fields; |
327.2.3
by Brian Aker
Refactoring of class Table |
1185 |
order_st group; |
851
by Brian Aker
Class rewrite of Session (aka get all of the junk out) |
1186 |
Tmp_Table_Param *tmp_param; |
1
by brian
clean slate |
1187 |
|
1188 |
table->mark_columns_needed_for_update(); |
|
1189 |
if (ignore) |
|
1190 |
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); |
|
1191 |
if (table == main_table) // First table in join |
|
1192 |
{
|
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1193 |
if (safe_update_on_fly(session, join->join_tab, (*it), all_tables)) |
1
by brian
clean slate |
1194 |
{
|
1195 |
table_to_update= main_table; // Update table on the fly |
|
1196 |
continue; |
|
1197 |
}
|
|
1198 |
}
|
|
1199 |
table->prepare_for_position(); |
|
1200 |
||
1201 |
tmp_param= tmp_table_param+cnt; |
|
1202 |
||
1203 |
/*
|
|
1204 |
Create a temporary table to store all fields that are changed for this
|
|
1205 |
table. The first field in the temporary table is a pointer to the
|
|
1206 |
original row so that we can find and update it. For the updatable
|
|
1207 |
VIEW a few following fields are rowids of tables used in the CHECK
|
|
1208 |
OPTION condition.
|
|
1209 |
*/
|
|
1210 |
||
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1211 |
List_iterator_fast<Table> tbl_it(unupdated_check_opt_tables); |
1212 |
Table *tbl= table; |
|
1
by brian
clean slate |
1213 |
do
|
1214 |
{
|
|
241
by Brian Aker
First pass of CHAR removal. |
1215 |
Field_varstring *field= new Field_varstring(tbl->file->ref_length, 0, |
1216 |
tbl->alias, tbl->s, &my_charset_bin); |
|
1
by brian
clean slate |
1217 |
if (!field) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1218 |
return(1); |
1
by brian
clean slate |
1219 |
field->init(tbl); |
1220 |
/*
|
|
1221 |
The field will be converted to varstring when creating tmp table if
|
|
1222 |
table to be updated was created by mysql 4.1. Deny this.
|
|
1223 |
*/
|
|
1224 |
Item_field *ifield= new Item_field((Field *) field); |
|
1225 |
if (!ifield) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1226 |
return(1); |
1
by brian
clean slate |
1227 |
ifield->maybe_null= 0; |
1228 |
if (temp_fields.push_back(ifield)) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1229 |
return(1); |
1
by brian
clean slate |
1230 |
} while ((tbl= tbl_it++)); |
1231 |
||
1232 |
temp_fields.concat(fields_for_table[cnt]); |
|
1233 |
||
1234 |
/* Make an unique key over the first field to avoid duplicated updates */
|
|
212.6.6
by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove(). |
1235 |
memset(&group, 0, sizeof(group)); |
1
by brian
clean slate |
1236 |
group.asc= 1; |
1237 |
group.item= (Item**) temp_fields.head_ref(); |
|
1238 |
||
1239 |
tmp_param->quick_group=1; |
|
1240 |
tmp_param->field_count=temp_fields.elements; |
|
1241 |
tmp_param->group_parts=1; |
|
1242 |
tmp_param->group_length= table->file->ref_length; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1243 |
if (!(tmp_tables[cnt]=create_tmp_table(session, |
1
by brian
clean slate |
1244 |
tmp_param, |
1245 |
temp_fields, |
|
327.2.3
by Brian Aker
Refactoring of class Table |
1246 |
(order_st*) &group, 0, 0, |
1
by brian
clean slate |
1247 |
TMP_TABLE_ALL_COLUMNS, |
1248 |
HA_POS_ERROR, |
|
1249 |
(char *) ""))) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1250 |
return(1); |
1
by brian
clean slate |
1251 |
tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE); |
1252 |
}
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1253 |
return(0); |
1
by brian
clean slate |
1254 |
}
|
1255 |
||
1256 |
||
1257 |
multi_update::~multi_update() |
|
1258 |
{
|
|
327.2.4
by Brian Aker
Refactoring table.h |
1259 |
TableList *table; |
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1260 |
for (list<TableList*>::iterator it= update_tables.begin(); |
1261 |
it != update_tables.end(); |
|
1262 |
++it) |
|
1
by brian
clean slate |
1263 |
{
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1264 |
table= *it; |
1
by brian
clean slate |
1265 |
table->table->no_keyread= table->table->no_cache= 0; |
1266 |
if (ignore) |
|
1267 |
table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); |
|
1268 |
}
|
|
1269 |
||
1270 |
if (tmp_tables) |
|
1271 |
{
|
|
482
by Brian Aker
Remove uint. |
1272 |
for (uint32_t cnt = 0; cnt < table_count; cnt++) |
1
by brian
clean slate |
1273 |
{
|
1274 |
if (tmp_tables[cnt]) |
|
1275 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1276 |
tmp_tables[cnt]->free_tmp_table(session); |
1
by brian
clean slate |
1277 |
tmp_table_param[cnt].cleanup(); |
1278 |
}
|
|
1279 |
}
|
|
1280 |
}
|
|
1281 |
if (copy_field) |
|
1282 |
delete [] copy_field; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1283 |
session->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting |
77.1.45
by Monty Taylor
Warning fixes. |
1284 |
assert(trans_safe || !updated || |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1285 |
session->transaction.all.modified_non_trans_table); |
1
by brian
clean slate |
1286 |
}
|
1287 |
||
1288 |
||
575.1.2
by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead. |
1289 |
bool multi_update::send_data(List<Item> &) |
1
by brian
clean slate |
1290 |
{
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1291 |
for (list<TableList*>::iterator it= update_tables.begin(); |
1292 |
it != update_tables.end(); |
|
1293 |
++it) |
|
1
by brian
clean slate |
1294 |
{
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1295 |
Table *table= (*it)->table; |
1296 |
uint32_t offset= (*it)->shared; |
|
1
by brian
clean slate |
1297 |
/*
|
1298 |
Check if we are using outer join and we didn't find the row
|
|
1299 |
or if we have already updated this row in the previous call to this
|
|
1300 |
function.
|
|
1301 |
||
1302 |
The same row may be presented here several times in a join of type
|
|
1303 |
UPDATE t1 FROM t1,t2 SET t1.a=t2.a
|
|
1304 |
||
1305 |
In this case we will do the update for the first found row combination.
|
|
1306 |
The join algorithm guarantees that we will not find the a row in
|
|
1307 |
t1 several times.
|
|
1308 |
*/
|
|
1309 |
if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED)) |
|
1310 |
continue; |
|
1311 |
||
1312 |
/*
|
|
1313 |
We can use compare_record() to optimize away updates if
|
|
1314 |
the table handler is returning all columns OR if
|
|
1315 |
if all updated columns are read
|
|
1316 |
*/
|
|
1317 |
if (table == table_to_update) |
|
1318 |
{
|
|
1319 |
bool can_compare_record; |
|
1320 |
can_compare_record= (!(table->file->ha_table_flags() & |
|
1321 |
HA_PARTIAL_COLUMN_READ) || |
|
1005.2.3
by Monty Taylor
Further reversion of P. |
1322 |
bitmap_is_subset(table->write_set, |
1323 |
table->read_set)); |
|
1
by brian
clean slate |
1324 |
table->status|= STATUS_UPDATED; |
997.5.1
by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record |
1325 |
table->storeRecord(); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1326 |
if (fill_record(session, *fields_for_table[offset], |
1
by brian
clean slate |
1327 |
*values_for_table[offset], 0)) |
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1328 |
return(1); |
1
by brian
clean slate |
1329 |
|
1330 |
found++; |
|
355
by Brian Aker
More Table cleanup |
1331 |
if (!can_compare_record || table->compare_record()) |
1
by brian
clean slate |
1332 |
{
|
1333 |
int error; |
|
1334 |
if (!updated++) |
|
1335 |
{
|
|
1336 |
/*
|
|
1337 |
Inform the main table that we are going to update the table even
|
|
1338 |
while we may be scanning it. This will flush the read cache
|
|
1339 |
if it's used.
|
|
1340 |
*/
|
|
1341 |
main_table->file->extra(HA_EXTRA_PREPARE_FOR_UPDATE); |
|
1342 |
}
|
|
1343 |
if ((error=table->file->ha_update_row(table->record[1], |
|
1344 |
table->record[0])) && |
|
1345 |
error != HA_ERR_RECORD_IS_THE_SAME) |
|
1346 |
{
|
|
1347 |
updated--; |
|
1348 |
if (!ignore || |
|
1349 |
table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) |
|
1350 |
{
|
|
1351 |
/*
|
|
1352 |
If (ignore && error == is ignorable) we don't have to
|
|
1353 |
do anything; otherwise...
|
|
1354 |
*/
|
|
1355 |
myf flags= 0; |
|
1356 |
||
1357 |
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) |
|
1358 |
flags|= ME_FATALERROR; /* Other handler errors are fatal */ |
|
1359 |
||
1360 |
prepare_record_for_error_message(error, table); |
|
1361 |
table->file->print_error(error,MYF(flags)); |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1362 |
return(1); |
1
by brian
clean slate |
1363 |
}
|
1364 |
}
|
|
1365 |
else
|
|
1366 |
{
|
|
1367 |
if (error == HA_ERR_RECORD_IS_THE_SAME) |
|
1368 |
{
|
|
1369 |
error= 0; |
|
1370 |
updated--; |
|
1371 |
}
|
|
1372 |
/* non-transactional or transactional table got modified */
|
|
1373 |
/* either multi_update class' flag is raised in its branch */
|
|
1374 |
if (table->file->has_transactions()) |
|
1375 |
transactional_tables= 1; |
|
1376 |
else
|
|
1377 |
{
|
|
1378 |
trans_safe= 0; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1379 |
session->transaction.stmt.modified_non_trans_table= true; |
1
by brian
clean slate |
1380 |
}
|
1381 |
}
|
|
1382 |
}
|
|
1383 |
}
|
|
1384 |
else
|
|
1385 |
{
|
|
1386 |
int error; |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1387 |
Table *tmp_table= tmp_tables[offset]; |
1
by brian
clean slate |
1388 |
/*
|
1389 |
For updatable VIEW store rowid of the updated table and
|
|
1390 |
rowids of tables used in the CHECK OPTION condition.
|
|
1391 |
*/
|
|
482
by Brian Aker
Remove uint. |
1392 |
uint32_t field_num= 0; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1393 |
List_iterator_fast<Table> tbl_it(unupdated_check_opt_tables); |
1394 |
Table *tbl= table; |
|
1
by brian
clean slate |
1395 |
do
|
1396 |
{
|
|
1397 |
tbl->file->position(tbl->record[0]); |
|
629.3.7
by Kristian Nielsen
Remove last trace of Field_string. |
1398 |
Field_varstring *ref_field= |
1399 |
reinterpret_cast<Field_varstring *>(tmp_table->field[field_num]); |
|
1400 |
ref_field->store((char *)tbl->file->ref, tbl->file->ref_length, |
|
1401 |
&my_charset_bin); |
|
1
by brian
clean slate |
1402 |
field_num++; |
1403 |
} while ((tbl= tbl_it++)); |
|
1404 |
||
1405 |
/* Store regular updated fields in the row. */
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1406 |
fill_record(session, |
1
by brian
clean slate |
1407 |
tmp_table->field + 1 + unupdated_check_opt_tables.elements, |
1408 |
*values_for_table[offset], 1); |
|
1409 |
||
1410 |
/* Write row, ignoring duplicated updates to a row */
|
|
1411 |
error= tmp_table->file->ha_write_row(tmp_table->record[0]); |
|
1412 |
if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) |
|
1413 |
{
|
|
1414 |
if (error && |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1415 |
create_myisam_from_heap(session, tmp_table, |
1
by brian
clean slate |
1416 |
tmp_table_param[offset].start_recinfo, |
1417 |
&tmp_table_param[offset].recinfo, |
|
1418 |
error, 1)) |
|
1419 |
{
|
|
1420 |
do_update=0; |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1421 |
return(1); // Not a table_is_full error |
1
by brian
clean slate |
1422 |
}
|
1423 |
found++; |
|
1424 |
}
|
|
1425 |
}
|
|
1426 |
}
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1427 |
return(0); |
1
by brian
clean slate |
1428 |
}
|
1429 |
||
1430 |
||
482
by Brian Aker
Remove uint. |
1431 |
void multi_update::send_error(uint32_t errcode,const char *err) |
1
by brian
clean slate |
1432 |
{
|
1433 |
/* First send error what ever it is ... */
|
|
1434 |
my_error(errcode, MYF(0), err); |
|
1435 |
}
|
|
1436 |
||
1437 |
||
1438 |
void multi_update::abort() |
|
1439 |
{
|
|
1440 |
/* the error was handled or nothing deleted and no side effects return */
|
|
1441 |
if (error_handled || |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1442 |
(!session->transaction.stmt.modified_non_trans_table && !updated)) |
1
by brian
clean slate |
1443 |
return; |
1444 |
/*
|
|
1445 |
If all tables that has been updated are trans safe then just do rollback.
|
|
1446 |
If not attempt to do remaining updates.
|
|
1447 |
*/
|
|
1448 |
||
1449 |
if (! trans_safe) |
|
1450 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1451 |
assert(session->transaction.stmt.modified_non_trans_table); |
1
by brian
clean slate |
1452 |
if (do_update && table_count > 1) |
1453 |
{
|
|
1454 |
/* Add warning here */
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1455 |
/*
|
1
by brian
clean slate |
1456 |
todo/fixme: do_update() is never called with the arg 1.
|
1457 |
should it change the signature to become argless?
|
|
1458 |
*/
|
|
398.1.10
by Monty Taylor
Actually removed VOID() this time. |
1459 |
do_updates(); |
1
by brian
clean slate |
1460 |
}
|
1461 |
}
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1462 |
if (session->transaction.stmt.modified_non_trans_table) |
1
by brian
clean slate |
1463 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1464 |
session->transaction.all.modified_non_trans_table= true; |
1
by brian
clean slate |
1465 |
}
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1466 |
assert(trans_safe || !updated || session->transaction.stmt.modified_non_trans_table); |
1
by brian
clean slate |
1467 |
}
|
1468 |
||
1469 |
||
1470 |
int multi_update::do_updates() |
|
1471 |
{
|
|
327.2.4
by Brian Aker
Refactoring table.h |
1472 |
TableList *cur_table; |
1
by brian
clean slate |
1473 |
int local_error= 0; |
1474 |
ha_rows org_updated; |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1475 |
Table *table, *tmp_table; |
1476 |
List_iterator_fast<Table> check_opt_it(unupdated_check_opt_tables); |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1477 |
|
1
by brian
clean slate |
1478 |
do_update= 0; // Don't retry this function |
1479 |
if (!found) |
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1480 |
return(0); |
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1481 |
for (list<TableList*>::iterator it= update_tables.begin(); |
1482 |
it != update_tables.end(); |
|
1483 |
++it) |
|
1
by brian
clean slate |
1484 |
{
|
997.4.1
by Padraig O'Sullivan
Removed 1 instance of SQL_LIST from the source base. Replaced it with |
1485 |
cur_table= *it; |
1
by brian
clean slate |
1486 |
bool can_compare_record; |
482
by Brian Aker
Remove uint. |
1487 |
uint32_t offset= cur_table->shared; |
1
by brian
clean slate |
1488 |
|
1489 |
table = cur_table->table; |
|
1490 |
if (table == table_to_update) |
|
1491 |
continue; // Already updated |
|
1492 |
org_updated= updated; |
|
1493 |
tmp_table= tmp_tables[cur_table->shared]; |
|
1494 |
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache |
|
1495 |
(void) table->file->ha_rnd_init(0); |
|
1496 |
table->file->extra(HA_EXTRA_NO_CACHE); |
|
1497 |
||
1498 |
check_opt_it.rewind(); |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1499 |
while(Table *tbl= check_opt_it++) |
1
by brian
clean slate |
1500 |
{
|
1501 |
if (tbl->file->ha_rnd_init(1)) |
|
1502 |
goto err; |
|
1503 |
tbl->file->extra(HA_EXTRA_CACHE); |
|
1504 |
}
|
|
1505 |
||
1506 |
/*
|
|
1507 |
Setup copy functions to copy fields from temporary table
|
|
1508 |
*/
|
|
1509 |
List_iterator_fast<Item> field_it(*fields_for_table[offset]); |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1510 |
Field **field= tmp_table->field + |
1
by brian
clean slate |
1511 |
1 + unupdated_check_opt_tables.elements; // Skip row pointers |
1512 |
Copy_field *copy_field_ptr= copy_field, *copy_field_end; |
|
1513 |
for ( ; *field ; field++) |
|
1514 |
{
|
|
1515 |
Item_field *item= (Item_field* ) field_it++; |
|
1516 |
(copy_field_ptr++)->set(item->field, *field, 0); |
|
1517 |
}
|
|
1518 |
copy_field_end=copy_field_ptr; |
|
1519 |
||
1520 |
if ((local_error = tmp_table->file->ha_rnd_init(1))) |
|
1521 |
goto err; |
|
1522 |
||
1523 |
can_compare_record= (!(table->file->ha_table_flags() & |
|
1524 |
HA_PARTIAL_COLUMN_READ) || |
|
1005.2.3
by Monty Taylor
Further reversion of P. |
1525 |
bitmap_is_subset(table->write_set, |
1526 |
table->read_set)); |
|
1
by brian
clean slate |
1527 |
|
1528 |
for (;;) |
|
1529 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1530 |
if (session->killed && trans_safe) |
1
by brian
clean slate |
1531 |
goto err; |
1532 |
if ((local_error=tmp_table->file->rnd_next(tmp_table->record[0]))) |
|
1533 |
{
|
|
1534 |
if (local_error == HA_ERR_END_OF_FILE) |
|
1535 |
break; |
|
1536 |
if (local_error == HA_ERR_RECORD_DELETED) |
|
1537 |
continue; // May happen on dup key |
|
1538 |
goto err; |
|
1539 |
}
|
|
1540 |
||
1541 |
/* call rnd_pos() using rowids from temporary table */
|
|
1542 |
check_opt_it.rewind(); |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1543 |
Table *tbl= table; |
482
by Brian Aker
Remove uint. |
1544 |
uint32_t field_num= 0; |
1
by brian
clean slate |
1545 |
do
|
1546 |
{
|
|
629.3.7
by Kristian Nielsen
Remove last trace of Field_string. |
1547 |
Field_varstring *ref_field= |
1548 |
reinterpret_cast<Field_varstring *>(tmp_table->field[field_num]); |
|
1
by brian
clean slate |
1549 |
if((local_error= |
1550 |
tbl->file->rnd_pos(tbl->record[0], |
|
629.3.7
by Kristian Nielsen
Remove last trace of Field_string. |
1551 |
(unsigned char *) ref_field->ptr |
1552 |
+ ref_field->length_bytes))) |
|
1
by brian
clean slate |
1553 |
goto err; |
1554 |
field_num++; |
|
1555 |
} while((tbl= check_opt_it++)); |
|
1556 |
||
1557 |
table->status|= STATUS_UPDATED; |
|
997.5.1
by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record |
1558 |
table->storeRecord(); |
1
by brian
clean slate |
1559 |
|
1560 |
/* Copy data from temporary table to current table */
|
|
1561 |
for (copy_field_ptr=copy_field; |
|
1562 |
copy_field_ptr != copy_field_end; |
|
1563 |
copy_field_ptr++) |
|
1564 |
(*copy_field_ptr->do_copy)(copy_field_ptr); |
|
1565 |
||
355
by Brian Aker
More Table cleanup |
1566 |
if (!can_compare_record || table->compare_record()) |
1
by brian
clean slate |
1567 |
{
|
1568 |
if ((local_error=table->file->ha_update_row(table->record[1], |
|
1569 |
table->record[0])) && |
|
1570 |
local_error != HA_ERR_RECORD_IS_THE_SAME) |
|
1571 |
{
|
|
1572 |
if (!ignore || |
|
1573 |
table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY)) |
|
1574 |
goto err; |
|
1575 |
}
|
|
1576 |
if (local_error != HA_ERR_RECORD_IS_THE_SAME) |
|
1577 |
updated++; |
|
1578 |
else
|
|
1579 |
local_error= 0; |
|
1580 |
}
|
|
1581 |
}
|
|
1582 |
||
1583 |
if (updated != org_updated) |
|
1584 |
{
|
|
1585 |
if (table->file->has_transactions()) |
|
1586 |
transactional_tables= 1; |
|
1587 |
else
|
|
1588 |
{
|
|
1589 |
trans_safe= 0; // Can't do safe rollback |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1590 |
session->transaction.stmt.modified_non_trans_table= true; |
1
by brian
clean slate |
1591 |
}
|
1592 |
}
|
|
1593 |
(void) table->file->ha_rnd_end(); |
|
1594 |
(void) tmp_table->file->ha_rnd_end(); |
|
1595 |
check_opt_it.rewind(); |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1596 |
while (Table *tbl= check_opt_it++) |
1
by brian
clean slate |
1597 |
tbl->file->ha_rnd_end(); |
1598 |
}
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1599 |
return(0); |
1
by brian
clean slate |
1600 |
|
1601 |
err: |
|
1602 |
{
|
|
1603 |
prepare_record_for_error_message(local_error, table); |
|
1604 |
table->file->print_error(local_error,MYF(ME_FATALERROR)); |
|
1605 |
}
|
|
1606 |
||
1607 |
(void) table->file->ha_rnd_end(); |
|
1608 |
(void) tmp_table->file->ha_rnd_end(); |
|
1609 |
check_opt_it.rewind(); |
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
1610 |
while (Table *tbl= check_opt_it++) |
1
by brian
clean slate |
1611 |
tbl->file->ha_rnd_end(); |
1612 |
||
1613 |
if (updated != org_updated) |
|
1614 |
{
|
|
1615 |
if (table->file->has_transactions()) |
|
1616 |
transactional_tables= 1; |
|
1617 |
else
|
|
1618 |
{
|
|
1619 |
trans_safe= 0; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1620 |
session->transaction.stmt.modified_non_trans_table= true; |
1
by brian
clean slate |
1621 |
}
|
1622 |
}
|
|
51.2.2
by Patrick Galbraith
Removed DBUGs from |
1623 |
return(1); |
1
by brian
clean slate |
1624 |
}
|
1625 |
||
1626 |
||
1627 |
/* out: 1 if error, 0 if success */
|
|
1628 |
||
1629 |
bool multi_update::send_eof() |
|
1630 |
{
|
|
1631 |
char buff[STRING_BUFFER_USUAL_SIZE]; |
|
151
by Brian Aker
Ulonglong to uint64_t |
1632 |
uint64_t id; |
520.1.21
by Brian Aker
THD -> Session rename |
1633 |
Session::killed_state killed_status= Session::NOT_KILLED; |
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1634 |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1635 |
session->set_proc_info("updating reference tables"); |
1
by brian
clean slate |
1636 |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1637 |
/*
|
1
by brian
clean slate |
1638 |
Does updates for the last n - 1 tables, returns 0 if ok;
|
1639 |
error takes into account killed status gained in do_updates()
|
|
1640 |
*/
|
|
1641 |
int local_error = (table_count) ? do_updates() : 0; |
|
1642 |
/*
|
|
1643 |
if local_error is not set ON until after do_updates() then
|
|
1644 |
later carried out killing should not affect binlogging.
|
|
1645 |
*/
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1646 |
killed_status= (local_error == 0)? Session::NOT_KILLED : session->killed; |
1647 |
session->set_proc_info("end"); |
|
1
by brian
clean slate |
1648 |
|
1649 |
/*
|
|
1650 |
Write the SQL statement to the binlog if we updated
|
|
1651 |
rows and we succeeded or if we updated some non
|
|
1652 |
transactional tables.
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1653 |
|
1
by brian
clean slate |
1654 |
The query has to binlog because there's a modified non-transactional table
|
1655 |
either from the query's list or via a stored routine: bug#13270,23333
|
|
1656 |
*/
|
|
1657 |
||
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
1658 |
assert(trans_safe || !updated || |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1659 |
session->transaction.stmt.modified_non_trans_table); |
1660 |
if (local_error == 0 || session->transaction.stmt.modified_non_trans_table) |
|
1
by brian
clean slate |
1661 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1662 |
if (session->transaction.stmt.modified_non_trans_table) |
1663 |
session->transaction.all.modified_non_trans_table= true; |
|
1
by brian
clean slate |
1664 |
}
|
1665 |
if (local_error != 0) |
|
56
by brian
Next pass of true/false update. |
1666 |
error_handled= true; // to force early leave from ::send_error() |
1
by brian
clean slate |
1667 |
|
1668 |
if (local_error > 0) // if the above log write did not fail ... |
|
1669 |
{
|
|
1670 |
/* Safety: If we haven't got an error before (can happen in do_updates) */
|
|
1671 |
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update", |
|
1672 |
MYF(0)); |
|
836
by Brian Aker
Fixed session call from function to method. |
1673 |
return true; |
1
by brian
clean slate |
1674 |
}
|
1675 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1676 |
id= session->arg_of_last_insert_id_function ? |
1677 |
session->first_successful_insert_id_in_prev_stmt : 0; |
|
1
by brian
clean slate |
1678 |
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1679 |
(ulong) session->cuted_fields); |
1680 |
session->row_count_func= |
|
1681 |
(session->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; |
|
836
by Brian Aker
Fixed session call from function to method. |
1682 |
session->my_ok((ulong) session->row_count_func, id, buff); |
1683 |
||
1684 |
return false; |
|
1
by brian
clean slate |
1685 |
}
|