From: Konstantin Osipov <kostja@tarantool.org> To: Kirill Shcherbatov <kshcherbatov@tarantool.org> Cc: tarantool-patches@freelists.org, vdavydov.dev@gmail.com Subject: Re: [PATCH v4 4/4] box: introduce functional indexes Date: Thu, 25 Jul 2019 00:56:18 +0300 [thread overview] Message-ID: <20190724215618.GC11790@atlas> (raw) In-Reply-To: <e244e92d21226c8a869d9d87987ccc9cf21af803.1563953154.git.kshcherbatov@tarantool.org> * Kirill Shcherbatov <kshcherbatov@tarantool.org> [19/07/24 10:38]: > --- a/src/box/errcode.h > +++ b/src/box/errcode.h > @@ -250,6 +250,7 @@ struct errcode_record { > /*195 */_(ER_CREATE_CK_CONSTRAINT, "Failed to create check constraint '%s': %s") \ > /*196 */_(ER_CK_CONSTRAINT_FAILED, "Check constraint failed '%s': %s") \ > /*197 */_(ER_SQL_COLUMN_COUNT, "Unequal number of entries in row expression: left side has %u, but right side - %u") \ > + /*198 */_(ER_FUNCTIONAL_INDEX_FUNC_ERROR,"Functional index function '%s' error: %s") \ > There is ER_ prefix, no need to add ERROR suffix. The error code should reference index name and table name, not function name, or all of this. Imagine getting this error for a Lua procedure, it should not require too many extra steps to nail down the cause. There should be different error codes for different errors. Resetting the original error is also a very unfriendly, please add a ticket and a follow up patch to your todo list for stacked errors. I mean, it's the last drop, how many times shall we step on lack of stacked diagnostics before we add them? > +/** > + * Update func pointer for functional index key definitions. > + * @param def Index def, containing key definitions to update. > + * @param func The functional index function pointer. > + */ > +static inline void > +index_def_update_func(struct index_def *def, struct func *func) > +{ > + def->key_def->func_index_func = func; > + def->cmp_def->func_index_func = func; > +} should be set_func, not update_func. > uint32_t unique_part_count; > + /** > + * Count of parts in functional index defintion. > + * All functional_part_count key_part(s) of an > + * initialized key def instance have func != NULL pointer. > + * != 0 iff it is functional index definition. > + */ > + uint32_t functional_part_count; I don't get this comment, we don't store func pointer in key_part. Why do you need this at all? part_count should be enough. > + /** A pointer to functional index function. */ > + struct func *func_index_func; Please explain the life cycle of this member (it is not immediately initialized, when is it assigned then?, when is it safe to rely on it?) and how it is used. > + /** Space id of _func_index. */ > + BOX_FUNC_INDEX_ID = 372, Please explain how this space is used. Please document why we decided to have a separate space. > + *key = it->data; > + if (!it->validate) { Please document circumstances when validate is false. > + if (mp_typeof(*it->data) != MP_ARRAY) { > + diag_set(ClientError, ER_FUNCTIONAL_INDEX_FUNC_ERROR, > + if (part_count != functional_part_count) { > + const char *error_msg = > + diag_set(ClientError, ER_FUNCTIONAL_INDEX_FUNC_ERROR, > + if (key_validate_parts(it->key_def, rptr, functional_part_count, true, > + &key_end) != 0) { > + diag_set(ClientError, ER_FUNCTIONAL_INDEX_FUNC_ERROR, These three places should use its own error code, not ER_FUNC_INDEX_FUNC, ER_FUNC_INDEX_FUNC_FORMAT I guess. > @@ -251,8 +253,15 @@ index_def_to_key_def(struct rlist *index_defs, int *size) > { > int key_count = 0; > struct index_def *index_def; > - rlist_foreach_entry(index_def, index_defs, link) > + rlist_foreach_entry(index_def, index_defs, link) { > + /* > + * Don't use functional index key definition > + * to build a space format. > + */ > + if (key_def_is_functional(index_def->key_def)) > + continue; > key_count++; Why not skip such keys when building a space format? What is the benefit of depriving the format module of these key defs? > @@ -262,8 +271,11 @@ index_def_to_key_def(struct rlist *index_defs, int *size) > } > *size = key_count; > key_count = 0; > - rlist_foreach_entry(index_def, index_defs, link) > + rlist_foreach_entry(index_def, index_defs, link) { > + if (key_def_is_functional(index_def->key_def)) > + continue; > keys[key_count++] = index_def->key_def; > + } > return keys; Same here. I'm sure space format module can figure out that it deals with a functional key definition and skip it if necessary. > + if (index_def->iid == 0 && key_def_is_functional(index_def->key_def)) { > + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, > + space_name, "primary key cannot be functional"); primary key can not use a function > struct key_def * > -key_def_new(const struct key_part_def *parts, uint32_t part_count) > +key_def_new(const struct key_part_def *parts, uint32_t part_count, > + bool is_functional) I don't like it that key_def_new has become overly complicated with collations, multikey and functional indexes. Perhaps we need to introduce key_def_is_valid, similar to index_def_is_valid(), but I need to think. > key_def_can_merge(const struct key_def *key_def, > const struct key_part *to_merge) > { > + if (key_def_is_functional(key_def)) > + return true; Please explain what's going on here in a comment. > struct key_def * > key_def_merge(const struct key_def *first, const struct key_def *second) > { > + assert(!key_def_is_functional(second)); Same here. > - struct key_def *key_def = key_def_new(parts, part_count); > + struct key_def *key_def = key_def_new(parts, part_count, false); I don't get this, there should be two flags (is_multikey, is_functional). How did this compile? > > + if (index_opts->functional_fid > 0) { > + lua_pushnumber(L, index_opts->functional_fid); > + lua_setfield(L, -2, "func_id"); > + } Why not function name? > +template<bool is_nullable> > +static inline int > +functional_compare(struct tuple *tuple_a, hint_t tuple_a_hint, > + struct tuple *tuple_b, hint_t tuple_b_hint, > + struct key_def *key_def) > +{ Please solicit Vlad's review and explain the changes here in a changeset comment. > +static char * > +tuple_extract_key_stub(struct tuple *tuple, struct key_def *key_def, > + int multikey_idx, uint32_t *key_size) > +{ > + (void)tuple; (void)key_def; (void)multikey_idx; (void)key_size; > + unreachable(); > + return NULL; > +} > + > +static char * > +tuple_extract_key_raw_stub(const char *data, const char *data_end, > + struct key_def *key_def, int multikey_idx, > + uint32_t *key_size) > +{ > + (void)data; (void)data_end; > + (void)key_def; (void)multikey_idx; (void)key_size; > + unreachable(); > + return NULL; > +} Why do you need these? -- Konstantin Osipov, Moscow, Russia
next prev parent reply other threads:[~2019-07-24 21:56 UTC|newest] Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-07-24 7:36 [PATCH v4 0/4] box: " Kirill Shcherbatov 2019-07-24 7:36 ` [PATCH v4 1/4] box: introduce tuple_chunk infrastructure Kirill Shcherbatov 2019-07-24 7:36 ` [PATCH v4 2/4] box: generalize memtx_multikey_tree methods Kirill Shcherbatov 2019-07-24 19:24 ` Konstantin Osipov 2019-07-24 7:36 ` [PATCH v4 3/4] box: refactor memtx_tree_delete_identical Kirill Shcherbatov 2019-07-24 19:24 ` Konstantin Osipov 2019-07-24 7:36 ` [PATCH v4 4/4] box: introduce functional indexes Kirill Shcherbatov 2019-07-24 12:24 ` [tarantool-patches] " Kirill Shcherbatov 2019-07-24 19:41 ` Konstantin Osipov 2019-07-24 20:04 ` Konstantin Osipov 2019-07-24 20:22 ` Konstantin Osipov 2019-07-25 11:20 ` [tarantool-patches] " Kirill Shcherbatov 2019-07-24 20:44 ` Konstantin Osipov 2019-07-25 11:22 ` [tarantool-patches] " Kirill Shcherbatov 2019-07-24 21:07 ` Konstantin Osipov 2019-07-25 8:27 ` [tarantool-patches] " Kirill Shcherbatov 2019-07-25 8:40 ` Konstantin Osipov 2019-07-25 11:18 ` Kirill Shcherbatov 2019-07-24 21:17 ` Konstantin Osipov 2019-07-24 21:56 ` Konstantin Osipov [this message] 2019-07-25 8:33 ` [tarantool-patches] " Kirill Shcherbatov 2019-07-24 12:25 ` [tarantool-patches] [PATCH v4 4/5] box: fix memtx_tree_index_build_array_deduplicate Kirill Shcherbatov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190724215618.GC11790@atlas \ --to=kostja@tarantool.org \ --cc=kshcherbatov@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=vdavydov.dev@gmail.com \ --subject='Re: [PATCH v4 4/4] box: introduce functional indexes' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox