diff --git a/mod/box/box.m b/mod/box/box.m index 8361a76680bf15414c4b99976d797a6979a2b668..4d4b08a9dc4ee15b5ba081b3f893585178150228 100644 --- a/mod/box/box.m +++ b/mod/box/box.m @@ -1017,7 +1017,7 @@ prepare_update(struct box_txn *txn, struct tbuf *data) struct update_cmd *cmd = parse_update_cmd(data); /* Try to find the tuple. */ - txn->old_tuple = [txn->index find :cmd->key :cmd->key_cardinality]; + txn->old_tuple = [txn->index findByKey :cmd->key :cmd->key_cardinality]; if (txn->old_tuple == NULL) { /* Not found. For simplicity, skip the logging. */ txn->flags |= BOX_NOT_STORE; @@ -1070,7 +1070,7 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data) read_key(data, &key, &key_cardinality); struct iterator *it = index->position; - [index initIterator: it :ITER_FORWARD :key :key_cardinality]; + [index initIteratorByKey: it :ITER_FORWARD :key :key_cardinality]; while ((tuple = it->next_equal(it)) != NULL) { if (tuple->flags & GHOST) @@ -1101,7 +1101,7 @@ prepare_delete(struct box_txn *txn, struct tbuf *data) void *key; read_key(data, &key, &key_cardinality); /* try to find tuple in primary index */ - txn->old_tuple = [txn->index find :key :key_cardinality]; + txn->old_tuple = [txn->index findByKey :key :key_cardinality]; if (txn->old_tuple == NULL) { /* diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index 8ee57c9bbbe1af02d66545970e09c692cf851787..332c512b9041b312a28dbf2bd39f24d79394ec30 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -436,7 +436,7 @@ lbox_index_move(struct lua_State *L, enum iterator_type type) "does not match index cardinality (%d)", cardinality, index->key_def->part_count); it = [index allocIterator]; - [index initIterator: it :type :key :cardinality]; + [index initIteratorByKey: it :type :key :cardinality]; lbox_pushiterator(L, it); } else { /* 1 item on the stack and it's a userdata. */ it = lua_checkiterator(L, 2); diff --git a/mod/box/index.h b/mod/box/index.h index 99a6d72dc80987f7f8c1eb8abad5d0f9b7502bc8..d38ad1a2f1846f0d72d88bece1d4a2aad6a77895 100644 --- a/mod/box/index.h +++ b/mod/box/index.h @@ -117,7 +117,7 @@ struct key_def { - (size_t) size; - (struct box_tuple *) min; - (struct box_tuple *) max; -- (struct box_tuple *) find: (void *) key :(int) key_cardinality; +- (struct box_tuple *) findByKey: (void *) key :(int) parts; - (struct box_tuple *) findByTuple: (struct box_tuple *) tuple; - (void) remove: (struct box_tuple *) tuple; - (void) replace: (struct box_tuple *) old_tuple :(struct box_tuple *) new_tuple; @@ -126,10 +126,22 @@ struct key_def { * initialized separately. */ - (struct iterator *) allocIterator; -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type; -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type - :(void *) key - :(int) part_count; +- (void) initIterator: (struct iterator *) iterator + :(enum iterator_type) type; +- (void) initIteratorByKey: (struct iterator *) iterator + :(enum iterator_type) type + :(void *) key :(int) parts; +/** + * Check key cardinality. + */ +- (void) checkKeyParts: (int) parts :(bool) partial_key_allowed; +/** + * Unsafe search methods that do not check key cardinality. + */ +- (struct box_tuple *) findUnsafe: (void *) key :(int) key_cardinality; +- (void) initIteratorUnsafe: (struct iterator *) iterator + :(enum iterator_type) type + :(void *) key :(int) parts; @end struct iterator { diff --git a/mod/box/index.m b/mod/box/index.m index 5d0e48cc2079a388aafb5767918b37f81682f497..799e99f6c0091dc6c2ff36fbbbc1e2c38587d973 100644 --- a/mod/box/index.m +++ b/mod/box/index.m @@ -131,10 +131,16 @@ iterator_first_equal(struct iterator *it) return NULL; } -- (struct box_tuple *) find: (void *) key :(int) key_cardinality +- (struct box_tuple *) findByKey: (void *) key :(int) parts +{ + [self checkKeyParts: parts :false]; + return [self findUnsafe: key :parts]; +} + +- (struct box_tuple *) findUnsafe: (void *) key :(int) parts { (void) key; - (void) key_cardinality; + (void) parts; [self subclassResponsibility: _cmd]; return NULL; } @@ -173,16 +179,33 @@ iterator_first_equal(struct iterator *it) [self subclassResponsibility: _cmd]; } -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type - :(void *) key - :(int) key_cardinality +- (void) initIteratorByKey: (struct iterator *) iterator :(enum iterator_type) type + :(void *) key :(int) parts +{ + [self checkKeyParts: parts :true]; + [self initIteratorUnsafe: iterator :type :key :parts]; +} + +- (void) initIteratorUnsafe: (struct iterator *) iterator :(enum iterator_type) type + :(void *) key :(int) parts { (void) iterator; (void) type; (void) key; - (void) key_cardinality; + (void) parts; [self subclassResponsibility: _cmd]; } + +- (void) checkKeyParts: (int) parts :(bool) partial_key_allowed +{ + if (parts > key_def->part_count) + tnt_raise(ClientError, :ER_KEY_CARDINALITY, + parts, key_def->part_count); + if (!partial_key_allowed && parts < key_def->part_count) + tnt_raise(ClientError, :ER_EXACT_MATCH, + parts, key_def->part_count); +} + @end /* }}} */ @@ -279,7 +302,7 @@ hash_iterator_free(struct iterator *iterator) if (field == NULL) tnt_raise(ClientError, :ER_NO_SUCH_FIELD, key_def->parts[0].fieldno); - return [self find :field :1]; + return [self findUnsafe :field :1]; } - (struct iterator *) allocIterator @@ -292,6 +315,14 @@ hash_iterator_free(struct iterator *iterator) } return (struct iterator *) it; } + +- (void) checkKeyParts: (int) parts :(bool) partial_key_allowed +{ + /* Hash indexes never allows partial keys. */ + (void) partial_key_allowed; + [super checkKeyParts: parts :false]; +} + @end /* }}} */ @@ -299,20 +330,11 @@ hash_iterator_free(struct iterator *iterator) /* {{{ Hash32Index ************************************************/ static u32 -int32_key_to_value(void *key, int key_cardinality) +int32_key_to_value(void *key) { - if (key_cardinality > 1) - tnt_raise(ClientError, :ER_KEY_CARDINALITY, - key_cardinality, 1); - - if (key_cardinality < 1) - tnt_raise(ClientError, :ER_EXACT_MATCH, - key_cardinality, 1); - u32 key_size = load_varint32(&key); if (key_size != 4) tnt_raise(ClientError, :ER_KEY_FIELD_TYPE, "u32"); - return *((u32 *) key); } @@ -345,10 +367,12 @@ int32_key_to_value(void *key, int key_cardinality) return mh_size(int_hash); } -- (struct box_tuple *) find: (void *) key :(int) key_cardinality +- (struct box_tuple *) findUnsafe: (void *) key :(int) parts { + (void) parts; + struct box_tuple *ret = NULL; - u32 num = int32_key_to_value(key, key_cardinality); + u32 num = int32_key_to_value(key); mh_int_t k = mh_i32ptr_get(int_hash, num); if (k != mh_end(int_hash)) ret = mh_value(int_hash, k); @@ -361,7 +385,7 @@ int32_key_to_value(void *key, int key_cardinality) - (void) remove: (struct box_tuple *) tuple { void *field = tuple_field(tuple, key_def->parts[0].fieldno); - u32 num = int32_key_to_value(field, 1); + u32 num = int32_key_to_value(field); mh_int_t k = mh_i32ptr_get(int_hash, num); if (k != mh_end(int_hash)) mh_i32ptr_del(int_hash, k); @@ -374,7 +398,7 @@ int32_key_to_value(void *key, int key_cardinality) :(struct box_tuple *) new_tuple { void *field = tuple_field(new_tuple, key_def->parts[0].fieldno); - u32 num = int32_key_to_value(field, 1); + u32 num = int32_key_to_value(field); if (old_tuple != NULL) { void *old_field = tuple_field(old_tuple, @@ -407,17 +431,17 @@ int32_key_to_value(void *key, int key_cardinality) it->hash = int_hash; } -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type - :(void *) key - :(int) key_cardinality +- (void) initIteratorUnsafe: (struct iterator *) iterator :(enum iterator_type) type + :(void *) key :(int) parts { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); - + (void) parts; if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); - u32 num = int32_key_to_value(key, key_cardinality); + assert(iterator->next == hash_iterator_next); + struct hash_iterator *it = hash_iterator(iterator); + + u32 num = int32_key_to_value(key); it->base.next_equal = iterator_first_equal; it->h_pos = mh_i32ptr_get(int_hash, num); it->hash = int_hash; @@ -429,20 +453,11 @@ int32_key_to_value(void *key, int key_cardinality) /* {{{ Hash64Index ************************************************/ static u64 -int64_key_to_value(void *key, int key_cardinality) +int64_key_to_value(void *key) { - if (key_cardinality > 1) - tnt_raise(ClientError, :ER_KEY_CARDINALITY, - key_cardinality, 1); - - if (key_cardinality < 1) - tnt_raise(ClientError, :ER_EXACT_MATCH, - key_cardinality, 1); - u32 key_size = load_varint32(&key); if (key_size != 8) tnt_raise(ClientError, :ER_KEY_FIELD_TYPE, "u64"); - return *((u64 *) key); } @@ -473,10 +488,12 @@ int64_key_to_value(void *key, int key_cardinality) return mh_size(int64_hash); } -- (struct box_tuple *) find: (void *) key :(int) key_cardinality +- (struct box_tuple *) findUnsafe: (void *) key :(int) parts { + (void) parts; + struct box_tuple *ret = NULL; - u64 num = int64_key_to_value(key, key_cardinality); + u64 num = int64_key_to_value(key); mh_int_t k = mh_i64ptr_get(int64_hash, num); if (k != mh_end(int64_hash)) ret = mh_value(int64_hash, k); @@ -489,7 +506,7 @@ int64_key_to_value(void *key, int key_cardinality) - (void) remove: (struct box_tuple *) tuple { void *field = tuple_field(tuple, key_def->parts[0].fieldno); - u64 num = int64_key_to_value(field, 1); + u64 num = int64_key_to_value(field); mh_int_t k = mh_i64ptr_get(int64_hash, num); if (k != mh_end(int64_hash)) @@ -503,7 +520,7 @@ int64_key_to_value(void *key, int key_cardinality) :(struct box_tuple *) new_tuple { void *field = tuple_field(new_tuple, key_def->parts[0].fieldno); - u64 num = int64_key_to_value(field, 1); + u64 num = int64_key_to_value(field); if (old_tuple != NULL) { void *old_field = tuple_field(old_tuple, @@ -535,17 +552,17 @@ int64_key_to_value(void *key, int key_cardinality) it->hash = (struct mh_i32ptr_t *) int64_hash; } -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type - :(void *) key - :(int) key_cardinality +- (void) initIteratorUnsafe: (struct iterator *) iterator :(enum iterator_type) type + :(void *) key :(int) parts { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); - + (void) parts; if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); - u64 num = int64_key_to_value(key, key_cardinality); + assert(iterator->next == hash_iterator_next); + struct hash_iterator *it = hash_iterator(iterator); + + u64 num = int64_key_to_value(key); it->base.next_equal = iterator_first_equal; it->h_pos = mh_i64ptr_get(int64_hash, num); @@ -557,18 +574,6 @@ int64_key_to_value(void *key, int key_cardinality) /* {{{ HashStrIndex ***********************************************/ -static char * -str_key_to_value(void *key, int key_cardinality) -{ - if (key_cardinality > 1) - tnt_raise(ClientError, :ER_KEY_CARDINALITY, - key_cardinality, 1); - if (key_cardinality < 1) - tnt_raise(ClientError, :ER_EXACT_MATCH, - key_cardinality, 1); - return key; -} - @interface HashStrIndex: HashIndex { struct mh_lstrptr_t *str_hash; }; @@ -596,11 +601,11 @@ str_key_to_value(void *key, int key_cardinality) return mh_size(str_hash); } -- (struct box_tuple *) find: (void *) key :(int) key_cardinality +- (struct box_tuple *) findUnsafe: (void *) key :(int) parts { + (void) parts; struct box_tuple *ret = NULL; - void *lstr = str_key_to_value(key, key_cardinality); - mh_int_t k = mh_lstrptr_get(str_hash, lstr); + mh_int_t k = mh_lstrptr_get(str_hash, key); if (k != mh_end(str_hash)) ret = mh_value(str_hash, k); #ifdef DEBUG @@ -663,19 +668,19 @@ str_key_to_value(void *key, int key_cardinality) it->hash = (struct mh_i32ptr_t *) str_hash; } -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type - :(void *) key - :(int) key_cardinality +- (void) initIteratorUnsafe: (struct iterator *) iterator + :(enum iterator_type) type + :(void *) key :(int) parts { - assert(iterator->next == hash_iterator_next); - struct hash_iterator *it = hash_iterator(iterator); - + (void) parts; if (type == ITER_REVERSE) tnt_raise(IllegalParams, :"hash iterator is forward only"); - void *lstr = str_key_to_value(key, key_cardinality); + assert(iterator->next == hash_iterator_next); + struct hash_iterator *it = hash_iterator(iterator); + it->base.next_equal = iterator_first_equal; - it->h_pos = mh_lstrptr_get(str_hash, lstr); + it->h_pos = mh_lstrptr_get(str_hash, key); it->hash = (struct mh_i32ptr_t *) str_hash; } @end diff --git a/mod/box/memcached.m b/mod/box/memcached.m index 9e2deb1c97ff67c7185f1e4be58ef5969dc6ef4e..3669d19eff5dd719eac7252901f343e78a253c3f 100644 --- a/mod/box/memcached.m +++ b/mod/box/memcached.m @@ -131,7 +131,7 @@ delete(void *key) static struct box_tuple * find(void *key) { - return [memcached_index find :key :1]; + return [memcached_index findByKey :key :1]; } static struct meta * diff --git a/mod/box/tree.m b/mod/box/tree.m index 76d589e72877330c7ef96bd1ecb5a4bc5a4e520e..78e1e13615920eb03bbf6eb291b629515812b34d 100644 --- a/mod/box/tree.m +++ b/mod/box/tree.m @@ -864,22 +864,14 @@ tree_iterator_free(struct iterator *iterator) return [self unfold: node]; } -- (struct box_tuple *) find: (void *) key : (int) key_cardinality +- (struct box_tuple *) findUnsafe: (void *) key : (int) parts { struct key_data *key_data = alloca(sizeof(struct key_data) + - _SIZEOF_SPARSE_PARTS(key_cardinality)); - - if (key_cardinality > key_def->part_count) - tnt_raise(ClientError, :ER_KEY_CARDINALITY, - key_cardinality, key_def->part_count); - - if (key_cardinality < key_def->part_count) - tnt_raise(ClientError, :ER_EXACT_MATCH, - key_cardinality, key_def->part_count); + _SIZEOF_SPARSE_PARTS(parts)); key_data->data = key; - key_data->part_count = key_cardinality; + key_data->part_count = parts; fold_with_key_parts(key_def, key_data); void *node = sptree_index_find(&tree, key_data); @@ -938,22 +930,17 @@ tree_iterator_free(struct iterator *iterator) - (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type { - [self initIterator: iterator :type :NULL :0]; + [self initIteratorUnsafe: iterator :type :NULL :0]; } -- (void) initIterator: (struct iterator *) iterator :(enum iterator_type) type - :(void *) key - :(int) key_cardinality +- (void) initIteratorUnsafe: (struct iterator *) iterator :(enum iterator_type) type + :(void *) key :(int) parts { assert(iterator->free == tree_iterator_free); struct tree_iterator *it = tree_iterator(iterator); - if (key_cardinality > key_def->part_count) - tnt_raise(ClientError, :ER_KEY_CARDINALITY, - key_cardinality, key_def->part_count); - it->key_data.data = key; - it->key_data.part_count = key_cardinality; + it->key_data.part_count = parts; fold_with_key_parts(key_def, &it->key_data); if (type == ITER_FORWARD) {