tree data UPDATE key-less lists are always equivalent
... for comparison purposes.
diff --git a/src/diff.c b/src/diff.c
index 51189d2..fd5a176 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -366,7 +366,7 @@
LY_ERR rc = LY_SUCCESS;
const struct lysc_node *schema;
size_t buflen, bufused;
- uint32_t first_pos, second_pos;
+ uint32_t first_pos, second_pos, comp_opts;
assert(first || second);
@@ -402,7 +402,8 @@
} else if (!first) {
*op = LYD_DIFF_OP_CREATE;
} else {
- if (lyd_compare_single(second, userord_item->inst[second_pos], 0)) {
+ comp_opts = lysc_is_dup_inst_list(second->schema) ? LYD_COMPARE_FULL_RECURSION : 0;
+ if (lyd_compare_single(second, userord_item->inst[second_pos], comp_opts)) {
/* in first, there is a different instance on the second position, we are going to move 'first' node */
*op = LYD_DIFF_OP_REPLACE;
} else if ((options & LYD_DIFF_DEFAULTS) && ((first->flags & LYD_DEFAULT) != (second->flags & LYD_DEFAULT))) {
diff --git a/src/tree_data.c b/src/tree_data.c
index b7617ad..de5a120 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1372,28 +1372,30 @@
iter1 = lyd_child(node1);
iter2 = lyd_child(node2);
- if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
- /* lists with keys, their equivalence is based on their keys */
- for (const struct lysc_node *key = lysc_node_child(node1->schema);
- key && (key->flags & LYS_KEY);
- key = key->next) {
- if (!iter1 || !iter2) {
- return (iter1 == iter2) ? LY_SUCCESS : LY_ENOT;
- }
- r = lyd_compare_single_schema(iter1, iter2, options, 1);
- LY_CHECK_RET(r);
- r = lyd_compare_single_data(iter1, iter2, options);
- LY_CHECK_RET(r);
-
- iter1 = iter1->next;
- iter2 = iter2->next;
- }
-
- return LY_SUCCESS;
- } else {
- /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
+ if (options & LYD_COMPARE_FULL_RECURSION) {
return lyd_compare_siblings_(iter1, iter2, options, 1);
+ } else if (node1->schema->flags & LYS_KEYLESS) {
+ /* always equal */
+ return LY_SUCCESS;
}
+
+ /* lists with keys, their equivalence is based on their keys */
+ for (const struct lysc_node *key = lysc_node_child(node1->schema);
+ key && (key->flags & LYS_KEY);
+ key = key->next) {
+ if (!iter1 || !iter2) {
+ return (iter1 == iter2) ? LY_SUCCESS : LY_ENOT;
+ }
+ r = lyd_compare_single_schema(iter1, iter2, options, 1);
+ LY_CHECK_RET(r);
+ r = lyd_compare_single_data(iter1, iter2, options);
+ LY_CHECK_RET(r);
+
+ iter1 = iter1->next;
+ iter2 = iter2->next;
+ }
+
+ return LY_SUCCESS;
case LYS_ANYXML:
case LYS_ANYDATA:
any1 = (struct lyd_node_any *)node1;
@@ -2618,7 +2620,7 @@
/* we must search the instances from beginning to find the first matching one */
found = 0;
LYD_LIST_FOR_INST(siblings, target->schema, iter) {
- if (!lyd_compare_single(target, iter, 0)) {
+ if (!lyd_compare_single(target, iter, LYD_COMPARE_FULL_RECURSION)) {
found = 1;
break;
}
@@ -2640,8 +2642,14 @@
} else {
/* no children hash table */
for ( ; siblings; siblings = siblings->next) {
- if (!lyd_compare_single(siblings, target, LYD_COMPARE_OPAQ)) {
- break;
+ if (lysc_is_dup_inst_list(target->schema)) {
+ if (!lyd_compare_single(siblings, target, LYD_COMPARE_FULL_RECURSION)) {
+ break;
+ }
+ } else {
+ if (!lyd_compare_single(siblings, target, LYD_COMPARE_OPAQ)) {
+ break;
+ }
}
}
}
@@ -2728,6 +2736,7 @@
{
struct lyd_node **match_p, *first, *iter;
struct lyd_node_inner *parent;
+ uint32_t comp_opts;
LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
@@ -2739,6 +2748,9 @@
return LY_ENOTFOUND;
}
+ /* set options */
+ comp_opts = LYD_COMPARE_OPAQ | (lysc_is_dup_inst_list(target->schema) ? LYD_COMPARE_FULL_RECURSION : 0);
+
/* get first sibling */
siblings = lyd_first_sibling(siblings);
@@ -2763,7 +2775,7 @@
}
while (iter) {
/* add all found nodes into the set */
- if ((iter != first) && !lyd_compare_single(iter, target, 0) && ly_set_add(*set, iter, 1, NULL)) {
+ if ((iter != first) && !lyd_compare_single(iter, target, comp_opts) && ly_set_add(*set, iter, 1, NULL)) {
goto error;
}
@@ -2778,7 +2790,7 @@
} else {
/* no children hash table */
LY_LIST_FOR(siblings, siblings) {
- if (!lyd_compare_single(target, siblings, LYD_COMPARE_OPAQ)) {
+ if (!lyd_compare_single(target, siblings, comp_opts)) {
ly_set_add(*set, (void *)siblings, 1, NULL);
}
}
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index 4d73377..462913b 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -1,9 +1,9 @@
/**
* @file test_tree_data.c
- * @author: Radek Krejci <rkrejci@cesnet.cz>
- * @brief unit tests for functions from tress_data.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for functions from tree_data.c
*
- * Copyright (c) 2018-2019 CESNET, z.s.p.o.
+ * Copyright (c) 2018-2023 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -100,7 +100,7 @@
data2 = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
- assert_int_equal(LY_ENOT, lyd_compare_single(tree1->next, tree2->next, 0));
+ assert_int_equal(LY_ENOT, lyd_compare_single(tree1->next, tree2->next, LYD_COMPARE_FULL_RECURSION));
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next->next, tree2->next, 0));
lyd_free_all(tree1);
lyd_free_all(tree2);