Commit 5b2bf241 authored by Zardosht Kasheff's avatar Zardosht Kasheff Committed by Yoni Fogel

addresses #1619

move cmp related functions to new files

git-svn-id: file:///svn/mysql/tokudb-engine/src@10719 c7de825b-a66e-492c-adef-691d508d4ae1
parent 74071e15
...@@ -25,7 +25,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql ...@@ -25,7 +25,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
TOKUDB_DIR_REPLACE_ME/include TOKUDB_DIR_REPLACE_ME/include
TOKUDB_DIR_REPLACE_ME/toku_include) TOKUDB_DIR_REPLACE_ME/toku_include)
SET(TOKUDB_SOURCES hatoku_hton.cc ha_tokudb.cc hatoku_cmptrace.cc) SET(TOKUDB_SOURCES hatoku_hton.cc ha_tokudb.cc hatoku_cmptrace.cc hatoku_cmp.cc)
IF(NOT SOURCE_SUBLIBS) IF(NOT SOURCE_SUBLIBS)
ADD_LIBRARY(ha_tokudb ${TOKUDB_SOURCES}) ADD_LIBRARY(ha_tokudb ${TOKUDB_SOURCES})
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define MYSQL_SERVER 1 #define MYSQL_SERVER 1
#include "mysql_priv.h" #include "mysql_priv.h"
#include "hatoku_cmp.h"
extern "C" { extern "C" {
#include "stdint.h" #include "stdint.h"
#if defined(_WIN32) #if defined(_WIN32)
...@@ -215,228 +216,6 @@ ulong ha_tokudb::index_flags(uint idx, uint part, bool all_parts) const { ...@@ -215,228 +216,6 @@ ulong ha_tokudb::index_flags(uint idx, uint part, bool all_parts) const {
} }
static inline int tokudb_compare_two_hidden_keys(
const void* new_key_data,
const u_int32_t new_key_size,
const void* saved_key_data,
const u_int32_t saved_key_size
) {
assert( (new_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH) && (saved_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH) );
ulonglong a = hpk_char_to_num((uchar *) new_key_data);
ulonglong b = hpk_char_to_num((uchar *) saved_key_data);
return a < b ? -1 : (a > b ? 1 : 0);
}
static int tokudb_cmp_hidden_key(DB * file, const DBT * new_key, const DBT * saved_key) {
return tokudb_compare_two_hidden_keys(
new_key->data,
new_key->size,
saved_key->data,
saved_key->size
);
}
static int tokudb_compare_two_keys(
KEY *key,
const void* new_key_data,
const u_int32_t new_key_size,
const void* saved_key_data,
const u_int32_t saved_key_size,
bool cmp_prefix
) {
uchar new_key_inf_val = *(uchar *) new_key_data;
uchar saved_key_inf_val = *(uchar *) saved_key_data;
//
// first byte is "infinity" byte
//
uchar *new_key_ptr = (uchar *)(new_key_data) + 1;
uchar *saved_key_ptr = (uchar *)(saved_key_data) + 1;
KEY_PART_INFO *key_part = key->key_part, *end = key_part + key->key_parts;
int ret_val;
//
// do not include the inf val at the beginning
//
uint new_key_length = new_key_size - sizeof(uchar);
uint saved_key_length = saved_key_size - sizeof(uchar);
//DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) new_key_length > 0 && (int) saved_key_length > 0; key_part++) {
int cmp;
uint new_key_field_length;
uint saved_key_field_length;
if (key_part->field->null_bit) {
assert(new_key_ptr < (uchar *) new_key_data + new_key_size);
assert(saved_key_ptr < (uchar *) saved_key_data + saved_key_size);
if (*new_key_ptr != *saved_key_ptr) {
return ((int) *new_key_ptr - (int) *saved_key_ptr); }
saved_key_ptr++;
new_key_length--;
saved_key_length--;
if (!*new_key_ptr++) { continue; }
}
new_key_field_length = key_part->field->packed_col_length(new_key_ptr, key_part->length);
saved_key_field_length = key_part->field->packed_col_length(saved_key_ptr, key_part->length);
assert(new_key_length >= new_key_field_length);
assert(saved_key_length >= saved_key_field_length);
if ((cmp = key_part->field->pack_cmp(new_key_ptr, saved_key_ptr, key_part->length, 0)))
return cmp;
new_key_ptr += new_key_field_length;
new_key_length -= new_key_field_length;
saved_key_ptr += saved_key_field_length;
saved_key_length -= saved_key_field_length;
}
if (cmp_prefix || (new_key_length == 0 && saved_key_length == 0) ) {
ret_val = 0;
}
//
// at this point, one SHOULD be 0
//
else if (new_key_length == 0 && saved_key_length > 0) {
ret_val = (new_key_inf_val == COL_POS_INF ) ? 1 : -1;
}
else if (new_key_length > 0 && saved_key_length == 0) {
ret_val = (saved_key_inf_val == COL_POS_INF ) ? -1 : 1;
}
//
// this should never happen, perhaps we should assert(false)
//
else {
ret_val = new_key_length - saved_key_length;
}
return ret_val;
}
//
// this is super super ugly, copied from compare_two_keys so that it can get done fast
//
static int tokudb_compare_two_clustered_keys(KEY *key, KEY* primary_key, const DBT * new_key, const DBT * saved_key) {
uchar new_key_inf_val = *(uchar *) new_key->data;
uchar saved_key_inf_val = *(uchar *) saved_key->data;
//
// first byte is "infinity" byte
//
uchar *new_key_ptr = (uchar *)(new_key->data) + 1;
uchar *saved_key_ptr = (uchar *)(saved_key->data) + 1;
KEY_PART_INFO *key_part = key->key_part, *end = key_part + key->key_parts;
int ret_val;
//
// do not include the inf val at the beginning
//
uint new_key_length = new_key->size - sizeof(uchar);
uint saved_key_length = saved_key->size - sizeof(uchar);
//DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) new_key_length > 0 && (int) saved_key_length > 0; key_part++) {
int cmp;
uint new_key_field_length;
uint saved_key_field_length;
if (key_part->field->null_bit) {
assert(new_key_ptr < (uchar *) new_key->data + new_key->size);
assert(saved_key_ptr < (uchar *) saved_key->data + saved_key->size);
if (*new_key_ptr != *saved_key_ptr) {
return ((int) *new_key_ptr - (int) *saved_key_ptr); }
saved_key_ptr++;
new_key_length--;
saved_key_length--;
if (!*new_key_ptr++) { continue; }
}
new_key_field_length = key_part->field->packed_col_length(new_key_ptr, key_part->length);
saved_key_field_length = key_part->field->packed_col_length(saved_key_ptr, key_part->length);
assert(new_key_length >= new_key_field_length);
assert(saved_key_length >= saved_key_field_length);
if ((cmp = key_part->field->pack_cmp(new_key_ptr, saved_key_ptr, key_part->length, 0)))
return cmp;
new_key_ptr += new_key_field_length;
new_key_length -= new_key_field_length;
saved_key_ptr += saved_key_field_length;
saved_key_length -= saved_key_field_length;
}
if (new_key_length == 0 && saved_key_length == 0){
ret_val = 0;
}
else if (new_key_length == 0 && saved_key_length > 0) {
ret_val = (new_key_inf_val == COL_POS_INF ) ? 1 : -1;
}
else if (new_key_length > 0 && saved_key_length == 0) {
ret_val = (saved_key_inf_val == COL_POS_INF ) ? -1 : 1;
}
//
// now we compare the primary key
//
else {
if (primary_key == NULL) {
//
// primary key hidden
//
ulonglong a = hpk_char_to_num((uchar *) new_key_ptr);
ulonglong b = hpk_char_to_num((uchar *) saved_key_ptr);
ret_val = a < b ? -1 : (a > b ? 1 : 0);
}
else {
//
// primary key not hidden, I know this is bad, basically copying the code from above
//
key_part = primary_key->key_part;
end = key_part + primary_key->key_parts;
for (; key_part != end && (int) new_key_length > 0 && (int) saved_key_length > 0; key_part++) {
int cmp;
uint new_key_field_length;
uint saved_key_field_length;
if (key_part->field->null_bit) {
assert(new_key_ptr < (uchar *) new_key->data + new_key->size);
assert(saved_key_ptr < (uchar *) saved_key->data + saved_key->size);
if (*new_key_ptr != *saved_key_ptr) {
return ((int) *new_key_ptr - (int) *saved_key_ptr); }
saved_key_ptr++;
new_key_length--;
saved_key_length--;
if (!*new_key_ptr++) { continue; }
}
new_key_field_length = key_part->field->packed_col_length(new_key_ptr, key_part->length);
saved_key_field_length = key_part->field->packed_col_length(saved_key_ptr, key_part->length);
assert(new_key_length >= new_key_field_length);
assert(saved_key_length >= saved_key_field_length);
if ((cmp = key_part->field->pack_cmp(new_key_ptr, saved_key_ptr, key_part->length, 0)))
return cmp;
new_key_ptr += new_key_field_length;
new_key_length -= new_key_field_length;
saved_key_ptr += saved_key_field_length;
saved_key_length -= saved_key_field_length;
}
//
// at this point, we have compared the actual keys and the primary key, we return 0
//
ret_val = 0;
}
}
return ret_val;
}
static int tokudb_cmp_packed_key(DB *file, const DBT *keya, const DBT *keyb) {
assert(file->app_private != 0);
KEY *key = (KEY *) file->app_private;
KEY *primary_key = (KEY *) file->api_internal;
if (key->flags & HA_CLUSTERING) {
return tokudb_compare_two_clustered_keys(key, primary_key, keya, keyb);
}
return tokudb_compare_two_keys(key, keya->data, keya->size, keyb->data, keyb->size, false);
}
static int tokudb_cmp_primary_key(DB *file, const DBT *keya, const DBT *keyb) {
assert(file->app_private != 0);
KEY *key = (KEY *) file->api_internal;
return tokudb_compare_two_keys(key, keya->data, keya->size, keyb->data, keyb->size, false);
}
//TODO: QQQ Only do one direction for prefix.
static int tokudb_prefix_cmp_packed_key(DB *file, const DBT *keya, const DBT *keyb) {
assert(file->app_private != 0);
KEY *key = (KEY *) file->app_private;
return tokudb_compare_two_keys(key, keya->data, keya->size, keyb->data, keyb->size, true);
}
int primary_key_part_compare (const void* left, const void* right) { int primary_key_part_compare (const void* left, const void* right) {
PRIM_KEY_PART_INFO* left_part= (PRIM_KEY_PART_INFO *)left; PRIM_KEY_PART_INFO* left_part= (PRIM_KEY_PART_INFO *)left;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#endif #endif
#include <db.h> #include <db.h>
#include "hatoku_cmp.h"
typedef struct st_tokudb_share { typedef struct st_tokudb_share {
char *table_name; char *table_name;
...@@ -46,26 +47,6 @@ typedef struct st_tokudb_share { ...@@ -46,26 +47,6 @@ typedef struct st_tokudb_share {
uint ai_field_index; uint ai_field_index;
} TOKUDB_SHARE; } TOKUDB_SHARE;
//
// information for hidden primary keys
//
#define TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH 8
//
// function to convert a hidden primary key into a byte stream that can be stored in DBT
//
inline void hpk_num_to_char(uchar* to, ulonglong num) {
int8store(to, num);
}
//
// function that takes a byte stream of a hidden primary key and returns a ulonglong
//
inline ulonglong hpk_char_to_num(uchar* val) {
return uint8korr(val);
}
#define HA_TOKU_VERSION 2 #define HA_TOKU_VERSION 2
// //
// no capabilities yet // no capabilities yet
...@@ -85,18 +66,6 @@ typedef enum { ...@@ -85,18 +66,6 @@ typedef enum {
hatoku_ai_create_value hatoku_ai_create_value
} HA_METADATA_KEY ; } HA_METADATA_KEY ;
//
// for storing NULL byte in keys
//
#define NULL_COL_VAL 0
#define NONNULL_COL_VAL 1
//
// for storing if rest of key is +/- infinity
//
#define COL_NEG_INF 0
#define COL_POS_INF 1
typedef struct st_prim_key_part_info { typedef struct st_prim_key_part_info {
uint offset; uint offset;
uint part_index; uint part_index;
......
#include "mysql_priv.h"
extern "C" {
#include "stdint.h"
}
#include "hatoku_cmp.h"
inline int tokudb_compare_two_hidden_keys(
const void* new_key_data,
const u_int32_t new_key_size,
const void* saved_key_data,
const u_int32_t saved_key_size
) {
assert( (new_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH) && (saved_key_size >= TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH) );
ulonglong a = hpk_char_to_num((uchar *) new_key_data);
ulonglong b = hpk_char_to_num((uchar *) saved_key_data);
return a < b ? -1 : (a > b ? 1 : 0);
}
int tokudb_cmp_hidden_key(DB * file, const DBT * new_key, const DBT * saved_key) {
return tokudb_compare_two_hidden_keys(
new_key->data,
new_key->size,
saved_key->data,
saved_key->size
);
}
int tokudb_compare_two_keys(
KEY *key,
const void* new_key_data,
const u_int32_t new_key_size,
const void* saved_key_data,
const u_int32_t saved_key_size,
bool cmp_prefix
) {
uchar new_key_inf_val = *(uchar *) new_key_data;
uchar saved_key_inf_val = *(uchar *) saved_key_data;
//
// first byte is "infinity" byte
//
uchar *new_key_ptr = (uchar *)(new_key_data) + 1;
uchar *saved_key_ptr = (uchar *)(saved_key_data) + 1;
KEY_PART_INFO *key_part = key->key_part, *end = key_part + key->key_parts;
int ret_val;
//
// do not include the inf val at the beginning
//
uint new_key_length = new_key_size - sizeof(uchar);
uint saved_key_length = saved_key_size - sizeof(uchar);
//DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) new_key_length > 0 && (int) saved_key_length > 0; key_part++) {
int cmp;
uint new_key_field_length;
uint saved_key_field_length;
if (key_part->field->null_bit) {
assert(new_key_ptr < (uchar *) new_key_data + new_key_size);
assert(saved_key_ptr < (uchar *) saved_key_data + saved_key_size);
if (*new_key_ptr != *saved_key_ptr) {
return ((int) *new_key_ptr - (int) *saved_key_ptr); }
saved_key_ptr++;
new_key_length--;
saved_key_length--;
if (!*new_key_ptr++) { continue; }
}
new_key_field_length = key_part->field->packed_col_length(new_key_ptr, key_part->length);
saved_key_field_length = key_part->field->packed_col_length(saved_key_ptr, key_part->length);
assert(new_key_length >= new_key_field_length);
assert(saved_key_length >= saved_key_field_length);
if ((cmp = key_part->field->pack_cmp(new_key_ptr, saved_key_ptr, key_part->length, 0)))
return cmp;
new_key_ptr += new_key_field_length;
new_key_length -= new_key_field_length;
saved_key_ptr += saved_key_field_length;
saved_key_length -= saved_key_field_length;
}
if (cmp_prefix || (new_key_length == 0 && saved_key_length == 0) ) {
ret_val = 0;
}
//
// at this point, one SHOULD be 0
//
else if (new_key_length == 0 && saved_key_length > 0) {
ret_val = (new_key_inf_val == COL_POS_INF ) ? 1 : -1;
}
else if (new_key_length > 0 && saved_key_length == 0) {
ret_val = (saved_key_inf_val == COL_POS_INF ) ? -1 : 1;
}
//
// this should never happen, perhaps we should assert(false)
//
else {
ret_val = new_key_length - saved_key_length;
}
return ret_val;
}
//
// this is super super ugly, copied from compare_two_keys so that it can get done fast
//
int tokudb_compare_two_clustered_keys(KEY *key, KEY* primary_key, const DBT * new_key, const DBT * saved_key) {
uchar new_key_inf_val = *(uchar *) new_key->data;
uchar saved_key_inf_val = *(uchar *) saved_key->data;
//
// first byte is "infinity" byte
//
uchar *new_key_ptr = (uchar *)(new_key->data) + 1;
uchar *saved_key_ptr = (uchar *)(saved_key->data) + 1;
KEY_PART_INFO *key_part = key->key_part, *end = key_part + key->key_parts;
int ret_val;
//
// do not include the inf val at the beginning
//
uint new_key_length = new_key->size - sizeof(uchar);
uint saved_key_length = saved_key->size - sizeof(uchar);
//DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) new_key_length > 0 && (int) saved_key_length > 0; key_part++) {
int cmp;
uint new_key_field_length;
uint saved_key_field_length;
if (key_part->field->null_bit) {
assert(new_key_ptr < (uchar *) new_key->data + new_key->size);
assert(saved_key_ptr < (uchar *) saved_key->data + saved_key->size);
if (*new_key_ptr != *saved_key_ptr) {
return ((int) *new_key_ptr - (int) *saved_key_ptr); }
saved_key_ptr++;
new_key_length--;
saved_key_length--;
if (!*new_key_ptr++) { continue; }
}
new_key_field_length = key_part->field->packed_col_length(new_key_ptr, key_part->length);
saved_key_field_length = key_part->field->packed_col_length(saved_key_ptr, key_part->length);
assert(new_key_length >= new_key_field_length);
assert(saved_key_length >= saved_key_field_length);
if ((cmp = key_part->field->pack_cmp(new_key_ptr, saved_key_ptr, key_part->length, 0)))
return cmp;
new_key_ptr += new_key_field_length;
new_key_length -= new_key_field_length;
saved_key_ptr += saved_key_field_length;
saved_key_length -= saved_key_field_length;
}
if (new_key_length == 0 && saved_key_length == 0){
ret_val = 0;
}
else if (new_key_length == 0 && saved_key_length > 0) {
ret_val = (new_key_inf_val == COL_POS_INF ) ? 1 : -1;
}
else if (new_key_length > 0 && saved_key_length == 0) {
ret_val = (saved_key_inf_val == COL_POS_INF ) ? -1 : 1;
}
//
// now we compare the primary key
//
else {
if (primary_key == NULL) {
//
// primary key hidden
//
ulonglong a = hpk_char_to_num((uchar *) new_key_ptr);
ulonglong b = hpk_char_to_num((uchar *) saved_key_ptr);
ret_val = a < b ? -1 : (a > b ? 1 : 0);
}
else {
//
// primary key not hidden, I know this is bad, basically copying the code from above
//
key_part = primary_key->key_part;
end = key_part + primary_key->key_parts;
for (; key_part != end && (int) new_key_length > 0 && (int) saved_key_length > 0; key_part++) {
int cmp;
uint new_key_field_length;
uint saved_key_field_length;
if (key_part->field->null_bit) {
assert(new_key_ptr < (uchar *) new_key->data + new_key->size);
assert(saved_key_ptr < (uchar *) saved_key->data + saved_key->size);
if (*new_key_ptr != *saved_key_ptr) {
return ((int) *new_key_ptr - (int) *saved_key_ptr); }
saved_key_ptr++;
new_key_length--;
saved_key_length--;
if (!*new_key_ptr++) { continue; }
}
new_key_field_length = key_part->field->packed_col_length(new_key_ptr, key_part->length);
saved_key_field_length = key_part->field->packed_col_length(saved_key_ptr, key_part->length);
assert(new_key_length >= new_key_field_length);
assert(saved_key_length >= saved_key_field_length);
if ((cmp = key_part->field->pack_cmp(new_key_ptr, saved_key_ptr, key_part->length, 0)))
return cmp;
new_key_ptr += new_key_field_length;
new_key_length -= new_key_field_length;
saved_key_ptr += saved_key_field_length;
saved_key_length -= saved_key_field_length;
}
//
// at this point, we have compared the actual keys and the primary key, we return 0
//
ret_val = 0;
}
}
return ret_val;
}
int tokudb_cmp_packed_key(DB *file, const DBT *keya, const DBT *keyb) {
assert(file->app_private != 0);
KEY *key = (KEY *) file->app_private;
KEY *primary_key = (KEY *) file->api_internal;
if (key->flags & HA_CLUSTERING) {
return tokudb_compare_two_clustered_keys(key, primary_key, keya, keyb);
}
return tokudb_compare_two_keys(key, keya->data, keya->size, keyb->data, keyb->size, false);
}
int tokudb_cmp_primary_key(DB *file, const DBT *keya, const DBT *keyb) {
assert(file->app_private != 0);
KEY *key = (KEY *) file->api_internal;
return tokudb_compare_two_keys(key, keya->data, keya->size, keyb->data, keyb->size, false);
}
//TODO: QQQ Only do one direction for prefix.
int tokudb_prefix_cmp_packed_key(DB *file, const DBT *keya, const DBT *keyb) {
assert(file->app_private != 0);
KEY *key = (KEY *) file->app_private;
return tokudb_compare_two_keys(key, keya->data, keya->size, keyb->data, keyb->size, true);
}
#ifndef _HATOKU_CMP
#define _HATOKU_CMP
#include "mysql_priv.h"
extern "C" {
#include "stdint.h"
}
#include <db.h>
//
// for storing NULL byte in keys
//
#define NULL_COL_VAL 0
#define NONNULL_COL_VAL 1
//
// for storing if rest of key is +/- infinity
//
#define COL_NEG_INF 0
#define COL_POS_INF 1
//
// information for hidden primary keys
//
#define TOKUDB_HIDDEN_PRIMARY_KEY_LENGTH 8
//
// function to convert a hidden primary key into a byte stream that can be stored in DBT
//
inline void hpk_num_to_char(uchar* to, ulonglong num) {
int8store(to, num);
}
//
// function that takes a byte stream of a hidden primary key and returns a ulonglong
//
inline ulonglong hpk_char_to_num(uchar* val) {
return uint8korr(val);
}
inline int tokudb_compare_two_hidden_keys(
const void* new_key_data,
const u_int32_t new_key_size,
const void* saved_key_data,
const u_int32_t saved_key_size
);
int tokudb_compare_two_keys(
KEY *key,
const void* new_key_data,
const u_int32_t new_key_size,
const void* saved_key_data,
const u_int32_t saved_key_size,
bool cmp_prefix
);
int tokudb_cmp_hidden_key(
DB* file,
const DBT* new_key,
const DBT* saved_key
);
int tokudb_compare_two_clustered_keys(
KEY *key,
KEY* primary_key,
const DBT * new_key,
const DBT * saved_key
);
int tokudb_cmp_packed_key(DB *file, const DBT *keya, const DBT *keyb);
int tokudb_cmp_primary_key(DB *file, const DBT *keya, const DBT *keyb);
//TODO: QQQ Only do one direction for prefix.
int tokudb_prefix_cmp_packed_key(DB *file, const DBT *keya, const DBT *keyb);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment