ldb_tdb: Rework list_union to not return duplicates, and keep sort order
authorAndrew Bartlett <abartlet@samba.org>
Mon, 21 Aug 2017 23:07:45 +0000 (11:07 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 22 Sep 2017 19:20:23 +0000 (21:20 +0200)
This allows the binary search to still operate on the list, even after
a or operator in the search expression

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
lib/ldb/ldb_tdb/ldb_index.c

index 45dfbebceb273a9a473ff791ffdfdc0dde0ffac0..97ff823ec393499479e2f19804ece7d89b822517 100644 (file)
@@ -890,6 +890,7 @@ static bool list_union(struct ldb_context *ldb,
                       struct dn_list *list, struct dn_list *list2)
 {
        struct ldb_val *dn3;
+       unsigned int i = 0, j = 0, k = 0;
 
        if (list2->count == 0) {
                /* X | 0 == X */
@@ -921,12 +922,38 @@ static bool list_union(struct ldb_context *ldb,
                return false;
        }
 
-       /* we allow for duplicates here, and get rid of them later */
-       memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count);
-       memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count);
+       while (i < list->count || j < list2->count) {
+               int cmp;
+               if (i >= list->count) {
+                       cmp = 1;
+               } else if (j >= list2->count) {
+                       cmp = -1;
+               } else {
+                       cmp = ldb_val_equal_exact_ordered(list->dn[i],
+                                                         &list2->dn[j]);
+               }
+
+               if (cmp < 0) {
+                       /* Take list */
+                       dn3[k] = list->dn[i];
+                       i++;
+                       k++;
+               } else if (cmp > 0) {
+                       /* Take list2 */
+                       dn3[k] = list2->dn[j];
+                       j++;
+                       k++;
+               } else {
+                       /* Equal, take list */
+                       dn3[k] = list->dn[i];
+                       i++;
+                       j++;
+                       k++;
+               }
+       }
 
        list->dn = dn3;
-       list->count += list2->count;
+       list->count = k;
 
        return true;
 }