diff --git a/src/box/index_def.c b/src/box/index_def.c index 28de89274ea78496f3fb40147299160c7cfc85ab..eb309a30c6bbfc4ac398b559e7de756367833b49 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -291,7 +291,7 @@ index_def_is_valid(struct index_def *index_def, const char *space_name) space_name, "too many key parts"); return false; } - if (index_def->iid == 0 && key_def_is_multikey(index_def->key_def)) { + if (index_def->iid == 0 && index_def->key_def->is_multikey) { diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, space_name, "primary key cannot be multikey"); return false; diff --git a/src/box/key_def.c b/src/box/key_def.c index eebfb7fe4c9c0da06a998271581bd5e7cb21eb27..2aa095091e44ff6e1dedc10e38f484c479003aac 100644 --- a/src/box/key_def.c +++ b/src/box/key_def.c @@ -181,6 +181,7 @@ key_def_set_part_path(struct key_def *def, uint32_t part_no, const char *path, def->multikey_path = part->path; def->multikey_fieldno = part->fieldno; def->multikey_path_len = (uint32_t) multikey_path_len; + def->is_multikey = true; } else if (def->multikey_fieldno != part->fieldno || json_path_cmp(path, multikey_path_len, def->multikey_path, def->multikey_path_len, @@ -752,6 +753,7 @@ key_def_merge(const struct key_def *first, const struct key_def *second) new_def->is_nullable = first->is_nullable || second->is_nullable; new_def->has_optional_parts = first->has_optional_parts || second->has_optional_parts; + new_def->is_multikey = first->is_multikey || second->is_multikey; /* JSON paths data in the new key_def. */ char *path_pool = (char *)new_def + key_def_sizeof(new_part_count, 0); diff --git a/src/box/key_def.h b/src/box/key_def.h index f4a1a8fd1e7e79500a24a427e1f569c77054d38d..ab4b7c0878699650bcb70ecea11f8234bb97225e 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -196,6 +196,8 @@ struct key_def { bool is_nullable; /** True if some key part has JSON path. */ bool has_json_paths; + /** True if it is multikey key definition. */ + bool is_multikey; /** * True, if some key parts can be absent in a tuple. These * fields assumed to be MP_NIL. @@ -220,14 +222,14 @@ struct key_def { const char *multikey_path; /** * The length of the key_def::multikey_path. - * Valid when key_def_is_multikey(key_def) is true, + * Valid when key_def->is_multikey is true, * undefined otherwise. */ uint32_t multikey_path_len; /** * The index of the root field of the multikey JSON * path index key_def::multikey_path. - * Valid when key_def_is_multikey(key_def) is true, + * Valid when key_def->is_multikey is true, * undefined otherwise. */ uint32_t multikey_fieldno; @@ -469,12 +471,6 @@ key_def_is_sequential(const struct key_def *key_def) return true; } -static inline bool -key_def_is_multikey(const struct key_def *key_def) -{ - return key_def->multikey_path != NULL; -} - /** * Return true if @a key_def defines has fields that requires * special collation comparison. diff --git a/src/box/memtx_bitset.c b/src/box/memtx_bitset.c index 8c626684ce5c7aec3ebf3841f7394435f0b10dc0..59bc96427ba9f45de2a4b51b903c5ea5d5acd4c5 100644 --- a/src/box/memtx_bitset.c +++ b/src/box/memtx_bitset.c @@ -276,7 +276,7 @@ memtx_bitset_index_replace(struct index *base, struct tuple *old_tuple, struct memtx_bitset_index *index = (struct memtx_bitset_index *)base; assert(!base->def->opts.is_unique); - assert(!key_def_is_multikey(base->def->key_def)); + assert(!base->def->key_def->is_multikey); assert(old_tuple != NULL || new_tuple != NULL); (void) mode; diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c index 869cd343a4f9d4b07ca8ec5c5ac51660c9b96317..428491c2d8421a9d3daf4370964a44d61882e1f2 100644 --- a/src/box/memtx_engine.c +++ b/src/box/memtx_engine.c @@ -1251,7 +1251,6 @@ memtx_index_def_change_requires_rebuild(struct index *index, TUPLE_INDEX_BASE) != 0) return true; } - assert(key_def_is_multikey(old_cmp_def) == - key_def_is_multikey(new_cmp_def)); + assert(old_cmp_def->is_multikey == new_cmp_def->is_multikey); return false; } diff --git a/src/box/memtx_rtree.c b/src/box/memtx_rtree.c index b91a405d768da4bff9309b1f7a2961e17babac52..8badad797b4ab251824364ebc7ad14adbd43d4ea 100644 --- a/src/box/memtx_rtree.c +++ b/src/box/memtx_rtree.c @@ -120,7 +120,7 @@ extract_rectangle(struct rtree_rect *rect, struct tuple *tuple, struct index_def *index_def) { assert(index_def->key_def->part_count == 1); - assert(!key_def_is_multikey(index_def->key_def)); + assert(!index_def->key_def->is_multikey); const char *elems = tuple_field_by_part(tuple, index_def->key_def->parts, MULTIKEY_NONE); unsigned dimension = index_def->opts.dimension; diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index 09277b0295f2db786329368bf68e3f2221f87191..a8e7b8080cf4ec5df355d31bcbac781aacf7b4c8 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -653,7 +653,7 @@ memtx_space_check_index_def(struct space *space, struct index_def *index_def) "HASH index must be unique"); return -1; } - if (key_def_is_multikey(index_def->key_def)) { + if (index_def->key_def->is_multikey) { diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, space_name(space), "HASH index cannot be multikey"); @@ -682,7 +682,7 @@ memtx_space_check_index_def(struct space *space, struct index_def *index_def) "RTREE index field type must be ARRAY"); return -1; } - if (key_def_is_multikey(index_def->key_def)) { + if (index_def->key_def->is_multikey) { diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, space_name(space), "RTREE index cannot be multikey"); @@ -710,7 +710,7 @@ memtx_space_check_index_def(struct space *space, struct index_def *index_def) "BITSET index field type must be NUM or STR"); return -1; } - if (key_def_is_multikey(index_def->key_def)) { + if (index_def->key_def->is_multikey) { diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, space_name(space), "BITSET index cannot be multikey"); diff --git a/src/box/memtx_tree.c b/src/box/memtx_tree.c index 268ce4050f1c38b1b0d5a8c40effd45c543af263..3edf94044d1ace228431aefaddd6fdbf800e6517 100644 --- a/src/box/memtx_tree.c +++ b/src/box/memtx_tree.c @@ -882,7 +882,7 @@ memtx_tree_index_end_build(struct index *base) struct key_def *cmp_def = memtx_tree_cmp_def(&index->tree); qsort_arg(index->build_array, index->build_array_size, sizeof(index->build_array[0]), memtx_tree_qcompare, cmp_def); - if (key_def_is_multikey(cmp_def)) { + if (cmp_def->is_multikey) { /* * Multikey index may have equal(in terms of * cmp_def) keys inserted by different multikey @@ -1027,7 +1027,7 @@ memtx_tree_index_new(struct memtx_engine *memtx, struct index_def *def) "malloc", "struct memtx_tree_index"); return NULL; } - const struct index_vtab *vtab = key_def_is_multikey(def->key_def) ? + const struct index_vtab *vtab = def->key_def->is_multikey ? &memtx_tree_index_multikey_vtab : &memtx_tree_index_vtab; if (index_create(&index->base, (struct engine *)memtx, diff --git a/src/box/tuple.c b/src/box/tuple.c index a7ef332b2fb7534c3201eb6251ff42cef34805c5..c0e94d55b6ac2cbf691bee6bd668e1b20da9ebdd 100644 --- a/src/box/tuple.c +++ b/src/box/tuple.c @@ -553,7 +553,7 @@ tuple_raw_multikey_count(struct tuple_format *format, const char *data, const uint32_t *field_map, struct key_def *key_def) { - assert(key_def_is_multikey(key_def)); + assert(key_def->is_multikey); const char *array_raw = tuple_field_raw_by_path(format, data, field_map, key_def->multikey_fieldno, diff --git a/src/box/tuple_bloom.c b/src/box/tuple_bloom.c index 8b74da22c836bad8c7ee43fbb5113d9c4163ee04..420a7c60ea967970238ed81502a72dfaa0b0aee0 100644 --- a/src/box/tuple_bloom.c +++ b/src/box/tuple_bloom.c @@ -109,7 +109,7 @@ tuple_bloom_builder_add(struct tuple_bloom_builder *builder, int multikey_idx) { assert(builder->part_count == key_def->part_count); - assert(!key_def_is_multikey(key_def) || multikey_idx != MULTIKEY_NONE); + assert(!key_def->is_multikey || multikey_idx != MULTIKEY_NONE); uint32_t h = HASH_SEED; uint32_t carry = 0; @@ -204,7 +204,7 @@ bool tuple_bloom_maybe_has(const struct tuple_bloom *bloom, struct tuple *tuple, struct key_def *key_def, int multikey_idx) { - assert(!key_def_is_multikey(key_def) || multikey_idx != MULTIKEY_NONE); + assert(!key_def->is_multikey || multikey_idx != MULTIKEY_NONE); if (bloom->is_legacy) { return bloom_maybe_has(&bloom->parts[0], diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc index 95a0f58c941daea4e9959e592d7c4c965f4ac75f..c03b584d0237ded8569bb9e2eed797dae211be69 100644 --- a/src/box/tuple_compare.cc +++ b/src/box/tuple_compare.cc @@ -460,9 +460,9 @@ tuple_compare_slowpath(struct tuple *tuple_a, hint_t tuple_a_hint, assert(!has_optional_parts || is_nullable); assert(is_nullable == key_def->is_nullable); assert(has_optional_parts == key_def->has_optional_parts); - assert(key_def_is_multikey(key_def) == is_multikey); - assert(!is_multikey || (is_multikey == has_json_paths && - tuple_a_hint != HINT_NONE && tuple_b_hint != HINT_NONE)); + assert(key_def->is_multikey == is_multikey); + assert(!is_multikey || (tuple_a_hint != HINT_NONE && + tuple_b_hint != HINT_NONE)); int rc = 0; if (!is_multikey && (rc = hint_cmp(tuple_a_hint, tuple_b_hint)) != 0) return rc; @@ -619,9 +619,9 @@ tuple_compare_with_key_slowpath(struct tuple *tuple, hint_t tuple_hint, assert(has_optional_parts == key_def->has_optional_parts); assert(key != NULL || part_count == 0); assert(part_count <= key_def->part_count); - assert(key_def_is_multikey(key_def) == is_multikey); - assert(!is_multikey || (is_multikey == has_json_paths && - tuple_hint != HINT_NONE && key_hint == HINT_NONE)); + assert(key_def->is_multikey == is_multikey); + assert(!is_multikey || (tuple_hint != HINT_NONE && + key_hint == HINT_NONE)); int rc = 0; if (!is_multikey && (rc = hint_cmp(tuple_hint, key_hint)) != 0) return rc; @@ -1573,7 +1573,7 @@ template <enum field_type type, bool is_nullable> static hint_t key_hint(const char *key, uint32_t part_count, struct key_def *key_def) { - assert(!key_def_is_multikey(key_def)); + assert(!key_def->is_multikey); if (part_count == 0) return HINT_NONE; return field_hint<type, is_nullable>(key, key_def->parts->coll); @@ -1583,7 +1583,7 @@ template <enum field_type type, bool is_nullable> static hint_t tuple_hint(struct tuple *tuple, struct key_def *key_def) { - assert(!key_def_is_multikey(key_def)); + assert(!key_def->is_multikey); const char *field = tuple_field_by_part(tuple, key_def->parts, MULTIKEY_NONE); if (is_nullable && field == NULL) @@ -1607,7 +1607,7 @@ key_hint_multikey(const char *key, uint32_t part_count, struct key_def *key_def) * do nothing on key hint calculation an it is valid * because it is never used(unlike tuple hint). */ - assert(key_def_is_multikey(key_def)); + assert(key_def->is_multikey); return HINT_NONE; } @@ -1641,7 +1641,7 @@ key_def_set_hint_func(struct key_def *def) static void key_def_set_hint_func(struct key_def *def) { - if (key_def_is_multikey(def)) { + if (def->is_multikey) { def->key_hint = key_hint_multikey; def->tuple_hint = tuple_hint_multikey; return; @@ -1756,7 +1756,7 @@ static void key_def_set_compare_func_json(struct key_def *def) { assert(def->has_json_paths); - if (key_def_is_multikey(def)) { + if (def->is_multikey) { def->tuple_compare = tuple_compare_slowpath <is_nullable, has_optional_parts, true, true>; def->tuple_compare_with_key = tuple_compare_with_key_slowpath diff --git a/src/box/tuple_extract_key.cc b/src/box/tuple_extract_key.cc index 3bd3cde70b3024979255998e7c5c7d72c6af1d7b..471c7df80870f9fa7bc7cd5ab4fa1d58c13c6bd6 100644 --- a/src/box/tuple_extract_key.cc +++ b/src/box/tuple_extract_key.cc @@ -118,8 +118,8 @@ tuple_extract_key_slowpath(struct tuple *tuple, struct key_def *key_def, assert(has_optional_parts == key_def->has_optional_parts); assert(contains_sequential_parts == key_def_contains_sequential_parts(key_def)); - assert(is_multikey == key_def_is_multikey(key_def)); - assert(!key_def_is_multikey(key_def) || multikey_idx != MULTIKEY_NONE); + assert(is_multikey == key_def->is_multikey); + assert(!key_def->is_multikey || multikey_idx != MULTIKEY_NONE); assert(mp_sizeof_nil() == 1); const char *data = tuple_data(tuple); uint32_t part_count = key_def->part_count; @@ -250,7 +250,7 @@ tuple_extract_key_slowpath_raw(const char *data, const char *data_end, assert(has_json_paths == key_def->has_json_paths); assert(!has_optional_parts || key_def->is_nullable); assert(has_optional_parts == key_def->has_optional_parts); - assert(!key_def_is_multikey(key_def) || multikey_idx != MULTIKEY_NONE); + assert(!key_def->is_multikey || multikey_idx != MULTIKEY_NONE); assert(mp_sizeof_nil() == 1); /* allocate buffer with maximal possible size */ char *key = (char *) region_alloc(&fiber()->gc, data_end - data); @@ -366,7 +366,7 @@ static void key_def_set_extract_func_plain(struct key_def *def) { assert(!def->has_json_paths); - assert(!key_def_is_multikey(def)); + assert(!def->is_multikey); if (key_def_is_sequential(def)) { assert(contains_sequential_parts || def->part_count == 1); def->tuple_extract_key = tuple_extract_key_sequential @@ -387,7 +387,7 @@ static void key_def_set_extract_func_json(struct key_def *def) { assert(def->has_json_paths); - if (key_def_is_multikey(def)) { + if (def->is_multikey) { def->tuple_extract_key = tuple_extract_key_slowpath <contains_sequential_parts, has_optional_parts, true, true>; @@ -452,7 +452,7 @@ tuple_key_contains_null(struct tuple *tuple, struct key_def *def, int tuple_validate_key_parts(struct key_def *key_def, struct tuple *tuple) { - assert(!key_def_is_multikey(key_def)); + assert(!key_def->is_multikey); for (uint32_t idx = 0; idx < key_def->part_count; idx++) { struct key_part *part = &key_def->parts[idx]; const char *field = tuple_field_by_part(tuple, part, diff --git a/src/box/tuple_hash.cc b/src/box/tuple_hash.cc index 223c5f6f45943038d975925d980574fe6eacc2f0..780e3d053622bb52b191b1ac23aaab2870626884 100644 --- a/src/box/tuple_hash.cc +++ b/src/box/tuple_hash.cc @@ -155,7 +155,7 @@ struct TupleHash { static uint32_t hash(struct tuple *tuple, struct key_def *key_def) { - assert(!key_def_is_multikey(key_def)); + assert(!key_def->is_multikey); uint32_t h = HASH_SEED; uint32_t carry = 0; uint32_t total_size = 0; @@ -172,7 +172,7 @@ template <> struct TupleHash<FIELD_TYPE_UNSIGNED> { static uint32_t hash(struct tuple *tuple, struct key_def *key_def) { - assert(!key_def_is_multikey(key_def)); + assert(!key_def->is_multikey); const char *field = tuple_field_by_part(tuple, key_def->parts, MULTIKEY_NONE); @@ -364,7 +364,7 @@ tuple_hash_slowpath(struct tuple *tuple, struct key_def *key_def) { assert(has_json_paths == key_def->has_json_paths); assert(has_optional_parts == key_def->has_optional_parts); - assert(!key_def_is_multikey(key_def)); + assert(!key_def->is_multikey); uint32_t h = HASH_SEED; uint32_t carry = 0; uint32_t total_size = 0; diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 5c0114ac67a53d0788647dfecebf722d4391f679..f68958ba195293496d917606ed4d4c599f6bec52 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -1019,8 +1019,7 @@ vinyl_index_def_change_requires_rebuild(struct index *index, TUPLE_INDEX_BASE) != 0) return true; } - assert(key_def_is_multikey(old_cmp_def) == - key_def_is_multikey(new_cmp_def)); + assert(old_cmp_def->is_multikey == new_cmp_def->is_multikey); return false; } @@ -1643,7 +1642,7 @@ vy_check_is_unique_secondary(struct vy_tx *tx, const struct vy_read_view **rv, { if (!lsm->check_is_unique) return 0; - if (!key_def_is_multikey(lsm->cmp_def)) { + if (!lsm->cmp_def->is_multikey) { return vy_check_is_unique_secondary_one(tx, rv, space_name, index_name, lsm, stmt, MULTIKEY_NONE); diff --git a/src/box/vy_stmt.h b/src/box/vy_stmt.h index a80456add05acd079bbe48dc3e59d365f1abfbab..25219230d05aa7abb44d391b8996b755bcfddba7 100644 --- a/src/box/vy_stmt.h +++ b/src/box/vy_stmt.h @@ -696,7 +696,7 @@ vy_stmt_str(struct tuple *stmt); static inline int vy_entry_multikey_idx(struct vy_entry entry, struct key_def *key_def) { - if (!key_def_is_multikey(key_def) || vy_stmt_is_key(entry.stmt)) + if (!key_def->is_multikey || vy_stmt_is_key(entry.stmt)) return MULTIKEY_NONE; assert(entry.hint != HINT_NONE); return (int)entry.hint; @@ -766,11 +766,11 @@ vy_entry_compare_with_raw_key(struct vy_entry entry, */ #define vy_stmt_foreach_entry(entry, src_stmt, key_def) \ for (uint32_t multikey_idx = 0, \ - multikey_count = !key_def_is_multikey((key_def)) ? 1 : \ + multikey_count = !(key_def)->is_multikey ? 1 : \ tuple_multikey_count((src_stmt), (key_def)); \ multikey_idx < multikey_count && \ (((entry).stmt = (src_stmt)), \ - ((entry).hint = !key_def_is_multikey((key_def)) ? \ + ((entry).hint = !(key_def)->is_multikey ? \ vy_stmt_hint((src_stmt), (key_def)) : \ multikey_idx), true); \ ++multikey_idx)