Commit d635d023 authored by Zardosht Kasheff's avatar Zardosht Kasheff Committed by Yoni Fogel

addresses #1105

fix records_in_range to be able to handle a prefix that is passed in

git-svn-id: file:///svn/mysql/tokudb-engine/src@6073 c7de825b-a66e-492c-adef-691d508d4ae1
parent 613e868e
...@@ -1013,6 +1013,16 @@ static void smart_dbt_callback_rowread_heavi(DBT const *key, DBT const *row, vo ...@@ -1013,6 +1013,16 @@ static void smart_dbt_callback_rowread_heavi(DBT const *key, DBT const *row, vo
smart_dbt_callback_rowread(key,row,context); smart_dbt_callback_rowread(key,row,context);
} }
//
// Smart DBT callback function in records_in_range
//
static void smart_dbt_callback_ror_heavi(DBT const *key, DBT const *row, void *context, int r_h) {
DBT* copied_key = (DBT *)context;
copied_key->size = key->size;
memcpy(copied_key->data, key->data, key->size);
}
// //
// macro for Smart DBT callback function, // macro for Smart DBT callback function,
// so we do not need to put this long line of code in multiple places // so we do not need to put this long line of code in multiple places
...@@ -4185,22 +4195,39 @@ cleanup: ...@@ -4185,22 +4195,39 @@ cleanup:
// //
ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* end_key) { ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* end_key) {
TOKUDB_DBUG_ENTER("ha_tokudb::records_in_range"); TOKUDB_DBUG_ENTER("ha_tokudb::records_in_range");
DBT key; DBT key, after_key;
ha_rows ret_val = HA_TOKUDB_RANGE_COUNT; ha_rows ret_val = HA_TOKUDB_RANGE_COUNT;
DB *kfile = share->key_file[keynr]; DB *kfile = share->key_file[keynr];
u_int64_t less, equal, greater; u_int64_t less, equal, greater;
u_int64_t start_rows, end_rows, rows; u_int64_t start_rows, end_rows, rows;
int is_exact; int is_exact;
int error; int error;
struct heavi_info heavi_info;
DBC* tmp_cursor = NULL;
u_int64_t after_key_less, after_key_equal, after_key_greater;
heavi_info.db = kfile;
heavi_info.key = &key;
after_key.data = key_buff2;
error = kfile->cursor(kfile, transaction, &tmp_cursor, 0);
if (error) {
ret_val = HA_TOKUDB_RANGE_COUNT;
goto cleanup;
}
// //
// get start_rows and end_rows values so that we can estimate range // get start_rows and end_rows values so that we can estimate range
// when calling key_range64, the only value we can trust is the value for less
// The reason is that the key being passed in may be a prefix of keys in the DB
// As a result, equal may be 0 and greater may actually be equal+greater
// So, we call key_range64 on the key, and the key that is after it.
// //
if (start_key) { if (start_key) {
pack_key(&key, keynr, key_buff, start_key->key, start_key->length);
error = kfile->key_range64( error = kfile->key_range64(
kfile, kfile,
transaction, transaction,
pack_key(&key, keynr, key_buff, start_key->key, start_key->length), &key,
&less, &less,
&equal, &equal,
&greater, &greater,
...@@ -4214,7 +4241,38 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* ...@@ -4214,7 +4241,38 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range*
start_rows= less; start_rows= less;
} }
else { else {
start_rows = less + equal; error = tmp_cursor->c_getf_heavi(
tmp_cursor,
0,
smart_dbt_callback_ror_heavi,
&after_key,
after_key_heavi,
&heavi_info,
1
);
if (error && error != DB_NOTFOUND) {
ret_val = HA_TOKUDB_RANGE_COUNT;
goto cleanup;
}
else if (error == DB_NOTFOUND) {
start_rows = stats.records;
}
else {
error = kfile->key_range64(
kfile,
transaction,
&after_key,
&after_key_less,
&after_key_equal,
&after_key_greater,
&is_exact
);
if (error) {
ret_val = HA_TOKUDB_RANGE_COUNT;
goto cleanup;
}
start_rows = after_key_less;
}
} }
} }
else { else {
...@@ -4222,10 +4280,11 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* ...@@ -4222,10 +4280,11 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range*
} }
if (end_key) { if (end_key) {
pack_key(&key, keynr, key_buff, end_key->key, end_key->length);
error = kfile->key_range64( error = kfile->key_range64(
kfile, kfile,
transaction, transaction,
pack_key(&key, keynr, key_buff, end_key->key, end_key->length), &key,
&less, &less,
&equal, &equal,
&greater, &greater,
...@@ -4239,14 +4298,45 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* ...@@ -4239,14 +4298,45 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range*
end_rows= less; end_rows= less;
} }
else { else {
end_rows= less + equal; error = tmp_cursor->c_getf_heavi(
tmp_cursor,
0,
smart_dbt_callback_ror_heavi,
&after_key,
after_key_heavi,
&heavi_info,
1
);
if (error && error != DB_NOTFOUND) {
ret_val = HA_TOKUDB_RANGE_COUNT;
goto cleanup;
}
else if (error == DB_NOTFOUND) {
end_rows = stats.records;
}
else {
error = kfile->key_range64(
kfile,
transaction,
&after_key,
&after_key_less,
&after_key_equal,
&after_key_greater,
&is_exact
);
if (error) {
ret_val = HA_TOKUDB_RANGE_COUNT;
goto cleanup;
}
end_rows= after_key_less;
}
} }
} }
else { else {
end_rows = stats.records; end_rows = stats.records;
} }
rows = end_rows - start_rows; rows = (end_rows > start_rows) ? end_rows - start_rows : 1;
// //
// MySQL thinks a return value of 0 means there are exactly 0 rows // MySQL thinks a return value of 0 means there are exactly 0 rows
...@@ -4254,6 +4344,10 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range* ...@@ -4254,6 +4344,10 @@ ha_rows ha_tokudb::records_in_range(uint keynr, key_range* start_key, key_range*
// //
ret_val = (ha_rows) (rows <= 1 ? 1 : rows); ret_val = (ha_rows) (rows <= 1 ? 1 : rows);
cleanup: cleanup:
if (tmp_cursor) {
tmp_cursor->c_close(tmp_cursor);
tmp_cursor = NULL;
}
TOKUDB_DBUG_RETURN(ret_val); TOKUDB_DBUG_RETURN(ret_val);
} }
......
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