google_cloud_spanner/
key.rs

1use prost_types::{ListValue, Value};
2
3use google_cloud_googleapis::spanner::v1::key_range::{EndKeyType, StartKeyType};
4use google_cloud_googleapis::spanner::v1::KeyRange as InternalKeyRange;
5use google_cloud_googleapis::spanner::v1::KeySet as InternalKeySet;
6
7use crate::statement::ToKind;
8
9/// A Key can be either a Cloud Spanner row's primary key or a secondary index
10/// key. A Key can be used as:
11///
12///   - A primary key which uniquely identifies a Cloud Spanner row.
13///   - A secondary index key which maps to a set of Cloud Spanner rows indexed under it.
14///   - An endpoint of primary key/secondary index ranges; see the KeyRange type.
15///
16/// Rows that are identified by the Key type are outputs of read operation or
17/// targets of delete operation in a mutation. Note that for
18/// insert/update/insert_or_update/delete mutation types, although they don't
19/// require a primary key explicitly, the column list provided must contain
20/// enough columns that can comprise a primary key.
21///
22/// Keys are easy to construct.  For example, suppose you have a table with a
23/// primary key of username and product ID.  To make a key for this table:
24/// ```
25/// use google_cloud_spanner::key::Key;
26///
27/// let key = Key::composite(&[&"john", &16]);
28/// ```
29/// See the description of Row and Mutation types for how Go types are mapped to
30/// Cloud Spanner types. For convenience, Key type supports a range of Rust
31/// types:
32///   - i64 and Option<i64> are mapped to Cloud Spanner's INT64 type.
33///   - f64 and Option<f64> are mapped to Cloud Spanner's FLOAT64 type.
34///   - bool and Option<bool> are mapped to Cloud Spanner's BOOL type.
35///   - Vec<u8>, &[u8], Option<Vec<u8>> and Option<&[u8]> is mapped to Cloud Spanner's BYTES type.
36///   - String, &str, Option<String>, Option<&str> are mapped to Cloud Spanner's STRING type.
37///   - time::OffsetDateTime and Option<time::OffsetDateTime> are mapped to Cloud Spanner's TIMESTAMP type.
38///   - time::Date and Option<time::Date> are mapped to Cloud Spanner's DATE type.
39///   - google_cloud_spanner::value::CommitTimestamp and Option<google_cloud_spanner::value::CommitTimestamp> are mapped to Cloud Spanner's TIMESTAMP type.
40#[derive(Clone)]
41pub struct Key {
42    pub(crate) values: ListValue,
43}
44
45/// / A KeySet defines a collection of Cloud Spanner keys and/or key ranges. All
46/// / the keys are expected to be in the same table or index. The keys need not be
47/// / sorted in any particular way.
48/// /
49/// / An individual Key can act as a KeySet, as can a KeyRange. Use the KeySets
50/// / function to create a KeySet consisting of multiple Keys and KeyRanges. To
51/// / obtain an empty KeySet, call KeySets with no arguments.
52/// /
53/// / If the same key is specified multiple times in the set (for example if two
54/// / ranges, two keys, or a key and a range overlap), the Cloud Spanner backend
55/// / behaves as if the key were only specified once.
56#[derive(Clone)]
57pub struct KeySet {
58    pub(crate) inner: InternalKeySet,
59}
60
61#[derive(Clone, PartialEq, Eq, Debug)]
62pub enum RangeKind {
63    /// ClosedOpen is closed on the left and open on the right: the Start
64    /// key is included, the End key is excluded.
65    ClosedOpen,
66
67    /// ClosedClosed is closed on the left and the right: both keys are included.
68    ClosedClosed,
69
70    /// OpenClosed is open on the left and closed on the right: the Start
71    /// key is excluded, the End key is included.
72    OpenClosed,
73
74    /// OpenOpen is open on the left and the right: neither key is included.
75    OpenOpen,
76}
77
78///  A KeyRange represents a range of rows in a table or index.
79///
80///  A range has a Start key and an End key.  IncludeStart and IncludeEnd
81///  indicate whether the Start and End keys are included in the range.
82///
83///  For example, consider the following table definition:
84///
85///     CREATE TABLE UserEvents (
86///         UserName STRING(MAX),
87///         EventDate STRING(10),
88///     ) PRIMARY KEY(UserName, EventDate);
89///
90///  The following keys name rows in this table:
91///
92///  ```
93///    use google_cloud_spanner::key::Key;
94///    use google_cloud_spanner::statement::ToKind;
95///    let key1 = Key::composite(&[&"Bob", &"2014-09-23"]);
96///    let key2 = Key::composite(&[&"Alfred", &"2015-06-12"]);
97///  ```
98///
99///  Since the UserEvents table's PRIMARY KEY clause names two columns, each
100///  UserEvents key has two elements; the first is the UserName, and the second
101///  is the EventDate.
102///
103///  Key ranges with multiple components are interpreted lexicographically by
104///  component using the table or index key's declared sort order. For example,
105///  the following range returns all events for user "Bob" that occurred in the
106///  year 2015:
107///  ```
108///    use google_cloud_spanner::key::{Key, KeyRange, RangeKind};
109///    use google_cloud_spanner::statement::ToKind;
110///    let range = KeyRange::new(
111///        Key::composite(&[&"Bob", &"2015-01-01"]),
112///        Key::composite(&[&"Bob", &"2015-12-31"]),
113///        RangeKind::ClosedClosed
114///    );
115///  ```
116///
117///  Start and end keys can omit trailing key components. This affects the
118///  inclusion and exclusion of rows that exactly match the provided key
119///  components: if IncludeStart is true, then rows that exactly match the
120///  provided components of the Start key are included; if IncludeStart is false
121///  then rows that exactly match are not included.  IncludeEnd and End key
122///  behave in the same fashion.
123///
124///  For example, the following range includes all events for "Bob" that occurred
125///  during and after the year 2000:
126///  ```
127///    use google_cloud_spanner::key::{Key, KeyRange, RangeKind};
128///    use google_cloud_spanner::statement::ToKind;
129///    KeyRange::new(
130///     Key::composite(&[&"Bob", &"2000-01-01"]),
131///     Key::new(&"Bob"),
132///     RangeKind::ClosedClosed
133///    );
134///  ```
135///
136///  The next example retrieves all events for "Bob":
137///
138///     Key::new("Bob").to_prefix()
139///
140///  To retrieve events before the year 2000:
141///  ```
142///    use google_cloud_spanner::key::{Key, KeyRange, RangeKind};
143///    use google_cloud_spanner::statement::ToKind;
144///    let range = KeyRange::new(
145///     Key::new(&"Bob"),
146///     Key::composite(&[&"Bob", &"2000-01-01"]),
147///     RangeKind::ClosedOpen
148///    );
149///  ```
150///
151///  Key ranges honor column sort order. For example, suppose a table is defined
152///  as follows:
153///
154///     CREATE TABLE DescendingSortedTable {
155///         Key INT64,
156///         ...
157///     ) PRIMARY KEY(Key DESC);
158///
159///  The following range retrieves all rows with key values between 1 and 100
160///  inclusive:
161///
162///  ```
163///    use google_cloud_spanner::key::{Key, KeyRange, RangeKind};
164///    let range = KeyRange::new(
165///         Key::new(&100),
166///         Key::new(&1),
167///    RangeKind::ClosedClosed,
168///    );
169///  ```
170///
171///  Note that 100 is passed as the start, and 1 is passed as the end, because
172///  Key is a descending column in the schema.
173#[derive(Clone)]
174pub struct KeyRange {
175    /// start specifies the left boundary of the key range;.
176    pub(crate) start: Key,
177
178    /// end specifies the right boundary of the key range.
179    pub(crate) end: Key,
180
181    /// kind describes whether the boundaries of the key range include
182    /// their keys.
183    pub kind: RangeKind,
184}
185
186/// all_keys returns a KeySet that represents all Keys of a table or a index.
187pub fn all_keys() -> KeySet {
188    KeySet {
189        inner: InternalKeySet {
190            keys: vec![],
191            ranges: vec![],
192            all: true,
193        },
194    }
195}
196
197impl From<KeySet> for InternalKeySet {
198    fn from(key_set: KeySet) -> Self {
199        key_set.inner
200    }
201}
202
203impl KeyRange {
204    pub fn new(start: Key, end: Key, kind: RangeKind) -> KeyRange {
205        KeyRange { start, end, kind }
206    }
207}
208
209impl From<KeyRange> for InternalKeyRange {
210    fn from(key_range: KeyRange) -> Self {
211        let (start, end) = match key_range.kind {
212            RangeKind::ClosedClosed => (
213                Some(StartKeyType::StartClosed(key_range.start.values)),
214                Some(EndKeyType::EndClosed(key_range.end.values)),
215            ),
216            RangeKind::ClosedOpen => (
217                Some(StartKeyType::StartClosed(key_range.start.values)),
218                Some(EndKeyType::EndOpen(key_range.end.values)),
219            ),
220            RangeKind::OpenClosed => (
221                Some(StartKeyType::StartOpen(key_range.start.values)),
222                Some(EndKeyType::EndClosed(key_range.end.values)),
223            ),
224            RangeKind::OpenOpen => (
225                Some(StartKeyType::StartOpen(key_range.start.values)),
226                Some(EndKeyType::EndOpen(key_range.end.values)),
227            ),
228        };
229        InternalKeyRange {
230            start_key_type: start,
231            end_key_type: end,
232        }
233    }
234}
235
236impl From<KeyRange> for KeySet {
237    fn from(key_range: KeyRange) -> Self {
238        KeySet {
239            inner: InternalKeySet {
240                keys: vec![],
241                ranges: vec![key_range.into()],
242                all: false,
243            },
244        }
245    }
246}
247
248impl Key {
249    /// one creates new Key
250    /// # Examples
251    /// ```
252    ///    use google_cloud_spanner::key::Key;
253    ///    use google_cloud_spanner::statement::ToKind;
254    ///    let key1 = Key::new(&"a");
255    ///    let key2 = Key::new(&1);
256    /// ```
257    pub fn new(value: &dyn ToKind) -> Key {
258        Key::composite(&[value])
259    }
260
261    /// one creates new Key
262    /// # Examples
263    /// ```
264    ///    use google_cloud_spanner::key::Key;
265    ///    use google_cloud_spanner::statement::ToKind;
266    ///    let multi_key = Key::composite(&[&"a", &1]);
267    /// ```
268    pub fn composite(values: &[&dyn ToKind]) -> Key {
269        Key {
270            values: ListValue {
271                values: values
272                    .iter()
273                    .map(|x| Value {
274                        kind: Some(x.to_kind()),
275                    })
276                    .collect(),
277            },
278        }
279    }
280}
281
282impl From<Key> for KeySet {
283    fn from(key: Key) -> Self {
284        KeySet {
285            inner: InternalKeySet {
286                keys: vec![key.values],
287                ranges: vec![],
288                all: false,
289            },
290        }
291    }
292}
293
294impl From<Vec<Key>> for KeySet {
295    fn from(keys: Vec<Key>) -> Self {
296        let keys = keys.into_iter().map(|key| key.values).collect();
297        KeySet {
298            inner: InternalKeySet {
299                keys,
300                ranges: vec![],
301                all: false,
302            },
303        }
304    }
305}
306
307#[cfg(test)]
308mod tests {
309    use prost_types::value::Kind;
310
311    use google_cloud_googleapis::spanner::*;
312
313    use crate::key::*;
314
315    #[test]
316    fn test_key_new() {
317        let mut key = Key::new(&true);
318        match key.values.values.pop().unwrap().kind.unwrap() {
319            Kind::BoolValue(s) => assert!(s),
320            _ => panic!("invalid kind"),
321        }
322    }
323
324    #[test]
325    fn test_key_keys() {
326        let mut key = Key::composite(&[&true, &1, &"aaa"]);
327        match key.values.values.pop().unwrap().kind.unwrap() {
328            Kind::StringValue(s) => assert_eq!(s, "aaa"),
329            _ => panic!("invalid kind"),
330        }
331    }
332
333    #[test]
334    fn test_key_one() {
335        let mut key = Key::new(&1);
336        match key.values.values.pop().unwrap().kind.unwrap() {
337            Kind::StringValue(s) => assert_eq!(s, "1"),
338            _ => panic!("invalid kind"),
339        }
340    }
341
342    #[test]
343    fn test_key_range() {
344        let start = Key::new(&1);
345        let end = Key::new(&100);
346        let range = KeyRange::new(start, end, RangeKind::ClosedClosed);
347        let raw_range: v1::KeyRange = range.into();
348        match raw_range.start_key_type.unwrap() {
349            v1::key_range::StartKeyType::StartClosed(mut v) => match v.values.pop().unwrap().kind.unwrap() {
350                Kind::StringValue(v) => assert_eq!(v, "1"),
351                _ => panic!("invalid start kind"),
352            },
353            _ => panic!("invalid start key trype"),
354        }
355
356        match raw_range.end_key_type.unwrap() {
357            v1::key_range::EndKeyType::EndClosed(mut v) => match v.values.pop().unwrap().kind.unwrap() {
358                Kind::StringValue(v) => assert_eq!(v, "100"),
359                _ => panic!("invalid end kind"),
360            },
361            _ => panic!("invalid end key trype"),
362        }
363    }
364}