Skip to main content

mysql_handler/engine/
rkey_function.rs

1// Copyright (C) 2026 ren-yamanashi
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of this program hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, see <https://www.gnu.org/licenses/>.
22
23//! Index-lookup search semantics, mirroring MySQL's `ha_rkey_function`.
24
25/// Search semantics for an index lookup, mirroring MySQL's `ha_rkey_function`.
26///
27/// Passed to [`StorageEngine::index_read_map`] to describe how the supplied key
28/// should be matched: an exact hit, the nearest neighbour in a direction, a
29/// prefix, or one of the spatial (minimum-bounding-rectangle) relations.
30///
31/// [`StorageEngine::index_read_map`]: crate::engine::StorageEngine::index_read_map
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33#[non_exhaustive]
34pub enum RKeyFunction {
35    /// Find the first record with exactly this key, else error
36    KeyExact,
37    /// This record or the next one
38    KeyOrNext,
39    /// This record or the previous one
40    KeyOrPrev,
41    /// First record after this key
42    AfterKey,
43    /// First record before this key
44    BeforeKey,
45    /// First record sharing this key prefix
46    Prefix,
47    /// Last record sharing this key prefix
48    PrefixLast,
49    /// Last record with this prefix, or the previous one
50    PrefixLastOrPrev,
51    /// Minimum bounding rectangle contains the key
52    MbrContain,
53    /// Minimum bounding rectangle intersects the key
54    MbrIntersect,
55    /// Minimum bounding rectangle is within the key
56    MbrWithin,
57    /// Minimum bounding rectangle is disjoint from the key
58    MbrDisjoint,
59    /// Minimum bounding rectangle equals the key
60    MbrEqual,
61    /// Nearest-neighbour spatial search
62    NearestNeighbor,
63    /// Unrecognised value; MySQL's `HA_READ_INVALID` or an out-of-range code
64    Invalid,
65}
66
67impl RKeyFunction {
68    /// Map the raw `ha_rkey_function` integer supplied at the FFI boundary to a
69    /// variant. Any unknown code (including `HA_READ_INVALID == -1`) becomes
70    /// [`RKeyFunction::Invalid`] so the engine never observes an undefined value.
71    pub(crate) fn from_raw(raw: i32) -> Self {
72        match raw {
73            0 => Self::KeyExact,
74            1 => Self::KeyOrNext,
75            2 => Self::KeyOrPrev,
76            3 => Self::AfterKey,
77            4 => Self::BeforeKey,
78            5 => Self::Prefix,
79            6 => Self::PrefixLast,
80            7 => Self::PrefixLastOrPrev,
81            8 => Self::MbrContain,
82            9 => Self::MbrIntersect,
83            10 => Self::MbrWithin,
84            11 => Self::MbrDisjoint,
85            12 => Self::MbrEqual,
86            13 => Self::NearestNeighbor,
87            _ => Self::Invalid,
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn maps_known_codes() {
98        assert_eq!(RKeyFunction::from_raw(0), RKeyFunction::KeyExact);
99        assert_eq!(RKeyFunction::from_raw(7), RKeyFunction::PrefixLastOrPrev);
100        assert_eq!(RKeyFunction::from_raw(13), RKeyFunction::NearestNeighbor);
101    }
102
103    #[test]
104    fn unknown_codes_become_invalid() {
105        assert_eq!(RKeyFunction::from_raw(-1), RKeyFunction::Invalid);
106        assert_eq!(RKeyFunction::from_raw(14), RKeyFunction::Invalid);
107        assert_eq!(RKeyFunction::from_raw(i32::MAX), RKeyFunction::Invalid);
108    }
109}