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}