diff options
author | unknown <jani@hynda.mysql.fi> | 2007-06-27 17:49:12 +0300 |
---|---|---|
committer | unknown <jani@hynda.mysql.fi> | 2007-06-27 17:49:12 +0300 |
commit | f2839e0f016b4e43ba62b0d2e846d0960de02b4d (patch) | |
tree | eb82a0418f88b83d49bf66dfc659d59862535683 /storage/maria/ma_range.c | |
parent | e4fd17d1154b59c921affac45a41cb11c79844b6 (diff) | |
parent | de28fd57082de2fb5d12e27c789553be4ce548c4 (diff) | |
download | mariadb-git-f2839e0f016b4e43ba62b0d2e846d0960de02b4d.tar.gz |
Merge jamppa@bk-internal.mysql.com:/home/bk/mysql-5.1
into hynda.mysql.fi:/home/my/mysql-maria
BitKeeper/etc/ignore:
auto-union
Makefile.am:
Auto merged
BUILD/SETUP.sh:
Auto merged
BitKeeper/deleted/.del-init_db.sql~a77d572c39d5a1f8:
Auto merged
client/mysqldump.c:
Auto merged
include/Makefile.am:
Auto merged
include/m_string.h:
Auto merged
include/my_base.h:
Auto merged
include/my_dbug.h:
Auto merged
libmysql/CMakeLists.txt:
Auto merged
libmysql/Makefile.shared:
Auto merged
libmysqld/Makefile.am:
Auto merged
mysql-test/include/varchar.inc:
Auto merged
mysql-test/lib/mtr_cases.pl:
Auto merged
mysql-test/lib/mtr_io.pl:
Auto merged
mysql-test/lib/mtr_misc.pl:
Auto merged
mysql-test/mysql-test-run.pl:
Auto merged
mysql-test/lib/mtr_process.pl:
Auto merged
mysql-test/lib/mtr_report.pl:
Auto merged
mysql-test/r/events_logs_tests.result:
Auto merged
mysql-test/r/view.result:
Auto merged
mysql-test/t/disabled.def:
Auto merged
mysql-test/t/events_logs_tests.test:
Auto merged
mysql-test/t/myisam.test:
Auto merged
mysql-test/t/view.test:
Auto merged
mysys/Makefile.am:
Auto merged
mysys/my_create.c:
Auto merged
mysys/my_handler.c:
Auto merged
mysys/my_init.c:
Auto merged
mysys/my_open.c:
Auto merged
mysys/safemalloc.c:
Auto merged
plugin/daemon_example/daemon_example.cc:
Auto merged
sql/Makefile.am:
Auto merged
sql/filesort.cc:
Auto merged
sql/gen_lex_hash.cc:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/handler.cc:
Auto merged
sql/handler.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_func.h:
Auto merged
sql/log.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/opt_range.cc:
Auto merged
sql/slave.cc:
Auto merged
sql/slave.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/share/errmsg.txt:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_test.cc:
Auto merged
sql/udf_example.c:
Auto merged
sql/uniques.cc:
Auto merged
sql/unireg.cc:
Auto merged
storage/csv/ha_tina.cc:
Auto merged
storage/myisam/ft_boolean_search.c:
Auto merged
storage/myisam/ft_nlq_search.c:
Auto merged
storage/myisam/ft_parser.c:
Auto merged
storage/myisam/ft_stopwords.c:
Auto merged
storage/myisam/ft_update.c:
Auto merged
storage/myisam/fulltext.h:
Auto merged
storage/myisam/ha_myisam.h:
Auto merged
storage/myisam/mi_checksum.c:
Auto merged
storage/myisam/mi_create.c:
Auto merged
storage/myisam/mi_delete.c:
Auto merged
storage/myisam/mi_delete_all.c:
Auto merged
storage/myisam/mi_key.c:
Auto merged
storage/myisam/mi_log.c:
Auto merged
storage/myisam/mi_open.c:
Auto merged
storage/myisam/mi_range.c:
Auto merged
storage/myisam/mi_rkey.c:
Auto merged
storage/myisam/mi_rsamepos.c:
Auto merged
storage/myisam/mi_search.c:
Auto merged
storage/myisam/mi_test1.c:
Auto merged
storage/myisam/mi_test2.c:
Auto merged
storage/myisam/mi_unique.c:
Auto merged
storage/myisam/mi_update.c:
Auto merged
storage/myisam/myisamlog.c:
Auto merged
storage/myisam/myisampack.c:
Auto merged
storage/myisam/rt_index.c:
Auto merged
storage/myisam/sort.c:
Auto merged
storage/myisam/sp_test.c:
Auto merged
storage/myisammrg/ha_myisammrg.h:
Auto merged
storage/ndb/src/mgmapi/mgmapi.cpp:
Auto merged
unittest/Makefile.am:
Auto merged
BitKeeper/triggers/post-commit:
Manual merge from mysql-5.1 to mysql-maria
configure.in:
Manual merge from mysql-5.1 to mysql-maria
include/ft_global.h:
Manual merge from mysql-5.1 to mysql-maria
include/keycache.h:
Manual merge from mysql-5.1 to mysql-maria
include/my_atomic.h:
Manual merge from mysql-5.1 to mysql-maria
include/my_global.h:
Manual merge from mysql-5.1 to mysql-maria
include/my_sys.h:
Manual merge from mysql-5.1 to mysql-maria
include/myisam.h:
Manual merge from mysql-5.1 to mysql-maria
mysys/array.c:
Manual merge from mysql-5.1 to mysql-maria
mysys/mf_keycache.c:
Manual merge from mysql-5.1 to mysql-maria
mysys/mf_keycaches.c:
Manual merge from mysql-5.1 to mysql-maria
mysys/my_pread.c:
Manual merge from mysql-5.1 to mysql-maria
sql/mysqld.cc:
Manual merge from mysql-5.1 to mysql-maria
sql/net_serv.cc:
Manual merge from mysql-5.1 to mysql-maria
sql/set_var.cc:
Manual merge from mysql-5.1 to mysql-maria
sql/set_var.h:
Manual merge from mysql-5.1 to mysql-maria
sql/sql_class.h:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/ft_static.c:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/ha_myisam.cc:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/mi_check.c:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/mi_dynrec.c:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/mi_packrec.c:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/mi_write.c:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/myisamchk.c:
Manual merge from mysql-5.1 to mysql-maria
storage/myisam/myisamdef.h:
Manual merge from mysql-5.1 to mysql-maria
storage/myisammrg/ha_myisammrg.cc:
Manual merge from mysql-5.1 to mysql-maria
unittest/mysys/Makefile.am:
Manual merge from mysql-5.1 to mysql-maria
unittest/mysys/my_atomic-t.c:
Manual merge from mysql-5.1 to mysql-maria
Diffstat (limited to 'storage/maria/ma_range.c')
-rw-r--r-- | storage/maria/ma_range.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c new file mode 100644 index 00000000000..b359868e8e4 --- /dev/null +++ b/storage/maria/ma_range.c @@ -0,0 +1,262 @@ +/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Gives a approximated number of how many records there is between two keys. + Used when optimizing querries. + */ + +#include "maria_def.h" +#include "ma_rt_index.h" + +static ha_rows _ma_record_pos(MARIA_HA *info,const byte *key,uint key_len, + enum ha_rkey_function search_flag); +static double _ma_search_pos(MARIA_HA *info,MARIA_KEYDEF *keyinfo, byte *key, + uint key_len,uint nextflag, my_off_t pos); +static uint _ma_keynr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *page, + byte *keypos, uint *ret_max_key); + + +/** + @brief Estimate how many records there is in a given range + + @param info MARIA handler + @param inx Index to use + @param min_key Min key. Is = 0 if no min range + @param max_key Max key. Is = 0 if no max range + + @note + We should ONLY return 0 if there is no rows in range + + @return Estimated number of rows or error + @retval HA_POS_ERROR error (or we can't estimate number of rows) + @retval number Estimated number of rows +*/ + +ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key, + key_range *max_key) +{ + ha_rows start_pos,end_pos,res; + DBUG_ENTER("maria_records_in_range"); + + if ((inx = _ma_check_index(info,inx)) < 0) + DBUG_RETURN(HA_POS_ERROR); + + if (fast_ma_readinfo(info)) + DBUG_RETURN(HA_POS_ERROR); + info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED); + if (info->s->concurrent_insert) + rw_rdlock(&info->s->key_root_lock[inx]); + + switch(info->s->keyinfo[inx].key_alg){ +#ifdef HAVE_RTREE_KEYS + case HA_KEY_ALG_RTREE: + { + byte *key_buff; + uint start_key_len; + + /* + The problem is that the optimizer doesn't support + RTree keys properly at the moment. + Hope this will be fixed some day. + But now NULL in the min_key means that we + didn't make the task for the RTree key + and expect BTree functionality from it. + As it's not able to handle such request + we return the error. + */ + if (!min_key) + { + res= HA_POS_ERROR; + break; + } + key_buff= info->lastkey+info->s->base.max_key_length; + start_key_len= _ma_pack_key(info,inx, key_buff, + min_key->key, min_key->length, + (HA_KEYSEG**) 0); + res= maria_rtree_estimate(info, inx, key_buff, start_key_len, + maria_read_vec[min_key->flag]); + res= res ? res : 1; /* Don't return 0 */ + break; + } +#endif + case HA_KEY_ALG_BTREE: + default: + start_pos= (min_key ? + _ma_record_pos(info, min_key->key, min_key->length, + min_key->flag) : + (ha_rows) 0); + end_pos= (max_key ? + _ma_record_pos(info, max_key->key, max_key->length, + max_key->flag) : + info->state->records+ (ha_rows) 1); + res= (end_pos < start_pos ? (ha_rows) 0 : + (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos)); + if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR) + res=HA_POS_ERROR; + } + + if (info->s->concurrent_insert) + rw_unlock(&info->s->key_root_lock[inx]); + fast_ma_writeinfo(info); + + /** + @todo LOCK + If res==0 (no rows), if we need to guarantee repeatability of the search, + we will need to set a next-key lock in this statement. + Also SELECT COUNT(*)... + */ + + DBUG_PRINT("info",("records: %ld",(ulong) (res))); + DBUG_RETURN(res); +} + + + /* Find relative position (in records) for key in index-tree */ + +static ha_rows _ma_record_pos(MARIA_HA *info, const byte *key, uint key_len, + enum ha_rkey_function search_flag) +{ + uint inx=(uint) info->lastinx, nextflag; + MARIA_KEYDEF *keyinfo=info->s->keyinfo+inx; + byte *key_buff; + double pos; + DBUG_ENTER("_ma_record_pos"); + DBUG_PRINT("enter",("search_flag: %d",search_flag)); + + if (key_len == 0) + key_len= USE_WHOLE_KEY; + key_buff=info->lastkey+info->s->base.max_key_length; + key_len= _ma_pack_key(info, inx, key_buff, key, key_len, + (HA_KEYSEG**) 0); + DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, keyinfo->seg, + key_buff, key_len);); + nextflag=maria_read_vec[search_flag]; + if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) + key_len=USE_WHOLE_KEY; + + pos= _ma_search_pos(info,keyinfo, key_buff, key_len, + nextflag | SEARCH_SAVE_BUFF, + info->s->state.key_root[inx]); + if (pos >= 0.0) + { + DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records))); + DBUG_RETURN((ulong) (pos*info->state->records+0.5)); + } + DBUG_RETURN(HA_POS_ERROR); +} + + + /* This is a modified version of _ma_search */ + /* Returns offset for key in indextable (decimal 0.0 <= x <= 1.0) */ + +static double _ma_search_pos(register MARIA_HA *info, + register MARIA_KEYDEF *keyinfo, + byte *key, uint key_len, uint nextflag, + register my_off_t pos) +{ + int flag; + uint nod_flag,keynr,max_keynr; + my_bool after_key; + byte *keypos, *buff; + double offset; + DBUG_ENTER("_ma_search_pos"); + LINT_INIT(max_keynr); + + if (pos == HA_OFFSET_ERROR) + DBUG_RETURN(0.5); + + if (!(buff= _ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,1))) + goto err; + flag=(*keyinfo->bin_search)(info, keyinfo, buff, key, key_len, nextflag, + &keypos,info->lastkey, &after_key); + nod_flag=_ma_test_if_nod(buff); + keynr= _ma_keynr(info,keyinfo,buff,keypos,&max_keynr); + + if (flag) + { + if (flag == MARIA_FOUND_WRONG_KEY) + DBUG_RETURN(-1); /* error */ + /* + Didn't found match. keypos points at next (bigger) key + Try to find a smaller, better matching key. + Matches keynr + [0-1] + */ + if (flag > 0 && ! nod_flag) + offset= 1.0; + else if ((offset= _ma_search_pos(info,keyinfo,key,key_len,nextflag, + _ma_kpos(nod_flag,keypos))) < 0) + DBUG_RETURN(offset); + } + else + { + /* + Found match. Keypos points at the start of the found key + Matches keynr+1 + */ + offset=1.0; /* Matches keynr+1 */ + if ((nextflag & SEARCH_FIND) && nod_flag && + ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME || + key_len != USE_WHOLE_KEY)) + { + /* + There may be identical keys in the tree. Try to match on of those. + Matches keynr + [0-1] + */ + if ((offset= _ma_search_pos(info,keyinfo,key,key_len,SEARCH_FIND, + _ma_kpos(nod_flag,keypos))) < 0) + DBUG_RETURN(offset); /* Read error */ + } + } + DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d", + keynr,offset,max_keynr,nod_flag,flag)); + DBUG_RETURN((keynr+offset)/(max_keynr+1)); +err: + DBUG_PRINT("exit",("Error: %d",my_errno)); + DBUG_RETURN (-1.0); +} + + + /* Get keynummer of current key and max number of keys in nod */ + +static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, + byte *page, byte *keypos, uint *ret_max_key) +{ + uint nod_flag,keynr,max_key; + byte t_buff[HA_MAX_KEY_BUFF],*end; + + end= page+maria_data_on_page(page); + nod_flag=_ma_test_if_nod(page); + page+=2+nod_flag; + + if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) + { + *ret_max_key= (uint) (end-page)/(keyinfo->keylength+nod_flag); + return (uint) (keypos-page)/(keyinfo->keylength+nod_flag); + } + + max_key=keynr=0; + t_buff[0]=0; /* Safety */ + while (page < end) + { + if (!(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff)) + return 0; /* Error */ + max_key++; + if (page == keypos) + keynr=max_key; + } + *ret_max_key=max_key; + return(keynr); +} |