00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <drizzled/sql_select.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/probes.h>
00026 #include <drizzled/sql_base.h>
00027 #include <drizzled/field/epoch.h>
00028 #include <drizzled/sql_parse.h>
00029 #include <drizzled/optimizer/range.h>
00030 #include <drizzled/records.h>
00031 #include <drizzled/internal/my_sys.h>
00032 #include <drizzled/internal/iocache.h>
00033 #include <drizzled/transaction_services.h>
00034 #include <drizzled/filesort.h>
00035 #include <drizzled/plugin/storage_engine.h>
00036 #include <drizzled/key.h>
00037 #include <drizzled/sql_lex.h>
00038 #include <drizzled/diagnostics_area.h>
00039 #include <drizzled/util/test.h>
00040 #include <drizzled/statistics_variables.h>
00041 #include <drizzled/session/transactions.h>
00042
00043 #include <boost/dynamic_bitset.hpp>
00044 #include <list>
00045
00046 using namespace std;
00047
00048 namespace drizzled {
00049
00062 static void prepare_record_for_error_message(int error, Table *table)
00063 {
00064 Field **field_p= NULL;
00065 Field *field= NULL;
00066 uint32_t keynr= 0;
00067
00068
00069
00070
00071
00072 if ((error != HA_ERR_FOUND_DUPP_KEY) ||
00073 ! (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)))
00074 return;
00075
00076
00077
00078
00079
00080 if ((keynr= table->get_dup_key(error)) >= MAX_KEY)
00081 return;
00082
00083
00084 boost::dynamic_bitset<> unique_map(table->getShare()->sizeFields());
00085 table->mark_columns_used_by_index_no_reset(keynr, unique_map);
00086
00087
00088 unique_map-= *table->read_set;
00089 unique_map-= *table->write_set;
00090
00091
00092
00093
00094
00095
00096 if (unique_map.none())
00097 return;
00098
00099
00100 table->cursor->position(table->getInsertRecord());
00101
00102 *table->read_set|= unique_map;
00103
00104 (void) table->cursor->rnd_pos(table->getUpdateRecord(), table->cursor->ref);
00105
00106 for (field_p= table->getFields(); (field= *field_p); field_p++)
00107 {
00108 if (unique_map.test(field->position()))
00109 {
00110 field->copy_from_tmp(table->getShare()->rec_buff_length);
00111 }
00112 }
00113
00114 return;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 int update_query(Session *session, TableList *table_list,
00138 List<Item> &fields, List<Item> &values, COND *conds,
00139 uint32_t order_num, Order *order,
00140 ha_rows limit, enum enum_duplicates,
00141 bool ignore)
00142 {
00143 bool using_limit= limit != HA_POS_ERROR;
00144 bool used_key_is_modified;
00145 bool transactional_table;
00146 int error= 0;
00147 uint used_index= MAX_KEY, dup_key_found;
00148 bool need_sort= true;
00149 ha_rows updated, found;
00150 key_map old_covering_keys;
00151 Table *table;
00152 optimizer::SqlSelect *select= NULL;
00153 ReadRecord info;
00154 Select_Lex *select_lex= &session->lex().select_lex;
00155 uint64_t id;
00156 List<Item> all_fields;
00157 Session::killed_state_t killed_status= Session::NOT_KILLED;
00158
00159 DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
00160 if (session->openTablesLock(table_list))
00161 {
00162 DRIZZLE_UPDATE_DONE(1, 0, 0);
00163 return 1;
00164 }
00165
00166 session->set_proc_info("init");
00167 table= table_list->table;
00168
00169
00170 table->covering_keys= table->getShare()->keys_in_use;
00171 table->quick_keys.reset();
00172
00173 if (prepare_update(session, table_list, &conds, order_num, order))
00174 {
00175 DRIZZLE_UPDATE_DONE(1, 0, 0);
00176 return 1;
00177 }
00178
00179 old_covering_keys= table->covering_keys;
00180
00181 if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
00182 {
00183 DRIZZLE_UPDATE_DONE(1, 0, 0);
00184 return 1;
00185 }
00186
00187 if (table->timestamp_field)
00188 {
00189
00190 if (table->timestamp_field->isWriteSet())
00191 {
00192 table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
00193 }
00194 else
00195 {
00196 if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
00197 table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
00198 {
00199 table->setWriteSet(table->timestamp_field->position());
00200 }
00201 }
00202 }
00203
00204 if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
00205 {
00206 free_underlaid_joins(session, select_lex);
00207 DRIZZLE_UPDATE_DONE(1, 0, 0);
00208
00209 return 1;
00210 }
00211
00212 if (select_lex->inner_refs_list.size() &&
00213 fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
00214 {
00215 DRIZZLE_UPDATE_DONE(1, 0, 0);
00216 return 1;
00217 }
00218
00219 if (conds)
00220 {
00221 Item::cond_result cond_value;
00222 conds= remove_eq_conds(session, conds, &cond_value);
00223 if (cond_value == Item::COND_FALSE)
00224 limit= 0;
00225 }
00226
00227
00228
00229
00230
00231
00232 if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) &&
00233 table->timestamp_field &&
00234 (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
00235 table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
00236 {
00237 *table->read_set|= *table->write_set;
00238 }
00239
00240 table->covering_keys.reset();
00241
00242
00243 table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
00244
00245 select= optimizer::make_select(table, 0, 0, conds, 0, &error);
00246 if (error || !limit ||
00247 (select && select->check_quick(session, false, limit)))
00248 {
00249 delete select;
00254 session->main_da().reset_diagnostics_area();
00255 free_underlaid_joins(session, select_lex);
00256 if (error || session->is_error())
00257 {
00258 DRIZZLE_UPDATE_DONE(1, 0, 0);
00259 return 1;
00260 }
00261 DRIZZLE_UPDATE_DONE(0, 0, 0);
00262 session->my_ok();
00263 return 0;
00264 }
00265 if (!select && limit != HA_POS_ERROR)
00266 {
00267 if ((used_index= optimizer::get_index_for_order(table, order, limit)) != MAX_KEY)
00268 need_sort= false;
00269 }
00270
00271 if (table->quick_keys.none())
00272 {
00273 session->server_status|=SERVER_QUERY_NO_INDEX_USED;
00274 }
00275
00276 table->mark_columns_needed_for_update();
00277
00278
00279
00280 if (select && select->quick)
00281 {
00282 used_index= select->quick->index;
00283 used_key_is_modified= (!select->quick->unique_key_range() &&
00284 select->quick->is_keys_used(*table->write_set));
00285 }
00286 else
00287 {
00288 used_key_is_modified= 0;
00289 if (used_index == MAX_KEY)
00290 used_index= table->cursor->key_used_on_scan;
00291 if (used_index != MAX_KEY)
00292 used_key_is_modified= is_key_used(table, used_index, *table->write_set);
00293 }
00294
00295
00296 if (used_key_is_modified || order)
00297 {
00298
00299
00300
00301
00302 if (used_index < MAX_KEY && old_covering_keys.test(used_index))
00303 {
00304 table->key_read=1;
00305 table->mark_columns_used_by_index(used_index);
00306 }
00307 else
00308 {
00309 table->use_all_columns();
00310 }
00311
00312
00313 if (order && (need_sort || used_key_is_modified))
00314 {
00315
00316
00317
00318
00319
00320 uint32_t length= 0;
00321 SortField *sortorder;
00322 ha_rows examined_rows;
00323 FileSort filesort(*session);
00324
00325 table->sort.io_cache= new internal::io_cache_st;
00326 sortorder=make_unireg_sortorder(order, &length, NULL);
00327
00328 if ((table->sort.found_records= filesort.run(table, sortorder, length, select, limit, 1, examined_rows)) == HA_POS_ERROR)
00329 goto err;
00330
00331
00332
00333
00334 safe_delete(select);
00335 }
00336 else
00337 {
00338
00339
00340
00341
00342
00343
00344 internal::io_cache_st tempfile;
00345 if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
00346 {
00347 goto err;
00348 }
00349
00350
00351 if (select && select->quick && select->quick->reset())
00352 goto err;
00353 table->cursor->try_semi_consistent_read(1);
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 if (used_index == MAX_KEY || (select && select->quick))
00367 {
00368 if ((error= info.init_read_record(session, table, select, 0, true)))
00369 goto err;
00370 }
00371 else
00372 {
00373 if ((error= info.init_read_record_idx(session, table, 1, used_index)))
00374 goto err;
00375 }
00376
00377 session->set_proc_info("Searching rows for update");
00378 ha_rows tmp_limit= limit;
00379
00380 while (not(error= info.read_record(&info)) && not session->getKilled())
00381 {
00382 if (!(select && select->skip_record()))
00383 {
00384 if (table->cursor->was_semi_consistent_read())
00385 continue;
00386
00387 table->cursor->position(table->getInsertRecord());
00388 if (tempfile.write(table->cursor->ref, table->cursor->ref_length))
00389 {
00390 error=1;
00391 break;
00392 }
00393 if (!--limit && using_limit)
00394 {
00395 error= -1;
00396 break;
00397 }
00398 }
00399 else
00400 table->cursor->unlock_row();
00401 }
00402 if (session->getKilled() && not error)
00403 error= 1;
00404 limit= tmp_limit;
00405 table->cursor->try_semi_consistent_read(0);
00406 info.end_read_record();
00407
00408
00409 if (select)
00410 {
00411 safe_delete(select->quick);
00412 if (select->free_cond)
00413 delete select->cond;
00414 select->cond=0;
00415 }
00416 else
00417 {
00418 select= new optimizer::SqlSelect();
00419 select->head=table;
00420 }
00421 if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
00422 error=1;
00423
00424 memcpy(select->file, &tempfile, sizeof(tempfile));
00425 if (error >= 0)
00426 goto err;
00427 }
00428 if (table->key_read)
00429 table->restore_column_maps_after_mark_index();
00430 }
00431
00432 if (ignore)
00433 table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
00434
00435 if (select && select->quick && select->quick->reset())
00436 goto err;
00437 table->cursor->try_semi_consistent_read(1);
00438 if ((error= info.init_read_record(session, table, select, 0, true)))
00439 {
00440 goto err;
00441 }
00442
00443 updated= found= 0;
00444
00445
00446
00447
00448
00449
00450
00451
00452 session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00453 session->cuted_fields= 0L;
00454 session->set_proc_info("Updating");
00455
00456 transactional_table= table->cursor->has_transactions();
00457 session->setAbortOnWarning(test(!ignore));
00458
00459
00460
00461
00462
00463 if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ))
00464 table->prepare_for_position();
00465
00466 while (not (error=info.read_record(&info)) && not session->getKilled())
00467 {
00468 if (not (select && select->skip_record()))
00469 {
00470 if (table->cursor->was_semi_consistent_read())
00471 continue;
00472
00473 table->storeRecord();
00474 if (fill_record(session, fields, values))
00475 break;
00476
00477 found++;
00478
00479 if (! table->records_are_comparable() || table->compare_records())
00480 {
00481
00482 error= table->cursor->updateRecord(table->getUpdateRecord(),
00483 table->getInsertRecord());
00484
00485 table->auto_increment_field_not_null= false;
00486
00487 if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
00488 {
00489 if (error != HA_ERR_RECORD_IS_THE_SAME)
00490 updated++;
00491 else
00492 error= 0;
00493 }
00494 else if (! ignore ||
00495 table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
00496 {
00497
00498
00499
00500
00501 myf flags= 0;
00502
00503 if (table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
00504 flags|= ME_FATALERROR;
00505
00506 prepare_record_for_error_message(error, table);
00507 table->print_error(error,MYF(flags));
00508 error= 1;
00509 break;
00510 }
00511 }
00512
00513 if (!--limit && using_limit)
00514 {
00515 error= -1;
00516 break;
00517 }
00518 }
00519 else
00520 table->cursor->unlock_row();
00521 session->row_count++;
00522 }
00523 dup_key_found= 0;
00524
00525
00526
00527
00528
00529
00530
00531
00532 killed_status= session->getKilled();
00533
00534 error= (killed_status == Session::NOT_KILLED)? error : 1;
00535
00536 updated-= dup_key_found;
00537 table->cursor->try_semi_consistent_read(0);
00538
00539 if (!transactional_table && updated > 0)
00540 session->transaction.stmt.markModifiedNonTransData();
00541
00542 info.end_read_record();
00543 delete select;
00544 session->set_proc_info("end");
00545 table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
00557 {
00558 if (session->transaction.stmt.hasModifiedNonTransData())
00559 session->transaction.all.markModifiedNonTransData();
00560 }
00561 assert(transactional_table || !updated || session->transaction.stmt.hasModifiedNonTransData());
00562 free_underlaid_joins(session, select_lex);
00563
00564
00565 id= session->arg_of_last_insert_id_function ?
00566 session->first_successful_insert_id_in_prev_stmt : 0;
00567
00568 if (error < 0)
00569 {
00570 char buff[STRING_BUFFER_USUAL_SIZE];
00571 snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
00572 (ulong) session->cuted_fields);
00573 session->row_count_func= updated;
00578 session->main_da().reset_diagnostics_area();
00579 session->my_ok((ulong) session->rowCount(), found, id, buff);
00580 session->status_var.updated_row_count+= session->rowCount();
00581 }
00582 session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00583 session->setAbortOnWarning(false);
00584 DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
00585 return ((error >= 0 || session->is_error()) ? 1 : 0);
00586
00587 err:
00588 if (error != 0)
00589 table->print_error(error,MYF(0));
00590
00591 delete select;
00592 free_underlaid_joins(session, select_lex);
00593 if (table->key_read)
00594 {
00595 table->key_read=0;
00596 table->cursor->extra(HA_EXTRA_NO_KEYREAD);
00597 }
00598 session->setAbortOnWarning(false);
00599
00600 DRIZZLE_UPDATE_DONE(1, 0, 0);
00601 return 1;
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 bool prepare_update(Session *session, TableList *table_list,
00620 Item **conds, uint32_t order_num, Order *order)
00621 {
00622 List<Item> all_fields;
00623 Select_Lex *select_lex= &session->lex().select_lex;
00624
00625 session->lex().allow_sum_func= 0;
00626
00627 if (setup_tables_and_check_access(session, &select_lex->context, &select_lex->top_join_list, table_list, &select_lex->leaf_tables, false) ||
00628 session->setup_conds(table_list, conds))
00629 return true;
00630 select_lex->setup_ref_array(session, order_num);
00631 if (setup_order(session, select_lex->ref_pointer_array, table_list, all_fields, all_fields, order))
00632 return true;
00633
00634
00635 if (unique_table(table_list, table_list->next_global))
00636 {
00637 my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
00638 return true;
00639 }
00640
00641 return false;
00642 }
00643
00644 }