summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <serg@janus.mylan>2007-03-17 09:12:26 +0100
committerunknown <serg@janus.mylan>2007-03-17 09:12:26 +0100
commit9128a807d87f56bc55719034c1f1d248f2231798 (patch)
tree16be454773d14989bed92a8b6e12d9208651d563
parent84d24679b955ede6ad0194100355fe4b9139301a (diff)
parent7d383909db64d10283c1e37a7b45026d5b3b2e3c (diff)
downloadmariadb-git-9128a807d87f56bc55719034c1f1d248f2231798.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into janus.mylan:/usr/home/serg/Abk/mysql-5.1 sql/sql_insert.cc: Auto merged
-rw-r--r--BUILD/FINISH.sh2
-rwxr-xr-xBUILD/compile-alpha-ccc4
-rwxr-xr-xBUILD/compile-alpha-cxx4
-rwxr-xr-xBUILD/compile-alpha-debug4
-rwxr-xr-xBUILD/compile-dist2
-rwxr-xr-xBUILD/compile-hpux11-parisc2-aCC2
-rwxr-xr-xBUILD/compile-ia64-debug-max2
-rwxr-xr-xBUILD/compile-irix-mips64-mipspro2
-rwxr-xr-xBUILD/compile-pentium-pgcc4
-rwxr-xr-xBUILD/compile-solaris-sparc-forte2
-rwxr-xr-xBUILD/compile-solaris-sparc-purify2
-rwxr-xr-xBitKeeper/triggers/post-commit2
-rw-r--r--dbug/dbug.c6
-rw-r--r--dbug/user.r11
-rw-r--r--include/heap.h4
-rw-r--r--include/my_atomic.h8
-rw-r--r--include/my_base.h13
-rw-r--r--include/my_global.h10
-rw-r--r--include/myisam.h7
-rw-r--r--include/myisammrg.h6
-rw-r--r--[-rwxr-xr-x]server-tools/CMakeLists.txt0
-rw-r--r--sql/event_db_repository.cc5
-rw-r--r--sql/ha_ndbcluster.cc19
-rw-r--r--sql/ha_ndbcluster.h2
-rw-r--r--sql/ha_partition.cc50
-rw-r--r--sql/ha_partition.h11
-rw-r--r--sql/handler.cc33
-rw-r--r--sql/handler.h55
-rw-r--r--sql/item_subselect.cc6
-rw-r--r--sql/key.cc14
-rw-r--r--sql/log.cc2
-rw-r--r--sql/log_event.cc8
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/opt_range.cc260
-rw-r--r--sql/opt_range.h40
-rw-r--r--sql/opt_sum.cc18
-rw-r--r--sql/slave.cc2
-rw-r--r--sql/sp.cc5
-rw-r--r--sql/sql_acl.cc33
-rw-r--r--sql/sql_handler.cc6
-rw-r--r--sql/sql_help.cc5
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_plugin.cc3
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_servers.cc13
-rw-r--r--sql/sql_udf.cc5
-rw-r--r--sql/table.cc34
-rw-r--r--sql/table.h5
-rw-r--r--sql/tztime.cc12
-rw-r--r--storage/blackhole/ha_blackhole.cc9
-rw-r--r--storage/blackhole/ha_blackhole.h8
-rw-r--r--storage/example/ha_example.cc2
-rw-r--r--storage/example/ha_example.h2
-rw-r--r--storage/federated/ha_federated.cc1
-rw-r--r--storage/heap/ha_heap.cc13
-rw-r--r--storage/heap/ha_heap.h10
-rw-r--r--storage/heap/heapdef.h6
-rw-r--r--storage/heap/hp_hash.c24
-rw-r--r--storage/heap/hp_rkey.c4
-rw-r--r--storage/myisam/ha_myisam.cc24
-rw-r--r--storage/myisam/ha_myisam.h10
-rw-r--r--storage/myisam/mi_check.c2
-rw-r--r--storage/myisam/mi_key.c51
-rw-r--r--storage/myisam/mi_range.c46
-rw-r--r--storage/myisam/mi_rkey.c13
-rw-r--r--storage/myisam/myisamdef.h5
-rw-r--r--storage/myisam/rt_test.c2
-rw-r--r--storage/myisam/sp_test.c2
-rw-r--r--storage/myisammrg/ha_myisammrg.cc15
-rw-r--r--storage/myisammrg/ha_myisammrg.h10
-rw-r--r--storage/myisammrg/myrg_rkey.c6
-rw-r--r--support-files/Makefile.am3
-rw-r--r--support-files/mysql.m4108
-rw-r--r--unittest/mysys/my_atomic-t.c3
75 files changed, 667 insertions, 481 deletions
diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh
index 6f0600c9de3..142ff7eb08e 100644
--- a/BUILD/FINISH.sh
+++ b/BUILD/FINISH.sh
@@ -4,7 +4,7 @@ extra_configs="$extra_configs $local_infile_configs"
configure="./configure $base_configs $extra_configs"
commands="\
-$make -k distclean || true
+$make -k maintainer-clean || true
/bin/rm -rf */.deps/*.P configure config.cache storage/*/configure storage/*/config.cache autom4te.cache storage/*/autom4te.cache;
path=`dirname $0`
diff --git a/BUILD/compile-alpha-ccc b/BUILD/compile-alpha-ccc
index 889592295b5..59ed241d51c 100755
--- a/BUILD/compile-alpha-ccc
+++ b/BUILD/compile-alpha-ccc
@@ -1,5 +1,7 @@
+#! /bin/sh
+
/bin/rm -f */.deps/*.P */*.o
-make -k clean
+make -k maintainer-clean
/bin/rm -f */.deps/*.P */*.o
/bin/rm -f config.cache mysql-*.tar.gz
diff --git a/BUILD/compile-alpha-cxx b/BUILD/compile-alpha-cxx
index 1624f4ed622..a1b5605ac5e 100755
--- a/BUILD/compile-alpha-cxx
+++ b/BUILD/compile-alpha-cxx
@@ -1,5 +1,7 @@
+#! /bin/sh
+
/bin/rm -f */.deps/*.P */*.o
-make -k clean
+make -k maintainer-clean
/bin/rm -f */.deps/*.P */*.o
/bin/rm -f */.deps/*.P config.cache storage/innobase/config.cache mysql-*.tar.gz
diff --git a/BUILD/compile-alpha-debug b/BUILD/compile-alpha-debug
index b565a18272f..94fe8a2b414 100755
--- a/BUILD/compile-alpha-debug
+++ b/BUILD/compile-alpha-debug
@@ -1,5 +1,7 @@
+#! /bin/sh
+
/bin/rm -f */.deps/*.P */*.o
-make -k clean
+make -k maintainer-clean
/bin/rm -f */.deps/*.P */*.o
/bin/rm -f */.deps/*.P config.cache storage/innobase/config.cache mysql-*.tar.gz
diff --git a/BUILD/compile-dist b/BUILD/compile-dist
index 0504b308ceb..0ecb386bf71 100755
--- a/BUILD/compile-dist
+++ b/BUILD/compile-dist
@@ -6,7 +6,7 @@
# tree can then be picked up by "make dist" to create the "pristine source
# package" that is used as the basis for all other binary builds.
#
-test -f Makefile && make distclean
+test -f Makefile && make maintainer-clean
(cd storage/innobase && aclocal && autoheader && \
libtoolize --automake --force --copy && \
automake --force --add-missing --copy && autoconf)
diff --git a/BUILD/compile-hpux11-parisc2-aCC b/BUILD/compile-hpux11-parisc2-aCC
index c286488bb26..0e825715663 100755
--- a/BUILD/compile-hpux11-parisc2-aCC
+++ b/BUILD/compile-hpux11-parisc2-aCC
@@ -61,7 +61,7 @@ done
set -x
-make distclean
+make maintainer-clean
path=`dirname $0`
. "$path/autorun.sh"
diff --git a/BUILD/compile-ia64-debug-max b/BUILD/compile-ia64-debug-max
index d1017ad506b..123bfb06300 100755
--- a/BUILD/compile-ia64-debug-max
+++ b/BUILD/compile-ia64-debug-max
@@ -1,4 +1,4 @@
-gmake -k clean || true
+gmake -k maintainer-clean || true
/bin/rm -f */.deps/*.P config.cache storage/innobase/config.cache
path=`dirname $0`
diff --git a/BUILD/compile-irix-mips64-mipspro b/BUILD/compile-irix-mips64-mipspro
index 0cebb4b9f5b..5e34df20c28 100755
--- a/BUILD/compile-irix-mips64-mipspro
+++ b/BUILD/compile-irix-mips64-mipspro
@@ -33,7 +33,7 @@ else
fi
set -x
-make distclean
+make maintainer-clean
path=`dirname $0`
. "$path/autorun.sh"
diff --git a/BUILD/compile-pentium-pgcc b/BUILD/compile-pentium-pgcc
index 411241451cf..c13a6ff14f7 100755
--- a/BUILD/compile-pentium-pgcc
+++ b/BUILD/compile-pentium-pgcc
@@ -1,5 +1,7 @@
+#! /bin/sh
+
AM_MAKEFLAGS="-j 2"
-gmake -k clean || true
+gmake -k maintainer-clean || true
/bin/rm -f */.deps/*.P config.cache
path=`dirname $0`
diff --git a/BUILD/compile-solaris-sparc-forte b/BUILD/compile-solaris-sparc-forte
index 936266670d9..2a8b7dbae48 100755
--- a/BUILD/compile-solaris-sparc-forte
+++ b/BUILD/compile-solaris-sparc-forte
@@ -5,7 +5,7 @@
PATH=/opt/SUNWspro/bin/:/usr/ccs/bin:$PATH
-make -k clean || true
+make -k maintainer-clean || true
/bin/rm -f */.deps/*.P config.cache
path=`dirname $0`
diff --git a/BUILD/compile-solaris-sparc-purify b/BUILD/compile-solaris-sparc-purify
index d7473230607..08308f05f4e 100755
--- a/BUILD/compile-solaris-sparc-purify
+++ b/BUILD/compile-solaris-sparc-purify
@@ -31,7 +31,7 @@ do
shift
done
-make -k clean || true
+make -k maintainer-clean || true
/bin/rm -f */.deps/*.P config.cache
path=`dirname $0`
diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit
index 86f3db012ee..b4dcb311dde 100755
--- a/BitKeeper/triggers/post-commit
+++ b/BitKeeper/triggers/post-commit
@@ -72,7 +72,7 @@ X-CSetKey: <$CSETKEY>
$BH
EOF
bk changes -v -r+
- bk cset -r+ -d
+ bk rset -r+ -ah | bk gnupatch -h -dup -T
) > $BKROOT/BitKeeper/tmp/dev_public.txt
$SENDMAIL -t < $BKROOT/BitKeeper/tmp/dev_public.txt
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 6a17db588ad..c4ae89f837f 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -1995,12 +1995,14 @@ static char *DbugMalloc(size_t size)
/*
- * strtok lookalike - splits on ':', magically handles :\ and :/
+ * strtok lookalike - splits on ':', magically handles ::, :\ and :/
*/
static const char *DbugStrTok(const char *s)
{
- while (s[0] && (s[0] != ':' || (s[1] == '\\' || s[1] == '/')))
+ const char *start=s;
+ while (s[0] && (s[0] != ':' ||
+ (s[1] == '\\' || s[1] == '/' || (s[1] == ':' && s++))))
s++;
return s;
}
diff --git a/dbug/user.r b/dbug/user.r
index 3bcc0c91d1d..e41367de321 100644
--- a/dbug/user.r
+++ b/dbug/user.r
@@ -908,9 +908,10 @@ via the
.B DBUG_PUSH
or
.B DBUG_SET
-macros. Control string consists of colon separate flags. A flag
-may take an argument or a list of arguments. If a control string
-starts from a '+' sign it works
+macros. Control string consists of colon separate flags. Colons
+that are part of ':\\', ':/', or '::' are not considered flag
+separators. A flag may take an argument or a list of arguments.
+If a control string starts from a '+' sign it works
.I incrementally,
that is, it can modify existing state without overriding it. In such a
string every flag may be preceded by a '+' or '-' to enable or disable
@@ -923,9 +924,7 @@ optional.
.LI a[,file]
Redirect the debugger output stream and append it to the specified
file. The default output stream is stderr. A null argument list
-causes output to be redirected to stdout. A colon that is followed by
-the '\\' or '/' is cosidered a part of the path and not a flag
-separator.
+causes output to be redirected to stdout.
.SP 1
EX: \fCa,C:\\tmp\\log\fR
.LI A[,file]
diff --git a/include/heap.h b/include/heap.h
index af053341203..6cacb7fc529 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -225,8 +225,8 @@ extern void heap_update_auto_increment(HP_INFO *info, const byte *record);
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
key_range *max_key);
int hp_panic(enum ha_panic_function flag);
-int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
- uint key_len, enum ha_rkey_function find_flag);
+int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
+ key_part_map keypart_map, enum ha_rkey_function find_flag);
extern gptr heap_find(HP_INFO *info,int inx,const byte *key);
extern int heap_check_heap(HP_INFO *info, my_bool print_status);
extern byte *heap_position(HP_INFO *info);
diff --git a/include/my_atomic.h b/include/my_atomic.h
index 7b066e9b529..a1347d26401 100644
--- a/include/my_atomic.h
+++ b/include/my_atomic.h
@@ -134,14 +134,6 @@ make_atomic_swap(ptr)
#undef _atomic_h_cleanup_
#endif
-#if SIZEOF_CHARP == SIZEOF_INT
-typedef int intptr;
-#elif SIZEOF_CHARP == SIZEOF_LONG
-typedef long intptr;
-#else
-#error
-#endif
-
#define MY_ATOMIC_OK 0
#define MY_ATOMIC_NOT_1CPU 1
extern int my_atomic_initialize();
diff --git a/include/my_base.h b/include/my_base.h
index 26d513ba2a7..dd21362e8f7 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -385,16 +385,20 @@ enum ha_base_keytype {
#define HA_ERR_TABLE_NEEDS_UPGRADE 164 /* The table changed in storage engine */
#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */
-#define HA_ERR_AUTOINC_READ_FAILED 166/* Failed to get the next autoinc value */
-#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set the row autoinc value */
-#define HA_ERR_LAST 167 /*Copy last error nr.*/
+#define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */
+#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */
+#define HA_ERR_GENERIC 168 /* Generic error */
+#define HA_ERR_LAST 168 /*Copy last error nr.*/
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
/* Other constants */
#define HA_NAMELEN 64 /* Max length of saved filename */
-#define NO_SUCH_KEY ((uint)~0) /* used as a key no. */
+#define NO_SUCH_KEY (~(uint)0) /* used as a key no. */
+
+typedef ulong key_part_map;
+#define HA_WHOLE_KEY (~(key_part_map)0)
/* Intern constants in databases */
@@ -468,6 +472,7 @@ typedef struct st_key_range
{
const byte *key;
uint length;
+ key_part_map keypart_map;
enum ha_rkey_function flag;
} key_range;
diff --git a/include/my_global.h b/include/my_global.h
index c41ac8f915f..addc2f24e7f 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -986,7 +986,7 @@ typedef long int32;
typedef unsigned long uint32;
#endif
#else
-#error "Neither int or long is of 4 bytes width"
+#error Neither int or long is of 4 bytes width
#endif
#if !defined(HAVE_ULONG) && !defined(__USE_MISC)
@@ -1016,6 +1016,14 @@ typedef unsigned __int64 my_ulonglong;
typedef unsigned long long my_ulonglong;
#endif
+#if SIZEOF_CHARP == SIZEOF_INT
+typedef int intptr;
+#elif SIZEOF_CHARP == SIZEOF_LONG
+typedef long intptr;
+#else
+#error sizeof(void *) is neither sizeof(int) nor sizeof(long)
+#endif
+
#ifdef USE_RAID
/*
The following is done with a if to not get problems with pre-processors
diff --git a/include/myisam.h b/include/myisam.h
index f763bf07719..b05440e5ae4 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -274,9 +274,8 @@ extern struct st_myisam_info *mi_open(const char *name,int mode,
uint wait_if_locked);
extern int mi_panic(enum ha_panic_function function);
extern int mi_rfirst(struct st_myisam_info *file,byte *buf,int inx);
-extern int mi_rkey(struct st_myisam_info *file,byte *buf,int inx,
- const byte *key,
- uint key_len, enum ha_rkey_function search_flag);
+extern int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key,
+ key_part_map keypart_map, enum ha_rkey_function search_flag);
extern int mi_rlast(struct st_myisam_info *file,byte *buf,int inx);
extern int mi_rnext(struct st_myisam_info *file,byte *buf,int inx);
extern int mi_rnext_same(struct st_myisam_info *info, byte *buf);
@@ -303,7 +302,7 @@ extern int mi_extra(struct st_myisam_info *file,
enum ha_extra_function function,
void *extra_arg);
extern int mi_reset(struct st_myisam_info *file);
-extern ha_rows mi_records_in_range(struct st_myisam_info *info,int inx,
+extern ha_rows mi_records_in_range(MI_INFO *info, int inx,
key_range *min_key, key_range *max_key);
extern int mi_log(int activate_log);
extern int mi_is_changed(struct st_myisam_info *info);
diff --git a/include/myisammrg.h b/include/myisammrg.h
index 6587613697a..02e81cf806d 100644
--- a/include/myisammrg.h
+++ b/include/myisammrg.h
@@ -86,8 +86,8 @@ extern int myrg_rlast(MYRG_INFO *file,byte *buf,int inx);
extern int myrg_rnext(MYRG_INFO *file,byte *buf,int inx);
extern int myrg_rprev(MYRG_INFO *file,byte *buf,int inx);
extern int myrg_rnext_same(MYRG_INFO *file,byte *buf);
-extern int myrg_rkey(MYRG_INFO *file,byte *buf,int inx,const byte *key,
- uint key_len, enum ha_rkey_function search_flag);
+extern int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
+ key_part_map keypart_map, enum ha_rkey_function search_flag);
extern int myrg_rrnd(MYRG_INFO *file,byte *buf,ulonglong pos);
extern int myrg_rsame(MYRG_INFO *file,byte *record,int inx);
extern int myrg_update(MYRG_INFO *file,const byte *old,byte *new_rec);
@@ -100,7 +100,7 @@ extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function,
void *extra_arg);
extern int myrg_reset(MYRG_INFO *info);
extern void myrg_extrafunc(MYRG_INFO *info,invalidator_by_filename inv);
-extern ha_rows myrg_records_in_range(MYRG_INFO *info,int inx,
+extern ha_rows myrg_records_in_range(MYRG_INFO *info, int inx,
key_range *min_key, key_range *max_key);
extern ulonglong myrg_position(MYRG_INFO *info);
diff --git a/server-tools/CMakeLists.txt b/server-tools/CMakeLists.txt
index 3f02ba88f1d..3f02ba88f1d 100755..100644
--- a/server-tools/CMakeLists.txt
+++ b/server-tools/CMakeLists.txt
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 940930ec4c6..c5d015cdea7 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -288,7 +288,7 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
{
key_copy(key_buf, event_table->record[0], key_info, key_len);
if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
- key_len, HA_READ_PREFIX)))
+ (key_part_map)1, HA_READ_PREFIX)))
{
DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
do
@@ -843,8 +843,7 @@ Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0], 0, key,
- table->key_info->key_length,
+ if (table->file->index_read_idx(table->record[0], 0, key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
DBUG_PRINT("info", ("Row not found"));
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index dfdcffc4e71..bc1c3c8e324 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1104,7 +1104,7 @@ int ha_ndbcluster::create_indexes(Ndb *ndb, TABLE *tab)
KEY* key_info= tab->key_info;
const char **key_name= tab->s->keynames.type_names;
DBUG_ENTER("ha_ndbcluster::create_indexes");
-
+
for (i= 0; i < tab->s->keys; i++, key_info++, key_name++)
{
index_name= *key_name;
@@ -3370,19 +3370,6 @@ int ha_ndbcluster::index_read(byte *buf,
}
-int ha_ndbcluster::index_read_idx(byte *buf, uint index_no,
- const byte *key, uint key_len,
- enum ha_rkey_function find_flag)
-{
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
- DBUG_ENTER("ha_ndbcluster::index_read_idx");
- DBUG_PRINT("enter", ("index_no: %u, key_len: %u", index_no, key_len));
- close_scan();
- index_init(index_no, 0);
- DBUG_RETURN(index_read(buf, key, key_len, find_flag));
-}
-
-
int ha_ndbcluster::index_next(byte *buf)
{
DBUG_ENTER("ha_ndbcluster::index_next");
@@ -3549,10 +3536,10 @@ int ha_ndbcluster::close_scan()
m_multi_cursor= 0;
if (!m_active_cursor && !m_multi_cursor)
- DBUG_RETURN(1);
+ DBUG_RETURN(0);
NdbScanOperation *cursor= m_active_cursor ? m_active_cursor : m_multi_cursor;
-
+
if (m_lock_tuple)
{
/*
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 63665fde0f8..6cc0e423f2f 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -642,8 +642,6 @@ class ha_ndbcluster: public handler
int index_end();
int index_read(byte *buf, const byte *key, uint key_len,
enum ha_rkey_function find_flag);
- int index_read_idx(byte *buf, uint index, const byte *key, uint key_len,
- enum ha_rkey_function find_flag);
int index_next(byte *buf);
int index_prev(byte *buf);
int index_first(byte *buf);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index db0d118c2e0..d3979fa0718 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -3336,13 +3336,14 @@ int ha_partition::index_end()
*/
int ha_partition::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
DBUG_ENTER("ha_partition::index_read");
end_range= 0;
m_index_scan_type= partition_index_read;
- DBUG_RETURN(common_index_read(buf, key, key_len, find_flag));
+ DBUG_RETURN(common_index_read(buf, key, keypart_map, find_flag));
}
@@ -3355,14 +3356,17 @@ int ha_partition::index_read(byte * buf, const byte * key,
see index_read for rest
*/
-int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len,
+int ha_partition::common_index_read(byte *buf, const byte *key,
+ key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
int error;
bool reverse_order= FALSE;
+ uint key_len= calculate_key_len(table, active_index, key, keypart_map);
DBUG_ENTER("ha_partition::common_index_read");
memcpy((void*)m_start_key.key, key, key_len);
+ m_start_key.keypart_map= keypart_map;
m_start_key.length= key_len;
m_start_key.flag= find_flag;
@@ -3491,33 +3495,6 @@ int ha_partition::common_first_last(byte *buf)
/*
- Perform index read using index where always only one row is returned
-
- SYNOPSIS
- index_read_idx()
- see index_read for rest of parameters and return values
-
- DESCRIPTION
- Positions an index cursor to the index specified in key. Fetches the
- row if any. This is only used to read whole keys.
- TODO: Optimise this code to avoid index_init and index_end
-*/
-
-int ha_partition::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len,
- enum ha_rkey_function find_flag)
-{
- int res;
- DBUG_ENTER("ha_partition::index_read_idx");
-
- index_init(index, 0);
- res= index_read(buf, key, key_len, find_flag);
- index_end();
- DBUG_RETURN(res);
-}
-
-
-/*
Read last using key
SYNOPSIS
@@ -3535,14 +3512,15 @@ int ha_partition::index_read_idx(byte * buf, uint index, const byte * key,
Can only be used on indexes supporting HA_READ_ORDER
*/
-int ha_partition::index_read_last(byte *buf, const byte *key, uint keylen)
+int ha_partition::index_read_last(byte *buf, const byte *key,
+ key_part_map keypart_map)
{
DBUG_ENTER("ha_partition::index_read_last");
m_ordered= TRUE; // Safety measure
end_range= 0;
m_index_scan_type= partition_index_read_last;
- DBUG_RETURN(common_index_read(buf, key, keylen, HA_READ_PREFIX_LAST));
+ DBUG_RETURN(common_index_read(buf, key, keypart_map, HA_READ_PREFIX_LAST));
}
@@ -3688,7 +3666,7 @@ int ha_partition::read_range_first(const key_range *start_key,
m_index_scan_type= partition_index_read;
error= common_index_read(m_rec0,
start_key->key,
- start_key->length, start_key->flag);
+ start_key->keypart_map, start_key->flag);
}
DBUG_RETURN(error);
}
@@ -3887,7 +3865,7 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf)
case partition_index_read:
DBUG_PRINT("info", ("index_read on partition %d", i));
error= file->index_read(buf, m_start_key.key,
- m_start_key.length,
+ m_start_key.keypart_map,
m_start_key.flag);
break;
case partition_index_first:
@@ -3979,7 +3957,7 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order)
case partition_index_read:
error= file->index_read(rec_buf_ptr,
m_start_key.key,
- m_start_key.length,
+ m_start_key.keypart_map,
m_start_key.flag);
break;
case partition_index_first:
@@ -3993,7 +3971,7 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order)
case partition_index_read_last:
error= file->index_read_last(rec_buf_ptr,
m_start_key.key,
- m_start_key.length);
+ m_start_key.keypart_map);
reverse_order= TRUE;
break;
default:
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 1069dd058d5..a081e4bb472 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -384,9 +384,8 @@ public:
any end processing needed.
*/
virtual int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- virtual int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
virtual int index_init(uint idx, bool sorted);
virtual int index_end();
@@ -399,7 +398,8 @@ public:
virtual int index_first(byte * buf);
virtual int index_last(byte * buf);
virtual int index_next_same(byte * buf, const byte * key, uint keylen);
- virtual int index_read_last(byte * buf, const byte * key, uint keylen);
+ virtual int index_read_last(byte * buf, const byte * key,
+ key_part_map keypart_map);
/*
read_first_row is virtual method but is only implemented by
@@ -425,7 +425,8 @@ public:
private:
int common_index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
int common_first_last(byte * buf);
int partition_scan_set_up(byte * buf, bool idx_read_flag);
int handle_unordered_next(byte * buf, bool next_same);
diff --git a/sql/handler.cc b/sql/handler.cc
index 23c3103493e..6df8a4a5021 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1843,7 +1843,7 @@ int handler::update_auto_increment()
nr= compute_next_insert_id(nr-1, variables);
}
- if (table->s->next_number_key_offset == 0)
+ if (table->s->next_number_keypart == 0)
{
/* We must defer the appending until "nr" has been possibly truncated */
append= TRUE;
@@ -1963,7 +1963,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
table->read_set);
column_bitmaps_signal();
index_init(table->s->next_number_index, 1);
- if (!table->s->next_number_key_offset)
+ if (table->s->next_number_keypart == 0)
{ // Autoincrement at key-start
error=index_last(table->record[1]);
/*
@@ -1979,7 +1979,8 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
key_copy(key, table->record[0],
table->key_info + table->s->next_number_index,
table->s->next_number_key_offset);
- error= index_read(table->record[1], key, table->s->next_number_key_offset,
+ error= index_read(table->record[1], key,
+ make_prev_keypart_map(table->s->next_number_keypart),
HA_READ_PREFIX_LAST);
/*
MySQL needs to call us for next row: assume we are inserting ("a",null)
@@ -3079,9 +3080,9 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
multi_range_curr < multi_range_end;
multi_range_curr++)
{
- result= read_range_first(multi_range_curr->start_key.length ?
+ result= read_range_first(multi_range_curr->start_key.keypart_map ?
&multi_range_curr->start_key : 0,
- multi_range_curr->end_key.length ?
+ multi_range_curr->end_key.keypart_map ?
&multi_range_curr->end_key : 0,
test(multi_range_curr->range_flag & EQ_RANGE),
multi_range_sorted);
@@ -3146,9 +3147,9 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
multi_range_curr < multi_range_end;
multi_range_curr++)
{
- result= read_range_first(multi_range_curr->start_key.length ?
+ result= read_range_first(multi_range_curr->start_key.keypart_map ?
&multi_range_curr->start_key : 0,
- multi_range_curr->end_key.length ?
+ multi_range_curr->end_key.keypart_map ?
&multi_range_curr->end_key : 0,
test(multi_range_curr->range_flag & EQ_RANGE),
multi_range_sorted);
@@ -3207,7 +3208,7 @@ int handler::read_range_first(const key_range *start_key,
else
result= index_read(table->record[0],
start_key->key,
- start_key->length,
+ start_key->keypart_map,
start_key->flag);
if (result)
DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
@@ -3279,15 +3280,19 @@ int handler::compare_key(key_range *range)
return cmp;
}
+
int handler::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
- int error= ha_index_init(index, 0);
- if (!error)
- error= index_read(buf, key, key_len, find_flag);
+ int error, error1;
+ error= index_init(index, 0);
if (!error)
- error= ha_index_end();
- return error;
+ {
+ error= index_read(buf, key, keypart_map, find_flag);
+ error1= index_end();
+ }
+ return error ? error : error1;
}
diff --git a/sql/handler.h b/sql/handler.h
index 82970cc1ac6..0158cbad515 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -867,6 +867,18 @@ public:
{}
};
+uint calculate_key_len(TABLE *, uint, const byte *, key_part_map);
+/*
+ bitmap with first N+1 bits set
+ (keypart_map for a key prefix of [0..N] keyparts)
+*/
+#define make_keypart_map(N) (((key_part_map)2 << (N)) - 1)
+/*
+ bitmap with first N bits set
+ (keypart_map for a key prefix of [0..N-1] keyparts)
+*/
+#define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1)
+
/*
The handler class is the interface for dynamically loadable
storage engines. Do not add ifdefs and take care when adding or
@@ -1202,11 +1214,32 @@ public:
DBUG_ASSERT(FALSE);
return HA_ERR_WRONG_COMMAND;
}
- virtual int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ private:
+ virtual int index_read(byte * buf, const byte * key, uint key_len,
+ enum ha_rkey_function find_flag)
{ return HA_ERR_WRONG_COMMAND; }
+ public:
+/**
+ @brief
+ Positions an index cursor to the index specified in the handle. Fetches the
+ row if available. If the key value is null, begin at the first key of the
+ index.
+*/
+ virtual int index_read(byte * buf, const byte * key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
+ {
+ uint key_len= calculate_key_len(table, active_index, key, keypart_map);
+ return index_read(buf, key, key_len, find_flag);
+ }
+/**
+ @brief
+ Positions an index cursor to the index specified in the handle. Fetches the
+ row if available. If the key value is null, begin at the first key of the
+ index.
+*/
virtual int index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
virtual int index_next(byte * buf)
{ return HA_ERR_WRONG_COMMAND; }
virtual int index_prev(byte * buf)
@@ -1216,8 +1249,21 @@ public:
virtual int index_last(byte * buf)
{ return HA_ERR_WRONG_COMMAND; }
virtual int index_next_same(byte *buf, const byte *key, uint keylen);
+ private:
virtual int index_read_last(byte * buf, const byte * key, uint key_len)
{ return (my_errno=HA_ERR_WRONG_COMMAND); }
+ public:
+/**
+ @brief
+ The following functions works like index_read, but it find the last
+ row with the current key value or prefix.
+*/
+ virtual int index_read_last(byte * buf, const byte * key,
+ key_part_map keypart_map)
+ {
+ uint key_len= calculate_key_len(table, active_index, key, keypart_map);
+ return index_read_last(buf, key, key_len);
+ }
virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
KEY_MULTI_RANGE *ranges, uint range_count,
bool sorted, HANDLER_BUFFER *buffer);
@@ -1243,8 +1289,7 @@ public:
{ return HA_ERR_WRONG_COMMAND; }
virtual int rnd_same(byte *buf, uint inx)
{ return HA_ERR_WRONG_COMMAND; }
- virtual ha_rows records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
+ virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key)
{ return (ha_rows) 10; }
virtual void position(const byte *record)=0;
virtual int info(uint)=0; // see my_base.h for full description
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 135ed33feec..e1abda2f612 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -2045,7 +2045,8 @@ int subselect_uniquesubquery_engine::exec()
table->file->ha_index_init(tab->ref.key, 0);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT);
if (error &&
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
error= report_error(table, error);
@@ -2154,7 +2155,8 @@ int subselect_indexsubquery_engine::exec()
table->file->ha_index_init(tab->ref.key, 1);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT);
if (error &&
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
error= report_error(table, error);
diff --git a/sql/key.cc b/sql/key.cc
index bd614b10a70..faa7bf1f04b 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -29,6 +29,7 @@
field Field to search after
key_length On partial match, contains length of fields before
field
+ keypart key part # of a field
NOTES
Used when calculating key for NEXT_NUMBER
@@ -45,7 +46,7 @@
*/
int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
- uint *key_length)
+ uint *key_length, uint *keypart)
{
reg2 int i;
reg3 KEY *key_info;
@@ -60,8 +61,8 @@ int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
{
if (key_info->key_part[0].offset == fieldpos)
{ /* Found key. Calc keylength */
- *key_length=0;
- return(i); /* Use this key */
+ *key_length= *keypart= 0;
+ return i; /* Use this key */
}
}
@@ -78,8 +79,11 @@ int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
j++, key_part++)
{
if (key_part->offset == fieldpos)
- return(i); /* Use this key */
- *key_length+=key_part->store_length;
+ {
+ *keypart= j;
+ return i; /* Use this key */
+ }
+ *key_length+= key_part->store_length;
}
}
return(-1); /* No key is ok */
diff --git a/sql/log.cc b/sql/log.cc
index deb77890f35..1994660bf5b 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3773,7 +3773,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
nb_elements()));
/*
If the auto_increment was second in a table's index (possible with
- MyISAM or BDB) (table->next_number_key_offset != 0), such event is
+ MyISAM or BDB) (table->next_number_keypart != 0), such event is
in fact not necessary. We could avoid logging it.
*/
Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
diff --git a/sql/log_event.cc b/sql/log_event.cc
index f8d3c43bfba..0448aacd4f3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -6854,9 +6854,8 @@ replace_record(THD *thd, TABLE *table,
}
key_copy((byte*)key.get(), table->record[0], table->key_info + keynum, 0);
- error= table->file->index_read_idx(table->record[1], keynum,
- (const byte*)key.get(),
- table->key_info[keynum].key_length,
+ error= table->file->index_read_idx(table->record[1], keynum,
+ (const byte*)key.get(), HA_WHOLE_KEY,
HA_READ_KEY_EXACT);
if (error)
DBUG_RETURN(error);
@@ -7040,8 +7039,7 @@ static int find_and_fetch_row(TABLE *table, byte *key)
my_ptrdiff_t const pos=
table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0;
table->record[1][pos]= 0xFF;
- if ((error= table->file->index_read(table->record[1], key,
- table->key_info->key_length,
+ if ((error= table->file->index_read(table->record[1], key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT)))
{
table->file->print_error(error, MYF(0));
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 00dca667bff..099c9b98c1f 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -47,7 +47,6 @@ typedef Bitmap<64> key_map; /* Used for finding keys */
#else
typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
#endif
-typedef ulong key_part_map; /* Used for finding key parts */
typedef ulong nesting_map; /* Used for flags of nesting constructs */
/*
Used to identify NESTED_JOIN structures within a join (applicable only to
@@ -1493,7 +1492,7 @@ void print_plan(JOIN* join,uint idx, double record_count, double read_time,
void mysql_print_status();
/* key.cc */
int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
- uint *key_length);
+ uint *key_length, uint *keypart);
void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length);
void key_restore(byte *to_record, byte *from_key, KEY *key_info,
uint key_length);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index beceb4ba6b7..52faaf25b42 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -312,7 +312,8 @@ public:
min_value=arg->max_value;
min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
}
- void store_min(uint length,char **min_key,uint min_key_flag)
+ /* returns a number of keypart values (0 or 1) appended to the key buffer */
+ int store_min(uint length,char **min_key,uint min_key_flag)
{
if ((min_flag & GEOM_FLAG) ||
(!(min_flag & NO_MIN_RANGE) &&
@@ -326,12 +327,13 @@ public:
else
memcpy(*min_key,min_value,length);
(*min_key)+= length;
+ return 1;
}
+ return 0;
}
- void store(uint length,char **min_key,uint min_key_flag,
- char **max_key, uint max_key_flag)
+ /* returns a number of keypart values (0 or 1) appended to the key buffer */
+ int store_max(uint length,char **max_key, uint max_key_flag)
{
- store_min(length, min_key, min_key_flag);
if (!(max_flag & NO_MAX_RANGE) &&
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
{
@@ -343,33 +345,41 @@ public:
else
memcpy(*max_key,max_value,length);
(*max_key)+= length;
+ return 1;
}
+ return 0;
}
- void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
+ /* returns a number of keypart values appended to the key buffer */
+ int store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
{
SEL_ARG *key_tree= first();
- key_tree->store(key[key_tree->part].store_length,
- range_key,*range_key_flag,range_key,NO_MAX_RANGE);
+ uint res= key_tree->store_min(key[key_tree->part].store_length,
+ range_key, *range_key_flag);
*range_key_flag|= key_tree->min_flag;
if (key_tree->next_key_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
- key_tree->next_key_part->store_min_key(key,range_key, range_key_flag);
+ res+= key_tree->next_key_part->store_min_key(key, range_key,
+ range_key_flag);
+ return res;
}
- void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
+ /* returns a number of keypart values appended to the key buffer */
+ int store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
{
SEL_ARG *key_tree= last();
- key_tree->store(key[key_tree->part].store_length,
- range_key, NO_MIN_RANGE, range_key,*range_key_flag);
+ uint res=key_tree->store_max(key[key_tree->part].store_length,
+ range_key, *range_key_flag);
(*range_key_flag)|= key_tree->max_flag;
if (key_tree->next_key_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
- key_tree->next_key_part->store_max_key(key,range_key, range_key_flag);
+ res+= key_tree->next_key_part->store_max_key(key, range_key,
+ range_key_flag);
+ return res;
}
SEL_ARG *insert(SEL_ARG *key);
@@ -583,11 +593,11 @@ static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field,
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond);
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
-static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree,
+static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree,
bool update_tbl_stats);
static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
- char *min_key,uint min_key_flag,
- char *max_key, uint max_key_flag);
+ char *min_key, uint min_key_flag, int,
+ char *max_key, uint max_key_flag, int);
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
SEL_ARG *key_tree,
@@ -1453,6 +1463,7 @@ QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT()
QUICK_RANGE::QUICK_RANGE()
:min_key(0),max_key(0),min_length(0),max_length(0),
+ min_keypart_map(0), max_keypart_map(0),
flag(NO_MIN_RANGE | NO_MAX_RANGE)
{}
@@ -4031,9 +4042,9 @@ void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
The calculation is conducted as follows:
Lets denote #records(keypart1, ... keypartK) as n_k. We need to calculate
- n_{k1} n_{k_2}
+ n_{k1} n_{k2}
--------- * --------- * .... (3)
- n_{k1-1} n_{k2_1}
+ n_{k1-1} n_{k2-1}
where k1,k2,... are key parts which fields were not yet marked as fixed
( this is result of application of option b) of the recursion step for
@@ -4041,9 +4052,9 @@ void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
Since it is reasonable to expect that most of the fields are not marked
as fixed, we calculate (3) as
- n_{i1} n_{i_2}
+ n_{i1} n_{i2}
(3) = n_{max_key_part} / ( --------- * --------- * .... )
- n_{i1-1} n_{i2_1}
+ n_{i1-1} n_{i2-1}
where i1,i2, .. are key parts that were already marked as fixed.
@@ -4052,7 +4063,6 @@ void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
RETURN
Selectivity of given ROR scan.
-
*/
static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
@@ -4063,6 +4073,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
byte key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
char *key_ptr= (char*) key_val;
SEL_ARG *sel_arg, *tuple_arg= NULL;
+ key_part_map keypart_map= 0;
bool cur_covered;
bool prev_covered= test(bitmap_is_set(&info->covered_fields,
key_part->fieldnr-1));
@@ -4073,7 +4084,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
max_range.key= (byte*) key_val;
max_range.flag= HA_READ_AFTER_KEY;
ha_rows prev_records= info->param->table->file->stats.records;
- DBUG_ENTER("ror_intersect_selectivity");
+ DBUG_ENTER("ror_scan_selectivity");
for (sel_arg= scan->sel_arg; sel_arg;
sel_arg= sel_arg->next_key_part)
@@ -4090,13 +4101,17 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
tuple_arg= scan->sel_arg;
/* Here we use the length of the first key part */
tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
+ keypart_map= 1;
}
while (tuple_arg->next_key_part != sel_arg)
{
tuple_arg= tuple_arg->next_key_part;
- tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0);
+ tuple_arg->store_min(key_part[tuple_arg->part].store_length,
+ &key_ptr, 0);
+ keypart_map= (keypart_map << 1) | 1;
}
min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
+ min_range.keypart_map= max_range.keypart_map= keypart_map;
records= (info->param->table->file->
records_in_range(scan->keynr, &min_range, &max_range));
if (cur_covered)
@@ -5305,12 +5320,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
*/
for (uint i= 1 ; i < cond_func->arg_count ; i++)
{
-
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
{
field_item= (Item_field*) (cond_func->arguments()[i]->real_item());
SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func,
- field_item, (Item*) i, inv);
+ field_item, (Item*)(intptr)i, inv);
if (inv)
tree= !tree ? tmp : tree_or(param, tree, tmp);
else
@@ -7057,7 +7071,9 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree, bool update_tbl_stats)
}
param->n_ranges= 0;
- records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
+ records= check_quick_keys(param, idx, tree,
+ param->min_key, 0, -1,
+ param->max_key, 0, -1);
if (records != HA_POS_ERROR)
{
if (update_tbl_stats)
@@ -7120,12 +7136,13 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree, bool update_tbl_stats)
*/
static ha_rows
-check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
- char *min_key,uint min_key_flag, char *max_key,
- uint max_key_flag)
+check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
+ char *min_key, uint min_key_flag, int min_keypart,
+ char *max_key, uint max_key_flag, int max_keypart)
{
ha_rows records=0, tmp;
uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length;
+ uint tmp_min_keypart= min_keypart, tmp_max_keypart= max_keypart;
char *tmp_min_key, *tmp_max_key;
uint8 save_first_null_comp= param->first_null_comp;
@@ -7139,18 +7156,21 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
This is not a ROR scan if the key is not Clustered Primary Key.
*/
param->is_ror_scan= FALSE;
- records=check_quick_keys(param,idx,key_tree->left,min_key,min_key_flag,
- max_key,max_key_flag);
+ records=check_quick_keys(param, idx, key_tree->left,
+ min_key, min_key_flag, min_keypart,
+ max_key, max_key_flag, max_keypart);
if (records == HA_POS_ERROR) // Impossible
return records;
}
tmp_min_key= min_key;
tmp_max_key= max_key;
- key_tree->store(param->key[idx][key_tree->part].store_length,
- &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
- min_key_length= (uint) (tmp_min_key- param->min_key);
- max_key_length= (uint) (tmp_max_key- param->max_key);
+ tmp_min_keypart+= key_tree->store_min(param->key[idx][key_tree->part].store_length,
+ &tmp_min_key, min_key_flag);
+ tmp_max_keypart+= key_tree->store_max(param->key[idx][key_tree->part].store_length,
+ &tmp_max_key, max_key_flag);
+ min_key_length= (uint) (tmp_min_key - param->min_key);
+ max_key_length= (uint) (tmp_max_key - param->max_key);
if (param->is_ror_scan)
{
@@ -7173,12 +7193,13 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
{ // const key as prefix
if (min_key_length == max_key_length &&
- !memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
+ !memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) &&
!key_tree->min_flag && !key_tree->max_flag)
{
- tmp=check_quick_keys(param,idx,key_tree->next_key_part,
- tmp_min_key, min_key_flag | key_tree->min_flag,
- tmp_max_key, max_key_flag | key_tree->max_flag);
+ tmp=check_quick_keys(param,idx,key_tree->next_key_part, tmp_min_key,
+ min_key_flag | key_tree->min_flag, tmp_min_keypart,
+ tmp_max_key, max_key_flag | key_tree->max_flag,
+ tmp_max_keypart);
goto end; // Ugly, but efficient
}
else
@@ -7190,18 +7211,20 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
tmp_min_flag=key_tree->min_flag;
tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
+ tmp_min_keypart+=
key_tree->next_key_part->store_min_key(param->key[idx], &tmp_min_key,
&tmp_min_flag);
if (!tmp_max_flag)
+ tmp_max_keypart+=
key_tree->next_key_part->store_max_key(param->key[idx], &tmp_max_key,
&tmp_max_flag);
- min_key_length= (uint) (tmp_min_key- param->min_key);
- max_key_length= (uint) (tmp_max_key- param->max_key);
+ min_key_length= (uint) (tmp_min_key - param->min_key);
+ max_key_length= (uint) (tmp_max_key - param->max_key);
}
else
{
- tmp_min_flag=min_key_flag | key_tree->min_flag;
- tmp_max_flag=max_key_flag | key_tree->max_flag;
+ tmp_min_flag= min_key_flag | key_tree->min_flag;
+ tmp_max_flag= max_key_flag | key_tree->max_flag;
}
keynr=param->real_keynr[idx];
@@ -7209,9 +7232,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
if (!tmp_min_flag && ! tmp_max_flag &&
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
(param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
- HA_NOSAME &&
- min_key_length == max_key_length &&
- !memcmp(param->min_key,param->max_key,min_key_length) &&
+ HA_NOSAME && min_key_length == max_key_length &&
+ !memcmp(param->min_key, param->max_key, min_key_length) &&
!param->first_null_comp)
{
tmp=1; // Max one record
@@ -7231,7 +7253,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
first members of clustered primary key.
*/
if (!(min_key_length == max_key_length &&
- !memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
+ !memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) &&
!key_tree->min_flag && !key_tree->max_flag &&
is_key_scan_ror(param, keynr, key_tree->part + 1)))
param->is_ror_scan= FALSE;
@@ -7243,11 +7265,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
key_range min_range;
min_range.key= (byte*) param->min_key;
min_range.length= min_key_length;
+ min_range.keypart_map= make_keypart_map(tmp_min_keypart);
/* In this case tmp_min_flag contains the handler-read-function */
min_range.flag= (ha_rkey_function) (tmp_min_flag ^ GEOM_FLAG);
- tmp= param->table->file->records_in_range(keynr, &min_range,
- (key_range*) 0);
+ tmp= param->table->file->records_in_range(keynr,
+ &min_range, (key_range*) 0);
}
else
{
@@ -7257,10 +7280,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
min_range.length= min_key_length;
min_range.flag= (tmp_min_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
HA_READ_KEY_EXACT);
+ min_range.keypart_map= make_keypart_map(tmp_min_keypart);
max_range.key= (byte*) param->max_key;
max_range.length= max_key_length;
max_range.flag= (tmp_max_flag & NEAR_MAX ?
HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY);
+ max_range.keypart_map= make_keypart_map(tmp_max_keypart);
tmp=param->table->file->records_in_range(keynr,
(min_key_length ? &min_range :
(key_range*) 0),
@@ -7281,8 +7306,9 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
This is not a ROR scan if the key is not Clustered Primary Key.
*/
param->is_ror_scan= FALSE;
- tmp=check_quick_keys(param,idx,key_tree->right,min_key,min_key_flag,
- max_key,max_key_flag);
+ tmp=check_quick_keys(param, idx, key_tree->right,
+ min_key, min_key_flag, min_keypart,
+ max_key, max_key_flag, max_keypart);
if (tmp == HA_POS_ERROR)
return tmp;
records+=tmp;
@@ -7429,6 +7455,8 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
{
QUICK_RANGE *range;
uint flag;
+ int min_part= key_tree->part-1, // # of keypart values in min_key buffer
+ max_part= key_tree->part-1; // # of keypart values in max_key buffer
if (key_tree->left != &null_element)
{
@@ -7437,16 +7465,18 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
return 1;
}
char *tmp_min_key=min_key,*tmp_max_key=max_key;
- key_tree->store(key[key_tree->part].store_length,
- &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
+ min_part+= key_tree->store_min(key[key_tree->part].store_length,
+ &tmp_min_key,min_key_flag);
+ max_part+= key_tree->store_max(key[key_tree->part].store_length,
+ &tmp_max_key,max_key_flag);
if (key_tree->next_key_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
{ // const key as prefix
- if (!((tmp_min_key - min_key) != (tmp_max_key - max_key) ||
- memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) ||
- key_tree->min_flag || key_tree->max_flag))
+ if ((tmp_min_key - min_key) == (tmp_max_key - max_key) &&
+ memcmp(min_key, max_key, (uint)(tmp_max_key - max_key))==0 &&
+ key_tree->min_flag==0 && key_tree->max_flag==0)
{
if (get_quick_keys(param,quick,key,key_tree->next_key_part,
tmp_min_key, min_key_flag | key_tree->min_flag,
@@ -7457,10 +7487,10 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
{
uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
- key_tree->next_key_part->store_min_key(key, &tmp_min_key,
+ min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
&tmp_min_flag);
if (!tmp_max_flag)
- key_tree->next_key_part->store_max_key(key, &tmp_max_key,
+ max_part+= key_tree->next_key_part->store_max_key(key, &tmp_max_key,
&tmp_max_flag);
flag=tmp_min_flag | tmp_max_flag;
}
@@ -7511,13 +7541,15 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
/* Get range for retrieving rows in QUICK_SELECT::get_next */
if (!(range= new QUICK_RANGE((const char *) param->min_key,
(uint) (tmp_min_key - param->min_key),
+ min_part >=0 ? make_keypart_map(min_part) : 0,
(const char *) param->max_key,
(uint) (tmp_max_key - param->max_key),
+ max_part >=0 ? make_keypart_map(max_part) : 0,
flag)))
return 1; // out of memory
- set_if_bigger(quick->max_used_key_length,range->min_length);
- set_if_bigger(quick->max_used_key_length,range->max_length);
+ set_if_bigger(quick->max_used_key_length, range->min_length);
+ set_if_bigger(quick->max_used_key_length, range->max_length);
set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
if (insert_dynamic(&quick->ranges, (gptr)&range))
return 1;
@@ -7615,13 +7647,13 @@ bool QUICK_ROR_UNION_SELECT::is_keys_used(const MY_BITMAP *fields)
thd Thread handle
table Table to access
ref ref[_or_null] scan parameters
- records Estimate of number of records (needed only to construct
+ records Estimate of number of records (needed only to construct
quick select)
NOTES
This allocates things in a new memory root, as this may be called many
times during a query.
-
- RETURN
+
+ RETURN
Quick select that retrieves the same rows as passed ref scan
NULL on error.
*/
@@ -7657,8 +7689,10 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
!(range= new(alloc) QUICK_RANGE()))
goto err; // out of memory
- range->min_key=range->max_key=(char*) ref->key_buff;
- range->min_length=range->max_length=ref->key_length;
+ range->min_key= range->max_key= (char*) ref->key_buff;
+ range->min_length= range->max_length= ref->key_length;
+ range->min_keypart_map= range->max_keypart_map=
+ make_prev_keypart_map(ref->key_parts);
range->flag= ((ref->key_length == key_info->key_length &&
(key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
HA_NOSAME) ? EQ_RANGE : 0);
@@ -7671,7 +7705,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
{
key_part->part=part;
key_part->field= key_info->key_part[part].field;
- key_part->length= key_info->key_part[part].length;
+ key_part->length= key_info->key_part[part].length;
key_part->store_length= key_info->key_part[part].store_length;
key_part->null_bit= key_info->key_part[part].null_bit;
key_part->flag= (uint8) key_info->key_part[part].key_part_flag;
@@ -7690,11 +7724,11 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
QUICK_RANGE *null_range;
*ref->null_ref_key= 1; // Set null byte then create a range
- if (!(null_range= new (alloc) QUICK_RANGE((char*)ref->key_buff,
- ref->key_length,
- (char*)ref->key_buff,
- ref->key_length,
- EQ_RANGE)))
+ if (!(null_range= new (alloc)
+ QUICK_RANGE((char*)ref->key_buff, ref->key_length,
+ make_prev_keypart_map(ref->key_parts),
+ (char*)ref->key_buff, ref->key_length,
+ make_prev_keypart_map(ref->key_parts), EQ_RANGE)))
goto err;
*ref->null_ref_key= 0; // Clear null byte
if (insert_dynamic(&quick->ranges,(gptr)&null_range))
@@ -8146,6 +8180,7 @@ int QUICK_RANGE_SELECT::get_next()
start_key->flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
(last_range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
+ start_key->keypart_map= last_range->min_keypart_map;
end_key->key= (const byte*) last_range->max_key;
end_key->length= last_range->max_length;
/*
@@ -8154,6 +8189,7 @@ int QUICK_RANGE_SELECT::get_next()
*/
end_key->flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
HA_READ_AFTER_KEY);
+ end_key->keypart_map= last_range->max_keypart_map;
mrange_slot->range_flag= last_range->flag;
}
@@ -8203,7 +8239,9 @@ end:
other if some error occurred
*/
-int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
+int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
+ key_part_map keypart_map,
+ byte *cur_prefix)
{
DBUG_ENTER("QUICK_RANGE_SELECT::get_next_prefix");
@@ -8215,8 +8253,7 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
{
/* Read the next record in the same range with prefix after cur_prefix. */
DBUG_ASSERT(cur_prefix != 0);
- result= file->index_read(record, cur_prefix, prefix_length,
- HA_READ_AFTER_KEY);
+ result= file->index_read(record, cur_prefix, keypart_map, HA_READ_AFTER_KEY);
if (result || (file->compare_key(file->end_range) <= 0))
DBUG_RETURN(result);
}
@@ -8232,11 +8269,13 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
start_key.key= (const byte*) last_range->min_key;
start_key.length= min(last_range->min_length, prefix_length);
+ start_key.keypart_map= last_range->min_keypart_map & keypart_map;
start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
(last_range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
end_key.key= (const byte*) last_range->max_key;
end_key.length= min(last_range->max_length, prefix_length);
+ end_key.keypart_map= last_range->max_keypart_map & keypart_map;
/*
We use READ_AFTER_KEY here because if we are reading on a key
prefix we want to find all keys with this prefix
@@ -8244,8 +8283,8 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
end_key.flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
HA_READ_AFTER_KEY);
- result= file->read_range_first(last_range->min_length ? &start_key : 0,
- last_range->max_length ? &end_key : 0,
+ result= file->read_range_first(last_range->min_keypart_map ? &start_key : 0,
+ last_range->max_keypart_map ? &end_key : 0,
test(last_range->flag & EQ_RANGE),
sorted);
if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE))
@@ -8285,9 +8324,8 @@ int QUICK_RANGE_SELECT_GEOM::get_next()
}
last_range= *(cur_range++);
- result= file->index_read(record,
- (byte*) last_range->min_key,
- last_range->min_length,
+ result= file->index_read(record, (byte*) last_range->min_key,
+ last_range->min_keypart_map,
(ha_rkey_function)(last_range->flag ^ GEOM_FLAG));
if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
@@ -8419,15 +8457,15 @@ int QUICK_SELECT_DESC::get_next()
if (last_range->flag & EQ_RANGE)
{
- result= file->index_read(record, (byte*) last_range->max_key,
- last_range->max_length, HA_READ_KEY_EXACT);
+ result = file->index_read(record, (byte*) last_range->max_key,
+ last_range->max_keypart_map, HA_READ_KEY_EXACT);
}
else
{
DBUG_ASSERT(last_range->flag & NEAR_MAX ||
range_reads_after_key(last_range));
result=file->index_read(record, (byte*) last_range->max_key,
- last_range->max_length,
+ last_range->max_keypart_map,
((last_range->flag & NEAR_MAX) ?
HA_READ_BEFORE_KEY :
HA_READ_PREFIX_LAST_OR_PREV));
@@ -8747,8 +8785,7 @@ void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names,
static inline uint get_field_keypart(KEY *index, Field *field);
static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
PARAM *param, uint *param_idx);
-static bool
-get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
+static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
KEY_PART_INFO *first_non_group_part,
KEY_PART_INFO *min_max_arg_part,
KEY_PART_INFO *last_part, THD *thd,
@@ -9146,7 +9183,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
NULL;
first_non_infix_part= min_max_arg_part ?
(min_max_arg_part < last_part) ?
- min_max_arg_part + 1 :
+ min_max_arg_part :
NULL :
NULL;
if (first_non_group_part &&
@@ -9203,7 +9240,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
if (first_non_infix_part)
{
- for (cur_part= first_non_infix_part; cur_part != last_part; cur_part++)
+ cur_part= first_non_infix_part +
+ (min_max_arg_part && (min_max_arg_part < last_part));
+ for (; cur_part != last_part; cur_part++)
{
if (bitmap_is_set(table->read_set, cur_part->field->field_index))
goto next_index;
@@ -9749,7 +9788,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
RETURN
New QUICK_GROUP_MIN_MAX_SELECT object if successfully created,
- NULL o/w.
+ NULL otherwise.
*/
QUICK_SELECT_I *
@@ -9762,10 +9801,10 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
param->thd->lex->current_select->join,
have_min, have_max, min_max_arg_part,
- group_prefix_len, used_key_parts,
- index_info, index, read_cost, records,
- key_infix_len, key_infix,
- parent_alloc);
+ group_prefix_len, group_key_parts,
+ used_key_parts, index_info, index,
+ read_cost, records, key_infix_len,
+ key_infix, parent_alloc);
if (!quick)
DBUG_RETURN(NULL);
@@ -9854,7 +9893,7 @@ QUICK_GROUP_MIN_MAX_SELECT::
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
bool have_max_arg,
KEY_PART_INFO *min_max_arg_part_arg,
- uint group_prefix_len_arg,
+ uint group_prefix_len_arg, uint group_key_parts_arg,
uint used_key_parts_arg, KEY *index_info_arg,
uint use_index, double read_cost_arg,
ha_rows records_arg, uint key_infix_len_arg,
@@ -9864,7 +9903,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
have_max(have_max_arg), seen_first_key(FALSE),
min_max_arg_part(min_max_arg_part_arg), key_infix(key_infix_arg),
key_infix_len(key_infix_len_arg), min_functions_it(NULL),
- max_functions_it(NULL)
+ max_functions_it(NULL), group_key_parts(group_key_parts_arg)
{
head= table;
file= head->file;
@@ -9874,6 +9913,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
read_time= read_cost_arg;
records= records_arg;
used_key_parts= used_key_parts_arg;
+ real_key_parts= used_key_parts_arg;
real_prefix_len= group_prefix_len + key_infix_len;
group_prefix= NULL;
min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
@@ -10040,7 +10080,9 @@ bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
range_flag|= EQ_RANGE; /* equality condition */
}
range= new QUICK_RANGE(sel_range->min_value, min_max_arg_len,
+ make_keypart_map(sel_range->part),
sel_range->max_value, min_max_arg_len,
+ make_keypart_map(sel_range->part),
range_flag);
if (!range)
return TRUE;
@@ -10279,7 +10321,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
first sub-group with the extended prefix.
*/
if (!have_min && !have_max && key_infix_len > 0)
- result= file->index_read(record, group_prefix, real_prefix_len,
+ result= file->index_read(record, group_prefix,
+ make_prev_keypart_map(real_key_parts),
HA_READ_KEY_EXACT);
result= have_min ? min_res : have_max ? max_res : result;
@@ -10342,7 +10385,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
/* Apply the constant equality conditions to the non-group select fields */
if (key_infix_len > 0)
{
- if ((result= file->index_read(record, group_prefix, real_prefix_len,
+ if ((result= file->index_read(record, group_prefix,
+ make_prev_keypart_map(real_key_parts),
HA_READ_KEY_EXACT)))
DBUG_RETURN(result);
}
@@ -10359,7 +10403,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
/* Find the first subsequent record without NULL in the MIN/MAX field. */
key_copy(tmp_record, record, index_info, 0);
result= file->index_read(record, tmp_record,
- real_prefix_len + min_max_arg_len,
+ make_keypart_map(real_key_parts),
HA_READ_AFTER_KEY);
/*
Check if the new record belongs to the current group by comparing its
@@ -10415,7 +10459,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max()
if (min_max_ranges.elements > 0)
result= next_max_in_range();
else
- result= file->index_read(record, group_prefix, real_prefix_len,
+ result= file->index_read(record, group_prefix,
+ make_prev_keypart_map(real_key_parts),
HA_READ_PREFIX_LAST);
DBUG_RETURN(result);
}
@@ -10451,7 +10496,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
{
byte *cur_prefix= seen_first_key ? group_prefix : NULL;
if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
- cur_prefix)))
+ make_prev_keypart_map(group_key_parts), cur_prefix)))
DBUG_RETURN(result);
seen_first_key= TRUE;
}
@@ -10467,7 +10512,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
else
{
/* Load the first key in this group into record. */
- result= file->index_read(record, group_prefix, group_prefix_len,
+ result= file->index_read(record, group_prefix,
+ make_prev_keypart_map(group_key_parts),
HA_READ_AFTER_KEY);
if (result)
DBUG_RETURN(result);
@@ -10509,7 +10555,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
{
ha_rkey_function find_flag;
- uint search_prefix_len;
+ key_part_map keypart_map;
QUICK_RANGE *cur_range;
bool found_null= FALSE;
int result= HA_ERR_KEY_NOT_FOUND;
@@ -10531,22 +10577,21 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
if (cur_range->flag & NO_MIN_RANGE)
{
+ keypart_map= make_prev_keypart_map(real_key_parts);
find_flag= HA_READ_KEY_EXACT;
- search_prefix_len= real_prefix_len;
}
else
{
/* Extend the search key with the lower boundary for this range. */
memcpy(group_prefix + real_prefix_len, cur_range->min_key,
cur_range->min_length);
- search_prefix_len= real_prefix_len + min_max_arg_len;
+ keypart_map= make_keypart_map(real_key_parts);
find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
}
- result= file->index_read(record, group_prefix, search_prefix_len,
- find_flag);
+ result= file->index_read(record, group_prefix, keypart_map, find_flag);
if (result)
{
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
@@ -10643,7 +10688,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
{
ha_rkey_function find_flag;
- uint search_prefix_len;
+ key_part_map keypart_map;
QUICK_RANGE *cur_range;
int result;
@@ -10665,22 +10710,21 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
if (cur_range->flag & NO_MAX_RANGE)
{
+ keypart_map= make_prev_keypart_map(real_key_parts);
find_flag= HA_READ_PREFIX_LAST;
- search_prefix_len= real_prefix_len;
}
else
{
/* Extend the search key with the upper boundary for this range. */
memcpy(group_prefix + real_prefix_len, cur_range->max_key,
cur_range->max_length);
- search_prefix_len= real_prefix_len + min_max_arg_len;
+ keypart_map= make_keypart_map(real_key_parts);
find_flag= (cur_range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
}
- result= file->index_read(record, group_prefix, search_prefix_len,
- find_flag);
+ result= file->index_read(record, group_prefix, keypart_map, find_flag);
if (result)
{
diff --git a/sql/opt_range.h b/sql/opt_range.h
index d82e1dc459e..1ad9567cddd 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -37,17 +37,23 @@ class QUICK_RANGE :public Sql_alloc {
public:
char *min_key,*max_key;
uint16 min_length,max_length,flag;
+ key_part_map min_keypart_map, // bitmap of used keyparts in min_key
+ max_keypart_map; // bitmap of used keyparts in max_key
#ifdef HAVE_purify
uint16 dummy; /* Avoid warnings on 'flag' */
#endif
QUICK_RANGE(); /* Full range */
- QUICK_RANGE(const char *min_key_arg,uint min_length_arg,
- const char *max_key_arg,uint max_length_arg,
+ QUICK_RANGE(const char *min_key_arg, uint min_length_arg,
+ key_part_map min_keypart_map_arg,
+ const char *max_key_arg, uint max_length_arg,
+ key_part_map max_keypart_map_arg,
uint flag_arg)
: min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)),
max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)),
min_length((uint16) min_length_arg),
max_length((uint16) max_length_arg),
+ min_keypart_map(min_keypart_map_arg),
+ max_keypart_map(max_keypart_map_arg),
flag((uint16) flag_arg)
{
#ifdef HAVE_purify
@@ -60,11 +66,11 @@ class QUICK_RANGE :public Sql_alloc {
/*
Quick select interface.
This class is a parent for all QUICK_*_SELECT and FT_SELECT classes.
-
+
The usage scenario is as follows:
1. Create quick select
quick= new QUICK_XXX_SELECT(...);
-
+
2. Perform lightweight initialization. This can be done in 2 ways:
2.a: Regular initialization
if (quick->init())
@@ -75,29 +81,29 @@ class QUICK_RANGE :public Sql_alloc {
2.b: Special initialization for quick selects merged by QUICK_ROR_*_SELECT
if (quick->init_ror_merged_scan())
delete quick;
-
+
3. Perform zero, one, or more scans.
while (...)
{
// initialize quick select for scan. This may allocate
- // buffers and/or prefetch rows.
+ // buffers and/or prefetch rows.
if (quick->reset())
{
//the only valid action after failed reset() call is delete
delete quick;
//abort query
}
-
+
// perform the scan
do
{
res= quick->get_next();
} while (res && ...)
}
-
+
4. Delete the select:
delete quick;
-
+
*/
class QUICK_SELECT_I
@@ -123,6 +129,8 @@ public:
Max. number of (first) key parts this quick select uses for retrieval.
eg. for "(key1p1=c1 AND key1p2=c2) OR key1p1=c2" used_key_parts == 2.
Applicable if index!= MAX_KEY.
+
+ For QUICK_GROUP_MIN_MAX_SELECT it includes MIN/MAX argument keyparts.
*/
uint used_key_parts;
@@ -318,7 +326,8 @@ public:
int reset(void);
int get_next();
void range_end();
- int get_next_prefix(uint prefix_length, byte *cur_prefix);
+ int get_next_prefix(uint prefix_length, key_part_map keypart_map,
+ byte *cur_prefix);
bool reverse_sorted() { return 0; }
bool unique_key_range();
int init_ror_merged_scan(bool reuse_handler);
@@ -605,6 +614,7 @@ private:
byte *tmp_record; /* Temporary storage for next_min(), next_max(). */
byte *group_prefix; /* Key prefix consisting of the GROUP fields. */
uint group_prefix_len; /* Length of the group prefix. */
+ uint group_key_parts; /* A number of keyparts in the group prefix */
byte *last_prefix; /* Prefix of the last group for detecting EOF. */
bool have_min; /* Specify whether we are computing */
bool have_max; /* a MIN, a MAX, or both. */
@@ -616,6 +626,7 @@ private:
uint key_infix_len;
DYNAMIC_ARRAY min_max_ranges; /* Array of range ptrs for the MIN/MAX field. */
uint real_prefix_len; /* Length of key prefix extended with key_infix. */
+ uint real_key_parts; /* A number of keyparts in the above value. */
List<Item_sum> *min_functions;
List<Item_sum> *max_functions;
List_iterator<Item_sum> *min_functions_it;
@@ -638,10 +649,11 @@ private:
public:
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
bool have_max, KEY_PART_INFO *min_max_arg_part,
- uint group_prefix_len, uint used_key_parts,
- KEY *index_info, uint use_index, double read_cost,
- ha_rows records, uint key_infix_len,
- byte *key_infix, MEM_ROOT *parent_alloc);
+ uint group_prefix_len, uint group_key_parts,
+ uint used_key_parts, KEY *index_info, uint
+ use_index, double read_cost, ha_rows records, uint
+ key_infix_len, byte *key_infix, MEM_ROOT
+ *parent_alloc);
~QUICK_GROUP_MIN_MAX_SELECT();
bool add_range(SEL_ARG *sel_range);
void update_key_stat();
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 5bd5ec4b42d..f9a06f3fb6e 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -251,7 +251,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
error= table->file->index_first(table->record[0]);
else
error= table->file->index_read(table->record[0],key_buff,
- ref.key_length,
+ make_prev_keypart_map(ref.key_parts),
range_fl & NEAR_MIN ?
HA_READ_AFTER_KEY :
HA_READ_KEY_OR_NEXT);
@@ -338,11 +338,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
error= table->file->index_last(table->record[0]);
else
error= table->file->index_read(table->record[0], key_buff,
- ref.key_length,
+ make_prev_keypart_map(ref.key_parts),
range_fl & NEAR_MAX ?
HA_READ_BEFORE_KEY :
HA_READ_PREFIX_LAST_OR_PREV);
- if (!error && reckey_in_range(1, &ref, item_field->field,
+ if (!error && reckey_in_range(1, &ref, item_field->field,
conds, range_fl, prefix_len))
error= HA_ERR_KEY_NOT_FOUND;
if (table->key_read)
@@ -605,15 +605,13 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
/* Check if field is part of the tested partial key */
byte *key_ptr= ref->key_buff;
KEY_PART_INFO *part;
- for (part= keyinfo->key_part;
- ;
- key_ptr+= part++->store_length)
+ for (part= keyinfo->key_part; ; key_ptr+= part++->store_length)
{
if (part > field_part)
return 0; // Field is beyond the tested parts
if (part->field->eq(((Item_field*) args[0])->field))
- break; // Found a part od the key for the field
+ break; // Found a part of the key for the field
}
bool is_field_part= part == field_part;
@@ -625,8 +623,11 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
{
uint length= (key_ptr-ref->key_buff)+part->store_length;
if (ref->key_length < length)
+ {
/* Ultimately ref->key_length will contain the length of the search key */
ref->key_length= length;
+ ref->key_parts= (part - keyinfo->key_part) + 1;
+ }
if (!*prefix_len && part+1 == field_part)
*prefix_len= length;
if (is_field_part && eq_type)
@@ -773,6 +774,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
{
ref->key= idx;
ref->key_length= 0;
+ ref->key_parts= 0;
key_part_map key_part_used= 0;
*range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
if (matching_cond(max_fl, ref, keyinfo, part, cond,
@@ -788,6 +790,8 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
*/
ref->key_buff[ref->key_length]= 1;
ref->key_length+= part->store_length;
+ ref->key_parts++;
+ DBUG_ASSERT(ref->key_parts == jdx+1);
*range_fl&= ~NO_MIN_RANGE;
*range_fl|= NEAR_MIN; // > NULL
}
diff --git a/sql/slave.cc b/sql/slave.cc
index 6f62f74647a..6bd5fd3da21 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -31,6 +31,8 @@
#include "rpl_tblmap.h"
int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
+static Log_event* next_event(RELAY_LOG_INFO* rli);
+
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
diff --git a/sql/sp.cc b/sql/sp.cc
index 0c0bc8e8869..eef5dc01912 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -218,8 +218,7 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
key_copy(key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0], 0,
- key, table->key_info->key_length,
+ if (table->file->index_read_idx(table->record[0], 0, key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
DBUG_RETURN(SP_KEY_NOT_FOUND);
@@ -925,7 +924,7 @@ sp_drop_db_routines(THD *thd, char *db)
table->file->ha_index_init(0, 1);
if (! table->file->index_read(table->record[0],
(byte *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
- key_len, HA_READ_KEY_EXACT))
+ (key_part_map)1, HA_READ_KEY_EXACT))
{
int nxtres;
bool deleted= FALSE;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index e9122723e5a..aaa88071173 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1813,8 +1813,7 @@ static bool update_user_table(THD *thd, TABLE *table,
table->key_info->key_length);
if (table->file->index_read_idx(table->record[0], 0,
- (byte *) user_key,
- table->key_info->key_length,
+ (byte *) user_key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
@@ -1905,8 +1904,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0], 0,
- user_key, table->key_info->key_length,
+ if (table->file->index_read_idx(table->record[0], 0, user_key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
/* what == 'N' means revoke */
@@ -2123,8 +2121,7 @@ static int replace_db_table(TABLE *table, const char *db,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0],0,
- user_key, table->key_info->key_length,
+ if (table->file->index_read_idx(table->record[0],0, user_key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
if (what == 'N')
@@ -2341,9 +2338,8 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
col_privs->field[4]->store("",0, &my_charset_latin1);
col_privs->file->ha_index_init(0, 1);
- if (col_privs->file->index_read(col_privs->record[0],
- (byte*) key,
- key_prefix_len, HA_READ_KEY_EXACT))
+ if (col_privs->file->index_read(col_privs->record[0], (byte*) key,
+ (key_part_map)15, HA_READ_KEY_EXACT))
{
cols = 0; /* purecov: deadcode */
col_privs->file->ha_index_end();
@@ -2479,7 +2475,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
table->field[3]->store(table_name,(uint) strlen(table_name),
system_charset_info);
- /* Get length of 3 first key parts */
+ /* Get length of 4 first key parts */
key_prefix_length= (key_part[0].store_length + key_part[1].store_length +
key_part[2].store_length + key_part[3].store_length);
key_copy(key, table->record[0], table->key_info, key_prefix_length);
@@ -2505,8 +2501,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read(table->record[0], user_key,
- table->key_info->key_length,
+ if (table->file->index_read(table->record[0], user_key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
if (revoke_grant)
@@ -2582,8 +2577,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_copy(user_key, table->record[0], table->key_info,
key_prefix_length);
- if (table->file->index_read(table->record[0], user_key,
- key_prefix_length,
+ if (table->file->index_read(table->record[0], user_key, (key_part_map)15,
HA_READ_KEY_EXACT))
goto end;
@@ -2684,8 +2678,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0], 0,
- user_key, table->key_info->key_length,
+ if (table->file->index_read_idx(table->record[0], 0, user_key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
/*
@@ -2803,13 +2796,13 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
table->field[3]->store(routine_name,(uint) strlen(routine_name),
&my_charset_latin1);
- table->field[4]->store((longlong)(is_proc ?
+ table->field[4]->store((longlong)(is_proc ?
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION),
TRUE);
store_record(table,record[1]); // store at pos 1
- if (table->file->index_read_idx(table->record[0],0,
- (byte*) table->field[0]->ptr,0,
+ if (table->file->index_read_idx(table->record[0], 0,
+ (byte*) table->field[0]->ptr, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
/*
@@ -5008,7 +5001,7 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
if ((error= table->file->index_read_idx(table->record[0], 0,
- user_key, key_prefix_length,
+ user_key, (key_part_map)3,
HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 91e61be0478..cd87330cedb 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -515,7 +515,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
List_iterator<Item> it_ke(*key_expr);
Item *item;
- for (key_len=0 ; (item=it_ke++) ; key_part++)
+ key_part_map keypart_map;
+ for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++)
{
my_bitmap_map *old_map;
// 'item' can be changed by fix_fields() call
@@ -532,6 +533,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
(void) item->save_in_field(key_part->field, 1);
dbug_tmp_restore_column_map(table->write_set, old_map);
key_len+=key_part->store_length;
+ keypart_map= (keypart_map << 1) | 1;
}
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
@@ -540,7 +542,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
table->file->ha_index_init(keyno, 1);
key_copy(key, table->record[0], table->key_info + keyno, key_len);
error= table->file->index_read(table->record[0],
- key,key_len,ha_rkey_mode);
+ key, keypart_map, ha_rkey_mode);
mode=rkey_to_rnext[(int)ha_rkey_mode];
break;
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 6cb87c7e601..b677111c019 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -295,8 +295,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
rkey_id->store((longlong) key_id, TRUE);
rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
- (byte *) buff,
- rkey_id->pack_length(),
+ (byte *) buff, (key_part_map)1,
HA_READ_KEY_EXACT);
for ( ;
@@ -310,7 +309,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW);
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
- field->pack_length(), HA_READ_KEY_EXACT))
+ (key_part_map)1, HA_READ_KEY_EXACT))
{
memorize_variant_topic(thd,topics,count,find_fields,
names,name,description,example);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 52f3fd507e4..3ba8963a700 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1214,9 +1214,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
key_copy((byte*) key,table->record[0],table->key_info+key_nr,0);
if ((error=(table->file->index_read_idx(table->record[1],key_nr,
- (byte*) key,
- table->key_info[key_nr].
- key_length,
+ (byte*) key, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))))
goto err;
}
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index e3e24c1f375..70bc9ef23d5 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -943,8 +943,7 @@ my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
table->use_all_columns();
table->field[0]->store(name->str, name->length, system_charset_info);
if (! table->file->index_read_idx(table->record[0], 0,
- (byte *)table->field[0]->ptr,
- table->key_info[0].key_length,
+ (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
int error;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index efdedcc5e84..8184b2a732e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -10980,7 +10980,8 @@ int safe_index_read(JOIN_TAB *tab)
TABLE *table= tab->table;
if ((error=table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length, HA_READ_KEY_EXACT)))
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT)))
return report_error(table, error);
return 0;
}
@@ -11118,7 +11119,8 @@ join_read_const(JOIN_TAB *tab)
{
error=table->file->index_read_idx(table->record[0],tab->ref.key,
(byte*) tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT);
}
if (error)
{
@@ -11161,7 +11163,8 @@ join_read_key(JOIN_TAB *tab)
}
error=table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT);
if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
}
@@ -11189,7 +11192,8 @@ join_read_always_key(JOIN_TAB *tab)
return -1;
if ((error=table->file->index_read(table->record[0],
tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT)))
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -11215,8 +11219,7 @@ join_read_last_key(JOIN_TAB *tab)
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
return -1;
if ((error=table->file->index_read_last(table->record[0],
- tab->ref.key_buff,
- tab->ref.key_length)))
+ tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts))))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -11757,7 +11760,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
group->buff[-1]= (char) group->field->is_null();
}
if (!table->file->index_read(table->record[1],
- join->tmp_table_param.group_buff,0,
+ join->tmp_table_param.group_buff, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{ /* Update old record */
restore_record(table,record[1]);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 2e01e54e4ca..ca93179f9d9 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -192,7 +192,7 @@ typedef struct st_join_table {
JOIN *join;
/* Bitmap of nested joins this table is part of */
nested_join_map embedding_map;
-
+
void cleanup();
inline bool is_using_loose_index_scan()
{
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 9a5176d9fe3..7b3b71cdd9a 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -25,6 +25,7 @@
#include "sp_head.h"
#include "sp.h"
+static my_bool servers_load(THD *thd, TABLE_LIST *tables);
HASH servers_cache;
pthread_mutex_t servers_cache_mutex; // To init the hash
uint servers_cache_initialised=FALSE;
@@ -353,8 +354,7 @@ my_bool server_exists_in_table(THD *thd, LEX_SERVER_OPTIONS *server_options)
system_charset_info);
if ((error= table->file->index_read_idx(table->record[0], 0,
- (byte *)table->field[0]->ptr,
- table->key_info[0].key_length,
+ (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@@ -554,8 +554,7 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
/* read index until record is that specified in server_name */
if ((error= table->file->index_read_idx(table->record[0], 0,
- (byte *)table->field[0]->ptr,
- table->key_info[0].key_length,
+ (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
HA_READ_KEY_EXACT)))
{
/* if not found, err */
@@ -873,8 +872,7 @@ int update_server_record(TABLE *table, FOREIGN_SERVER *server)
system_charset_info);
if ((error= table->file->index_read_idx(table->record[0], 0,
- (byte *)table->field[0]->ptr,
- table->key_info[0].key_length,
+ (byte *)table->field[0]->ptr, ~(longlong)0,
HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@@ -928,8 +926,7 @@ int delete_server_record(TABLE *table,
table->field[0]->store(server_name, server_name_length, system_charset_info);
if ((error= table->file->index_read_idx(table->record[0], 0,
- (byte *)table->field[0]->ptr,
- table->key_info[0].key_length,
+ (byte *)table->field[0]->ptr, HA_WHOLE_KEY,
HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 7dec58d9b6e..4c584bff72a 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -514,8 +514,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
table->use_all_columns();
table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin);
if (!table->file->index_read_idx(table->record[0], 0,
- (byte*) table->field[0]->ptr,
- table->key_info[0].key_length,
+ (byte*) table->field[0]->ptr, HA_WHOLE_KEY,
HA_READ_KEY_EXACT))
{
int error;
@@ -524,7 +523,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
}
close_thread_tables(thd);
- rw_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(0);
err:
rw_unlock(&THR_LOCK_udf);
diff --git a/sql/table.cc b/sql/table.cc
index fd810ae7478..f2bf25e6a75 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1222,12 +1222,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if ((int) (share->next_number_index= (uint)
find_ref_key(share->key_info, share->keys,
share->default_values, reg_field,
- &share->next_number_key_offset)) < 0)
+ &share->next_number_key_offset,
+ &share->next_number_keypart)) < 0)
{
/* Wrong field definition */
- DBUG_ASSERT(0);
- reg_field->unireg_check= Field::NONE; /* purecov: inspected */
- share->found_next_number_field= 0;
+ error= 4;
+ goto err;
}
else
reg_field->flags |= AUTO_INCREMENT_FLAG;
@@ -2244,6 +2244,30 @@ char *get_field(MEM_ROOT *mem, Field *field)
return to;
}
+/*
+ DESCRIPTION
+ given a buffer with a key value, and a map of keyparts
+ that are present in this value, returns the length of the value
+*/
+uint calculate_key_len(TABLE *table, uint key, const byte *buf,
+ key_part_map keypart_map)
+{
+ /* works only with key prefixes */
+ DBUG_ASSERT(((keypart_map + 1) & keypart_map) == 0);
+
+ KEY *key_info= table->s->key_info+key;
+ KEY_PART_INFO *key_part= key_info->key_part;
+ KEY_PART_INFO *end_key_part= key_part + key_info->key_parts;
+ uint length= 0;
+
+ while (key_part < end_key_part && keypart_map)
+ {
+ length+= key_part->store_length;
+ keypart_map >>= 1;
+ key_part++;
+ }
+ return length;
+}
/*
Check if database name is valid
@@ -3938,7 +3962,7 @@ void st_table::mark_auto_increment_column()
*/
bitmap_set_bit(read_set, found_next_number_field->field_index);
bitmap_set_bit(write_set, found_next_number_field->field_index);
- if (s->next_number_key_offset)
+ if (s->next_number_keypart)
mark_columns_used_by_index_no_reset(s->next_number_index, read_set);
file->column_bitmaps_signal();
}
diff --git a/sql/table.h b/sql/table.h
index 086df5f28f8..aa053f207b3 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -197,8 +197,9 @@ typedef struct st_table_share
uint rowid_field_offset; /* Field_nr +1 to rowid field */
/* Index of auto-updated TIMESTAMP field in field array */
uint primary_key;
- uint next_number_index;
- uint next_number_key_offset;
+ uint next_number_index; /* autoincrement key number */
+ uint next_number_key_offset; /* autoinc keypart offset in a key */
+ uint next_number_keypart; /* autoinc keypart number in a key */
uint error, open_errno, errarg; /* error from open_table_def() */
uint column_bitmap_size;
uchar frm_version;
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 914c7be46de..18161022dc3 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1917,9 +1917,9 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
(void)table->file->ha_index_init(0, 1);
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
- 0, HA_READ_KEY_EXACT))
+ HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
-#ifdef EXTRA_DEBUG
+#ifdef EXTRA_DEBUG
/*
Most probably user has mistyped time zone name, so no need to bark here
unless we need it for debugging.
@@ -1945,7 +1945,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
(void)table->file->ha_index_init(0, 1);
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
- 0, HA_READ_KEY_EXACT))
+ HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
sql_print_error("Can't find description of time zone '%u'", tzid);
goto end;
@@ -1972,9 +1972,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
table->field[0]->store((longlong) tzid, TRUE);
(void)table->file->ha_index_init(0, 1);
- // FIXME Is there any better approach than explicitly specifying 4 ???
res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
- 4, HA_READ_KEY_EXACT);
+ (key_part_map)1, HA_READ_KEY_EXACT);
while (!res)
{
ttid= (uint)table->field[1]->val_int();
@@ -2045,9 +2044,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
table->field[0]->store((longlong) tzid, TRUE);
(void)table->file->ha_index_init(0, 1);
- // FIXME Is there any better approach than explicitly specifying 4 ???
res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
- 4, HA_READ_KEY_EXACT);
+ (key_part_map)1, HA_READ_KEY_EXACT);
while (!res)
{
ttime= (my_time_t)table->field[1]->val_int();
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 3fbb4e9ef93..6f07c4183f1 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -152,7 +152,8 @@ THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd,
int ha_blackhole::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
DBUG_ENTER("ha_blackhole::index_read");
DBUG_RETURN(HA_ERR_END_OF_FILE);
@@ -160,14 +161,16 @@ int ha_blackhole::index_read(byte * buf, const byte * key,
int ha_blackhole::index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
DBUG_ENTER("ha_blackhole::index_read_idx");
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
-int ha_blackhole::index_read_last(byte * buf, const byte * key, uint key_len)
+int ha_blackhole::index_read_last(byte * buf, const byte * key,
+ key_part_map keypart_map)
{
DBUG_ENTER("ha_blackhole::index_read_last");
DBUG_RETURN(HA_ERR_END_OF_FILE);
diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index 5388dcfc187..2af12b33077 100644
--- a/storage/blackhole/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
@@ -64,11 +64,11 @@ public:
int rnd_init(bool scan);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ int index_read(byte * buf, const byte * key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_last(byte * buf, const byte * key, uint key_len);
+ key_part_map keypart_map, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, key_part_map keypart_map);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index bde6c41d777..999e36a4242 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -415,7 +415,7 @@ int ha_example::delete_row(const byte * buf)
*/
int ha_example::index_read(byte * buf, const byte * key,
- uint key_len __attribute__((unused)),
+ key_part_map keypart_map __attribute__((unused)),
enum ha_rkey_function find_flag
__attribute__((unused)))
{
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index 9b912514887..9777a478209 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -191,7 +191,7 @@ public:
skip it and and MySQL will treat it as not implemented.
*/
int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
+ key_part_map keypart_map, enum ha_rkey_function find_flag);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 14ffe5da984..441c1785e74 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -363,7 +363,6 @@ static handler *federated_create_handler(handlerton *hton,
static int federated_commit(handlerton *hton, THD *thd, bool all);
static int federated_rollback(handlerton *hton, THD *thd, bool all);
-
/* Federated storage engine handlerton */
static handler *federated_create_handler(handlerton *hton,
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index f2caa7e6d18..5831ec6167a 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -238,34 +238,35 @@ int ha_heap::delete_row(const byte * buf)
return res;
}
-int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
+int ha_heap::index_read(byte * buf, const byte * key, key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
DBUG_ASSERT(inited==INDEX);
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error = heap_rkey(file,buf,active_index, key, key_len, find_flag);
+ int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
table->status = error ? STATUS_NOT_FOUND : 0;
return error;
}
-int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
+int ha_heap::index_read_last(byte *buf, const byte *key, key_part_map keypart_map)
{
DBUG_ASSERT(inited==INDEX);
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error= heap_rkey(file, buf, active_index, key, key_len,
+ int error= heap_rkey(file, buf, active_index, key, keypart_map,
HA_READ_PREFIX_LAST);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
}
int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error = heap_rkey(file, buf, index, key, key_len, find_flag);
+ int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
table->status = error ? STATUS_NOT_FOUND : 0;
return error;
}
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index 2de80c76999..a2d531fc515 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -75,11 +75,11 @@ public:
ulonglong nb_desired_values,
ulonglong *first_value,
ulonglong *nb_reserved_values);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_last(byte * buf, const byte * key, uint key_len);
+ int index_read(byte * buf, const byte * key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ int index_read_last(byte *buf, const byte *key, key_part_map keypart_map);
+ int index_read_idx(byte * buf, uint index, const byte * key,
+ key_part_map keypart_map, enum ha_rkey_function find_flag);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
diff --git a/storage/heap/heapdef.h b/storage/heap/heapdef.h
index 016c83db8e0..b52a6c60ac6 100644
--- a/storage/heap/heapdef.h
+++ b/storage/heap/heapdef.h
@@ -90,7 +90,7 @@ extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
-extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
+extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos);
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
@@ -99,8 +99,8 @@ extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int hp_close(register HP_INFO *info);
extern void hp_clear(HP_SHARE *info);
extern void hp_clear_keys(HP_SHARE *info);
-extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
- uint k_len);
+extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
+ key_part_map keypart_map);
#ifdef THREAD
extern pthread_mutex_t THR_LOCK_heap;
#else
diff --git a/storage/heap/hp_hash.c b/storage/heap/hp_hash.c
index c5a30a3ef65..fbf3e541372 100644
--- a/storage/heap/hp_hash.c
+++ b/storage/heap/hp_hash.c
@@ -35,7 +35,7 @@
HA_READ_KEY_EXACT Include the key in the range
HA_READ_AFTER_KEY Don't include key in range
- max_key.flag can have one of the following values:
+ max_key.flag can have one of the following values:
HA_READ_BEFORE_KEY Don't include key in range
HA_READ_AFTER_KEY Include all 'end_key' values in the range
@@ -62,7 +62,7 @@ ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
{
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
(uchar*) min_key->key,
- min_key->length);
+ min_key->keypart_map);
start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
&custom_arg);
}
@@ -70,12 +70,12 @@ ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
{
start_pos= 0;
}
-
+
if (max_key)
{
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
(uchar*) max_key->key,
- max_key->length);
+ max_key->keypart_map);
end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
&custom_arg);
}
@@ -772,7 +772,7 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
char_length / seg->charset->mbmaxlen);
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
if (char_length < seg->length)
- seg->charset->cset->fill(seg->charset, (char*) key + char_length,
+ seg->charset->cset->fill(seg->charset, (char*) key + char_length,
seg->length - char_length, ' ');
}
memcpy(key, rec + seg->start, (size_t) char_length);
@@ -784,30 +784,26 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
- uint k_len)
+ key_part_map keypart_map)
{
HA_KEYSEG *seg, *endseg;
uchar *start_key= key;
-
+
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
- seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
+ seg < endseg && keypart_map; old+= seg->length, seg++)
{
uint char_length;
+ keypart_map>>= 1;
if (seg->null_bit)
{
- k_len--;
if (!(*key++= (char) 1 - *old++))
- {
- k_len-= seg->length;
continue;
}
- }
if (seg->flag & HA_SWAP_KEY)
{
uint length= seg->length;
byte *pos= (byte*) old + length;
- k_len-= length;
while (length--)
{
*key++= *--pos;
@@ -822,7 +818,6 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
CHARSET_INFO *cs= seg->charset;
char_length= length/cs->mbmaxlen;
- k_len-= 2+length;
old+= 2;
set_if_smaller(length,tmp_length); /* Safety */
FIX_LENGTH(cs, old, length, char_length);
@@ -843,7 +838,6 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
}
memcpy(key, old, (size_t) char_length);
key+= seg->length;
- k_len-= seg->length;
}
return (uint) (key - start_key);
}
diff --git a/storage/heap/hp_rkey.c b/storage/heap/hp_rkey.c
index a095336d295..ced81985f99 100644
--- a/storage/heap/hp_rkey.c
+++ b/storage/heap/hp_rkey.c
@@ -16,7 +16,7 @@
#include "heapdef.h"
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map, enum ha_rkey_function find_flag)
{
byte *pos;
HP_SHARE *share= info->s;
@@ -38,7 +38,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
custom_arg.keyseg= info->s->keydef[inx].seg;
custom_arg.key_length= info->lastkey_len=
hp_rb_pack_key(keyinfo, (uchar*) info->lastkey,
- (uchar*) key, key_len);
+ (uchar*) key, keypart_map);
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
/* for next rkey() after deletion */
if (find_flag == HA_READ_AFTER_KEY)
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index dc1c6515266..48f1d9b2395 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -1555,34 +1555,37 @@ int ha_myisam::delete_row(const byte * buf)
return mi_delete(file,buf);
}
-int ha_myisam::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+int ha_myisam::index_read(byte *buf, const byte *key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
DBUG_ASSERT(inited==INDEX);
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
+ int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
-int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+int ha_myisam::index_read_idx(byte *buf, uint index, const byte *key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error=mi_rkey(file,buf,index, key, key_len, find_flag);
+ int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
-int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
+int ha_myisam::index_read_last(byte *buf, const byte *key,
+ key_part_map keypart_map)
{
DBUG_ENTER("ha_myisam::index_read_last");
DBUG_ASSERT(inited==INDEX);
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
+ int error=mi_rkey(file, buf, active_index, key, keypart_map,
+ HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
DBUG_RETURN(error);
}
@@ -1891,8 +1894,9 @@ void ha_myisam::get_auto_increment(ulonglong offset, ulonglong increment,
key_copy(key, table->record[0],
table->key_info + table->s->next_number_index,
table->s->next_number_key_offset);
- error= mi_rkey(file,table->record[1],(int) table->s->next_number_index,
- key,table->s->next_number_key_offset,HA_READ_PREFIX_LAST);
+ error= mi_rkey(file, table->record[1], (int) table->s->next_number_index,
+ key, make_prev_keypart_map(table->s->next_number_keypart),
+ HA_READ_PREFIX_LAST);
if (error)
nr= 1;
else
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index 882900bd35f..647e72d53eb 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -69,11 +69,11 @@ class ha_myisam: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_last(byte * buf, const byte * key, uint key_len);
+ int index_read(byte *buf, const byte *key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ int index_read_idx(byte *buf, uint index, const byte *key,
+ key_part_map keypart_map, enum ha_rkey_function find_flag);
+ int index_read_last(byte *buf, const byte *key, key_part_map keypart_map);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 7bcb8041fe0..7a4d47954a5 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -532,7 +532,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
mi_extra(info,HA_EXTRA_KEYREAD,0);
bzero(info->lastkey,keyinfo->seg->length);
if (!mi_rkey(info, info->rec_buff, key, (const byte*) info->lastkey,
- keyinfo->seg->length, HA_READ_KEY_EXACT))
+ (key_part_map)1, HA_READ_KEY_EXACT))
{
/* Don't count this as a real warning, as myisamchk can't correct it */
uint save=param->warning_printed;
diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c
index b203286d544..2f4915dec39 100644
--- a/storage/myisam/mi_key.c
+++ b/storage/myisam/mi_key.c
@@ -206,7 +206,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
uint keynr key number
key Store packed key here
old Not packed key
- k_length Length of 'old' to use
+ keypart_map bitmap of used keyparts
last_used_keyseg out parameter. May be NULL
RETURN
@@ -216,34 +216,36 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
*/
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
- uint k_length, HA_KEYSEG **last_used_keyseg)
+ key_part_map keypart_map, HA_KEYSEG **last_used_keyseg)
{
uchar *start_key=key;
HA_KEYSEG *keyseg;
my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
DBUG_ENTER("_mi_pack_key");
- for (keyseg=info->s->keyinfo[keynr].seg ;
- keyseg->type && (int) k_length > 0;
- old+=keyseg->length, keyseg++)
+ /* "one part" rtree key is 2*SPDIMS part key in MyISAM */
+ if (info->s->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE)
+ keypart_map= (((key_part_map)1) << (2*SPDIMS)) - 1;
+
+ /* only key prefixes are supported */
+ DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
+
+ for (keyseg= info->s->keyinfo[keynr].seg ; keyseg->type && keypart_map;
+ old+= keyseg->length, keyseg++)
{
- enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
- uint length=min((uint) keyseg->length,(uint) k_length);
+ enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
+ uint length= keyseg->length;
uint char_length;
uchar *pos;
CHARSET_INFO *cs=keyseg->charset;
+ keypart_map>>= 1;
if (keyseg->null_bit)
{
- k_length--;
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
{
- k_length-=length;
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
- {
- k_length-=2; /* Skip length */
old+= 2;
- }
continue; /* Found NULL */
}
}
@@ -262,7 +264,6 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
while (pos < end && pos[0] == ' ')
pos++;
}
- k_length-=length;
length=(uint) (end-pos);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
@@ -274,7 +275,6 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
{
/* Length of key-part used with mi_rkey() always 2 */
uint tmp_length=uint2korr(pos);
- k_length-= 2+length;
pos+=2;
set_if_smaller(length,tmp_length); /* Safety */
FIX_LENGTH(cs, pos, length, char_length);
@@ -287,11 +287,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
else if (keyseg->flag & HA_SWAP_KEY)
{ /* Numerical column */
pos+=length;
- k_length-=length;
while (length--)
- {
*key++ = *--pos;
- }
continue;
}
FIX_LENGTH(cs, pos, length, char_length);
@@ -299,30 +296,10 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
if (length > char_length)
cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
- k_length-=length;
}
if (last_used_keyseg)
*last_used_keyseg= keyseg;
-#ifdef NOT_USED
- if (keyseg->type)
- {
- /* Part-key ; fill with ASCII 0 for easier searching */
- length= (uint) -k_length; /* unused part of last key */
- do
- {
- if (keyseg->flag & HA_NULL_PART)
- length++;
- if (keyseg->flag & HA_SPACE_PACK)
- length+=2;
- else
- length+= keyseg->length;
- keyseg++;
- } while (keyseg->type);
- bzero((byte*) key,length);
- key+=length;
- }
-#endif
DBUG_RETURN((uint) (key-start_key));
} /* _mi_pack_key */
diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c
index 6655f5a7de6..2cdb02b2c80 100644
--- a/storage/myisam/mi_range.c
+++ b/storage/myisam/mi_range.c
@@ -21,13 +21,10 @@
#include "myisamdef.h"
#include "rt_index.h"
-static ha_rows _mi_record_pos(MI_INFO *info,const byte *key,uint key_len,
- enum ha_rkey_function search_flag);
-static double _mi_search_pos(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
- uint key_len,uint nextflag,my_off_t pos);
-static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
- uchar *keypos,uint *ret_max_key);
-
+static ha_rows _mi_record_pos(MI_INFO *, const byte *, key_part_map,
+ enum ha_rkey_function);
+static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,my_off_t);
+static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *);
/*
Estimate how many records there is in a given range
@@ -47,9 +44,8 @@ static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
number Estimated number of rows
*/
-
-ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
- key_range *max_key)
+ha_rows mi_records_in_range(MI_INFO *info, int inx,
+ key_range *min_key, key_range *max_key)
{
ha_rows start_pos,end_pos,res;
DBUG_ENTER("mi_records_in_range");
@@ -87,7 +83,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
}
key_buff= info->lastkey+info->s->base.max_key_length;
start_key_len= _mi_pack_key(info,inx, key_buff,
- (uchar*) min_key->key, min_key->length,
+ (uchar*) min_key->key, min_key->keypart_map,
(HA_KEYSEG**) 0);
res= rtree_estimate(info, inx, key_buff, start_key_len,
myisam_read_vec[min_key->flag]);
@@ -97,24 +93,22 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
#endif
case HA_KEY_ALG_BTREE:
default:
- start_pos= (min_key ?
- _mi_record_pos(info, min_key->key, min_key->length,
- min_key->flag) :
- (ha_rows) 0);
- end_pos= (max_key ?
- _mi_record_pos(info, max_key->key, max_key->length,
- max_key->flag) :
- info->state->records+ (ha_rows) 1);
+ start_pos= (min_key ? _mi_record_pos(info, min_key->key,
+ min_key->keypart_map, min_key->flag)
+ : (ha_rows) 0);
+ end_pos= (max_key ? _mi_record_pos(info, max_key->key,
+ max_key->keypart_map, 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_mi_writeinfo(info);
-
+
DBUG_PRINT("info",("records: %ld",(ulong) (res)));
DBUG_RETURN(res);
}
@@ -122,21 +116,21 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
/* Find relative position (in records) for key in index-tree */
-static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len,
+static ha_rows _mi_record_pos(MI_INFO *info, const byte *key,
+ key_part_map keypart_map,
enum ha_rkey_function search_flag)
{
- uint inx=(uint) info->lastinx, nextflag;
+ uint inx=(uint) info->lastinx, nextflag, key_len;
MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
uchar *key_buff;
double pos;
DBUG_ENTER("_mi_record_pos");
DBUG_PRINT("enter",("search_flag: %d",search_flag));
+ DBUG_ASSERT(keypart_map);
- if (key_len == 0)
- key_len=USE_WHOLE_KEY;
key_buff=info->lastkey+info->s->base.max_key_length;
- key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len,
+ key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key, keypart_map,
(HA_KEYSEG**) 0);
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
(uchar*) key_buff,key_len););
diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c
index 917ba381504..373ab303bf0 100644
--- a/storage/myisam/mi_rkey.c
+++ b/storage/myisam/mi_rkey.c
@@ -21,8 +21,8 @@
/* Read a record using key */
/* Ordinary search_flag is 0 ; Give error if no record with key */
-int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
- enum ha_rkey_function search_flag)
+int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key,
+ key_part_map keypart_map, enum ha_rkey_function search_flag)
{
uchar *key_buff;
MYISAM_SHARE *share=info->s;
@@ -47,18 +47,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
key is already packed!; This happens when we are using a MERGE TABLE
*/
key_buff=info->lastkey+info->s->base.max_key_length;
- pack_key_length= key_len;
- bmove(key_buff,key,key_len);
+ pack_key_length= keypart_map;
+ bmove(key_buff, key, pack_key_length);
last_used_keyseg= 0;
}
else
{
- if (key_len == 0)
- key_len=USE_WHOLE_KEY;
+ DBUG_ASSERT(keypart_map);
/* Save the packed key for later use in the second buffer of lastkey. */
key_buff=info->lastkey+info->s->base.max_key_length;
pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key,
- key_len, &last_used_keyseg);
+ keypart_map, &last_used_keyseg);
/* Save packed_key_length for use by the MERGE engine. */
info->pack_key_length= pack_key_length;
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg,
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index dceccd10ae2..7325340b970 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -604,8 +604,9 @@ extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos,
extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo,int level);
extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key,
const byte *record,my_off_t filepos);
-extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
- uint key_length, HA_KEYSEG **last_used_keyseg);
+extern uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key,
+ uchar *old, key_part_map keypart_map,
+ HA_KEYSEG **last_used_keyseg);
extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
uint length,int re_read_if_possibly);
diff --git a/storage/myisam/rt_test.c b/storage/myisam/rt_test.c
index 1126266d2f9..55b52c0c3bf 100644
--- a/storage/myisam/rt_test.c
+++ b/storage/myisam/rt_test.c
@@ -323,7 +323,7 @@ static int run_test(const char *filename)
range.key= record+1;
range.length= 1000; /* Big enough */
range.flag= HA_READ_MBR_INTERSECT;
- hrows= mi_records_in_range(file,0, &range, (key_range*) 0);
+ hrows= mi_records_in_range(file, 0, &range, (key_range*) 0);
printf(" %ld rows\n", (long) hrows);
if (mi_close(file)) goto err;
diff --git a/storage/myisam/sp_test.c b/storage/myisam/sp_test.c
index c7226589811..96ba05e8a74 100644
--- a/storage/myisam/sp_test.c
+++ b/storage/myisam/sp_test.c
@@ -255,7 +255,7 @@ int run_test(const char *filename)
max_range.key= record+1;
max_range.length= 1000; /* Big enough */
max_range.flag= HA_READ_KEY_EXACT;
- hrows= mi_records_in_range(file,0, &min_range, &max_range);
+ hrows= mi_records_in_range(file, 0, &min_range, &max_range);
printf(" %ld rows\n", (long) hrows);
if (mi_close(file)) goto err;
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index d9e7e1d5700..96f7db6e633 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -179,30 +179,33 @@ int ha_myisammrg::delete_row(const byte * buf)
}
int ha_myisammrg::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag);
+ int error=myrg_rkey(file,buf,active_index, key, keypart_map, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error=myrg_rkey(file,buf,index, key, key_len, find_flag);
+ int error=myrg_rkey(file,buf,index, key, keypart_map, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
-int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
+int ha_myisammrg::index_read_last(byte * buf, const byte * key,
+ key_part_map keypart_map)
{
statistic_increment(table->in_use->status_var.ha_read_key_count,
&LOCK_status);
- int error=myrg_rkey(file,buf,active_index, key, key_len,
+ int error=myrg_rkey(file,buf,active_index, key, keypart_map,
HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index 04379f6cf70..7bbe659d4b7 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -56,11 +56,11 @@ class ha_myisammrg: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_last(byte * buf, const byte * key, uint key_len);
+ int index_read(byte * buf, const byte * key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ int index_read_idx(byte * buf, uint index, const byte * key,
+ key_part_map keypart_map, enum ha_rkey_function find_flag);
+ int index_read_last(byte * buf, const byte * key, key_part_map keypart_map);
int index_next(byte * buf);
int index_prev(byte * buf);
int index_first(byte * buf);
diff --git a/storage/myisammrg/myrg_rkey.c b/storage/myisammrg/myrg_rkey.c
index f7b7f082019..0eefe7eb173 100644
--- a/storage/myisammrg/myrg_rkey.c
+++ b/storage/myisammrg/myrg_rkey.c
@@ -36,7 +36,7 @@
*/
int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
- uint key_len, enum ha_rkey_function search_flag)
+ key_part_map keypart_map, enum ha_rkey_function search_flag)
{
byte *key_buff;
uint pack_key_length;
@@ -56,7 +56,7 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
if (table == info->open_tables)
{
- err=mi_rkey(mi,0,inx,key,key_len,search_flag);
+ err=mi_rkey(mi, 0, inx, key, keypart_map, search_flag);
/* Get the saved packed key and packed key length. */
key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
pack_key_length=mi->pack_key_length;
@@ -64,7 +64,7 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
else
{
mi->once_flags|= USE_PACKED_KEYS;
- err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag);
+ err=mi_rkey(mi, 0, inx, key_buff, pack_key_length, search_flag);
}
info->last_used_table=table+1;
diff --git a/support-files/Makefile.am b/support-files/Makefile.am
index af835bf350e..b3ef3b77b76 100644
--- a/support-files/Makefile.am
+++ b/support-files/Makefile.am
@@ -44,6 +44,9 @@ pkgdata_DATA = my-small.cnf \
pkgdata_SCRIPTS = mysql.server
+aclocaldir = $(datadir)/aclocal
+aclocal_DATA = mysql.m4
+
noinst_DATA = mysql-@VERSION@.spec \
MySQL-shared-compat.spec
diff --git a/support-files/mysql.m4 b/support-files/mysql.m4
new file mode 100644
index 00000000000..a440353c196
--- /dev/null
+++ b/support-files/mysql.m4
@@ -0,0 +1,108 @@
+# Copyright (C) 2007 MySQL 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
+
+AC_DEFUN([_MYSQL_CONFIG],[
+ AC_ARG_WITH([mysql-config],
+ AS_HELP_STRING([--with-mysql-config=PATH], [A path to mysql_config script]),
+ [mysql_config="$withval"], [mysql_config=mysql_config])
+])
+
+dnl
+dnl Usage:
+dnl
+dnl MYSQL_CLIENT([version], [client|thread-safe|embedded])
+dnl
+dnl Two optional arguments:
+dnl first: The minimal version of the MySQL to use
+dnl if not specified, any version will be accepted.
+dnl The version should be specified as three numbers,
+dnl without suffixes. E.g. 4.10.15 or 5.0.3
+dnl second: force the specified library flavor to be selected,
+dnl if not specified, a user will be able to choose
+dnl between client (non-thread-safe) and embedded
+dnl
+dnl On successful execution sets MYSQL_CLIENT_CFLAGS and
+dnl MYSQL_CLIENT_LIBS shell variables and makes substitutions
+dnl out of them (calls AC_SUBST)
+dnl
+
+AC_DEFUN([MYSQL_CLIENT],[
+ AC_REQUIRE([_MYSQL_CONFIG])
+ AC_MSG_CHECKING([for MySQL])
+ ifelse([$2], [client],
+ [mysql_libs=--libs mysql_cflags=--cflags],
+ [$2], [thread-safe],
+ [mysql_libs=--libs_r mysql_cflags=--cflags],
+ [$2], [embedded],
+ [mysql_libs=--libmysqld-libs mysql_cflags=--cflags],
+ [$2], [], [
+ AC_ARG_WITH([mysql-library],
+ AS_HELP_STRING([--with-mysql-library], ['client' or 'embedded']),
+ [mysql_lib="$withval"], [mysql_lib=client])
+[
+ case "$mysql_lib" in
+ client) mysql_libs=--libs mysql_cflags=--cflags ;;
+ embedded) mysql_libs=--libmysqld-libs mysql_cflags=--cflags ;;
+ *) ]AC_MSG_ERROR([Bad value for --with-mysql-library])[
+ esac
+]
+ ],
+ [AC_FATAL([Bad second (library flavor) argument to MYSQL_CLIENT])])
+[
+ mysql_version=`$mysql_config --version`
+ if test -z "$mysql_version" ; then
+ ]AC_MSG_ERROR([Cannot execute $mysql_config])[
+ fi
+]
+ ifelse([$1], [], [], [
+ ifelse(regexp([$1], [^[0-9][0-9]?\.[0-9][0-9]?\.[0-9][0-9]?$]), -1,
+ [AC_FATAL([Bad first (version) argument to MYSQL_CLIENT])], [
+dnl
+dnl Transformation below works as follows:
+dnl assume, we have a number 1.2.3-beta
+dnl *a* line removes the suffix and adds first and last dot to the version:
+dnl .1.2.3.
+dnl *b* line adds a 0 to a "single digit surrounded by dots"
+dnl .01.2.03.
+dnl note that the pattern that matched .1. has eaten the dot for .2.
+dnl and 2 still has no 0
+dnl *c* we repeat the same replacement as in *b*, matching .2. this time
+dnl .01.02.03.
+dnl the last replacement removes all dots
+dnl 010203
+dnl giving us a number we can compare with
+dnl
+ mysql_ver=`echo ${mysql_version}|dnl
+ sed 's/[[-a-z]].*//; s/.*/.&./;dnl *a*
+ s/\.\([[0-9]]\)\./.0\1./g;dnl *b*
+ s/\.\([[0-9]]\)\./.0\1./g;dnl *c*
+ s/\.//g'`
+ if test "$mysql_ver" -lt]dnl
+dnl the same as sed transformation above, without suffix-stripping, in m4
+ patsubst(patsubst(patsubst(.[$1]., [\.\([0-9]\)\.], [.0\1.]), [\.\([0-9]\)\.], [.0\1.]), [\.], [])[ ; then
+ AC_MSG_ERROR([MySQL version $mysql_version is too low, minimum of $1 is required])
+ fi
+ ])])
+
+ MYSQL_CLIENT_CFLAGS=`$mysql_config $mysql_cflags`
+ MYSQL_CLIENT_LIBS=`$mysql_config $mysql_libs`
+ AC_SUBST(MYSQL_CLIENT_CFLAGS)
+ AC_SUBST(MYSQL_CLIENT_LIBS)
+
+ # should we try to build a test program ?
+
+ AC_MSG_RESULT([$mysql_version])
+])
+
diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c
index c4ba7850ae1..8280aff5422 100644
--- a/unittest/mysys/my_atomic-t.c
+++ b/unittest/mysys/my_atomic-t.c
@@ -182,9 +182,6 @@ int main()
test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS, CYCLES);
test_atomic("my_atomic_swap32", test_atomic_swap_handler, THREADS, CYCLES);
test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS, CYCLES);
-
- /* workaround until we know why this includes dbug but not safemalloc */
- if(err) { my_thread_global_init(); my_free(my_malloc(0, MYF(0)), MYF(0)); }
/*
workaround until we know why it crashes randomly on some machine
(BUG#22320).