diff options
Diffstat (limited to 'storage/innobase/row/row0sel.c')
-rw-r--r-- | storage/innobase/row/row0sel.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index a3199055b54..fdf6aa46351 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -3619,6 +3619,32 @@ shortcut_fails_too_big_rec: pcur, 0, &mtr); pcur->trx_if_known = trx; + + rec = btr_pcur_get_rec(pcur); + + if (!moves_up + && !page_rec_is_supremum(rec) + && set_also_gap_locks + && !(srv_locks_unsafe_for_binlog + || trx->isolation_level == TRX_ISO_READ_COMMITTED) + && prebuilt->select_lock_type != LOCK_NONE) { + + /* Try to place a gap lock on the next index record + to prevent phantoms in ORDER BY ... DESC queries */ + + offsets = rec_get_offsets(page_rec_get_next(rec), + index, offsets, + ULINT_UNDEFINED, &heap); + err = sel_set_rec_lock(page_rec_get_next(rec), + index, offsets, + prebuilt->select_lock_type, + LOCK_GAP, thr); + + if (err != DB_SUCCESS) { + + goto lock_wait_or_error; + } + } } else { if (mode == PAGE_CUR_G) { btr_pcur_open_at_index_side( @@ -4493,3 +4519,149 @@ row_search_check_if_query_cache_permitted( return(ret); } + +/*********************************************************************** +Read the AUTOINC column from the current row. */ +static +ib_longlong +row_search_autoinc_read_column( +/*===========================*/ + /* out: value read from the column */ + dict_index_t* index, /* in: index to read from */ + const rec_t* rec, /* in: current rec */ + ulint col_no, /* in: column number */ + ibool unsigned_type) /* in: signed or unsigned flag */ +{ + ulint len; + const byte* data; + ib_longlong value; + mem_heap_t* heap = NULL; + byte dest[sizeof(value)]; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + ulint* offsets = offsets_; + + *offsets_ = sizeof offsets_ / sizeof *offsets_; + + /* TODO: We have to cast away the const of rec for now. This needs + to be fixed later.*/ + offsets = rec_get_offsets( + (rec_t*) rec, index, offsets, ULINT_UNDEFINED, &heap); + + /* TODO: We have to cast away the const of rec for now. This needs + to be fixed later.*/ + data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len); + + ut_a(len != UNIV_SQL_NULL); + ut_a(len <= sizeof value); + + /* Copy integer data and restore sign bit */ + if (unsigned_type || (data[0] & 128)) + memset(dest, 0x00, sizeof(dest)); + else + memset(dest, 0xff, sizeof(dest)); + + memcpy(dest + (sizeof(value) - len), data, len); + + if (!unsigned_type) + dest[sizeof(value) - len] ^= 128; + + /* The assumption here is that the AUTOINC value can't be negative.*/ + value = (((ib_longlong) mach_read_from_4(dest)) << 32) | + ((ib_longlong) mach_read_from_4(dest + 4)); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + ut_a(value >= 0); + + return(value); +} + +/*********************************************************************** +Get the last row. */ +static +const rec_t* +row_search_autoinc_get_rec( +/*=======================*/ + /* out: current rec or NULL */ + btr_pcur_t* pcur, /* in: the current cursor */ + mtr_t* mtr) /* in: mini transaction */ +{ + do { + const rec_t* rec = btr_pcur_get_rec(pcur); + + if (page_rec_is_user_rec(rec)) { + return(rec); + } + } while (btr_pcur_move_to_prev(pcur, mtr)); + + return(NULL); +} + +/*********************************************************************** +Read the max AUTOINC value from an index. */ + +ulint +row_search_max_autoinc( +/*===================*/ + /* out: DB_SUCCESS if all OK else + error code, DB_RECORD_NOT_FOUND if + column name can't be found in index */ + dict_index_t* index, /* in: index to search */ + const char* col_name, /* in: name of autoinc column */ + ib_longlong* value) /* out: AUTOINC value read */ +{ + ulint i; + ulint n_cols; + dict_field_t* dfield = NULL; + ulint error = DB_SUCCESS; + + n_cols = dict_index_get_n_ordering_defined_by_user(index); + + /* Search the index for the AUTOINC column name */ + for (i = 0; i < n_cols; ++i) { + dfield = dict_index_get_nth_field(index, i); + + if (strcmp(col_name, dfield->name) == 0) { + break; + } + } + + *value = 0; + + /* Must find the AUTOINC column name */ + if (i < n_cols && dfield) { + mtr_t mtr; + btr_pcur_t pcur; + + mtr_start(&mtr); + + /* Open at the high/right end (FALSE), and INIT + cursor (TRUE) */ + btr_pcur_open_at_index_side( + FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr); + + if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) { + const rec_t* rec; + + rec = row_search_autoinc_get_rec(&pcur, &mtr); + + if (rec != NULL) { + ibool unsigned_type = ( + dfield->col->prtype & DATA_UNSIGNED); + + *value = row_search_autoinc_read_column( + index, rec, i, unsigned_type); + } + } + + btr_pcur_close(&pcur); + + mtr_commit(&mtr); + } else { + error = DB_RECORD_NOT_FOUND; + } + + return(error); +} |