00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include <config.h>
00027 #include <fcntl.h>
00028 #include <drizzled/error.h>
00029 #include <drizzled/field/epoch.h>
00030 #include <drizzled/gettext.h>
00031 #include <drizzled/internal/my_sys.h>
00032 #include <drizzled/item/empty_string.h>
00033 #include <drizzled/item/int.h>
00034 #include <drizzled/lock.h>
00035 #include <drizzled/message/table.h>
00036 #include <drizzled/optimizer/cost_vector.h>
00037 #include <drizzled/plugin/client.h>
00038 #include <drizzled/plugin/event_observer.h>
00039 #include <drizzled/plugin/storage_engine.h>
00040 #include <drizzled/probes.h>
00041 #include <drizzled/session.h>
00042 #include <drizzled/sql_base.h>
00043 #include <drizzled/sql_parse.h>
00044 #include <drizzled/transaction_services.h>
00045 #include <drizzled/key.h>
00046 #include <drizzled/sql_lex.h>
00047 #include <drizzled/resource_context.h>
00048 #include <drizzled/statistics_variables.h>
00049 #include <drizzled/system_variables.h>
00050
00051 using namespace std;
00052
00053 namespace drizzled {
00054
00055
00056
00057
00058 Cursor::Cursor(plugin::StorageEngine &engine_arg,
00059 Table &arg)
00060 : table(arg),
00061 engine(engine_arg),
00062 estimation_rows_to_insert(0),
00063 ref(0),
00064 key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
00065 ref_length(sizeof(internal::my_off_t)),
00066 inited(NONE),
00067 locked(false),
00068 next_insert_id(0), insert_id_for_cur_row(0)
00069 { }
00070
00071 Cursor::~Cursor()
00072 {
00073 assert(not locked);
00074
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 Cursor *Cursor::clone(memory::Root *mem_root)
00084 {
00085 Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
00086
00087
00088
00089
00090
00091 new_handler->ref= mem_root->alloc(ALIGN_SIZE(ref_length)*2);
00092 identifier::Table identifier(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName(), getTable()->getShare()->getType());
00093 return new_handler->ha_open(identifier, getTable()->getDBStat(), HA_OPEN_IGNORE_IF_LOCKED) ? NULL : new_handler;
00094 }
00095
00096
00097
00098
00099
00100
00101 uint32_t Cursor::calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg)
00102 {
00103
00104 assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
00105
00106 const KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
00107 const KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
00108 uint32_t length= 0;
00109
00110 while (key_part_found < end_key_part_found && keypart_map_arg)
00111 {
00112 length+= key_part_found->store_length;
00113 keypart_map_arg >>= 1;
00114 key_part_found++;
00115 }
00116 return length;
00117 }
00118
00119 int Cursor::startIndexScan(uint32_t idx, bool sorted)
00120 {
00121 int result;
00122 assert(inited == NONE);
00123 if (!(result= doStartIndexScan(idx, sorted)))
00124 inited=INDEX;
00125 end_range= NULL;
00126 return result;
00127 }
00128
00129 int Cursor::endIndexScan()
00130 {
00131 assert(inited==INDEX);
00132 inited=NONE;
00133 end_range= NULL;
00134 return(doEndIndexScan());
00135 }
00136
00137 int Cursor::startTableScan(bool scan)
00138 {
00139 int result;
00140 assert(inited==NONE || (inited==RND && scan));
00141 inited= (result= doStartTableScan(scan)) ? NONE: RND;
00142
00143 return result;
00144 }
00145
00146 int Cursor::endTableScan()
00147 {
00148 assert(inited==RND);
00149 inited=NONE;
00150 return(doEndTableScan());
00151 }
00152
00153 int Cursor::ha_index_or_rnd_end()
00154 {
00155 return inited == INDEX ? endIndexScan() : inited == RND ? endTableScan() : 0;
00156 }
00157
00158 void Cursor::ha_start_bulk_insert(ha_rows rows)
00159 {
00160 estimation_rows_to_insert= rows;
00161 start_bulk_insert(rows);
00162 }
00163
00164 int Cursor::ha_end_bulk_insert()
00165 {
00166 estimation_rows_to_insert= 0;
00167 return end_bulk_insert();
00168 }
00169
00170 const key_map *Cursor::keys_to_use_for_scanning()
00171 {
00172 return &key_map_empty;
00173 }
00174
00175 bool Cursor::has_transactions()
00176 {
00177 return (getTable()->getShare()->db_type()->check_flag(HTON_BIT_DOES_TRANSACTIONS));
00178 }
00179
00180 void Cursor::ha_statistic_increment(uint64_t system_status_var::*offset) const
00181 {
00182 (getTable()->in_use->status_var.*offset)++;
00183 }
00184
00185 void **Cursor::ha_data(Session *session) const
00186 {
00187 return session->getEngineData(getEngine());
00188 }
00189
00190 bool Cursor::is_fatal_error(int error, uint32_t flags)
00191 {
00192 if (!error ||
00193 ((flags & HA_CHECK_DUP_KEY) &&
00194 (error == HA_ERR_FOUND_DUPP_KEY ||
00195 error == HA_ERR_FOUND_DUPP_UNIQUE)))
00196 return false;
00197 return true;
00198 }
00199
00200
00201 ha_rows Cursor::records() { return stats.records; }
00202 uint64_t Cursor::tableSize() { return stats.index_file_length + stats.data_file_length; }
00203 uint64_t Cursor::rowSize() { return getTable()->getRecordLength() + getTable()->sizeFields(); }
00204
00205 int Cursor::doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked)
00206 {
00207 return open(identifier.getPath().c_str(), mode, test_if_locked);
00208 }
00209
00216 int Cursor::ha_open(const identifier::Table &identifier,
00217 int mode,
00218 int test_if_locked)
00219 {
00220 int error;
00221
00222 if ((error= doOpen(identifier, mode, test_if_locked)))
00223 {
00224 if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
00225 (getTable()->db_stat & HA_TRY_READ_ONLY))
00226 {
00227 getTable()->db_stat|=HA_READ_ONLY;
00228 error= doOpen(identifier, O_RDONLY,test_if_locked);
00229 }
00230 }
00231 if (error)
00232 {
00233 errno= error;
00234 }
00235 else
00236 {
00237 if (getTable()->getShare()->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
00238 getTable()->db_stat|=HA_READ_ONLY;
00239 (void) extra(HA_EXTRA_NO_READCHECK);
00240
00241
00242 if (!ref)
00243 ref= getTable()->alloc(ALIGN_SIZE(ref_length)*2);
00244 dup_ref=ref+ALIGN_SIZE(ref_length);
00245 }
00246 return error;
00247 }
00248
00255 int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
00256 {
00257 int error;
00258
00259 ha_statistic_increment(&system_status_var::ha_read_first_count);
00260
00261
00262
00263
00264
00265
00266 if (stats.deleted < 10 || primary_key >= MAX_KEY ||
00267 !(getTable()->index_flags(primary_key) & HA_READ_ORDER))
00268 {
00269 error= startTableScan(1);
00270 if (error == 0)
00271 {
00272 while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
00273 (void) endTableScan();
00274 }
00275 }
00276 else
00277 {
00278
00279 error= startIndexScan(primary_key, 0);
00280 if (error == 0)
00281 {
00282 error=index_first(buf);
00283 (void) endIndexScan();
00284 }
00285 }
00286 return error;
00287 }
00288
00300 inline uint64_t
00301 compute_next_insert_id(uint64_t nr, drizzle_system_variables *variables)
00302 {
00303 if (variables->auto_increment_increment == 1)
00304 return (nr+1);
00305 nr= (((nr+ variables->auto_increment_increment -
00306 variables->auto_increment_offset)) /
00307 (uint64_t) variables->auto_increment_increment);
00308 return (nr* (uint64_t) variables->auto_increment_increment +
00309 variables->auto_increment_offset);
00310 }
00311
00312
00313 void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
00314 {
00315
00316
00317
00318
00319
00320 if ((next_insert_id > 0) && (nr >= next_insert_id))
00321 set_next_insert_id(compute_next_insert_id(nr, &getTable()->in_use->variables));
00322 }
00323
00324
00340 inline uint64_t
00341 prev_insert_id(uint64_t nr, drizzle_system_variables *variables)
00342 {
00343 if (unlikely(nr < variables->auto_increment_offset))
00344 {
00345
00346
00347
00348
00349
00350 return nr;
00351 }
00352 if (variables->auto_increment_increment == 1)
00353 return nr;
00354 nr= (((nr - variables->auto_increment_offset)) /
00355 (uint64_t) variables->auto_increment_increment);
00356 return (nr * (uint64_t) variables->auto_increment_increment +
00357 variables->auto_increment_offset);
00358 }
00359
00360
00430 #define AUTO_INC_DEFAULT_NB_ROWS 1 // Some prefer 1024 here
00431 #define AUTO_INC_DEFAULT_NB_MAX_BITS 16
00432 #define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
00433
00434 int Cursor::update_auto_increment()
00435 {
00436 uint64_t nr, nb_reserved_values;
00437 bool append= false;
00438 Session *session= getTable()->in_use;
00439 drizzle_system_variables *variables= &session->variables;
00440
00441
00442
00443
00444
00445 assert(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
00446
00447
00448
00449
00450
00451 if ((nr= getTable()->next_number_field->val_int()) != 0
00452 || getTable()->auto_increment_field_not_null)
00453 {
00454
00455
00456
00457
00458
00459
00460 adjust_next_insert_id_after_explicit_value(nr);
00461 insert_id_for_cur_row= 0;
00462
00463 return 0;
00464 }
00465
00466 if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
00467 {
00468 {
00469
00470
00471
00472
00473 uint32_t nb_already_reserved_intervals= 0;
00474 uint64_t nb_desired_values;
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 if (nb_already_reserved_intervals == 0 &&
00487 (estimation_rows_to_insert > 0))
00488 nb_desired_values= estimation_rows_to_insert;
00489 else
00490 {
00491
00492 if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
00493 {
00494 nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
00495 (1 << nb_already_reserved_intervals);
00496 set_if_smaller(nb_desired_values, (uint64_t)AUTO_INC_DEFAULT_NB_MAX);
00497 }
00498 else
00499 nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
00500 }
00501
00502 get_auto_increment(variables->auto_increment_offset,
00503 variables->auto_increment_increment,
00504 nb_desired_values, &nr,
00505 &nb_reserved_values);
00506 if (nr == ~(uint64_t) 0)
00507 return HA_ERR_AUTOINC_READ_FAILED;
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 nr= compute_next_insert_id(nr-1, variables);
00518 }
00519
00520 if (getTable()->getShare()->next_number_keypart == 0)
00521 {
00522
00523 append= true;
00524 }
00525 }
00526
00527 if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
00528 {
00529
00530
00531
00532 if (session->getKilled() == Session::KILL_BAD_DATA)
00533 return HA_ERR_AUTOINC_ERANGE;
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 nr= prev_insert_id(getTable()->next_number_field->val_int(), variables);
00544 if (unlikely(getTable()->next_number_field->store((int64_t) nr, true)))
00545 nr= getTable()->next_number_field->val_int();
00546 }
00547 if (append)
00548 auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values, variables->auto_increment_increment);
00549
00550
00551
00552
00553
00554
00555
00556
00557 insert_id_for_cur_row= nr;
00558
00559
00560
00561
00562 set_next_insert_id(compute_next_insert_id(nr, variables));
00563
00564 return 0;
00565 }
00566
00567
00584 void Cursor::ha_release_auto_increment()
00585 {
00586 release_auto_increment();
00587 insert_id_for_cur_row= 0;
00588 auto_inc_interval_for_cur_row.replace(0, 0, 0);
00589 next_insert_id= 0;
00590 }
00591
00592 void Cursor::drop_table()
00593 {
00594 close();
00595 }
00596
00597 int Cursor::ha_check(Session*)
00598 {
00599 return HA_ADMIN_OK;
00600 }
00601
00607 inline
00608 void
00609 Cursor::setTransactionReadWrite()
00610 {
00611
00612
00613
00614
00615
00616 if (not getTable()->in_use)
00617 return;
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 ResourceContext& resource_context= getTable()->in_use->getResourceContext(*getEngine());
00628 if (resource_context.isStarted())
00629 resource_context.markModifiedData();
00630 }
00631
00632
00643 int
00644 Cursor::ha_delete_all_rows()
00645 {
00646 setTransactionReadWrite();
00647
00648 int result= delete_all_rows();
00649
00650 if (result == 0)
00651 {
00658 Session& session= *getTable()->in_use;
00659 TransactionServices::truncateTable(session, *getTable());
00660 }
00661
00662 return result;
00663 }
00664
00665
00672 int
00673 Cursor::ha_reset_auto_increment(uint64_t value)
00674 {
00675 setTransactionReadWrite();
00676
00677 return reset_auto_increment(value);
00678 }
00679
00680
00687 int
00688 Cursor::ha_analyze(Session* session)
00689 {
00690 setTransactionReadWrite();
00691
00692 return analyze(session);
00693 }
00694
00701 int
00702 Cursor::ha_disable_indexes(uint32_t mode)
00703 {
00704 setTransactionReadWrite();
00705
00706 return disable_indexes(mode);
00707 }
00708
00709
00716 int
00717 Cursor::ha_enable_indexes(uint32_t mode)
00718 {
00719 setTransactionReadWrite();
00720
00721 return enable_indexes(mode);
00722 }
00723
00724
00731 int Cursor::ha_discard_or_import_tablespace(bool discard)
00732 {
00733 setTransactionReadWrite();
00734 return discard_or_import_tablespace(discard);
00735 }
00736
00743 void Cursor::closeMarkForDelete()
00744 {
00745 setTransactionReadWrite();
00746 return drop_table();
00747 }
00748
00749 int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
00750 {
00751 int error= index_next(buf);
00752 if (error)
00753 return error;
00754
00755 ptrdiff_t ptrdiff= buf - getTable()->getInsertRecord();
00756 unsigned char *save_record_0= NULL;
00757 KeyInfo *key_info= NULL;
00758 KeyPartInfo *key_part;
00759 KeyPartInfo *key_part_end= NULL;
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 if (ptrdiff)
00770 {
00771 save_record_0= getTable()->getInsertRecord();
00772 getTable()->record[0]= buf;
00773 key_info= getTable()->key_info + active_index;
00774 key_part= key_info->key_part;
00775 key_part_end= key_part + key_info->key_parts;
00776 for (; key_part < key_part_end; key_part++)
00777 {
00778 assert(key_part->field);
00779 key_part->field->move_field_offset(ptrdiff);
00780 }
00781 }
00782
00783 if (key_cmp_if_same(getTable(), key, active_index, keylen))
00784 {
00785 getTable()->status=STATUS_NOT_FOUND;
00786 error= HA_ERR_END_OF_FILE;
00787 }
00788
00789
00790 if (ptrdiff)
00791 {
00792 getTable()->record[0]= save_record_0;
00793 for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
00794 key_part->field->move_field_offset(-ptrdiff);
00795 }
00796 return error;
00797 }
00798
00799
00800
00801
00802
00803
00825 double Cursor::index_only_read_time(uint32_t keynr, double key_records)
00826 {
00827 uint32_t keys_per_block= (stats.block_size/2/
00828 (getTable()->key_info[keynr].key_length + ref_length) + 1);
00829 return ((double) (key_records + keys_per_block-1) /
00830 (double) keys_per_block);
00831 }
00832
00833
00834
00835
00836
00837
00869 ha_rows
00870 Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
00871 void *seq_init_param,
00872 uint32_t ,
00873 uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
00874 {
00875 KEY_MULTI_RANGE range;
00876 range_seq_t seq_it;
00877 ha_rows rows, total_rows= 0;
00878 uint32_t n_ranges=0;
00879
00880
00881 *bufsz= 0;
00882
00883 seq_it= seq->init(seq_init_param, n_ranges, *flags);
00884 while (!seq->next(seq_it, &range))
00885 {
00886 n_ranges++;
00887 key_range *min_endp, *max_endp;
00888 {
00889 min_endp= range.start_key.length? &range.start_key : NULL;
00890 max_endp= range.end_key.length? &range.end_key : NULL;
00891 }
00892 if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE))
00893 rows= 1;
00894 else
00895 {
00896 if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
00897 max_endp)))
00898 {
00899
00900 total_rows= HA_POS_ERROR;
00901 break;
00902 }
00903 }
00904 total_rows += rows;
00905 }
00906
00907 if (total_rows != HA_POS_ERROR)
00908 {
00909
00910 *flags |= HA_MRR_USE_DEFAULT_IMPL;
00911 cost->zero();
00912 cost->setAvgIOCost(1);
00913 if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
00914 cost->setIOCount(index_only_read_time(keyno, (uint32_t)total_rows));
00915 else
00916 cost->setIOCount(read_time(keyno, n_ranges, total_rows));
00917 cost->setCpuCost((double) total_rows / TIME_FOR_COMPARE + 0.01);
00918 }
00919 return total_rows;
00920 }
00921
00922
00957 int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
00958 uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost)
00959 {
00960 *bufsz= 0;
00961
00962 *flags |= HA_MRR_USE_DEFAULT_IMPL;
00963
00964 cost->zero();
00965 cost->setAvgIOCost(1);
00966
00967
00968 if (*flags & HA_MRR_INDEX_ONLY)
00969 cost->setIOCount(index_only_read_time(keyno, n_rows));
00970 else
00971 cost->setIOCount(read_time(keyno, n_ranges, n_rows));
00972 return 0;
00973 }
00974
00975
01017 int
01018 Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
01019 uint32_t n_ranges, uint32_t mode)
01020 {
01021 mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
01022 mrr_funcs= *seq_funcs;
01023 mrr_is_output_sorted= test(mode & HA_MRR_SORTED);
01024 mrr_have_range= false;
01025
01026 return 0;
01027 }
01028
01029
01043 int Cursor::multi_range_read_next(char **range_info)
01044 {
01045 int result= 0;
01046 int range_res= 0;
01047
01048 if (not mrr_have_range)
01049 {
01050 mrr_have_range= true;
01051 goto start;
01052 }
01053
01054 do
01055 {
01056
01057 if (mrr_cur_range.range_flag != (UNIQUE_RANGE | EQ_RANGE))
01058 {
01059 result= read_range_next();
01060
01061 if (result != HA_ERR_END_OF_FILE)
01062 break;
01063 }
01064 else
01065 {
01066 if (was_semi_consistent_read())
01067 goto scan_it_again;
01068
01069
01070
01071
01072 result= HA_ERR_END_OF_FILE;
01073 }
01074
01075 start:
01076
01077 while (!(range_res= mrr_funcs.next(mrr_iter, &mrr_cur_range)))
01078 {
01079 scan_it_again:
01080 result= read_range_first(mrr_cur_range.start_key.keypart_map ?
01081 &mrr_cur_range.start_key : 0,
01082 mrr_cur_range.end_key.keypart_map ?
01083 &mrr_cur_range.end_key : 0,
01084 test(mrr_cur_range.range_flag & EQ_RANGE),
01085 mrr_is_output_sorted);
01086 if (result != HA_ERR_END_OF_FILE)
01087 break;
01088 }
01089 }
01090 while ((result == HA_ERR_END_OF_FILE) && !range_res);
01091
01092 *range_info= mrr_cur_range.ptr;
01093 return result;
01094 }
01095
01096
01097
01098
01099
01100
01119 int Cursor::read_range_first(const key_range *start_key,
01120 const key_range *end_key,
01121 bool eq_range_arg,
01122 bool )
01123 {
01124 int result;
01125
01126 eq_range= eq_range_arg;
01127 end_range= 0;
01128 if (end_key)
01129 {
01130 end_range= &save_end_range;
01131 save_end_range= *end_key;
01132 key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
01133 (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
01134 }
01135 range_key_part= getTable()->key_info[active_index].key_part;
01136
01137 if (!start_key)
01138 result= index_first(getTable()->getInsertRecord());
01139 else
01140 result= index_read_map(getTable()->getInsertRecord(),
01141 start_key->key,
01142 start_key->keypart_map,
01143 start_key->flag);
01144 if (result)
01145 return((result == HA_ERR_KEY_NOT_FOUND)
01146 ? HA_ERR_END_OF_FILE
01147 : result);
01148
01149 return (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
01150 }
01151
01152
01166 int Cursor::read_range_next()
01167 {
01168 int result;
01169
01170 if (eq_range)
01171 {
01172
01173 return(index_next_same(getTable()->getInsertRecord(),
01174 end_range->key,
01175 end_range->length));
01176 }
01177 result= index_next(getTable()->getInsertRecord());
01178 if (result)
01179 return result;
01180 return(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
01181 }
01182
01183
01199 int Cursor::compare_key(key_range *range)
01200 {
01201 int cmp;
01202 if (not range)
01203 return 0;
01204 cmp= key_cmp(range_key_part, range->key, range->length);
01205 if (!cmp)
01206 cmp= key_compare_result_on_equal;
01207 return cmp;
01208 }
01209
01210 int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
01211 const unsigned char * key,
01212 key_part_map keypart_map,
01213 enum ha_rkey_function find_flag)
01214 {
01215 int error, error1;
01216 error= doStartIndexScan(index, 0);
01217 if (!error)
01218 {
01219 error= index_read_map(buf, key, keypart_map, find_flag);
01220 error1= doEndIndexScan();
01221 }
01222 return error ? error : error1;
01223 }
01224
01232 static bool log_row_for_replication(Table* table,
01233 const unsigned char *before_record,
01234 const unsigned char *after_record)
01235 {
01236 Session *const session= table->in_use;
01237
01238 if (table->getShare()->getType() || not TransactionServices::shouldConstructMessages())
01239 return false;
01240
01241 bool result= false;
01242
01243 switch (session->lex().sql_command)
01244 {
01245 case SQLCOM_CREATE_TABLE:
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 result= TransactionServices::insertRecord(*session, *table);
01256 break;
01257 case SQLCOM_REPLACE:
01258 case SQLCOM_REPLACE_SELECT:
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 if (after_record == NULL)
01278 {
01279
01280
01281
01282
01283
01284 TransactionServices::deleteRecord(*session, *table, true);
01285
01286
01287
01288
01289
01290 TransactionServices::finalizeStatementMessage(*session->getStatementMessage(), *session);
01291 }
01292 else
01293 {
01294 if (before_record == NULL)
01295 result= TransactionServices::insertRecord(*session, *table);
01296 else
01297 TransactionServices::updateRecord(*session, *table, before_record, after_record);
01298 }
01299 break;
01300 case SQLCOM_INSERT:
01301 case SQLCOM_INSERT_SELECT:
01302 case SQLCOM_LOAD:
01303
01304
01305
01306
01307
01308
01309 if (before_record == NULL)
01310 result= TransactionServices::insertRecord(*session, *table);
01311 else
01312 TransactionServices::updateRecord(*session, *table, before_record, after_record);
01313 break;
01314
01315 case SQLCOM_UPDATE:
01316 TransactionServices::updateRecord(*session, *table, before_record, after_record);
01317 break;
01318
01319 case SQLCOM_DELETE:
01320 TransactionServices::deleteRecord(*session, *table);
01321 break;
01322 default:
01323 break;
01324 }
01325
01326 return result;
01327 }
01328
01329 int Cursor::ha_external_lock(Session *session, int lock_type)
01330 {
01331
01332
01333
01334
01335
01336 assert(next_insert_id == 0);
01337
01338 if (DRIZZLE_CURSOR_RDLOCK_START_ENABLED() ||
01339 DRIZZLE_CURSOR_WRLOCK_START_ENABLED() ||
01340 DRIZZLE_CURSOR_UNLOCK_START_ENABLED())
01341 {
01342 if (lock_type == F_RDLCK)
01343 {
01344 DRIZZLE_CURSOR_RDLOCK_START(getTable()->getShare()->getSchemaName(),
01345 getTable()->getShare()->getTableName());
01346 }
01347 else if (lock_type == F_WRLCK)
01348 {
01349 DRIZZLE_CURSOR_WRLOCK_START(getTable()->getShare()->getSchemaName(),
01350 getTable()->getShare()->getTableName());
01351 }
01352 else if (lock_type == F_UNLCK)
01353 {
01354 DRIZZLE_CURSOR_UNLOCK_START(getTable()->getShare()->getSchemaName(),
01355 getTable()->getShare()->getTableName());
01356 }
01357 }
01358
01359
01360
01361
01362
01363
01364 int error= external_lock(session, lock_type);
01365
01366 if (DRIZZLE_CURSOR_RDLOCK_DONE_ENABLED() ||
01367 DRIZZLE_CURSOR_WRLOCK_DONE_ENABLED() ||
01368 DRIZZLE_CURSOR_UNLOCK_DONE_ENABLED())
01369 {
01370 if (lock_type == F_RDLCK)
01371 {
01372 DRIZZLE_CURSOR_RDLOCK_DONE(error);
01373 }
01374 else if (lock_type == F_WRLCK)
01375 {
01376 DRIZZLE_CURSOR_WRLOCK_DONE(error);
01377 }
01378 else if (lock_type == F_UNLCK)
01379 {
01380 DRIZZLE_CURSOR_UNLOCK_DONE(error);
01381 }
01382 }
01383
01384 return error;
01385 }
01386
01387
01391 int Cursor::ha_reset()
01392 {
01393
01394 assert(! getTable()->getShare()->all_set.none());
01395 assert(getTable()->key_read == 0);
01396
01397 assert(inited == NONE);
01398
01399 getTable()->free_io_cache();
01400
01401 getTable()->default_column_bitmaps();
01402 return(reset());
01403 }
01404
01405
01406 int Cursor::insertRecord(unsigned char *buf)
01407 {
01408 int error;
01409
01410
01411
01412
01413
01414
01415
01416 if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
01417 {
01418 getTable()->timestamp_field->set_time();
01419 }
01420
01421 DRIZZLE_INSERT_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
01422 setTransactionReadWrite();
01423
01424 if (unlikely(plugin::EventObserver::beforeInsertRecord(*getTable(), buf)))
01425 {
01426 error= ER_EVENT_OBSERVER_PLUGIN;
01427 }
01428 else
01429 {
01430 error= doInsertRecord(buf);
01431 if (unlikely(plugin::EventObserver::afterInsertRecord(*getTable(), buf, error)))
01432 {
01433 error= ER_EVENT_OBSERVER_PLUGIN;
01434 }
01435 }
01436
01437 ha_statistic_increment(&system_status_var::ha_write_count);
01438
01439 DRIZZLE_INSERT_ROW_DONE(error);
01440
01441 if (unlikely(error))
01442 {
01443 return error;
01444 }
01445
01446 if (unlikely(log_row_for_replication(getTable(), NULL, buf)))
01447 return HA_ERR_RBR_LOGGING_FAILED;
01448
01449 return 0;
01450 }
01451
01452
01453 int Cursor::updateRecord(const unsigned char *old_data, unsigned char *new_data)
01454 {
01455 int error;
01456
01457
01458
01459
01460
01461 assert(new_data == getTable()->getInsertRecord());
01462
01463 DRIZZLE_UPDATE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
01464 setTransactionReadWrite();
01465 if (unlikely(plugin::EventObserver::beforeUpdateRecord(*getTable(), old_data, new_data)))
01466 {
01467 error= ER_EVENT_OBSERVER_PLUGIN;
01468 }
01469 else
01470 {
01471 if (getTable()->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
01472 {
01473 getTable()->timestamp_field->set_time();
01474 }
01475
01476 error= doUpdateRecord(old_data, new_data);
01477 if (unlikely(plugin::EventObserver::afterUpdateRecord(*getTable(), old_data, new_data, error)))
01478 {
01479 error= ER_EVENT_OBSERVER_PLUGIN;
01480 }
01481 }
01482
01483 ha_statistic_increment(&system_status_var::ha_update_count);
01484
01485 DRIZZLE_UPDATE_ROW_DONE(error);
01486
01487 if (unlikely(error))
01488 {
01489 return error;
01490 }
01491
01492 if (unlikely(log_row_for_replication(getTable(), old_data, new_data)))
01493 return HA_ERR_RBR_LOGGING_FAILED;
01494
01495 return 0;
01496 }
01497 TableShare *Cursor::getShare()
01498 {
01499 return getTable()->getMutableShare();
01500 }
01501
01502 int Cursor::deleteRecord(const unsigned char *buf)
01503 {
01504 int error;
01505
01506 DRIZZLE_DELETE_ROW_START(getTable()->getShare()->getSchemaName(), getTable()->getShare()->getTableName());
01507 setTransactionReadWrite();
01508 if (unlikely(plugin::EventObserver::beforeDeleteRecord(*getTable(), buf)))
01509 {
01510 error= ER_EVENT_OBSERVER_PLUGIN;
01511 }
01512 else
01513 {
01514 error= doDeleteRecord(buf);
01515 if (unlikely(plugin::EventObserver::afterDeleteRecord(*getTable(), buf, error)))
01516 {
01517 error= ER_EVENT_OBSERVER_PLUGIN;
01518 }
01519 }
01520
01521 ha_statistic_increment(&system_status_var::ha_delete_count);
01522
01523 DRIZZLE_DELETE_ROW_DONE(error);
01524
01525 if (unlikely(error))
01526 return error;
01527
01528 if (unlikely(log_row_for_replication(getTable(), buf, NULL)))
01529 return HA_ERR_RBR_LOGGING_FAILED;
01530
01531 return 0;
01532 }
01533
01534 }