summaryrefslogtreecommitdiff
path: root/storage/maria/ma_search.c
diff options
context:
space:
mode:
authorMichael Widenius <monty@mysql.com>2008-06-26 08:18:28 +0300
committerMichael Widenius <monty@mysql.com>2008-06-26 08:18:28 +0300
commit52cb0c24a6a6674ee17c4bb86fa02527043ed90f (patch)
tree4cc1cd917bbf6ea5d3d27eab1434117d62d8f9e0 /storage/maria/ma_search.c
parentab75389acd66dd04756440ea0c7d00ed2be64a66 (diff)
downloadmariadb-git-52cb0c24a6a6674ee17c4bb86fa02527043ed90f.tar.gz
Added versioning of Maria index
Store max_trid in index file as state.create_trid. This is used to pack all transids in the index pages relative to max possible transid for file. Enable versioning for transactional tables with index. Tables with an auto-increment key, rtree or fulltext keys are not versioned. Changed info->lastkey to type MARIA_KEY. Removed info->lastkey_length as this is now part of info->lastkey Renamed old info->lastkey to info->lastkey_buff Use exact key lenghts for keys, not USE_WHOLE_KEY For partial key searches, use SEARCH_PART_KEY When searching to insert new key on page, use SEARCH_INSERT to mark that key has rowid Changes done in a lot of files: - Modified functions to use MARIA_KEY instead of key pointer and key length - Use keyinfo->root_lock instead of share->key_root_lock[keynr] - Simplify code by using local variable keyinfo instead if share->keyinfo[i] - Added #fdef EXTERNAL_LOCKING around removed state elements - HA_MAX_KEY_BUFF -> MARIA_MAX_KEY_BUFF (to reserve space for transid) - Changed type of 'nextflag' to uint32 to ensure all SEARCH_xxx flags fits into it .bzrignore: Added missing temporary directory extra/Makefile.am: comp_err is now deleted on make distclean include/maria.h: Added structure MARIA_KEY, which is used for intern key objects in Maria. Changed functions to take MARIA_KEY as an argument instead of pointer to packed key. Changed some functions that always return true or false to my_bool. Added virtual function make_key() to avoid if in _ma_make_key() Moved rw_lock_t for locking trees from share->key_root_lock to MARIA_KEYDEF. This makes usage of the locks simpler and faster include/my_base.h: Added HA_RTREE_INDEX flag to mark rtree index. Used for easier checks in ma_check() Added SEARCH_INSERT to be used when inserting new keys Added SEARCH_PART_KEY for partial searches Added SEARCH_USER_KEY_HAS_TRANSID to be used when key we use for searching in btree has a TRANSID Added SEARCH_PAGE_KEY_HAS_TRANSID to be used when key we found in btree has a transid include/my_handler.h: Make next_flag 32 bit to make sure we can handle all SEARCH_ bits mysql-test/include/maria_empty_logs.inc: Read and restore current database; Don't assume we are using mysqltest. Don't log use databasename to log. Using this include should not cause any result changes. mysql-test/r/maria-gis-rtree-dynamic.result: Updated results after adding some check table commands to help pinpoint errors mysql-test/r/maria-mvcc.result: New tests mysql-test/r/maria-purge.result: New result after adding removal of logs mysql-test/r/maria-recovery-big.result: maria_empty_logs doesn't log 'use mysqltest' anymore mysql-test/r/maria-recovery-bitmap.result: maria_empty_logs doesn't log 'use mysqltest' anymore mysql-test/r/maria-recovery-rtree-ft.result: maria_empty_logs doesn't log 'use mysqltest' anymore mysql-test/r/maria-recovery.result: maria_empty_logs doesn't log 'use mysqltest' anymore mysql-test/r/maria.result: New tests mysql-test/r/variables-big.result: Don't log id as it's not predictable mysql-test/suite/rpl_ndb/r/rpl_truncate_7ndb_2.result: Updated results to new binlog results. (Test has not been run in a long time as it requires --big) mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2-master.opt: Moved file to ndb replication test directory mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2.test: Fixed wrong path to included tests mysql-test/t/maria-gis-rtree-dynamic.test: Added some check table commands to help pinpoint errors mysql-test/t/maria-mvcc.test: New tests mysql-test/t/maria-purge.test: Remove logs to make test results predictable mysql-test/t/maria.test: New tests for some possible problems mysql-test/t/variables-big.test: Don't log id as it's not predictable mysys/my_handler.c: Updated function comment to reflect old code Changed nextflag to be uint32 to ensure we can have flags > 16 bit Changed checking if we are in insert with NULL keys as next_flag can now include additional bits that have to be ignored. Added SEARCH_INSERT flag to be used when inserting new keys in btree. This flag tells us the that the keys includes row position and it's thus safe to remove SEARCH_FIND Added comparision of transid. This is only done if the keys actually have a transid, which is indicated by nextflag mysys/my_lock.c: Fixed wrong test (Found by Guilhem) scripts/Makefile.am: Ensure that test programs are deleted by make clean sql/rpl_rli.cc: Moved assignment order to fix compiler warning storage/heap/hp_write.c: Add SEARCH_INSERT to signal ha_key_cmp that we we should also compare rowid for keys storage/maria/Makefile.am: Remove also maria log files when doing make distclean storage/maria/ha_maria.cc: Use 'file->start_state' as default state for transactional tables without versioning At table unlock, set file->state to point to live state. (Needed for information schema to pick up right number of rows) In ha_maria::implicit_commit() move all locked (ie open) tables to new transaction. This is needed to ensure ha_maria->info doesn't point to a deleted history event. Disable concurrent inserts for insert ... select and table changes with subqueries if statement based replication as this would cause wrong results on slave storage/maria/ma_blockrec.c: Updated comment storage/maria/ma_check.c: Compact key pages (removes transid) when doing --zerofill Check that 'page_flag' on key pages contains KEYPAGE_FLAG_HAS_TRANSID if there is a single key on the page with a transid Modified functions to use MARIA_KEY instead of key pointer and key length Use new interface to _ma_rec_pos(), _ma_dpointer(), _ma_ft_del(), ma_update_state_lsn() Removed not needed argument from get_record_for_key() Fixed that we check doesn't give errors for RTREE; We now treath these like SPATIAL Remove some SPATIAL specific code where the virtual functions can handle this in a general manner Use info->lastkey_buff instead of info->lastkey _ma_dpos() -> _ma_row_pos_from_key() _ma_make_key() -> keyinfo->make_key() _ma_print_key() -> _ma_print_keydata() _ma_move_key() -> ma_copy_copy() Add SEARCH_INSERT to signal ha_key_cmp that we we should also compare rowid for keys Ensure that data on page doesn't overwrite page checksum position Use DBUG_DUMP_KEY instead of DBUG_DUMP Use exact key lengths instead of USE_WHOLE_KEY to ha_key_cmp() Fixed check if rowid points outside of BLOCK_RECORD data file Use info->lastkey_buff instead of key on stack in some safe places Added #fdef EXTERNAL_LOCKING around removed state elements storage/maria/ma_close.c: Use keyinfo->root_lock instead of share->key_root_lock[keynr] storage/maria/ma_create.c: Removed assert that is already checked in maria_init() Force transactinal tables to be of type BLOCK_RECORD Fixed wrong usage of HA_PACK_RECORD (should be HA_OPTION_PACK_RECORD) Mark keys that uses HA_KEY_ALG_RTREE with HA_RTREE_INDEX for easier handling of these in ma_check Store max_trid in index file as state.create_trid. This is used to pack all transids in the index pages relative to max possible transid for file. storage/maria/ma_dbug.c: Changed _ma_print_key() to use MARIA_KEY storage/maria/ma_delete.c: Modified functions to use MARIA_KEY instead of key pointer and key length info->lastkey2-> info->lastkey_buff2 Added SEARCH_INSERT to signal ha_key_cmp that we we should also compare rowid for keys Use new interface for get_key(), _ma_get_last_key() and others _ma_dpos() -> ma_row_pos_from_key() Simplify setting of prev_key in del() Ensure that KEYPAGE_FLAG_HAS_TRANSID is set in page_flag if key page has transid Treath key pages that may have a transid as if keys would be of variable length storage/maria/ma_delete_all.c: Reset history state if maria_delete_all_rows() are called Update parameters to _ma_update_state_lsns() call storage/maria/ma_extra.c: Store and restore info->lastkey storage/maria/ma_ft_boolean_search.c: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_ft_nlq_search.c: Modified functions to use MARIA_KEY instead of key pointer and key length Use lastkey_buff2 instead of info->lastkey+info->s->base.max_key_length (same thing) storage/maria/ma_ft_update.c: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_ftdefs.h: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_fulltext.h: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_init.c: Check if blocksize is legal (Moved test here from ma_open()) storage/maria/ma_key.c: Added functions for storing/reading of transid Modified functions to use MARIA_KEY instead of key pointer and key length Moved _ma_sp_make_key() out of _ma_make_key() as we now use keyinfo->make_key to create keys Add transid to keys if table is versioned Added _ma_copy_key() storage/maria/ma_key_recover.c: Add logging of page_flag (holds information if there are keys with transid on page) Changed DBUG_PRINT("info" -> DBUG_PRINT("redo" as the redo logging can be quite extensive Added lots of DBUG_PRINT() Added support for index page operations: KEY_OP_SET_PAGEFLAG and KEY_OP_COMPACT_PAGE storage/maria/ma_key_recover.h: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_locking.c: Added new arguments to _ma_update_state_lsns_sub() storage/maria/ma_loghandler.c: Fixed all logging of LSN to look similar in DBUG log Changed if (left != 0) to if (left) as the later is used also later in the code storage/maria/ma_loghandler.h: Added new index page operations storage/maria/ma_open.c: Removed allocated "state_dummy" and instead use share->state.common for transactional tables that are not versioned This is needed to not get double increments of state.records (one in ma_write.c and on when log is written) Changed info->lastkey to MARIA_KEY type Removed resetting of MARIA_HA variables that have 0 as default value (as info is zerofilled) Enable versioning for transactional tables with index. Tables with an auto-increment key, rtree or fulltext keys are not versioned. Check on open that state.create_trid is correct Extend share->base.max_key_length in case of transactional table so that it can hold transid Removed 4.0 compatible fulltext key mode as this is not relevant for Maria Removed old and wrong #ifdef ENABLE_WHEN_WE_HAVE_TRANS_ROW_ID code block Initialize all new virtual function pointers Removed storing of state->unique, state->process and store state->create_trid instead storage/maria/ma_page.c: Added comment to describe key page structure Added functions to compact key page and log the compact operation storage/maria/ma_range.c: Modified functions to use MARIA_KEY instead of key pointer and key length Use SEARCH_PART_KEY indicator instead of USE_WHOLE_KEY to detect if we are doing a part key search Added handling of pages with transid storage/maria/ma_recovery.c: Don't assert if table we opened are not transactional. This may be a table which has been changed from transactional to not transactinal Added new arguments to _ma_update_state_lsns() storage/maria/ma_rename.c: Added new arguments to _ma_update_state_lsns() storage/maria/ma_rkey.c: Modified functions to use MARIA_KEY instead of key pointer and key length Don't use USE_WHOLE_KEY, use real length of key Use share->row_is_visible() to test if row is visible Moved search_flag == HA_READ_KEY_EXACT out of 'read-next-row' loop as this only need to be tested once Removed test if last_used_keyseg != 0 as this is always true storage/maria/ma_rnext.c: Modified functions to use MARIA_KEY instead of key pointer and key length Simplify code by using local variable keyinfo instead if share->keyinfo[i] Use share->row_is_visible() to test if row is visible storage/maria/ma_rnext_same.c: Modified functions to use MARIA_KEY instead of key pointer and key length lastkey2 -> lastkey_buff2 storage/maria/ma_rprev.c: Modified functions to use MARIA_KEY instead of key pointer and key length Simplify code by using local variable keyinfo instead if share->keyinfo[i] Use share->row_is_visible() to test if row is visible storage/maria/ma_rsame.c: Updated comment Simplify code by using local variable keyinfo instead if share->keyinfo[i] Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_rsamepos.c: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_rt_index.c: Modified functions to use MARIA_KEY instead of key pointer and key length Use better variable names Removed not needed casts _ma_dpos() -> _ma_row_pos_from_key() Use info->last_rtree_keypos to save position to key instead of info->int_keypos Simplify err: condition Changed return type for maria_rtree_insert() to my_bool as we are only intressed in ok/fail from this function storage/maria/ma_rt_index.h: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_rt_key.c: Modified functions to use MARIA_KEY instead of key pointer and key length Simplify maria_rtree_add_key by combining idenitcal code and removing added_len storage/maria/ma_rt_key.h: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_rt_mbr.c: Changed type of 'nextflag' to uint32 Added 'to' argument to RT_PAGE_MBR_XXX functions to more clearly see which variables changes value storage/maria/ma_rt_mbr.h: Changed type of 'nextflag' to uint32 storage/maria/ma_rt_split.c: Modified functions to use MARIA_KEY instead of key pointer and key length key_length -> key_data_length to catch possible errors storage/maria/ma_rt_test.c: Fixed wrong comment Reset recinfo to avoid valgrind varnings Fixed wrong argument to create_record() that caused test to fail storage/maria/ma_search.c: Modified functions to use MARIA_KEY instead of key pointer and key length Added support of keys with optional trid Test for SEARCH_PART_KEY instead of USE_WHOLE_KEY to detect part key reads _ma_dpos() -> _ma_row_pos_from_key() If there may be keys with transid on the page, have _ma_bin_search() call _ma_seq_search() Add _ma_skip_xxx() functions to quickly step over keys (faster than calling get_key() in most cases as we don't have to copy key data) Combine similar code at end of _ma_get_binary_pack_key() Removed not used function _ma_move_key() In _ma_search_next() don't call _ma_search() if we aren't on a nod page. Update info->cur_row.trid with trid for found key Removed some not needed casts Added _ma_trid_from_key() Use MARIA_SHARE instead of MARIA_HA as arguments to _ma_rec_pos(), _ma_dpointer() and _ma_xxx_keypos_to_recpos() to make functions faster and smaller storage/maria/ma_sort.c: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_sp_defs.h: _ma_sp_make_key() now fills in and returns (MARIA_KEY *) value storage/maria/ma_sp_key.c: _ma_sp_make_key() now fills in and returns (MARIA_KEY *) value Don't test sizeof(double), test against 8 as we are using float8store() Use mi_float8store() instead of doing swap of value (same thing but faster) storage/maria/ma_state.c: maria_versioning() now only calls _ma_block_get_status() if table supports versioning Added _ma_row_visible_xxx() functions for different occasions When emptying history, set info->state to point to the first history event. storage/maria/ma_state.h: Added _ma_row_visible_xxx() prototypes storage/maria/ma_static.c: Indentation changes storage/maria/ma_statrec.c: Fixed arguments to _ma_dpointer() and _ma_rec_pos() storage/maria/ma_test1.c: Call init_thr_lock() if we have versioning storage/maria/ma_test2.c: Call init_thr_lock() if we have versioning storage/maria/ma_unique.c: Modified functions to use MARIA_KEY storage/maria/ma_update.c: Modified functions to use MARIA_KEY instead of key pointer and key length storage/maria/ma_write.c: Modified functions to use MARIA_KEY instead of key pointer and key length Simplify code by using local variable keyinfo instead if share->keyinfo[i] In _ma_enlarge_root(), mark in page_flag if new key has transid _ma_dpos() -> _ma_row_pos_from_key() Changed return type of _ma_ck_write_tree() to my_bool as we are only testing if result is true or not Moved 'reversed' to outside block as area was used later storage/maria/maria_chk.c: Added error if trying to sort with HA_BINARY_PACK_KEY Use new interface to get_key() and _ma_dpointer() _ma_dpos() -> _ma_row_pos_from_key() storage/maria/maria_def.h: Modified functions to use MARIA_KEY instead of key pointer and key length Added 'common' to MARIA_SHARE->state for storing state for transactional tables without versioning Added create_trid to MARIA_SHARE Removed not used state variables 'process' and 'unique' Added defines for handling TRID's in index pages Changed to use MARIA_SHARE instead of MARIA_HA for some functions Added 'have_versioning' flag if table supports versioning Moved key_root_lock from MARIA_SHARE to MARIA_KEYDEF Changed last_key to be of type MARIA_KEY. Removed lastkey_length lastkey -> lastkey_buff, lastkey2 -> lastkey_buff2 Added _ma_get_used_and_nod_with_flag() for faster access to page data when page_flag is read Added DBUG_DUMP_KEY for easier DBUG_DUMP of a key Changed 'nextflag' and assocaited variables to uint32 storage/maria/maria_ftdump.c: lastkey -> lastkey_buff storage/maria/trnman.c: Fixed wrong initialization of min_read_from and max_commit_trid Added trnman_get_min_safe_trid() storage/maria/unittest/ma_test_all-t: Added --start-from storage/myisam/mi_check.c: Added SEARCH_INSERT, as ha_key_cmp() needs it when doing key comparision for inserting key on page in rowid order storage/myisam/mi_delete.c: Added SEARCH_INSERT, as ha_key_cmp() needs it when doing key comparision for inserting key on page in rowid order storage/myisam/mi_range.c: Updated comment storage/myisam/mi_write.c: Added SEARCH_INSERT, as ha_key_cmp() needs it when doing key comparision for inserting key on page in rowid order storage/myisam/rt_index.c: Fixed wrong parameter to rtree_get_req() which could cause crash
Diffstat (limited to 'storage/maria/ma_search.c')
-rw-r--r--storage/maria/ma_search.c848
1 files changed, 576 insertions, 272 deletions
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index e39fb832fbd..96c4a1d0add 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -18,12 +18,10 @@
#include "ma_fulltext.h"
#include "m_ctype.h"
-static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page,
- uchar *key, uchar *keypos,
- uint *return_key_length);
+static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos);
- /* Check index */
+
+/* Check that new index is ok */
int _ma_check_index(MARIA_HA *info, int inx)
{
@@ -57,18 +55,19 @@ int _ma_check_index(MARIA_HA *info, int inx)
@retval 1 If one should continue search on higher level
*/
-int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_len, uint nextflag, register my_off_t pos)
+int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
+ register my_off_t pos)
{
- my_bool last_key;
+ my_bool last_key_not_used;
int error,flag;
- uint nod_flag, used_length;
+ uint page_flag, nod_flag, used_length;
uchar *keypos,*maxpos;
- uchar lastkey[HA_MAX_KEY_BUFF],*buff;
+ uchar lastkey[MARIA_MAX_KEY_BUFF],*buff;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_search");
DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu",
(ulong) pos, nextflag, (ulong) info->cur_row.lastpos));
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_len););
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
if (pos == HA_OFFSET_ERROR)
{
@@ -79,23 +78,25 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_RETURN(1); /* Search at upper levels */
}
- if (!(buff= _ma_fetch_keypage(info,keyinfo, pos,
+ if (!(buff= _ma_fetch_keypage(info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff,
test(!(nextflag & SEARCH_SAVE_BUFF)), 0)))
goto err;
DBUG_DUMP("page", buff, _ma_get_page_used(info->s, buff));
- flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,lastkey, &last_key);
+ flag= (*keyinfo->bin_search)(key, buff, nextflag, &keypos, lastkey,
+ &last_key_not_used);
if (flag == MARIA_FOUND_WRONG_KEY)
DBUG_RETURN(-1);
- _ma_get_used_and_nod(info->s, buff, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(info->s, buff);
+ _ma_get_used_and_nod_with_flag(info->s, page_flag, buff, used_length,
+ nod_flag);
maxpos= buff + used_length -1;
if (flag)
{
- if ((error= _ma_search(info,keyinfo,key,key_len,nextflag,
+ if ((error= _ma_search(info, key, nextflag,
_ma_kpos(nod_flag,keypos))) <= 0)
DBUG_RETURN(error);
@@ -110,12 +111,13 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else
{
+ /* Found matching key */
if ((nextflag & SEARCH_FIND) && nod_flag &&
((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
- key_len != USE_WHOLE_KEY))
+ (key->flag & SEARCH_PART_KEY) || info->s->base.born_transactional))
{
- if ((error= _ma_search(info,keyinfo,key,key_len,SEARCH_FIND,
- _ma_kpos(nod_flag,keypos))) >= 0 ||
+ if ((error= _ma_search(info, key, nextflag,
+ _ma_kpos(nod_flag,keypos))) >= 0 ||
my_errno != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(error);
info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */
@@ -133,15 +135,21 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
maxpos=buff+(maxpos-old_buff);
}
+ info->last_key.keyinfo= keyinfo;
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
{
uint not_used[2];
- if (_ma_get_prev_key(info,keyinfo, buff, info->lastkey, keypos,
- &info->lastkey_length))
+ if (_ma_get_prev_key(&info->last_key, buff, keypos))
goto err;
+ /*
+ We have to use key->flag >> 1 here to transform
+ SEARCH_PAGE_KEY_HAS_TRANSID to SEARCH_USER_KEY_HAS_TRANSID
+ */
if (!(nextflag & SEARCH_SMALLER) &&
- ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key, key_len,
- SEARCH_FIND, not_used))
+ ha_key_cmp(keyinfo->seg, info->last_key.data, key->data,
+ key->data_length + key->ref_length,
+ SEARCH_FIND | (key->flag >> 1) | info->last_key.flag,
+ not_used))
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
goto err;
@@ -149,12 +157,17 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else
{
- info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey);
- if (!info->lastkey_length)
+ /* Set info->last_key to temporarily point to last key value */
+ info->last_key.data= lastkey;
+ /* Get key value (if not packed key) and position after key */
+ if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag, &keypos))
goto err;
- memcpy(info->lastkey,lastkey,info->lastkey_length);
+ memcpy(info->lastkey_buff, lastkey,
+ info->last_key.data_length + info->last_key.ref_length);
+ info->last_key.data= info->lastkey_buff;
}
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
/* Save position for a possible read next / previous */
info->int_keypos= info->keyread_buff+ (keypos-buff);
info->int_maxpos= info->keyread_buff+ (maxpos-buff);
@@ -176,25 +189,50 @@ err:
} /* _ma_search */
- /* Search after key in page-block */
- /* If packed key puts smaller or identical key in buff */
- /* ret_pos point to where find or bigger key starts */
- /* ARGSUSED */
+/*
+ Search after key in page-block
+
+ @fn _ma_bin_search
+ @param key Search after this key
+ @param page Start of data page
+ @param comp_flag How key should be compared
+ @param ret_pos
+ @param buff Buffer for holding a key (not used here)
+ @param last_key
+
+ @note
+ If keys are packed, then smaller or identical key is stored in buff
+
+ @return
+ @retval <0, 0 , >0 depending on if if found is smaller, equal or bigger than
+ 'key'
+ @retval ret_pos Points to where the identical or bigger key starts
+ @retval last_key Set to 1 if key is the last key in the page.
+*/
-int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint comp_flag, uchar **ret_pos,
+int _ma_bin_search(const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar **ret_pos,
uchar *buff __attribute__((unused)), my_bool *last_key)
{
int flag;
+ uint page_flag;
uint start, mid, end, save_end, totlength, nod_flag, used_length;
uint not_used[2];
- MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_SHARE *share= keyinfo->share;
DBUG_ENTER("_ma_bin_search");
LINT_INIT(flag);
- _ma_get_used_and_nod(share, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, page);
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ /* Keys have varying length, can't use binary search */
+ DBUG_RETURN(_ma_seq_search(key, page, comp_flag, ret_pos, buff, last_key));
+ }
+
+ _ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
+ nod_flag);
totlength= keyinfo->keylength + nod_flag;
DBUG_ASSERT(used_length >= share->keypage_header + nod_flag + totlength);
@@ -208,16 +246,18 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
while (start != end)
{
mid= (start+end)/2;
- if ((flag=ha_key_cmp(keyinfo->seg,(uchar*) page+(uint) mid*totlength,
- key, key_len, comp_flag, not_used))
+ if ((flag=ha_key_cmp(keyinfo->seg, page + (uint) mid * totlength,
+ key->data, key->data_length + key->ref_length,
+ comp_flag, not_used))
>= 0)
end=mid;
else
start=mid+1;
}
if (mid != start)
- flag=ha_key_cmp(keyinfo->seg, (uchar*) page+(uint) start*totlength,
- key, key_len, comp_flag, not_used);
+ flag=ha_key_cmp(keyinfo->seg, page + (uint) start * totlength,
+ key->data, key->data_length + key->ref_length, comp_flag,
+ not_used);
if (flag < 0)
start++; /* point at next, bigger key */
*ret_pos= (page + (uint) start * totlength);
@@ -227,54 +267,63 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_bin_search */
-/*
- Locate a packed key in a key page.
+/**
+ Locate a packed key in a key page.
- SYNOPSIS
- _ma_seq_search()
- info Open table information.
- keyinfo Key definition information.
- page Key page (beginning).
- key Search key.
- key_len Length to use from search key or USE_WHOLE_KEY
- comp_flag Search flags like SEARCH_SAME etc.
- ret_pos RETURN Position in key page behind this key.
- buff RETURN Copy of previous or identical unpacked key.
- last_key RETURN If key is last in page.
-
- DESCRIPTION
- Used instead of _ma_bin_search() when key is packed.
- Puts smaller or identical key in buff.
- Key is searched sequentially.
-
- RETURN
- > 0 Key in 'buff' is smaller than search key.
- 0 Key in 'buff' is identical to search key.
- < 0 Not found.
+ @fn _ma_seq_search()
+ @param key Search key.
+ @param page Key page (beginning).
+ @param comp_flag Search flags like SEARCH_SAME etc.
+ @param ret_pos
+ @param buff Buffer for holding temp keys
+ @param last_key
+
+ @description
+ Used instead of _ma_bin_search() when key is packed.
+ Puts smaller or identical key in buff.
+ Key is searched sequentially.
+
+ @todo
+ Don't copy key to buffer if we are not using key with prefix packing
+
+ @return
+ @retval > 0 Key in 'buff' is smaller than search key.
+ @retval 0 Key in 'buff' is identical to search key.
+ @retval < 0 Not found.
+
+ @retval ret_pos Points to where the identical or bigger key starts
+ @retval last_key Set to 1 if key is the last key in the page
+ @retval buff Copy of previous or identical unpacked key
*/
-int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint comp_flag, uchar **ret_pos,
+int _ma_seq_search(const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar **ret_pos,
uchar *buff, my_bool *last_key)
{
- MARIA_SHARE *share= info->s;
int flag;
- uint nod_flag, length, used_length, not_used[2];
- uchar t_buff[HA_MAX_KEY_BUFF], *end;
+ uint page_flag, nod_flag, length, used_length, not_used[2];
+ uchar t_buff[MARIA_MAX_KEY_BUFF], *end;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_SHARE *share= keyinfo->share;
+ MARIA_KEY tmp_key;
DBUG_ENTER("_ma_seq_search");
LINT_INIT(flag);
LINT_INIT(length);
- _ma_get_used_and_nod(share, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, page);
+ _ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
+ nod_flag);
end= page + used_length;
page+= share->keypage_header + nod_flag;
*ret_pos= (uchar*) page;
t_buff[0]=0; /* Avoid bugs */
+
+ tmp_key.data= t_buff;
+ tmp_key.keyinfo= keyinfo;
while (page < end)
{
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
+ length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &page);
if (length == 0 || page > end)
{
maria_print_error(share, HA_ERR_CRASHED);
@@ -284,8 +333,10 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
length, (long) page, (long) end));
DBUG_RETURN(MARIA_FOUND_WRONG_KEY);
}
- if ((flag= ha_key_cmp(keyinfo->seg, t_buff, key,
- key_len,comp_flag, not_used)) >= 0)
+ if ((flag= ha_key_cmp(keyinfo->seg, t_buff, key->data,
+ key->data_length + key->ref_length,
+ comp_flag | tmp_key.flag,
+ not_used)) >= 0)
break;
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("page: 0x%lx key: '%s' flag: %d", (long) page, t_buff,
@@ -302,12 +353,20 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_seq_search */
-int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint nextflag, uchar **ret_pos, uchar *buff,
+/**
+ Search for key on key page with string prefix compression
+
+ @notes
+ This is an optimized function compared to calling _ma_get_pack_key()
+ for each key in the buffer
+
+ Same interface as for _ma_seq_search()
+*/
+
+int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
+ uint32 nextflag, uchar **ret_pos, uchar *buff,
my_bool *last_key)
{
- MARIA_SHARE *share= info->s;
/*
my_flag is raw comparison result to be changed according to
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
@@ -315,16 +374,18 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
*/
int flag=0, my_flag=-1;
uint nod_flag, used_length, length, len, matched, cmplen, kseg_len;
- uint prefix_len,suffix_len;
+ uint page_flag, prefix_len,suffix_len;
int key_len_skip, seg_len_pack, key_len_left;
uchar *end;
uchar *vseg, *saved_vseg, *saved_from;
- uchar *sort_order= keyinfo->seg->charset->sort_order;
- uchar tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
+ uchar tt_buff[MARIA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
uchar *saved_to;
const uchar *kseg;
uint saved_length=0, saved_prefix_len=0;
uint length_pack;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_SHARE *share= keyinfo->share;
+ uchar *sort_order= keyinfo->seg->charset->sort_order;
DBUG_ENTER("_ma_prefix_search");
LINT_INIT(length);
@@ -335,17 +396,21 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
LINT_INIT(saved_vseg);
t_buff[0]=0; /* Avoid bugs */
- _ma_get_used_and_nod(share, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, page);
+ _ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
+ nod_flag);
+ page_flag&= KEYPAGE_FLAG_HAS_TRANSID; /* For faster test in loop */
end= page + used_length;
page+= share->keypage_header + nod_flag;
*ret_pos= page;
- kseg= key;
+ kseg= key->data;
get_key_pack_length(kseg_len, length_pack, kseg);
key_len_skip=length_pack+kseg_len;
- key_len_left=(int) key_len- (int) key_len_skip;
- /* If key_len is 0, then lenght_pack is 1, then key_len_left is -1. */
- cmplen=(key_len_left>=0) ? kseg_len : key_len-length_pack;
+ key_len_left=(int) (key->data_length + key->ref_length) - (int) key_len_skip;
+ /* If key_len is 0, then length_pack is 1, then key_len_left is -1. */
+ cmplen= ((key_len_left>=0) ? kseg_len :
+ (key->data_length + key->ref_length - length_pack));
DBUG_PRINT("info",("key: '%.*s'",kseg_len,kseg));
/*
@@ -367,6 +432,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
while (page < end)
{
uint packed= *page & 128;
+ uint key_flag;
vseg= (uchar*) page;
if (keyinfo->seg->length >= 127)
@@ -411,13 +477,12 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,
suffix_len,vseg));
{
+ /* Calculate length of one key */
uchar *from= vseg+suffix_len;
HA_KEYSEG *keyseg;
- uint l;
for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
{
-
if (keyseg->flag & HA_NULL_PART)
{
if (!(*from++))
@@ -425,14 +490,21 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
- get_key_length(l,from);
+ uint key_part_length;
+ get_key_length(key_part_length,from);
+ from+= key_part_length;
}
else
- l=keyseg->length;
-
- from+=l;
+ from+= keyseg->length;
}
from+= keyseg->length;
+ key_flag=0;
+
+ if (page_flag && key_has_transid(from-1))
+ {
+ from+= transid_packed_length(from);
+ key_flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
page= (uchar*) from+nod_flag;
length= (uint) (from-vseg);
}
@@ -482,7 +554,8 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/*
** len cmplen seg_left_len more_segs
** < matched=len; continue search
- ** > = prefix ? found : (matched=len; continue search)
+ ** > = prefix ? found : (matched=len;
+ * continue search)
** > < - ok, found
** = < - ok, found
** = = - ok, found
@@ -535,7 +608,8 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
{
uint not_used[2];
if ((flag = ha_key_cmp(keyinfo->seg+1,vseg,
- k, key_len_left, nextflag, not_used)) >= 0)
+ k, key_len_left, nextflag | key_flag,
+ not_used)) >= 0)
break;
}
else
@@ -582,7 +656,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_prefix_search */
- /* Get pos to a key_block */
+/* Get pos to a key_block */
my_off_t _ma_kpos(uint nod_flag, const uchar *after_key)
{
@@ -618,7 +692,7 @@ my_off_t _ma_kpos(uint nod_flag, const uchar *after_key)
} /* _kpos */
- /* Save pos to a key_block */
+/* Save pos to a key_block */
void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos)
{
@@ -645,14 +719,14 @@ void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos)
} /* _ma_kpointer */
- /* Calc pos to a data-record from a key */
+/* Calc pos to a data-record from a key */
-MARIA_RECORD_POS _ma_dpos(MARIA_HA *info, uint nod_flag,
- const uchar *after_key)
+MARIA_RECORD_POS _ma_row_pos_from_key(const MARIA_KEY *key)
{
my_off_t pos;
- after_key-=(nod_flag + info->s->rec_reflength);
- switch (info->s->rec_reflength) {
+ const uchar *after_key= key->data + key->data_length;
+ MARIA_SHARE *share= key->keyinfo->share;
+ switch (share->rec_reflength) {
#if SIZEOF_OFF_T > 4
case 8: pos= (my_off_t) mi_uint8korr(after_key); break;
case 7: pos= (my_off_t) mi_uint7korr(after_key); break;
@@ -670,18 +744,36 @@ MARIA_RECORD_POS _ma_dpos(MARIA_HA *info, uint nod_flag,
default:
pos=0L; /* Shut compiler up */
}
- return info->s->keypos_to_recpos(info, pos);
+ return (*share->keypos_to_recpos)(share, pos);
}
-/* Calc position from a record pointer ( in delete link chain ) */
+/**
+ Get trid from a key
+
+ @param key Maria key read from a page
-MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr)
+ @retval 0 If key doesn't have a trid
+ @retval trid
+*/
+
+TrID _ma_trid_from_key(const MARIA_KEY *key)
{
- MARIA_SHARE *s= info->s;
+ if (!(key->flag & (SEARCH_PAGE_KEY_HAS_TRANSID |
+ SEARCH_USER_KEY_HAS_TRANSID)))
+ return 0;
+ return transid_get_packed(key->keyinfo->share,
+ key->data + key->data_length +
+ key->keyinfo->share->rec_reflength);
+}
+
+
+/* Calc position from a record pointer ( in delete link chain ) */
+MARIA_RECORD_POS _ma_rec_pos(MARIA_SHARE *share, uchar *ptr)
+{
my_off_t pos;
- switch (s->rec_reflength) {
+ switch (share->rec_reflength) {
#if SIZEOF_OFF_T > 4
case 8:
pos= (my_off_t) mi_uint8korr(ptr);
@@ -708,7 +800,7 @@ MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr)
case 7:
case 6:
case 5:
- ptr+= (s->rec_reflength-4);
+ ptr+= (share->rec_reflength-4);
/* fall through */
#endif
case 4:
@@ -728,18 +820,18 @@ MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr)
break;
default: abort(); /* Impossible */
}
- return (*s->keypos_to_recpos)(info, pos);
+ return (*share->keypos_to_recpos)(share, pos);
}
/* save position to record */
-void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos)
+void _ma_dpointer(MARIA_SHARE *share, uchar *buff, my_off_t pos)
{
if (pos != HA_OFFSET_ERROR)
- pos= (*info->s->recpos_to_keypos)(info, pos);
+ pos= (*share->recpos_to_keypos)(share, pos);
- switch (info->s->rec_reflength) {
+ switch (share->rec_reflength) {
#if SIZEOF_OFF_T > 4
case 8: mi_int8store(buff,pos); break;
case 7: mi_int7store(buff,pos); break;
@@ -763,24 +855,24 @@ void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos)
} /* _ma_dpointer */
-my_off_t _ma_static_keypos_to_recpos(MARIA_HA *info, my_off_t pos)
+my_off_t _ma_static_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos)
{
- return pos * info->s->base.pack_reclength;
+ return pos * share->base.pack_reclength;
}
-my_off_t _ma_static_recpos_to_keypos(MARIA_HA *info, my_off_t pos)
+my_off_t _ma_static_recpos_to_keypos(MARIA_SHARE *share, my_off_t pos)
{
- return pos / info->s->base.pack_reclength;
+ return pos / share->base.pack_reclength;
}
-my_off_t _ma_transparent_recpos(MARIA_HA *info __attribute__((unused)),
+my_off_t _ma_transparent_recpos(MARIA_SHARE *share __attribute__((unused)),
my_off_t pos)
{
return pos;
}
-my_off_t _ma_transaction_keypos_to_recpos(MARIA_HA *info
+my_off_t _ma_transaction_keypos_to_recpos(MARIA_SHARE *share
__attribute__((unused)),
my_off_t pos)
{
@@ -788,7 +880,7 @@ my_off_t _ma_transaction_keypos_to_recpos(MARIA_HA *info
return pos >> 1;
}
-my_off_t _ma_transaction_recpos_to_keypos(MARIA_HA *info
+my_off_t _ma_transaction_recpos_to_keypos(MARIA_SHARE *share
__attribute__((unused)),
my_off_t pos)
{
@@ -798,48 +890,89 @@ my_off_t _ma_transaction_recpos_to_keypos(MARIA_HA *info
/*
@brief Get key from key-block
- @param nod_flag Is set to nod length if we on nod
+ @param key Should contain previous key. Will contain new key
+ @param page_flag Flag on page block
+ @param nod_flag Is set to nod length if we on nod
@param page Points at previous key; Its advanced to point at next key
- @param key Should contain previous key
@notes
Same as _ma_get_key but used with fixed length keys
- @retval Returns length of found key + pointers
+ @return
+ @retval key_length + length of data pointer (without nod length)
*/
-uint _ma_get_static_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page, uchar *key)
+uint _ma_get_static_key(MARIA_KEY *key, uint page_flag, uint nod_flag,
+ register uchar **page)
{
- memcpy((uchar*) key,(uchar*) *page,
- (size_t) (keyinfo->keylength+nod_flag));
- *page+=keyinfo->keylength+nod_flag;
- return(keyinfo->keylength);
+ register MARIA_KEYDEF *keyinfo= key->keyinfo;
+ size_t key_length= keyinfo->keylength;
+
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= key_length - key->ref_length;
+ key->flag= 0;
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ uchar *end= *page + keyinfo->keylength;
+ if (key_has_transid(end-1))
+ {
+ uint trans_length= transid_packed_length(end);
+ key->ref_length+= trans_length;
+ key_length+= trans_length;
+ key->flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
+ }
+ key_length+= nod_flag;
+ memcpy(key->data, *page, key_length);
+ *page+= key_length;
+ return key_length - nod_flag;
} /* _ma_get_static_key */
+/**
+ Skip over static length key from key-block
+
+ @fn _ma_skip_pack_key()
+ @param key Keyinfo and buffer that can be used
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param key Points at key
+
+ @retval pointer to next key
+*/
+
+uchar *_ma_skip_static_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page)
+{
+ page+= key->keyinfo->keylength;
+ if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) && key_has_transid(page-1))
+ page+= transid_packed_length(page);
+ return page+ nod_flag;
+}
+
+
/*
- get key witch is packed against previous key or key with a NULL column.
+ get key which is packed against previous key or key with a NULL column.
SYNOPSIS
_ma_get_pack_key()
- keyinfo key definition information.
- nod_flag If nod: Length of node pointer, else zero.
- page_pos RETURN position in key page behind this key.
- key IN/OUT in: prev key, out: unpacked key.
+ @param int_key Should contain previous key. Will contain new key
+ @param page_flag page_flag from page
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param page_pos Points at previous key; Its advanced to point at next key
- RETURN
- key_length + length of data pointer
+ @return
+ @retval key_length + length of data pointer
*/
-uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page_pos, register uchar *key)
+uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag,
+ uint nod_flag, uchar **page_pos)
{
reg1 HA_KEYSEG *keyseg;
- uchar *start_key,*page=*page_pos;
+ uchar *page= *page_pos;
uint length;
+ uchar *key= int_key->data;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
- start_key=key;
for (keyseg=keyinfo->seg ; keyseg->type ;keyseg++)
{
if (keyseg->flag & HA_PACK_KEY)
@@ -959,32 +1092,109 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
key+=length;
page+=length;
}
- length=keyseg->length+nod_flag;
- bmove((uchar*) key,(uchar*) page,length);
+
+ int_key->data_length= (key - int_key->data);
+ int_key->flag= 0;
+ length= keyseg->length;
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ uchar *end= page + length;
+ if (key_has_transid(end-1))
+ {
+ length+= transid_packed_length(end);
+ int_key->flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
+ }
+ int_key->ref_length= length;
+ length+= nod_flag;
+ bmove(key, page, length);
*page_pos= page+length;
- return ((uint) (key-start_key)+keyseg->length);
+
+ return (int_key->data_length + int_key->ref_length);
} /* _ma_get_pack_key */
+/**
+ skip key which is packed against previous key or key with a NULL column.
-/* key that is packed relatively to previous */
+ @fn _ma_skip_pack_key()
+ @param key Keyinfo and buffer that can be used
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param key Points at key
-uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page_pos, register uchar *key)
+ @retval pointer to next key
+*/
+
+uchar *_ma_skip_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page)
{
reg1 HA_KEYSEG *keyseg;
- uchar *start_key,*page,*page_end,*from,*from_end;
+ for (keyseg= key->keyinfo->seg ; keyseg->type ; keyseg++)
+ {
+ if (keyseg->flag & HA_PACK_KEY)
+ {
+ /* key with length, packed to previous key */
+ uint packed= *page & 128, length;
+ if (keyseg->length >= 127)
+ {
+ length= mi_uint2korr(page) & 32767;
+ page+= 2;
+ }
+ else
+ length= *page++ & 127;
+
+ if (packed)
+ {
+ if (length == 0) /* Same key */
+ continue;
+ get_key_length(length,page);
+ page+= length;
+ continue;
+ }
+ page+= length;
+ }
+ else
+ {
+ if (keyseg->flag & HA_NULL_PART)
+ if (!*page++)
+ continue;
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
+ {
+ uint length;
+ get_key_length(length,page);
+ page+=length;
+ }
+ else
+ page+= keyseg->length;
+ }
+ }
+ page+= keyseg->length;
+ if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) && key_has_transid(page-1))
+ page+= transid_packed_length(page);
+ return page + nod_flag;
+}
+
+
+/* Read key that is packed relatively to previous */
+
+uint _ma_get_binary_pack_key(MARIA_KEY *int_key, uint page_flag, uint nod_flag,
+ register uchar **page_pos)
+{
+ reg1 HA_KEYSEG *keyseg;
+ uchar *page, *page_end, *from, *from_end, *key;
uint length,tmp;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
DBUG_ENTER("_ma_get_binary_pack_key");
page= *page_pos;
- page_end=page+HA_MAX_KEY_BUFF+1;
- start_key=key;
+ page_end=page + MARIA_MAX_KEY_BUFF + 1;
+ key= int_key->data;
/*
Keys are compressed the following way:
- prefix length Packed length of prefix common with prev key. (1 or 3 bytes)
+ prefix length Packed length of prefix common with prev key.
+ (1 or 3 bytes)
for each key segment:
[is null] Null indicator if can be null (1 byte, zero means null)
[length] Packed length if varlength (1 or 3 bytes)
@@ -1046,10 +1256,10 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
/* Get length of dynamic length key part */
if ((length= (uint) (uchar) (*key++ = *from++)) == 255)
{
- /* If prefix is used up, switch to rest. */
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
length= ((uint) (uchar) ((*key++ = *from++))) << 8;
- /* If prefix is used up, switch to rest. */
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
length+= (uint) (uchar) ((*key++ = *from++));
}
@@ -1075,19 +1285,22 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
If we have mixed key blocks with data pointer and key block pointer,
we have to copy both.
*/
- length=keyseg->length+nod_flag;
+ int_key->data_length= (key - int_key->data);
+ int_key->ref_length= length= keyseg->length;
+ int_key->flag= 0;
if ((tmp=(uint) (from_end-from)) <= length)
{
- /* Remaining length is less or equal max possible length. */
- memcpy(key+tmp,page,length-tmp); /* Get last part of key */
- *page_pos= page+length-tmp;
+ /* Skip over the last common part of the data */
+ key+= tmp;
+ length-= tmp;
+ from= page;
}
else
{
/*
Remaining length is greater than max possible length.
This can happen only if we switched to the new key bytes already.
- 'page_end' is calculated with MI_MAX_KEY_BUFF. So it can be far
+ 'page_end' is calculated with MARIA_MAX_KEY_BUFF. So it can be far
behind the real end of the key.
*/
if (from_end != page_end)
@@ -1097,11 +1310,52 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); /* Error */
}
- /* Copy data pointer and, if appropriate, key block pointer. */
- memcpy((uchar*) key,(uchar*) from,(size_t) length);
- *page_pos= from+length;
}
- DBUG_RETURN((uint) (key-start_key)+keyseg->length);
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ uchar *end= from + length;
+ if (key_has_transid(end-1))
+ {
+ uint trans_length= transid_packed_length(end);
+ length+= trans_length;
+ int_key->ref_length+= trans_length;
+ int_key->flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
+ }
+
+ /* Copy rest of data ptr and, if appropriate, trans_id and node_ptr */
+ memcpy(key, from, length);
+ *page_pos= from + length + nod_flag;
+
+ DBUG_RETURN(int_key->data_length + int_key->ref_length);
+}
+
+/**
+ skip key which is ptefix packed against previous key
+
+ @fn _ma_skip_binary_key()
+ @param key Keyinfo and buffer that can be used
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param key Points at key
+
+ @note
+ We have to copy the key as otherwise we don't know how much left
+ data there is of the key.
+
+ @todo
+ Implement more efficient version of this. We can ignore to copy any rest
+ key parts that are not null or not packed. We also don't have to copy
+ rowid or transid.
+
+ @retval pointer to next key
+*/
+
+uchar *_ma_skip_binary_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page)
+{
+ if (!_ma_get_binary_pack_key(key, page_flag, nod_flag, &page))
+ return 0;
+ return page;
}
@@ -1111,35 +1365,40 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
@return pointer to next key
*/
-uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *key, uchar *keypos, uint *return_key_length)
+uchar *_ma_get_key(MARIA_KEY *key, uchar *page, uchar *keypos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_key");
- nod_flag=_ma_test_if_nod(info->s, page);
- if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ page_flag= _ma_get_keypage_flag(keyinfo->share, page);
+ nod_flag= _ma_test_if_nod(keyinfo->share, page);
+
+ if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- bmove((uchar*) key,(uchar*) keypos,keyinfo->keylength+nod_flag);
+ bmove(key->data, keypos, keyinfo->keylength+nod_flag);
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= keyinfo->keylength - key->ref_length;
+ key->flag= 0;
DBUG_RETURN(keypos+keyinfo->keylength+nod_flag);
}
else
{
- page+= info->s->keypage_header + nod_flag;
- key[0]=0; /* safety */
+ page+= keyinfo->share->keypage_header + nod_flag;
+ key->data[0]= 0; /* safety */
while (page <= keypos)
{
- *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
- if (*return_key_length == 0)
+ if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
- maria_print_error(info->s, HA_ERR_CRASHED);
+ maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
}
}
DBUG_PRINT("exit",("page: 0x%lx length: %u", (long) page,
- *return_key_length));
+ key->data_length + key->ref_length));
DBUG_RETURN(page);
} /* _ma_get_key */
@@ -1152,95 +1411,118 @@ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
@retval 1 error
*/
-static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, uchar *key, uchar *keypos,
- uint *return_key_length)
+static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_prev_key");
- nod_flag=_ma_test_if_nod(info->s, page);
- if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ page_flag= _ma_get_keypage_flag(keyinfo->share, page);
+ nod_flag= _ma_test_if_nod(keyinfo->share, page);
+
+ if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- *return_key_length=keyinfo->keylength;
- bmove((uchar*) key,(uchar*) keypos- *return_key_length-nod_flag,
- *return_key_length);
+ bmove(key->data, keypos - keyinfo->keylength - nod_flag,
+ keyinfo->keylength);
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= keyinfo->keylength - key->ref_length;
+ key->flag= 0;
DBUG_RETURN(0);
}
else
{
- page+= info->s->keypage_header + nod_flag;
- key[0]=0; /* safety */
+ page+= keyinfo->share->keypage_header + nod_flag;
+ key->data[0]= 0; /* safety */
+ DBUG_ASSERT(page != keypos);
while (page < keypos)
{
- *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
- if (*return_key_length == 0)
+ if (! (*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
- maria_print_error(info->s, HA_ERR_CRASHED);
+ maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1);
}
}
}
DBUG_RETURN(0);
-} /* _ma_get_key */
+} /* _ma_get_prev_key */
/*
@brief Get last key from key-page before 'endpos'
@note
- endpos may be either end of buffer or start of a key
+ endpos may be either end of buffer or start of a key
@return
@retval pointer to where key starts
*/
-uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *lastkey, uchar *endpos, uint *return_key_length)
+uchar *_ma_get_last_key(MARIA_KEY *key, uchar *page, uchar *endpos)
{
- uint nod_flag;
+ uint page_flag,nod_flag;
uchar *lastpos;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_last_key");
DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) page,
(long) endpos));
- nod_flag= _ma_test_if_nod(info->s, page);
- if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ page_flag= _ma_get_keypage_flag(keyinfo->share, page);
+ nod_flag= _ma_test_if_nod(keyinfo->share, page);
+ if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- lastpos=endpos-keyinfo->keylength-nod_flag;
- *return_key_length=keyinfo->keylength;
+ lastpos= endpos-keyinfo->keylength-nod_flag;
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= keyinfo->keylength - key->ref_length;
+ key->flag= 0;
if (lastpos > page)
- bmove((uchar*) lastkey,(uchar*) lastpos,keyinfo->keylength+nod_flag);
+ bmove(key->data, lastpos, keyinfo->keylength + nod_flag);
}
else
{
- page+= info->s->keypage_header + nod_flag;
+ page+= keyinfo->share->keypage_header + nod_flag;
lastpos= page;
- lastkey[0]=0;
+ key->data[0]=0; /* safety */
while (page < endpos)
{
- lastpos=page;
- *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey);
- if (*return_key_length == 0)
+ lastpos= page;
+ if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
(long) page));
- maria_print_error(info->s, HA_ERR_CRASHED);
+ maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
}
}
- DBUG_PRINT("exit",("lastpos: 0x%lx length: %u", (long) lastpos,
- *return_key_length));
+ DBUG_PRINT("exit",("lastpos: 0x%lx length: %u", (ulong) lastpos,
+ key->data_length + key->ref_length));
DBUG_RETURN(lastpos);
} /* _ma_get_last_key */
-/* Calculate length of key */
+/**
+ Calculate length of unpacked key
+
+ @param info Maria handler
+ @param keyinfo key handler
+ @param key data for key
+
+ @notes
+ This function is very seldom used. It's mainly used for debugging
+ or when calculating a key length from a stored key in batch insert.
+
+ This function does *NOT* calculate length of transid size!
+ This function can't be used against a prefix packed key on a page
+
+ @return
+ @retval total length for key
+*/
-uint _ma_keylength(MARIA_KEYDEF *keyinfo, register const uchar *key)
+uint _ma_keylength(MARIA_KEYDEF *keyinfo, const uchar *key)
{
reg1 HA_KEYSEG *keyseg;
const uchar *start;
@@ -1299,16 +1581,6 @@ uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register const uchar *key,
}
-/* Move a key */
-
-uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, const uchar *from)
-{
- reg1 uint length;
- memcpy(to, from, (size_t) (length= _ma_keylength(keyinfo, from)));
- return to+length;
-}
-
-
/*
Find next/previous record with same key
@@ -1316,18 +1588,20 @@ uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, const uchar *from)
This can't be used when database is touched after last read
*/
-int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length, uint nextflag, my_off_t pos)
+int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
+ uint32 nextflag, my_off_t pos)
{
int error;
- uint nod_flag;
- uchar lastkey[HA_MAX_KEY_BUFF];
+ uint page_flag,nod_flag;
+ uchar lastkey[MARIA_MAX_KEY_BUFF];
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_KEY tmp_key;
DBUG_ENTER("_ma_search_next");
- DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keyread_buff_used: %d",
+ DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: 0x%lx page_changed %d keyread_buff_used: %d",
nextflag, (ulong) info->cur_row.lastpos,
(ulong) info->int_keypos,
info->page_changed, info->keyread_buff_used));
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
/*
Force full read if we are at last key or if we are not on a leaf
@@ -1341,8 +1615,8 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->page_changed ||
(info->int_keytree_version != keyinfo->version &&
(info->int_nod_flag || info->keyread_buff_used)))
- DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF, pos));
+ DBUG_RETURN(_ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ pos));
if (info->keyread_buff_used)
{
@@ -1354,57 +1628,71 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
/* Last used buffer is in info->keyread_buff */
- nod_flag= _ma_test_if_nod(info->s, info->keyread_buff);
+ page_flag= _ma_get_keypage_flag(keyinfo->share, info->keyread_buff);
+ nod_flag= _ma_test_if_nod(keyinfo->share, info->keyread_buff);
+
+ tmp_key.data= lastkey;
+ info->last_key.keyinfo= tmp_key.keyinfo= keyinfo;
if (nextflag & SEARCH_BIGGER) /* Next key */
{
- my_off_t tmp_pos= _ma_kpos(nod_flag,info->int_keypos);
- if (tmp_pos != HA_OFFSET_ERROR)
+ if (nod_flag)
{
- if ((error= _ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
+ my_off_t tmp_pos= _ma_kpos(nod_flag,info->int_keypos);
+
+ if ((error= _ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ tmp_pos)) <=0)
DBUG_RETURN(error);
}
- memcpy(lastkey,key,key_length);
- if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,
- &info->int_keypos,lastkey)))
+ if (keyinfo->flag & (HA_PACK_KEY | HA_BINARY_PACK_KEY) &&
+ info->last_key.data != key->data)
+ memcpy(info->last_key.data, key->data,
+ key->data_length + key->ref_length);
+ if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag,
+ &info->int_keypos))
DBUG_RETURN(-1);
}
else /* Previous key */
{
- uint length;
/* Find start of previous key */
- info->int_keypos= _ma_get_last_key(info,keyinfo,info->keyread_buff,lastkey,
- info->int_keypos, &length);
+ info->int_keypos= _ma_get_last_key(&tmp_key, info->keyread_buff,
+ info->int_keypos);
if (!info->int_keypos)
DBUG_RETURN(-1);
if (info->int_keypos == info->keyread_buff + info->s->keypage_header)
- DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF, pos));
- if ((error= _ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF,
- _ma_kpos(nod_flag,info->int_keypos))) <= 0)
+ {
+ /* Previous key was first key, read key before this one */
+ DBUG_RETURN(_ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ pos));
+ }
+ if (nod_flag &&
+ (error= _ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ _ma_kpos(nod_flag,info->int_keypos))) <= 0)
DBUG_RETURN(error);
/* QQ: We should be able to optimize away the following call */
- if (! _ma_get_last_key(info,keyinfo,info->keyread_buff,lastkey,
- info->int_keypos,&info->lastkey_length))
+ if (! _ma_get_last_key(&info->last_key, info->keyread_buff,
+ info->int_keypos))
DBUG_RETURN(-1);
}
- memcpy(info->lastkey,lastkey,info->lastkey_length);
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
DBUG_RETURN(0);
} /* _ma_search_next */
- /* Search after position for the first row in an index */
- /* This is stored in info->cur_row.lastpos */
+/**
+ Search after position for the first row in an index
+
+ @return
+ Found row is stored in info->cur_row.lastpos
+*/
int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
register my_off_t pos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
uchar *page;
MARIA_SHARE *share= info->s;
DBUG_ENTER("_ma_search_first");
@@ -1424,12 +1712,14 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->cur_row.lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
- nod_flag=_ma_test_if_nod(share, info->keyread_buff);
+ page_flag= _ma_get_keypage_flag(share, info->keyread_buff);
+ nod_flag= _ma_test_if_nod(share, info->keyread_buff);
page= info->keyread_buff + share->keypage_header + nod_flag;
} while ((pos= _ma_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
- if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
- info->lastkey)))
+ info->last_key.keyinfo= keyinfo;
+
+ if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag, &page))
DBUG_RETURN(-1); /* Crashed */
info->int_keypos=page;
@@ -1439,20 +1729,25 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=info->keyread_buff_used=0;
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
DBUG_PRINT("exit",("found key at %lu", (ulong) info->cur_row.lastpos));
DBUG_RETURN(0);
} /* _ma_search_first */
- /* Search after position for the last row in an index */
- /* This is stored in info->cur_row.lastpos */
+/**
+ Search after position for the last row in an index
+
+ @return
+ Found row is stored in info->cur_row.lastpos
+*/
int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
register my_off_t pos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
uchar *buff,*end_of_page;
DBUG_ENTER("_ma_search_last");
@@ -1473,14 +1768,18 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->cur_row.lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
- _ma_get_used_and_nod(info->s, buff, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(info->s, info->keyread_buff);
+ _ma_get_used_and_nod_with_flag(info->s, page_flag, buff, used_length,
+ nod_flag);
end_of_page= buff + used_length;
} while ((pos= _ma_kpos(nod_flag, end_of_page)) != HA_OFFSET_ERROR);
- if (!_ma_get_last_key(info, keyinfo, buff, info->lastkey, end_of_page,
- &info->lastkey_length))
+ info->last_key.keyinfo= keyinfo;
+
+ if (!_ma_get_last_key(&info->last_key, buff, end_of_page))
DBUG_RETURN(-1);
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
info->int_keypos= info->int_maxpos= end_of_page;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
@@ -1509,27 +1808,29 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/* Static length key */
int
-_ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
+_ma_calc_static_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *next_pos __attribute__((unused)),
uchar *org_key __attribute__((unused)),
uchar *prev_key __attribute__((unused)),
- const uchar *key, MARIA_KEY_PARAM *s_temp)
+ MARIA_KEY_PARAM *s_temp)
{
- s_temp->key= key;
- return (int) (s_temp->move_length= keyinfo->keylength + nod_flag);
+ s_temp->key= key->data;
+ return (int) (s_temp->move_length= key->data_length + key->ref_length +
+ nod_flag);
}
/* Variable length key */
int
-_ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
+_ma_calc_var_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *next_pos __attribute__((unused)),
uchar *org_key __attribute__((unused)),
uchar *prev_key __attribute__((unused)),
- const uchar *key, MARIA_KEY_PARAM *s_temp)
+ MARIA_KEY_PARAM *s_temp)
{
- s_temp->key= key;
- return (int) (s_temp->move_length= _ma_keylength(keyinfo,key)+nod_flag);
+ s_temp->key= key->data;
+ return (int) (s_temp->move_length= key->data_length + key->ref_length +
+ nod_flag);
}
/**
@@ -1554,22 +1855,23 @@ _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
*/
int
-_ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
- uchar *next_key,
- uchar *org_key, uchar *prev_key, const uchar *key,
+_ma_calc_var_pack_key_length(const MARIA_KEY *int_key, uint nod_flag,
+ uchar *next_key, uchar *org_key, uchar *prev_key,
MARIA_KEY_PARAM *s_temp)
{
reg1 HA_KEYSEG *keyseg;
int length;
uint key_length,ref_length,org_key_length=0,
length_pack,new_key_length,diff_flag,pack_marker;
- const uchar *start,*end,*key_end;
+ const uchar *key, *start, *end, *key_end;
uchar *sort_order;
my_bool same_length;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
+ key= int_key->data;
length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
same_length=0; keyseg=keyinfo->seg;
- key_length= _ma_keylength(keyinfo,key)+nod_flag;
+ key_length= int_key->data_length + int_key->ref_length + nod_flag;
sort_order=0;
if ((keyinfo->flag & HA_FULLTEXT) &&
@@ -1840,15 +2142,17 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
/* Length of key which is prefix compressed */
-int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
+int _ma_calc_bin_pack_key_length(const MARIA_KEY *int_key,
+ uint nod_flag,
uchar *next_key,
uchar *org_key, uchar *prev_key,
- const uchar *key,
MARIA_KEY_PARAM *s_temp)
{
uint length,key_length,ref_length;
+ const uchar *key= int_key->data;
- s_temp->totlength=key_length= _ma_keylength(keyinfo,key)+nod_flag;
+ s_temp->totlength= key_length= (int_key->data_length + int_key->ref_length+
+ nod_flag);
#ifdef HAVE_purify
s_temp->n_length= s_temp->n_ref_length=0; /* For valgrind */
#endif