1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/*****************************************************************************
Copyright (c) 2020, 2025, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License, version 2.0, as published by the
Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
/** @file include/ddl0impl-compare.h
DDL key comparison.
Created 2020-11-01 by Sunny Bains. */
#ifndef ddl0impl_compare_h
#define ddl0impl_compare_h
#include "ddl0impl.h"
#include "rem0cmp.h"
namespace ddl {
/** Compare the keys of an index. */
struct Compare_key {
/** Constructor.
@param[in] index Compare the keys of this index.
@param[in,out] dups For capturing the duplicate entries.
@param[in] compare_all If set, compare all columns in the key. */
Compare_key(const dict_index_t *index, Dup *dups, bool compare_all) noexcept
: m_dups(dups),
m_n_unique(dict_index_get_n_unique(index)),
m_n_fields(compare_all ? dict_index_get_n_fields(index) : m_n_unique),
m_fields(index->fields) {
ut_a(m_n_unique <= m_n_fields);
ut_a(m_dups == nullptr || index == m_dups->m_index);
}
Compare_key(const Compare_key &) = default;
/** Destructor. */
~Compare_key() = default;
/** Compare two tuples.
@param[in] lhs Tuple to compare on the left hand side
@param[in] rhs Tuple to compare on the Right hand side
@retval +ve - if lhs > rhs
@retval -ve - if lhs < rhs
@retval 0 - if lhs == rhs */
int operator()(const dfield_t *lhs, const dfield_t *rhs) const noexcept {
auto f = m_fields;
auto lhs_f = lhs;
auto rhs_f = rhs;
auto n = m_n_unique;
ut_a(n > 0);
/* Compare the fields of the tuples until a difference is
found or we run out of fields to compare. If cmp == 0 at
the end, then the tuples are equal. */
int cmp;
do {
cmp = cmp_dfield_dfield(lhs_f++, rhs_f++, (f++)->is_ascending);
} while (cmp == 0 && --n);
if (cmp != 0) {
return cmp;
}
if (m_dups != nullptr) {
bool report{true};
/* Report a duplicate value error if the tuples are
logically equal. nullptr columns are logically inequal,
although they are equal in the sorting order. Find
out if any of the fields are nullptr. */
for (auto df = lhs; df != lhs_f; ++df) {
if (dfield_is_null(df)) {
report = false;
break;
}
}
if (report) {
m_dups->report(lhs);
}
}
/* The m_n_unique fields were equal, but we compare all fields so
that we will get the same (internal) order as in the B-tree. */
for (auto n = m_n_fields - m_n_unique + 1; --n;) {
cmp = cmp_dfield_dfield(lhs_f++, rhs_f++, (f++)->is_ascending);
if (cmp != 0) {
return cmp;
}
}
/* Creating a secondary index and a PRIMARY KEY and there is a duplicate
in the PRIMARY KEY that has not been detected yet. Internally, an index
must never contain duplicates. */
return cmp;
}
/** For collecting duplicates. */
Dup *m_dups{};
/** Number of unique fields in the index key. */
const size_t m_n_unique{};
/** Total number of fields in the index key. */
const size_t m_n_fields{};
/** Index key fields. */
const dict_field_t *m_fields{};
};
} // namespace ddl
#endif /* !ddl0impl_compare_h */
|