summaryrefslogtreecommitdiff
path: root/heap/hp_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'heap/hp_hash.c')
-rw-r--r--heap/hp_hash.c78
1 files changed, 66 insertions, 12 deletions
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index e28f4725caf..cd70d2ab532 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -30,27 +30,27 @@ ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
TREE *rb_tree = &keyinfo->rb_tree;
heap_rb_param custom_arg;
- info->lastinx = inx;
- custom_arg.keyseg = keyinfo->seg;
- custom_arg.search_flag = SEARCH_FIND | SEARCH_SAME;
- custom_arg.key_length = start_key_len;
+ info->lastinx= inx;
+ custom_arg.keyseg= keyinfo->seg;
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
if (start_key)
{
- hp_rb_pack_key(keyinfo, info->recbuf, start_key);
+ custom_arg.key_length= hp_rb_pack_key(keyinfo, info->recbuf, start_key,
+ start_key_len);
start_pos= tree_record_pos(rb_tree, info->recbuf, start_search_flag,
- &custom_arg);
+ &custom_arg);
}
else
{
start_pos= 0;
}
- custom_arg.key_length = end_key_len;
if (end_key)
{
- hp_rb_pack_key(keyinfo, info->recbuf, end_key);
+ custom_arg.key_length= hp_rb_pack_key(keyinfo, info->recbuf, end_key,
+ end_key_len);
end_pos= tree_record_pos(rb_tree, info->recbuf, end_search_flag,
- &custom_arg);
+ &custom_arg);
}
else
{
@@ -443,6 +443,43 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
continue;
}
+ if (seg->flag & HA_SWAP_KEY)
+ {
+ uint length= seg->length;
+ byte *pos= (byte*) rec + seg->start;
+
+#ifdef HAVE_ISNAN
+ if (seg->type == HA_KEYTYPE_FLOAT)
+ {
+ float nr;
+ float4get(nr, pos);
+ if (isnan(nr))
+ {
+ /* Replace NAN with zero */
+ bzero(key, length);
+ key+= length;
+ continue;
+ }
+ }
+ else if (seg->type == HA_KEYTYPE_DOUBLE)
+ {
+ double nr;
+ float8get(nr, pos);
+ if (isnan(nr))
+ {
+ bzero(key, length);
+ key+= length;
+ continue;
+ }
+ }
+#endif
+ pos+= length;
+ while (length--)
+ {
+ *key++= *--pos;
+ }
+ continue;
+ }
memcpy(key, rec + seg->start, (size_t) seg->length);
key+= seg->length;
}
@@ -450,21 +487,38 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
return key - start_key;
}
-uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old)
+uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
{
HA_KEYSEG *seg, *endseg;
uchar *start_key= key;
- for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg;
- old+= seg->length, seg++)
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs;
+ seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
{
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;
+ }
+ continue;
}
memcpy((byte*) key, old, seg->length);
key+= seg->length;
+ k_len-= seg->length;
}
return key - start_key;
}