#include "univ.i"#include "data0data.h"#include "que0types.h"#include "dict0types.h"#include "trx0types.h"#include "row0types.h"Include dependency graph for row0ins.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Classes | |
| struct | ins_node_struct |
Defines | |
| #define | INS_NODE_MAGIC_N 15849075 |
| #define | INS_SEARCHED 0 |
| #define | INS_VALUES 1 |
| #define | INS_DIRECT 2 |
| #define | INS_NODE_SET_IX_LOCK 1 |
| #define | INS_NODE_ALLOC_ROW_ID 2 |
| #define | INS_NODE_INSERT_ENTRIES 3 |
Functions | |
| ulint | row_ins_check_foreign_constraint (ibool check_ref, dict_foreign_t *foreign, dict_table_t *table, dtuple_t *entry, que_thr_t *thr) |
| ins_node_t * | ins_node_create (ulint ins_type, dict_table_t *table, mem_heap_t *heap) |
| void | ins_node_set_new_row (ins_node_t *node, dtuple_t *row) |
| ulint | row_ins_index_entry_low (ulint mode, dict_index_t *index, dtuple_t *entry, ulint *ext_vec, ulint n_ext_vec, que_thr_t *thr) |
| ulint | row_ins_index_entry (dict_index_t *index, dtuple_t *entry, ulint *ext_vec, ulint n_ext_vec, que_thr_t *thr) |
| ulint | row_ins (ins_node_t *node, que_thr_t *thr) |
| que_thr_t * | row_ins_step (que_thr_t *thr) |
| #define INS_DIRECT 2 |
Definition at line 156 of file row0ins.h.
Referenced by ind_create_graph_create(), row_get_prebuilt_insert_row(), and tab_create_graph_create().
| #define INS_NODE_ALLOC_ROW_ID 2 |
Definition at line 161 of file row0ins.h.
Referenced by row_ins(), row_ins_alloc_row_id_step(), row_ins_step(), and row_insert_for_mysql().
| #define INS_NODE_INSERT_ENTRIES 3 |
| #define INS_NODE_MAGIC_N 15849075 |
| #define INS_NODE_SET_IX_LOCK 1 |
Definition at line 160 of file row0ins.h.
Referenced by ins_node_create(), ins_node_set_new_row(), row_ins_step(), and row_insert_for_mysql().
| #define INS_SEARCHED 0 |
Definition at line 154 of file row0ins.h.
Referenced by pars_insert_statement(), row_ins(), and row_ins_step().
| #define INS_VALUES 1 |
| ins_node_t* ins_node_create | ( | ulint | ins_type, | |
| dict_table_t * | table, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 73 of file row0ins.c.
References ins_node_struct::common, ins_node_struct::entry, ins_node_struct::entry_sys_heap, ins_node_struct::index, INS_NODE_MAGIC_N, INS_NODE_SET_IX_LOCK, ins_node_struct::ins_type, ins_node_struct::magic_n, mem_heap_alloc(), mem_heap_create, NULL, QUE_NODE_INSERT, ins_node_struct::select, ins_node_struct::state, ins_node_struct::table, ins_node_struct::trx_id, que_common_struct::type, and ut_dulint_zero.
Referenced by ind_create_graph_create(), pars_insert_statement(), row_get_prebuilt_insert_row(), and tab_create_graph_create().
00075 : insert node struct */ 00076 ulint ins_type, /* in: INS_VALUES, ... */ 00077 dict_table_t* table, /* in: table where to insert */ 00078 mem_heap_t* heap) /* in: mem heap where created */ 00079 { 00080 ins_node_t* node; 00081 00082 node = mem_heap_alloc(heap, sizeof(ins_node_t)); 00083 00084 node->common.type = QUE_NODE_INSERT; 00085 00086 node->ins_type = ins_type; 00087 00088 node->state = INS_NODE_SET_IX_LOCK; 00089 node->table = table; 00090 node->index = NULL; 00091 node->entry = NULL; 00092 00093 node->select = NULL; 00094 00095 node->trx_id = ut_dulint_zero; 00096 00097 node->entry_sys_heap = mem_heap_create(128); 00098 00099 node->magic_n = INS_NODE_MAGIC_N; 00100 00101 return(node); 00102 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void ins_node_set_new_row | ( | ins_node_t * | node, | |
| dtuple_t * | row | |||
| ) |
Definition at line 191 of file row0ins.c.
References ins_node_struct::entry, ins_node_struct::entry_sys_heap, ins_node_struct::index, ins_node_create_entry_list(), INS_NODE_SET_IX_LOCK, mem_heap_empty(), NULL, ins_node_struct::row, row_ins_alloc_sys_fields(), ins_node_struct::state, ins_node_struct::trx_id, and ut_dulint_zero.
Referenced by dict_build_col_def_step(), dict_build_field_def_step(), dict_build_index_def_step(), pars_insert_statement(), and row_get_prebuilt_insert_row().
00193 : insert node */ 00194 dtuple_t* row) /* in: new row (or first row) for the node */ 00195 { 00196 node->state = INS_NODE_SET_IX_LOCK; 00197 node->index = NULL; 00198 node->entry = NULL; 00199 00200 node->row = row; 00201 00202 mem_heap_empty(node->entry_sys_heap); 00203 00204 /* Create templates for index entries */ 00205 00206 ins_node_create_entry_list(node); 00207 00208 /* Allocate from entry_sys_heap buffers for sys fields */ 00209 00210 row_ins_alloc_sys_fields(node); 00211 00212 /* As we allocated a new trx id buf, the trx id should be written 00213 there again: */ 00214 00215 node->trx_id = ut_dulint_zero; 00216 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint row_ins | ( | ins_node_t * | node, | |
| que_thr_t * | thr | |||
| ) |
Definition at line 2354 of file row0ins.c.
References DB_SUCCESS, dict_table_get_first_index(), dict_table_get_next_index(), ins_node_struct::entry, err, ins_node_struct::index, INS_NODE_ALLOC_ROW_ID, INS_NODE_INSERT_ENTRIES, INS_SEARCHED, INS_VALUES, NULL, row_ins_alloc_row_id_step(), row_ins_get_row_from_select(), row_ins_get_row_from_values(), row_ins_index_entry_step(), ins_node_struct::state, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by row_ins_step().
02356 : DB_SUCCESS if operation successfully 02357 completed, else error code or DB_LOCK_WAIT */ 02358 ins_node_t* node, /* in: row insert node */ 02359 que_thr_t* thr) /* in: query thread */ 02360 { 02361 ulint err; 02362 02363 ut_ad(node && thr); 02364 02365 if (node->state == INS_NODE_ALLOC_ROW_ID) { 02366 02367 row_ins_alloc_row_id_step(node); 02368 02369 node->index = dict_table_get_first_index(node->table); 02370 node->entry = UT_LIST_GET_FIRST(node->entry_list); 02371 02372 if (node->ins_type == INS_SEARCHED) { 02373 02374 row_ins_get_row_from_select(node); 02375 02376 } else if (node->ins_type == INS_VALUES) { 02377 02378 row_ins_get_row_from_values(node); 02379 } 02380 02381 node->state = INS_NODE_INSERT_ENTRIES; 02382 } 02383 02384 ut_ad(node->state == INS_NODE_INSERT_ENTRIES); 02385 02386 while (node->index != NULL) { 02387 err = row_ins_index_entry_step(node, thr); 02388 02389 if (err != DB_SUCCESS) { 02390 02391 return(err); 02392 } 02393 02394 node->index = dict_table_get_next_index(node->index); 02395 node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); 02396 } 02397 02398 ut_ad(node->entry == NULL); 02399 02400 node->state = INS_NODE_ALLOC_ROW_ID; 02401 02402 return(DB_SUCCESS); 02403 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint row_ins_check_foreign_constraint | ( | ibool | check_ref, | |
| dict_foreign_t * | foreign, | |||
| dict_table_t * | table, | |||
| dtuple_t * | entry, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 1178 of file row0ins.c.
References trx_struct::check_foreigns, cmp, DB_SUCCESS, dfield_get_len(), dict_operation_lock, dtuple_get_nth_field(), err, FALSE, upd_node_struct::foreign, upd_node_struct::is_delete, dict_foreign_struct::n_fields, NULL, que_node_get_type(), QUE_NODE_UPDATE, REC_OFFS_NORMAL_SIZE, que_thr_struct::run_node, RW_LOCK_SHARED, thr_get_trx(), and ut_ad.
Referenced by row_ins_check_foreign_constraints(), and row_upd_check_references_constraints().
01180 : DB_SUCCESS, 01181 DB_NO_REFERENCED_ROW, 01182 or DB_ROW_IS_REFERENCED */ 01183 ibool check_ref,/* in: TRUE if we want to check that 01184 the referenced table is ok, FALSE if we 01185 want to to check the foreign key table */ 01186 dict_foreign_t* foreign,/* in: foreign constraint; NOTE that the 01187 tables mentioned in it must be in the 01188 dictionary cache if they exist at all */ 01189 dict_table_t* table, /* in: if check_ref is TRUE, then the foreign 01190 table, else the referenced table */ 01191 dtuple_t* entry, /* in: index entry for index */ 01192 que_thr_t* thr) /* in: query thread */ 01193 { 01194 upd_node_t* upd_node; 01195 dict_table_t* check_table; 01196 dict_index_t* check_index; 01197 ulint n_fields_cmp; 01198 rec_t* rec; 01199 btr_pcur_t pcur; 01200 ibool moved; 01201 int cmp; 01202 ulint err; 01203 ulint i; 01204 mtr_t mtr; 01205 trx_t* trx = thr_get_trx(thr); 01206 mem_heap_t* heap = NULL; 01207 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01208 ulint* offsets = offsets_; 01209 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01210 01211 run_again: 01212 #ifdef UNIV_SYNC_DEBUG 01213 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED)); 01214 #endif /* UNIV_SYNC_DEBUG */ 01215 01216 err = DB_SUCCESS; 01217 01218 if (trx->check_foreigns == FALSE) { 01219 /* The user has suppressed foreign key checks currently for 01220 this session */ 01221 goto exit_func; 01222 } 01223 01224 /* If any of the foreign key fields in entry is SQL NULL, we 01225 suppress the foreign key check: this is compatible with Oracle, 01226 for example */ 01227 01228 for (i = 0; i < foreign->n_fields; i++) { 01229 if (UNIV_SQL_NULL == dfield_get_len( 01230 dtuple_get_nth_field(entry, i))) { 01231 01232 goto exit_func; 01233 } 01234 } 01235 01236 if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) { 01237 upd_node = thr->run_node; 01238 01239 if (!(upd_node->is_delete) && upd_node->foreign == foreign) { 01240 /* If a cascaded update is done as defined by a 01241 foreign key constraint, do not check that 01242 constraint for the child row. In ON UPDATE CASCADE 01243 the update of the parent row is only half done when 01244 we come here: if we would check the constraint here 01245 for the child row it would fail. 01246 01247 A QUESTION remains: if in the child table there are 01248 several constraints which refer to the same parent 01249 table, we should merge all updates to the child as 01250 one update? And the updates can be contradictory! 01251 Currently we just perform the update associated 01252 with each foreign key constraint, one after 01253 another, and the user has problems predicting in 01254 which order they are performed. */ 01255 01256 goto exit_func; 01257 } 01258 } 01259 01260 if (check_ref) { 01261 check_table = foreign->referenced_table; 01262 check_index = foreign->referenced_index; 01263 } else { 01264 check_table = foreign->foreign_table; 01265 check_index = foreign->foreign_index; 01266 } 01267 01268 if (check_table == NULL || check_table->ibd_file_missing) { 01269 if (check_ref) { 01270 FILE* ef = dict_foreign_err_file; 01271 01272 row_ins_set_detailed(trx, foreign); 01273 01274 mutex_enter(&dict_foreign_err_mutex); 01275 rewind(ef); 01276 ut_print_timestamp(ef); 01277 fputs(" Transaction:\n", ef); 01278 trx_print(ef, trx, 600); 01279 fputs("Foreign key constraint fails for table ", ef); 01280 ut_print_name(ef, trx, TRUE, 01281 foreign->foreign_table_name); 01282 fputs(":\n", ef); 01283 dict_print_info_on_foreign_key_in_create_format(ef, 01284 trx, foreign, TRUE); 01285 fputs("\nTrying to add to index ", ef); 01286 ut_print_name(ef, trx, FALSE, 01287 foreign->foreign_index->name); 01288 fputs(" tuple:\n", ef); 01289 dtuple_print(ef, entry); 01290 fputs("\nBut the parent table ", ef); 01291 ut_print_name(ef, trx, TRUE, 01292 foreign->referenced_table_name); 01293 fputs("\nor its .ibd file does not currently exist!\n", ef); 01294 mutex_exit(&dict_foreign_err_mutex); 01295 01296 err = DB_NO_REFERENCED_ROW; 01297 } 01298 01299 goto exit_func; 01300 } 01301 01302 ut_a(check_table && check_index); 01303 01304 if (check_table != table) { 01305 /* We already have a LOCK_IX on table, but not necessarily 01306 on check_table */ 01307 01308 err = lock_table(0, check_table, LOCK_IS, thr); 01309 01310 if (err != DB_SUCCESS) { 01311 01312 goto do_possible_lock_wait; 01313 } 01314 } 01315 01316 mtr_start(&mtr); 01317 01318 /* Store old value on n_fields_cmp */ 01319 01320 n_fields_cmp = dtuple_get_n_fields_cmp(entry); 01321 01322 dtuple_set_n_fields_cmp(entry, foreign->n_fields); 01323 01324 btr_pcur_open(check_index, entry, PAGE_CUR_GE, 01325 BTR_SEARCH_LEAF, &pcur, &mtr); 01326 01327 /* Scan index records and check if there is a matching record */ 01328 01329 for (;;) { 01330 page_t* page; 01331 rec = btr_pcur_get_rec(&pcur); 01332 page = buf_frame_align(rec); 01333 01334 if (rec == page_get_infimum_rec(page)) { 01335 01336 goto next_rec; 01337 } 01338 01339 offsets = rec_get_offsets(rec, check_index, 01340 offsets, ULINT_UNDEFINED, &heap); 01341 01342 if (rec == page_get_supremum_rec(page)) { 01343 01344 err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, 01345 check_index, offsets, thr); 01346 if (err != DB_SUCCESS) { 01347 01348 break; 01349 } 01350 01351 goto next_rec; 01352 } 01353 01354 cmp = cmp_dtuple_rec(entry, rec, offsets); 01355 01356 if (cmp == 0) { 01357 if (rec_get_deleted_flag(rec, 01358 rec_offs_comp(offsets))) { 01359 err = row_ins_set_shared_rec_lock( 01360 LOCK_ORDINARY, rec, 01361 check_index, offsets, thr); 01362 if (err != DB_SUCCESS) { 01363 01364 break; 01365 } 01366 } else { 01367 /* Found a matching record. Lock only 01368 a record because we can allow inserts 01369 into gaps */ 01370 01371 err = row_ins_set_shared_rec_lock( 01372 LOCK_REC_NOT_GAP, rec, 01373 check_index, offsets, thr); 01374 01375 if (err != DB_SUCCESS) { 01376 01377 break; 01378 } 01379 01380 if (check_ref) { 01381 err = DB_SUCCESS; 01382 01383 break; 01384 } else if (foreign->type != 0) { 01385 /* There is an ON UPDATE or ON DELETE 01386 condition: check them in a separate 01387 function */ 01388 01389 err = 01390 row_ins_foreign_check_on_constraint( 01391 thr, foreign, &pcur, entry, 01392 &mtr); 01393 if (err != DB_SUCCESS) { 01394 /* Since reporting a plain 01395 "duplicate key" error 01396 message to the user in 01397 cases where a long CASCADE 01398 operation would lead to a 01399 duplicate key in some 01400 other table is very 01401 confusing, map duplicate 01402 key errors resulting from 01403 FK constraints to a 01404 separate error code. */ 01405 01406 if (err == DB_DUPLICATE_KEY) { 01407 err = DB_FOREIGN_DUPLICATE_KEY; 01408 } 01409 01410 break; 01411 } 01412 } else { 01413 row_ins_foreign_report_err( 01414 "Trying to delete or update", 01415 thr, foreign, rec, entry); 01416 01417 err = DB_ROW_IS_REFERENCED; 01418 break; 01419 } 01420 } 01421 } 01422 01423 if (cmp < 0) { 01424 err = row_ins_set_shared_rec_lock(LOCK_GAP, 01425 rec, check_index, offsets, thr); 01426 if (err != DB_SUCCESS) { 01427 01428 break; 01429 } 01430 01431 if (check_ref) { 01432 err = DB_NO_REFERENCED_ROW; 01433 row_ins_foreign_report_add_err( 01434 trx, foreign, rec, entry); 01435 } else { 01436 err = DB_SUCCESS; 01437 } 01438 01439 break; 01440 } 01441 01442 ut_a(cmp == 0); 01443 next_rec: 01444 moved = btr_pcur_move_to_next(&pcur, &mtr); 01445 01446 if (!moved) { 01447 if (check_ref) { 01448 rec = btr_pcur_get_rec(&pcur); 01449 row_ins_foreign_report_add_err( 01450 trx, foreign, rec, entry); 01451 err = DB_NO_REFERENCED_ROW; 01452 } else { 01453 err = DB_SUCCESS; 01454 } 01455 01456 break; 01457 } 01458 } 01459 01460 btr_pcur_close(&pcur); 01461 01462 mtr_commit(&mtr); 01463 01464 /* Restore old value */ 01465 dtuple_set_n_fields_cmp(entry, n_fields_cmp); 01466 01467 do_possible_lock_wait: 01468 if (err == DB_LOCK_WAIT) { 01469 trx->error_state = err; 01470 01471 que_thr_stop_for_mysql(thr); 01472 01473 srv_suspend_mysql_thread(thr); 01474 01475 if (trx->error_state == DB_SUCCESS) { 01476 01477 goto run_again; 01478 } 01479 01480 err = trx->error_state; 01481 } 01482 01483 exit_func: 01484 if (UNIV_LIKELY_NULL(heap)) { 01485 mem_heap_free(heap); 01486 } 01487 return(err); 01488 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint row_ins_index_entry | ( | dict_index_t * | index, | |
| dtuple_t * | entry, | |||
| ulint * | ext_vec, | |||
| ulint | n_ext_vec, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 2152 of file row0ins.c.
References BTR_MODIFY_LEAF, BTR_MODIFY_TREE, DB_FAIL, DB_SUCCESS, err, index(), row_ins_check_foreign_constraints(), row_ins_index_entry_low(), and UT_LIST_GET_FIRST.
Referenced by row_ins_index_entry_step(), row_upd_clust_rec_by_insert(), and row_upd_sec_index_entry().
02154 : DB_SUCCESS, DB_LOCK_WAIT, 02155 DB_DUPLICATE_KEY, or some other error code */ 02156 dict_index_t* index, /* in: index */ 02157 dtuple_t* entry, /* in: index entry to insert */ 02158 ulint* ext_vec,/* in: array containing field numbers of 02159 externally stored fields in entry, or NULL */ 02160 ulint n_ext_vec,/* in: number of fields in ext_vec */ 02161 que_thr_t* thr) /* in: query thread */ 02162 { 02163 ulint err; 02164 02165 if (UT_LIST_GET_FIRST(index->table->foreign_list)) { 02166 err = row_ins_check_foreign_constraints(index->table, index, 02167 entry, thr); 02168 if (err != DB_SUCCESS) { 02169 02170 return(err); 02171 } 02172 } 02173 02174 /* Try first optimistic descent to the B-tree */ 02175 02176 err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry, 02177 ext_vec, n_ext_vec, thr); 02178 if (err != DB_FAIL) { 02179 02180 return(err); 02181 } 02182 02183 /* Try then pessimistic descent to the B-tree */ 02184 02185 err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry, 02186 ext_vec, n_ext_vec, thr); 02187 return(err); 02188 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint row_ins_index_entry_low | ( | ulint | mode, | |
| dict_index_t * | index, | |||
| dtuple_t * | entry, | |||
| ulint * | ext_vec, | |||
| ulint | n_ext_vec, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 1959 of file row0ins.c.
References btr_cur_get_page(), btr_cur_get_rec(), BTR_CUR_INSERT_TO_IBUF, btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(), btr_cur_position(), btr_cur_search_to_nth_level(), BTR_IGNORE_SEC_UNIQUE, BTR_INSERT, BTR_MODIFY_LEAF, BTR_MODIFY_TREE, btr_store_big_rec_extern_fields(), buf_LRU_buf_pool_running_out(), DB_LOCK_TABLE_FULL, DB_SUCCESS, DICT_CLUSTERED, dict_index_get_n_unique(), DICT_UNIQUE, dtuple_big_rec_free(), dtuple_convert_back_big_rec(), dtuple_get_n_fields(), err, btr_cur_struct::flag, index(), log_free_check(), btr_cur_struct::low_match, mem_heap_free, mtr_commit(), mtr_start(), NULL, page, PAGE_CUR_LE, page_get_infimum_rec(), page_get_supremum_rec(), page_rec_get_next(), page_t, rec_get_n_fields(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_set_field_extern_bits(), row_ins_clust_index_entry_by_modify(), row_ins_duplicate_error_in_clust(), row_ins_must_modify(), ROW_INS_NEXT, row_ins_scan_sec_index_for_duplicate(), row_ins_sec_index_entry_by_modify(), btr_cur_struct::thr, thr_get_trx(), btr_cur_struct::up_match, and ut_a.
Referenced by row_ins_index_entry().
01961 : DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL 01962 if pessimistic retry needed, or error code */ 01963 ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, 01964 depending on whether we wish optimistic or 01965 pessimistic descent down the index tree */ 01966 dict_index_t* index, /* in: index */ 01967 dtuple_t* entry, /* in: index entry to insert */ 01968 ulint* ext_vec,/* in: array containing field numbers of 01969 externally stored fields in entry, or NULL */ 01970 ulint n_ext_vec,/* in: number of fields in ext_vec */ 01971 que_thr_t* thr) /* in: query thread */ 01972 { 01973 btr_cur_t cursor; 01974 ulint ignore_sec_unique = 0; 01975 ulint modify = 0; /* remove warning */ 01976 rec_t* insert_rec; 01977 rec_t* rec; 01978 ulint err; 01979 ulint n_unique; 01980 big_rec_t* big_rec = NULL; 01981 mtr_t mtr; 01982 mem_heap_t* heap = NULL; 01983 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01984 ulint* offsets = offsets_; 01985 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01986 01987 log_free_check(); 01988 01989 mtr_start(&mtr); 01990 01991 cursor.thr = thr; 01992 01993 /* Note that we use PAGE_CUR_LE as the search mode, because then 01994 the function will return in both low_match and up_match of the 01995 cursor sensible values */ 01996 01997 if (!(thr_get_trx(thr)->check_unique_secondary)) { 01998 ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE; 01999 } 02000 02001 btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, 02002 mode | BTR_INSERT | ignore_sec_unique, 02003 &cursor, 0, &mtr); 02004 02005 if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) { 02006 /* The insertion was made to the insert buffer already during 02007 the search: we are done */ 02008 02009 err = DB_SUCCESS; 02010 02011 goto function_exit; 02012 } 02013 02014 #ifdef UNIV_DEBUG 02015 { 02016 page_t* page = btr_cur_get_page(&cursor); 02017 rec_t* first_rec = page_rec_get_next( 02018 page_get_infimum_rec(page)); 02019 02020 if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) { 02021 ut_a(rec_get_n_fields(first_rec, index) 02022 == dtuple_get_n_fields(entry)); 02023 } 02024 } 02025 #endif 02026 02027 n_unique = dict_index_get_n_unique(index); 02028 02029 if (index->type & DICT_UNIQUE && (cursor.up_match >= n_unique 02030 || cursor.low_match >= n_unique)) { 02031 02032 if (index->type & DICT_CLUSTERED) { 02033 /* Note that the following may return also 02034 DB_LOCK_WAIT */ 02035 02036 err = row_ins_duplicate_error_in_clust(&cursor, 02037 entry, thr, &mtr); 02038 if (err != DB_SUCCESS) { 02039 02040 goto function_exit; 02041 } 02042 } else { 02043 mtr_commit(&mtr); 02044 err = row_ins_scan_sec_index_for_duplicate(index, 02045 entry, thr); 02046 mtr_start(&mtr); 02047 02048 if (err != DB_SUCCESS) { 02049 02050 goto function_exit; 02051 } 02052 02053 /* We did not find a duplicate and we have now 02054 locked with s-locks the necessary records to 02055 prevent any insertion of a duplicate by another 02056 transaction. Let us now reposition the cursor and 02057 continue the insertion. */ 02058 02059 btr_cur_search_to_nth_level(index, 0, entry, 02060 PAGE_CUR_LE, mode | BTR_INSERT, 02061 &cursor, 0, &mtr); 02062 } 02063 } 02064 02065 modify = row_ins_must_modify(&cursor); 02066 02067 if (modify != 0) { 02068 /* There is already an index entry with a long enough common 02069 prefix, we must convert the insert into a modify of an 02070 existing record */ 02071 02072 if (modify == ROW_INS_NEXT) { 02073 rec = page_rec_get_next(btr_cur_get_rec(&cursor)); 02074 02075 btr_cur_position(index, rec, &cursor); 02076 } 02077 02078 if (index->type & DICT_CLUSTERED) { 02079 err = row_ins_clust_index_entry_by_modify(mode, 02080 &cursor, &big_rec, 02081 entry, 02082 ext_vec, n_ext_vec, 02083 thr, &mtr); 02084 } else { 02085 err = row_ins_sec_index_entry_by_modify(mode, &cursor, 02086 entry, 02087 thr, &mtr); 02088 } 02089 02090 } else { 02091 if (mode == BTR_MODIFY_LEAF) { 02092 err = btr_cur_optimistic_insert(0, &cursor, entry, 02093 &insert_rec, &big_rec, thr, &mtr); 02094 } else { 02095 ut_a(mode == BTR_MODIFY_TREE); 02096 if (buf_LRU_buf_pool_running_out()) { 02097 02098 err = DB_LOCK_TABLE_FULL; 02099 02100 goto function_exit; 02101 } 02102 err = btr_cur_pessimistic_insert(0, &cursor, entry, 02103 &insert_rec, &big_rec, thr, &mtr); 02104 } 02105 02106 if (err == DB_SUCCESS) { 02107 if (ext_vec) { 02108 rec_set_field_extern_bits(insert_rec, index, 02109 ext_vec, n_ext_vec, &mtr); 02110 } 02111 } 02112 } 02113 02114 function_exit: 02115 mtr_commit(&mtr); 02116 02117 if (big_rec) { 02118 rec_t* rec; 02119 mtr_start(&mtr); 02120 02121 btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, 02122 BTR_MODIFY_TREE, &cursor, 0, &mtr); 02123 rec = btr_cur_get_rec(&cursor); 02124 offsets = rec_get_offsets(rec, index, offsets, 02125 ULINT_UNDEFINED, &heap); 02126 02127 err = btr_store_big_rec_extern_fields(index, rec, 02128 offsets, big_rec, &mtr); 02129 02130 if (modify) { 02131 dtuple_big_rec_free(big_rec); 02132 } else { 02133 dtuple_convert_back_big_rec(index, entry, big_rec); 02134 } 02135 02136 mtr_commit(&mtr); 02137 } 02138 02139 if (UNIV_LIKELY_NULL(heap)) { 02140 mem_heap_free(heap); 02141 } 02142 return(err); 02143 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2410 of file row0ins.c.
References DB_SUCCESS, err, trx_struct::error_state, trx_struct::id, INS_NODE_ALLOC_ROW_ID, INS_NODE_SET_IX_LOCK, INS_SEARCHED, ins_node_struct::ins_type, LOCK_IX, lock_table(), NULL, que_thr_struct::prev_node, que_node_get_parent(), que_node_get_type(), QUE_NODE_INSERT, row_ins(), que_thr_struct::run_node, SEL_NODE_FETCH, SEL_NODE_NO_MORE_ROWS, SEL_NODE_OPEN, ins_node_struct::select, ins_node_struct::state, sel_node_struct::state, ins_node_struct::table, thr_get_trx(), ins_node_struct::trx_id, ins_node_struct::trx_id_buf, trx_start_if_not_started(), trx_write_trx_id(), ut_ad, and UT_DULINT_EQ.
Referenced by que_thr_step(), and row_insert_for_mysql().
02412 : query thread to run next or NULL */ 02413 que_thr_t* thr) /* in: query thread */ 02414 { 02415 ins_node_t* node; 02416 que_node_t* parent; 02417 sel_node_t* sel_node; 02418 trx_t* trx; 02419 ulint err; 02420 02421 ut_ad(thr); 02422 02423 trx = thr_get_trx(thr); 02424 02425 trx_start_if_not_started(trx); 02426 02427 node = thr->run_node; 02428 02429 ut_ad(que_node_get_type(node) == QUE_NODE_INSERT); 02430 02431 parent = que_node_get_parent(node); 02432 sel_node = node->select; 02433 02434 if (thr->prev_node == parent) { 02435 node->state = INS_NODE_SET_IX_LOCK; 02436 } 02437 02438 /* If this is the first time this node is executed (or when 02439 execution resumes after wait for the table IX lock), set an 02440 IX lock on the table and reset the possible select node. MySQL's 02441 partitioned table code may also call an insert within the same 02442 SQL statement AFTER it has used this table handle to do a search. 02443 This happens, for example, when a row update moves it to another 02444 partition. In that case, we have already set the IX lock on the 02445 table during the search operation, and there is no need to set 02446 it again here. But we must write trx->id to node->trx_id_buf. */ 02447 02448 trx_write_trx_id(node->trx_id_buf, trx->id); 02449 02450 if (node->state == INS_NODE_SET_IX_LOCK) { 02451 02452 /* It may be that the current session has not yet started 02453 its transaction, or it has been committed: */ 02454 02455 if (UT_DULINT_EQ(trx->id, node->trx_id)) { 02456 /* No need to do IX-locking */ 02457 02458 goto same_trx; 02459 } 02460 02461 err = lock_table(0, node->table, LOCK_IX, thr); 02462 02463 if (err != DB_SUCCESS) { 02464 02465 goto error_handling; 02466 } 02467 02468 node->trx_id = trx->id; 02469 same_trx: 02470 node->state = INS_NODE_ALLOC_ROW_ID; 02471 02472 if (node->ins_type == INS_SEARCHED) { 02473 /* Reset the cursor */ 02474 sel_node->state = SEL_NODE_OPEN; 02475 02476 /* Fetch a row to insert */ 02477 02478 thr->run_node = sel_node; 02479 02480 return(thr); 02481 } 02482 } 02483 02484 if ((node->ins_type == INS_SEARCHED) 02485 && (sel_node->state != SEL_NODE_FETCH)) { 02486 02487 ut_ad(sel_node->state == SEL_NODE_NO_MORE_ROWS); 02488 02489 /* No more rows to insert */ 02490 thr->run_node = parent; 02491 02492 return(thr); 02493 } 02494 02495 /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ 02496 02497 err = row_ins(node, thr); 02498 02499 error_handling: 02500 trx->error_state = err; 02501 02502 if (err != DB_SUCCESS) { 02503 /* err == DB_LOCK_WAIT or SQL error detected */ 02504 return(NULL); 02505 } 02506 02507 /* DO THE TRIGGER ACTIONS HERE */ 02508 02509 if (node->ins_type == INS_SEARCHED) { 02510 /* Fetch a row to insert */ 02511 02512 thr->run_node = sel_node; 02513 } else { 02514 thr->run_node = que_node_get_parent(node); 02515 } 02516 02517 return(thr); 02518 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

