From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Kirill Shcherbatov Subject: [PATCH v2 2/5] lib: introduce is_weak_cmp flag for json_path_cmp Date: Tue, 19 Mar 2019 15:32:07 +0300 Message-Id: <4bba9ffc9e05d9094682a9ad30b62a4e079d2b6d.1552998554.git.kshcherbatov@tarantool.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit To: tarantool-patches@freelists.org, vdavydov.dev@gmail.com Cc: Kirill Shcherbatov List-ID: Introduced is_weak_cmp flag for json_path_cmp routine: when this flag is set, strings are equal when whole b path is an a subpath (in terms of tokens). Needed for #1257 --- src/box/index_def.c | 2 +- src/box/key_def.c | 4 ++-- src/box/memtx_engine.c | 2 +- src/box/vinyl.c | 2 +- src/lib/json/json.c | 4 +++- src/lib/json/json.h | 6 +++++- test/unit/json.c | 13 ++++++++++--- test/unit/json.result | 4 +++- 8 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/box/index_def.c b/src/box/index_def.c index 6c37f9f1d..f0c7dc4f6 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -285,7 +285,7 @@ index_def_is_valid(struct index_def *index_def, const char *space_name) if (part_a->fieldno == part_b->fieldno && json_path_cmp(part_a->path, part_a->path_len, part_b->path, part_b->path_len, - TUPLE_INDEX_BASE) == 0) { + false, TUPLE_INDEX_BASE) == 0) { diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, space_name, "same key part is indexed twice"); diff --git a/src/box/key_def.c b/src/box/key_def.c index 55dcf1eb5..f9e464402 100644 --- a/src/box/key_def.c +++ b/src/box/key_def.c @@ -311,7 +311,7 @@ key_part_cmp(const struct key_part *parts1, uint32_t part_count1, key_part_is_nullable(part2) ? -1 : 1; int rc = json_path_cmp(part1->path, part1->path_len, part2->path, part2->path_len, - TUPLE_INDEX_BASE); + false, TUPLE_INDEX_BASE); if (rc != 0) return rc; } @@ -606,7 +606,7 @@ key_def_find(const struct key_def *key_def, const struct key_part *to_find) if (part->fieldno == to_find->fieldno && json_path_cmp(part->path, part->path_len, to_find->path, to_find->path_len, - TUPLE_INDEX_BASE) == 0) + false, TUPLE_INDEX_BASE) == 0) return part; } return NULL; diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c index d468d1cd8..3e959ff2e 100644 --- a/src/box/memtx_engine.c +++ b/src/box/memtx_engine.c @@ -1317,7 +1317,7 @@ memtx_index_def_change_requires_rebuild(struct index *index, return true; if (json_path_cmp(old_part->path, old_part->path_len, new_part->path, new_part->path_len, - TUPLE_INDEX_BASE) != 0) + false, TUPLE_INDEX_BASE) != 0) return true; } return false; diff --git a/src/box/vinyl.c b/src/box/vinyl.c index c2b7eb78f..78f29c624 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -1013,7 +1013,7 @@ vinyl_index_def_change_requires_rebuild(struct index *index, return true; if (json_path_cmp(old_part->path, old_part->path_len, new_part->path, new_part->path_len, - TUPLE_INDEX_BASE) != 0) + false, TUPLE_INDEX_BASE) != 0) return true; } return false; diff --git a/src/lib/json/json.c b/src/lib/json/json.c index 568e9c246..4e1efb7a9 100644 --- a/src/lib/json/json.c +++ b/src/lib/json/json.c @@ -281,7 +281,7 @@ json_token_cmp(const struct json_token *a, const struct json_token *b) int json_path_cmp(const char *a, int a_len, const char *b, int b_len, - int index_base) + bool is_weak_cmp, int index_base) { struct json_lexer lexer_a, lexer_b; json_lexer_create(&lexer_a, a, a_len, index_base); @@ -301,6 +301,8 @@ json_path_cmp(const char *a, int a_len, const char *b, int b_len, } /* Paths a and b must be valid. */ assert(rc_b == 0 && rc_b == 0); + if (is_weak_cmp) + return 0; /* * The parser stopped because the end of one of the paths * was reached. As JSON_TOKEN_END > JSON_TOKEN_{NUM, STR}, diff --git a/src/lib/json/json.h b/src/lib/json/json.h index 4c1bc18bc..53a0da5f9 100644 --- a/src/lib/json/json.h +++ b/src/lib/json/json.h @@ -245,12 +245,16 @@ json_lexer_next_token(struct json_lexer *lexer, struct json_token *token); * Compare two JSON paths using Lexer class. * - in case of paths that have same token-sequence prefix, * the path having more tokens is assumed to be greater + * (except the case when is_weak_cmp flag is set). * - both paths must be valid * (may be tested with json_path_validate). + * + * When is_weak_cmp flag is set, strings are assumed to be equal + * when all b path tokens are present in a path. */ int json_path_cmp(const char *a, int a_len, const char *b, int b_len, - int index_base); + bool is_weak_cmp, int index_base); /** * Check if the passed JSON path is valid. diff --git a/test/unit/json.c b/test/unit/json.c index 1db7e9364..10704451b 100644 --- a/test/unit/json.c +++ b/test/unit/json.c @@ -479,12 +479,12 @@ test_path_cmp() {"Data[1][\"Info\"].fname[1]", -1}, }; header(); - plan(lengthof(rc) + 6); + plan(lengthof(rc) + 8); for (size_t i = 0; i < lengthof(rc); ++i) { const char *path = rc[i].path; int errpos = rc[i].errpos; int rc = json_path_cmp(a, a_len, path, strlen(path), - INDEX_BASE); + false, INDEX_BASE); if (rc > 0) rc = 1; if (rc < 0) rc = -1; is(rc, errpos, "path cmp result \"%s\" with \"%s\": " @@ -493,7 +493,7 @@ test_path_cmp() char *multikey_a = "Data[*][\"FIO\"].fname[*]"; char *multikey_b = "[\"Data\"][*].FIO[\"fname\"][*]"; int ret = json_path_cmp(multikey_a, strlen(multikey_a), multikey_b, - strlen(multikey_b), INDEX_BASE); + strlen(multikey_b), false, INDEX_BASE); is(ret, 0, "path cmp result \"%s\" with \"%s\": have %d, expected %d", multikey_a, multikey_b, ret, 0); @@ -510,6 +510,13 @@ test_path_cmp() "test json_path_is_multikey: multikey path"); is(ret, 8, "test json_path_is_multikey: multikey path %d/%d", ret, 8); + is(json_path_cmp(a, a_len, multikey_b, ret, false, INDEX_BASE) == 0, false, + "test json_path_cmp with is_weak_cmp = false: compare %s and %.*s", + a, ret, multikey_b); + is(json_path_cmp(a, a_len, multikey_b, ret, true, INDEX_BASE) == 0, true, + "test json_path_cmp with is_weak_cmp = true: compare %s and %.*s", + a, ret, multikey_b); + check_plan(); footer(); } diff --git a/test/unit/json.result b/test/unit/json.result index 0da6c8c6b..e57dc748a 100644 --- a/test/unit/json.result +++ b/test/unit/json.result @@ -170,7 +170,7 @@ ok 2 - subtests ok 3 - subtests *** test_tree: done *** *** test_path_cmp *** - 1..11 + 1..13 ok 1 - path cmp result "Data[1]["FIO"].fname" with "Data[1]["FIO"].fname": have 0, expected 0 ok 2 - path cmp result "Data[1]["FIO"].fname" with "["Data"][1].FIO["fname"]": have 0, expected 0 ok 3 - path cmp result "Data[1]["FIO"].fname" with "Data[1]": have 1, expected 1 @@ -182,6 +182,8 @@ ok 3 - subtests ok 9 - test json_path_is_multikey: non-multikey path ok 10 - test json_path_is_multikey: multikey path ok 11 - test json_path_is_multikey: multikey path 8/8 + ok 12 - test json_path_cmp with is_weak_cmp = false: compare Data[1]["FIO"].fname and ["Data"] + ok 13 - test json_path_cmp with is_weak_cmp = true: compare Data[1]["FIO"].fname and ["Data"] ok 4 - subtests *** test_path_cmp: done *** *** test_path_snprint *** -- 2.21.0