Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coprocessor/scanner: set key_only=true if needed #2580

Merged
merged 8 commits into from
Dec 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 64 additions & 28 deletions src/coprocessor/dag/executor/index_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ impl IndexScanExecutor {
}

fn new_scanner(&self, range: KeyRange) -> Result<Scanner> {
// Since the unique index wouldn't always come with
// self.unique = true. so the key-only would always be false.
Scanner::new(&self.store, ScanOn::Index, self.desc, false, range).map_err(Error::from)
}

Expand Down Expand Up @@ -201,9 +203,15 @@ mod test {
const KEY_NUMBER: usize = 10;

// get_idx_range get range for index in [("abc",start),("abc", end))
pub fn get_idx_range(table_id: i64, idx_id: i64, start: i64, end: i64) -> KeyRange {
let (_, start_key) = generate_index_data(table_id, idx_id, start);
let (_, end_key) = generate_index_data(table_id, idx_id, end);
pub fn get_idx_range(
table_id: i64,
idx_id: i64,
start: i64,
end: i64,
unique: bool,
) -> KeyRange {
let (_, start_key) = generate_index_data(table_id, idx_id, start, unique);
let (_, end_key) = generate_index_data(table_id, idx_id, end, unique);
let mut key_range = KeyRange::new();
key_range.set_start(start_key);
key_range.set_end(end_key);
Expand All @@ -214,25 +222,34 @@ mod test {
table_id: i64,
index_id: i64,
handle: i64,
unique: bool,
) -> (HashMap<i64, Vec<u8>>, Vec<u8>) {
let indice = vec![
(2, Datum::Bytes(b"abc".to_vec())),
(3, Datum::Dec(handle.into())),
];
let mut expect_row = HashMap::default();
let v: Vec<_> = indice
let mut v: Vec<_> = indice
.iter()
.map(|&(ref cid, ref value)| {
expect_row.insert(*cid, datum::encode_key(&[value.clone()]).unwrap());
value.clone()
})
.collect();
if !unique {
v.push(Datum::I64(handle));
}
let encoded = datum::encode_key(&v).unwrap();
let idx_key = table::encode_index_seek_key(table_id, index_id, &encoded);
(expect_row, idx_key)
}

pub fn prepare_index_data(key_number: usize, table_id: i64, index_id: i64) -> Data {
pub fn prepare_index_data(
key_number: usize,
table_id: i64,
index_id: i64,
unique: bool,
) -> Data {
let cols = vec![
new_col_info(1, types::LONG_LONG),
new_col_info(2, types::VARCHAR),
Expand All @@ -243,10 +260,16 @@ mod test {
let mut expect_rows = Vec::new();

for handle in 0..key_number {
let (expect_row, idx_key) = generate_index_data(table_id, index_id, handle as i64);
let (expect_row, idx_key) =
generate_index_data(table_id, index_id, handle as i64, unique);
expect_rows.push(expect_row);
let mut value = Vec::with_capacity(8);
value.write_i64::<BigEndian>(handle as i64).unwrap();
let value = if unique {
let mut value = Vec::with_capacity(8);
value.write_i64::<BigEndian>(handle as i64).unwrap();
value
} else {
vec![1; 0]
};
kv_data.push((idx_key, value));
}
Data {
Expand All @@ -266,7 +289,7 @@ mod test {

impl IndexTestWrapper {
fn include_pk_cols() -> IndexTestWrapper {
let mut wrapper = IndexTestWrapper::default();
let mut wrapper = IndexTestWrapper::new(false);
let mut cols = wrapper.data.get_index_cols();
cols.push(wrapper.data.get_col_pk());
wrapper
Expand All @@ -275,19 +298,17 @@ mod test {
wrapper.cols = cols;
wrapper
}
}

impl Default for IndexTestWrapper {
fn default() -> IndexTestWrapper {
let test_data = prepare_index_data(KEY_NUMBER, TABLE_ID, INDEX_ID);
fn new(unique: bool) -> IndexTestWrapper {
let test_data = prepare_index_data(KEY_NUMBER, TABLE_ID, INDEX_ID, unique);
let test_store = TestStore::new(&test_data.kv_data);
let mut scan = IndexScan::new();
// prepare cols
let cols = test_data.get_index_cols();
let col_req = RepeatedField::from_vec(cols.clone());
scan.set_columns(col_req);
// prepare range
let range = get_idx_range(TABLE_ID, INDEX_ID, 0, i64::MAX);
let range = get_idx_range(TABLE_ID, INDEX_ID, 0, i64::MAX, unique);
let key_ranges = vec![range];
IndexTestWrapper {
data: test_data,
Expand All @@ -301,13 +322,15 @@ mod test {

#[test]
fn test_multiple_ranges() {
let mut wrapper = IndexTestWrapper::default();
let r1 = get_idx_range(TABLE_ID, INDEX_ID, 0, (KEY_NUMBER / 3) as i64);
let unique = false;
let mut wrapper = IndexTestWrapper::new(false);
let r1 = get_idx_range(TABLE_ID, INDEX_ID, 0, (KEY_NUMBER / 3) as i64, unique);
let r2 = get_idx_range(
TABLE_ID,
INDEX_ID,
(KEY_NUMBER / 3) as i64,
(KEY_NUMBER / 2) as i64,
unique,
);
wrapper.ranges = vec![r1, r2];
let (snapshot, start_ts) = wrapper.store.get_snapshot();
Expand All @@ -331,23 +354,29 @@ mod test {

#[test]
fn test_unique_index_scan() {
let mut wrapper = IndexTestWrapper::default();

let r1 = get_idx_range(TABLE_ID, INDEX_ID, 0, 1); // point get
let r2 = get_idx_range(TABLE_ID, INDEX_ID, 1, 4); // range seek
let r3 = get_idx_range(TABLE_ID, INDEX_ID, 4, 5); // point get
let r4 = get_idx_range(TABLE_ID, INDEX_ID, 5, (KEY_NUMBER + 1) as i64); // range seek
let unique = true;
let mut wrapper = IndexTestWrapper::new(unique);

// point get
let r1 = get_idx_range(TABLE_ID, INDEX_ID, 0, 1, unique);
// range seek
let r2 = get_idx_range(TABLE_ID, INDEX_ID, 1, 4, unique);
// point get
let r3 = get_idx_range(TABLE_ID, INDEX_ID, 4, 5, unique);
//range seek
let r4 = get_idx_range(TABLE_ID, INDEX_ID, 5, (KEY_NUMBER + 1) as i64, unique);
let r5 = get_idx_range(
TABLE_ID,
INDEX_ID,
(KEY_NUMBER + 1) as i64,
(KEY_NUMBER + 2) as i64,
unique,
); // point get but miss
wrapper.ranges = vec![r1, r2, r3, r4, r5];

let (snapshot, start_ts) = wrapper.store.get_snapshot();
let store = SnapshotStore::new(snapshot, start_ts, IsolationLevel::SI, true);
let mut scanner = IndexScanExecutor::new(wrapper.scan, wrapper.ranges, store, false);
let mut scanner = IndexScanExecutor::new(wrapper.scan, wrapper.ranges, store, unique);
for handle in 0..KEY_NUMBER {
let row = scanner.next().unwrap().unwrap();
assert_eq!(row.handle, handle as i64);
Expand All @@ -364,18 +393,25 @@ mod test {

#[test]
fn test_reverse_scan() {
let mut wrapper = IndexTestWrapper::default();
let unique = false;
let mut wrapper = IndexTestWrapper::new(unique);
wrapper.scan.set_desc(true);

let r1 = get_idx_range(TABLE_ID, INDEX_ID, i64::MIN, 0);
let r2 = get_idx_range(TABLE_ID, INDEX_ID, 0, (KEY_NUMBER / 2) as i64);
let r3 = get_idx_range(TABLE_ID, INDEX_ID, (KEY_NUMBER / 2) as i64, i64::MAX);
let r1 = get_idx_range(TABLE_ID, INDEX_ID, i64::MIN, 0, unique);
let r2 = get_idx_range(TABLE_ID, INDEX_ID, 0, (KEY_NUMBER / 2) as i64, unique);
let r3 = get_idx_range(
TABLE_ID,
INDEX_ID,
(KEY_NUMBER / 2) as i64,
i64::MAX,
unique,
);
wrapper.ranges = vec![r1, r2, r3];

let (snapshot, start_ts) = wrapper.store.get_snapshot();
let store = SnapshotStore::new(snapshot, start_ts, IsolationLevel::SI, true);

let mut scanner = IndexScanExecutor::new(wrapper.scan, wrapper.ranges, store, false);
let mut scanner = IndexScanExecutor::new(wrapper.scan, wrapper.ranges, store, unique);

for tid in 0..KEY_NUMBER {
let handle = KEY_NUMBER - tid - 1;
Expand Down
8 changes: 7 additions & 1 deletion src/coprocessor/dag/executor/table_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ impl TableScanExecutor {
}

fn new_scanner(&self, range: KeyRange) -> Result<Scanner> {
Scanner::new(&self.store, ScanOn::Table, self.desc, false, range).map_err(Error::from)
Scanner::new(
&self.store,
ScanOn::Table,
self.desc,
self.col_ids.is_empty(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about handle?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle wouldn't appear in self.col_ids since it was filtered on L47 @BusyJay

range,
).map_err(Error::from)
}
}

Expand Down