• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use cxx::SharedPtr;
15 use std::pin::Pin;
16 
17 use crate::config::OpenConfig;
18 use crate::params::{FromSql, Params};
19 use crate::wrapper::ffi::{self, Execute, NewRowEntity, Query};
20 use crate::wrapper::open_rdb_store;
21 
22 const E_OK: i32 = 0;
23 
24 /// `RdbStore` ffi wrapper.
25 pub struct RdbStore<'a> {
26     inner: RdbStoreInner<'a>,
27 }
28 
29 impl<'a> RdbStore<'a> {
30     /// Creates a new `RdbStore`.
open(config: OpenConfig) -> Result<Self, i32>31     pub fn open(config: OpenConfig) -> Result<Self, i32> {
32         let rdb = open_rdb_store(config)?;
33         if rdb.is_null() {
34             return Err(-1);
35         }
36         Ok(Self {
37             inner: RdbStoreInner::Shared(rdb),
38         })
39     }
40 
41     /// Creates a `RdbStore` from a C structure.
from_ffi(ffi: Pin<&'a mut ffi::RdbStore>) -> Self42     pub fn from_ffi(ffi: Pin<&'a mut ffi::RdbStore>) -> Self {
43         Self {
44             inner: RdbStoreInner::Ref(ffi),
45         }
46     }
47 
48     /// Executes a sql statement.
execute<P: Params>(&self, sql: &str, values: P) -> Result<(), i32>49     pub fn execute<P: Params>(&self, sql: &str, values: P) -> Result<(), i32> {
50         match Execute(self.inner.pin_mut(), sql, values.into_values_object()) {
51             0 => Ok(()),
52             err => Err(err),
53         }
54     }
55 
56     /// Queries results with a sql statement.
query<T>(&self, sql: &str, values: impl Params) -> Result<QuerySet<T>, i32>57     pub fn query<T>(&self, sql: &str, values: impl Params) -> Result<QuerySet<T>, i32> {
58         let result = Query(self.inner.pin_mut(), sql, values.into_values_object());
59         if result.is_null() {
60             return Err(-1);
61         }
62         let ptr = result.as_ref().unwrap() as *const ffi::ResultSet as *mut ffi::ResultSet;
63 
64         let mut column_count = 0;
65         match unsafe { Pin::new_unchecked(ptr.as_mut().unwrap()).GetColumnCount(&mut column_count) }
66         {
67             0 => {}
68             err => return Err(err),
69         };
70         Ok(QuerySet {
71             inner: result,
72             column_count,
73             phantom: std::marker::PhantomData,
74         })
75     }
76 }
77 
78 enum RdbStoreInner<'a> {
79     Shared(SharedPtr<ffi::RdbStore>),
80     Ref(Pin<&'a mut ffi::RdbStore>),
81 }
82 
83 impl RdbStoreInner<'_> {
pin_mut(&self) -> Pin<&mut ffi::RdbStore>84     fn pin_mut(&self) -> Pin<&mut ffi::RdbStore> {
85         match self {
86             Self::Shared(ffi) => {
87                 let ptr = ffi.as_ref().unwrap() as *const ffi::RdbStore as *mut ffi::RdbStore;
88                 unsafe { Pin::new_unchecked(ptr.as_mut().unwrap()) }
89             }
90             Self::Ref(ffi) => {
91                 let ptr = ffi.as_ref().get_ref() as *const ffi::RdbStore as *mut ffi::RdbStore;
92                 unsafe { Pin::new_unchecked(ptr.as_mut().unwrap()) }
93             }
94         }
95     }
96 }
97 
98 /// Query results.
99 pub struct QuerySet<T> {
100     inner: SharedPtr<ffi::ResultSet>,
101     column_count: i32,
102     phantom: std::marker::PhantomData<T>,
103 }
104 
105 impl<T> QuerySet<T> {
106     /// Gets the count of the rows in the query result.
row_count(&mut self) -> i32107     pub fn row_count(&mut self) -> i32 {
108         let mut row_count = 0;
109         match self.pin_mut().GetRowCount(&mut row_count) {
110             0 => row_count,
111             _err => 0,
112         }
113     }
114 
115     /// Gets the counts of the columns in the query result.
column_count(&self) -> i32116     pub fn column_count(&self) -> i32 {
117         self.column_count
118     }
119 
pin_mut(&mut self) -> Pin<&mut ffi::ResultSet>120     fn pin_mut(&mut self) -> Pin<&mut ffi::ResultSet> {
121         let ptr = self.inner.as_ref().unwrap() as *const ffi::ResultSet as *mut ffi::ResultSet;
122         unsafe { Pin::new_unchecked(ptr.as_mut().unwrap()) }
123     }
124 }
125 
126 impl<T> Iterator for QuerySet<T>
127 where
128     T: FromSql,
129 {
130     type Item = T;
131 
next(&mut self) -> Option<Self::Item>132     fn next(&mut self) -> Option<Self::Item> {
133         let mut row = NewRowEntity();
134         if self.pin_mut().GoToNextRow() != E_OK {
135             return None;
136         };
137         if self.pin_mut().GetRow(row.pin_mut()) != E_OK {
138             return None;
139         }
140         Some(T::from_sql(0, row.pin_mut()))
141     }
142 }
143 
144 macro_rules! single_tuple_impl {
145     ($(($field:tt $ftype:ident)),* $(,)?) => {
146         impl <$($ftype,) *> Iterator for QuerySet<($($ftype,) *)> where $($ftype: FromSql,)* {
147             type Item = ($($ftype,) *);
148             fn next(&mut self) -> Option<Self::Item> {
149                 let mut row = NewRowEntity();
150                 if self.pin_mut().GoToNextRow() != E_OK {
151                     return None;
152                 };
153                 if (self.pin_mut().GetRow(row.pin_mut()) != E_OK) {
154                     return None;
155                 }
156                 Some(($({
157                     $ftype::from_sql($field,row.pin_mut())
158                 }), *))
159 
160             }
161         }
162     };
163 }
164 
165 single_tuple_impl!((0 A), (1 B));
166 single_tuple_impl!((0 A), (1 B), (2 C));
167 single_tuple_impl!((0 A), (1 B), (2 C), (3 D));
168 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E));
169 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F));
170 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G));
171 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H));
172 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I));
173 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J));
174 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K));
175 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L));
176 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M));
177 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N));
178 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O));
179 single_tuple_impl!((0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O), (15 P));
180 
181 #[cfg(test)]
182 mod ut_database {
183     include!("../tests/ut/ut_database.rs");
184 }
185