Skip to content

Commit f7b38ca

Browse files
authored
Merge branch 'master' into credentials-param
2 parents 9870c95 + 2e2b34c commit f7b38ca

File tree

8 files changed

+522
-223
lines changed

8 files changed

+522
-223
lines changed

libindy/src/commands/non_secrets.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl NonSecretsCommandExecutor {
295295
}
296296

297297
let search_result = SearchRecords {
298-
total_count: None, // TODO: return search.get_total_count()?
298+
total_count: search.get_total_count()?,
299299
records: if records.is_empty() { None } else { Some(records) }
300300
};
301301

libindy/src/services/wallet/iterator.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,9 @@ impl WalletIterator {
4444
Ok(Some(WalletRecord::new(name, None, value, tags)))
4545
} else { Ok(None) }
4646
}
47+
48+
pub fn get_total_count(&self) -> Result<Option<usize>, WalletError> {
49+
let total_count = self.storage_iterator.get_total_count()?;
50+
Ok(total_count)
51+
}
4752
}

libindy/src/services/wallet/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,15 +640,15 @@ pub struct WalletSearch {
640640

641641
impl WalletSearch {
642642
pub fn get_total_count(&self) -> Result<Option<usize>, WalletError> {
643-
unimplemented!()
643+
self.iter.get_total_count()
644644
}
645645

646646
pub fn fetch_next_record(&mut self) -> Result<Option<WalletRecord>, WalletError> {
647647
self.iter.next()
648648
}
649649
}
650650

651-
#[derive(Debug, Serialize, Deserialize)]
651+
#[derive(Debug, Serialize, Deserialize, PartialEq)]
652652
#[serde(rename_all = "camelCase")]
653653
pub struct SearchOptions {
654654
pub retrieve_records: Option<bool>,
@@ -684,6 +684,18 @@ impl SearchOptions {
684684
}
685685
}
686686

687+
impl Default for SearchOptions {
688+
fn default() -> SearchOptions {
689+
SearchOptions {
690+
retrieve_records: Some(true),
691+
retrieve_total_count: Some(false),
692+
retrieve_type: Some(false),
693+
retrieve_value: Some(true),
694+
retrieve_tags: Some(false),
695+
}
696+
}
697+
}
698+
687699
impl JsonEncodable for SearchOptions {}
688700

689701
impl<'a> JsonDecodable<'a> for SearchOptions {}

libindy/src/services/wallet/storage/default/mod.rs

Lines changed: 70 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use utils::environment::EnvironmentUtils;
1515
use errors::wallet::WalletStorageError;
1616
use errors::common::CommonError;
1717
use services::wallet::language;
18-
use super::super::indy_crypto::utils::json::{JsonDecodable, JsonEncodable};
1918

20-
use super::{StorageIterator, WalletStorageType, WalletStorage, StorageEntity, EncryptedValue, Tag, TagName};
19+
use super::{StorageIterator, WalletStorageType, WalletStorage, StorageEntity, EncryptedValue, Tag, TagName, FetchOptions};
20+
use super::super::SearchOptions;
2121

2222
const _SQLITE_DB: &str = "sqlite.db";
2323
const _PLAIN_TAGS_QUERY: &str = "SELECT name, value from tags_plaintext where item_id = ?";
@@ -93,7 +93,8 @@ struct TagRetriever<'a> {
9393
encrypted_tags_stmt: rusqlite::Statement<'a>,
9494
}
9595

96-
type TagRetrieverOwned = OwningHandle<Rc<rusqlite::Connection>, Box<TagRetriever<'static>>>;
96+
type TagRetrieverOwned = OwningHandle<Rc<rusqlite::Connection>, Box<TagRetriever<'static>>>
97+
;
9798

9899
impl<'a> TagRetriever<'a> {
99100
fn new_owned(conn: Rc<rusqlite::Connection>) -> Result<TagRetrieverOwned, WalletStorageError> {
@@ -139,44 +140,52 @@ struct SQLiteStorageIterator {
139140
Box<rusqlite::Rows<'static>>>>,
140141
tag_retriever: Option<TagRetrieverOwned>,
141142
options: FetchOptions,
142-
fetch_type_: bool,
143+
total_count: Option<usize>,
143144
}
144145

145146

146147
impl SQLiteStorageIterator {
147-
fn new(stmt: OwningHandle<Rc<rusqlite::Connection>, Box<rusqlite::Statement<'static>>>,
148+
fn new(stmt: Option<OwningHandle<Rc<rusqlite::Connection>, Box<rusqlite::Statement<'static>>>>,
148149
args: &[&rusqlite::types::ToSql],
149150
options: FetchOptions,
150151
tag_retriever: Option<TagRetrieverOwned>,
151-
fetch_type_: bool) -> Result<SQLiteStorageIterator, WalletStorageError> {
152+
total_count: Option<usize>) -> Result<SQLiteStorageIterator, WalletStorageError> {
152153
let mut iter = SQLiteStorageIterator {
153154
rows: None,
154155
tag_retriever,
155156
options,
156-
fetch_type_,
157+
total_count
157158
};
158-
iter.rows = Some(OwningHandle::try_new(
159-
stmt, |stmt|
160-
unsafe {
161-
(*(stmt as *mut rusqlite::Statement)).query(args).map(Box::new)
162-
},
163-
)?);
159+
160+
if let Some(stmt) = stmt {
161+
iter.rows = Some(OwningHandle::try_new(
162+
stmt, |stmt|
163+
unsafe {
164+
(*(stmt as *mut rusqlite::Statement)).query(args).map(Box::new)
165+
},
166+
)?);
167+
}
164168
Ok(iter)
165169
}
166170
}
167171

168172

169173
impl StorageIterator for SQLiteStorageIterator {
170174
fn next(&mut self) -> Result<Option<StorageEntity>, WalletStorageError> {
175+
// if records are not requested.
176+
if self.rows.is_none() {
177+
return Ok(None);
178+
}
179+
171180
match self.rows.as_mut().unwrap().next() {
172181
Some(Ok(row)) => {
173182
let name = row.get(1);
174-
let value = if self.options.fetch_value {
183+
let value = if self.options.retrieve_value {
175184
Some(EncryptedValue::new(row.get(2), row.get(3)))
176185
} else {
177186
None
178187
};
179-
let tags = if self.options.fetch_tags {
188+
let tags = if self.options.retrieve_tags {
180189
match self.tag_retriever {
181190
Some(ref mut tag_retriever) => Some(tag_retriever.retrieve(row.get(0))?),
182191
None => return Err(WalletStorageError::CommonError(
@@ -186,7 +195,7 @@ impl StorageIterator for SQLiteStorageIterator {
186195
} else {
187196
None
188197
};
189-
let type_ = if self.fetch_type_ {
198+
let type_ = if self.options.retrieve_type {
190199
Some(row.get(4))
191200
} else {
192201
None
@@ -197,45 +206,12 @@ impl StorageIterator for SQLiteStorageIterator {
197206
None => Ok(None)
198207
}
199208
}
200-
}
201-
202-
203-
#[derive(Debug,Deserialize,Serialize)]
204-
struct FetchOptions {
205-
#[serde(rename="retrieveType")]
206-
fetch_type: bool,
207-
#[serde(rename="retrieveValue")]
208-
fetch_value: bool,
209-
#[serde(rename="retrieveTags")]
210-
fetch_tags: bool,
211-
}
212209

213-
impl FetchOptions {
214-
fn new(fetch_type: bool, fetch_value: bool, fetch_tags: bool) -> FetchOptions {
215-
FetchOptions {
216-
fetch_type: fetch_type,
217-
fetch_value: fetch_value,
218-
fetch_tags: fetch_tags,
219-
}
210+
fn get_total_count(&self) -> Result<Option<usize>, WalletStorageError> {
211+
Ok(self.total_count)
220212
}
221213
}
222214

223-
impl Default for FetchOptions {
224-
fn default() -> FetchOptions {
225-
FetchOptions {
226-
fetch_type: false,
227-
fetch_value: true,
228-
fetch_tags: false,
229-
}
230-
}
231-
}
232-
233-
impl JsonEncodable for FetchOptions {}
234-
235-
impl<'a> JsonDecodable<'a> for FetchOptions {}
236-
237-
238-
239215
#[derive(Debug)]
240216
struct SQLiteStorage {
241217
conn: Rc<rusqlite::Connection>,
@@ -305,9 +281,10 @@ impl WalletStorage for SQLiteStorage {
305281
Err(rusqlite::Error::QueryReturnedNoRows) => return Err(WalletStorageError::ItemNotFound),
306282
Err(err) => return Err(WalletStorageError::from(err))
307283
};
308-
let value = if options.fetch_value { Some(EncryptedValue::new(item.1, item.2)) } else { None };
309-
let type_ = if options.fetch_type { Some(type_.clone()) } else { None };
310-
let tags = if options.fetch_tags {
284+
let value = if options.retrieve_value
285+
{ Some(EncryptedValue::new(item.1, item.2)) } else { None };
286+
let type_ = if options.retrieve_type { Some(type_.clone()) } else { None };
287+
let tags = if options.retrieve_tags {
311288
let mut tags = Vec::new();
312289

313290
// get all encrypted.
@@ -552,31 +529,55 @@ impl WalletStorage for SQLiteStorage {
552529
fn get_all(&self) -> Result<Box<StorageIterator>, WalletStorageError> {
553530
let statement = self._prepare_statement("SELECT id, name, value, key, type FROM items;")?;
554531
let fetch_options = FetchOptions {
555-
fetch_type: true,
556-
fetch_value: true,
557-
fetch_tags: true,
532+
retrieve_type: true,
533+
retrieve_value: true,
534+
retrieve_tags: true,
558535
};
559536
let tag_retriever = Some(TagRetriever::new_owned(self.conn.clone())?);
560537

561-
let storage_iterator = SQLiteStorageIterator::new(statement, &[], fetch_options, tag_retriever, true)?;
538+
let storage_iterator = SQLiteStorageIterator::new(Some(statement), &[], fetch_options, tag_retriever, None)?;
562539
Ok(Box::new(storage_iterator))
563540
}
564541

565542
fn search(&self, type_: &Vec<u8>, query: &language::Operator, options: Option<&str>) -> Result<Box<StorageIterator>, WalletStorageError> {
566-
let fetch_options = match options {
567-
None => FetchOptions::default(),
543+
let search_options = match options {
544+
None => SearchOptions::default(),
568545
Some(option_str) => serde_json::from_str(option_str)?
569546
};
570-
let (query_string, query_arguments) = query::wql_to_sql(type_, query, options)?;
571547

572-
let statement = self._prepare_statement(&query_string)?;
573-
let tag_retriever = if fetch_options.fetch_tags {
574-
Some(TagRetriever::new_owned(self.conn.clone())?)
575-
} else {
576-
None
577-
};
578-
let storage_iterator = SQLiteStorageIterator::new(statement, &query_arguments, fetch_options, tag_retriever, false)?;
579-
Ok(Box::new(storage_iterator))
548+
let total_count: Option<usize> = if search_options.retrieve_total_count.unwrap_or(false) {
549+
let (query_string, query_arguments) = query::wql_to_sql_count(type_, query)?;
550+
551+
self.conn.query_row(
552+
&query_string,
553+
&query_arguments,
554+
|row| { let x: i64 = row.get(0); Some(x as usize) }
555+
)?
556+
} else {None};
557+
558+
559+
if search_options.retrieve_records.unwrap_or(true) {
560+
let fetch_options = FetchOptions {
561+
retrieve_value: search_options.retrieve_value.unwrap_or(true),
562+
retrieve_tags: search_options.retrieve_tags.unwrap_or(false),
563+
retrieve_type: search_options.retrieve_type.unwrap_or(false),
564+
};
565+
566+
let (query_string, query_arguments) = query::wql_to_sql(type_, query, options)?;
567+
568+
let statement = self._prepare_statement(&query_string)?;
569+
let tag_retriever = if fetch_options.retrieve_tags {
570+
Some(TagRetriever::new_owned(self.conn.clone())?)
571+
} else {
572+
None
573+
};
574+
let storage_iterator = SQLiteStorageIterator::new(Some(statement), &query_arguments, fetch_options, tag_retriever, total_count)?;
575+
Ok(Box::new(storage_iterator))
576+
}
577+
else {
578+
let storage_iterator = SQLiteStorageIterator::new(None, &[], FetchOptions::default(), None, total_count)?;
579+
Ok(Box::new(storage_iterator))
580+
}
580581
}
581582

582583
fn close(&mut self) -> Result<(), WalletStorageError> {

libindy/src/services/wallet/storage/default/query.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,20 @@ pub fn wql_to_sql<'a>(class: &'a Vec<u8>, op: &'a Operator, options: Option<&str
1111
let mut arguments: Vec<&ToSql> = Vec::new();
1212
arguments.push(class);
1313
let clause_string = operator_to_sql(op, &mut arguments)?;
14-
let mut query_string = "SELECT i.id, i.name, i.value, i.key FROM items as i WHERE i.type = ?".to_string();
14+
let mut query_string = "SELECT i.id, i.name, i.value, i.key, i.type FROM items as i WHERE i.type = ?".to_string();
15+
if !clause_string.is_empty() {
16+
query_string.push_str(" AND ");
17+
query_string.push_str(&clause_string);
18+
}
19+
Ok((query_string, arguments))
20+
}
21+
22+
23+
pub fn wql_to_sql_count<'a>(class: &'a Vec<u8>, op: &'a Operator) -> Result<(String, Vec<&'a ToSql>), WalletQueryError> {
24+
let mut arguments: Vec<&ToSql> = Vec::new();
25+
arguments.push(class);
26+
let clause_string = operator_to_sql(op, &mut arguments)?;
27+
let mut query_string = "SELECT count(*) FROM items as i WHERE i.type = ?".to_string();
1528
if !clause_string.is_empty() {
1629
query_string.push_str(" AND ");
1730
query_string.push_str(&clause_string);

libindy/src/services/wallet/storage/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,62 @@ pub mod plugged;
44
use errors::wallet::WalletStorageError;
55
use services::wallet::language;
66
use services::wallet::wallet::EncryptedValue;
7+
use super::indy_crypto::utils::json::{JsonDecodable, JsonEncodable};
8+
use serde_json;
79

810
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
911
pub enum Tag {
1012
Encrypted(Vec<u8>, Vec<u8>),
1113
PlainText(Vec<u8>, String)
1214
}
1315

16+
1417
#[derive(Debug)]
1518
pub enum TagName {
1619
OfEncrypted(Vec<u8>),
1720
OfPlain(Vec<u8>),
1821
}
1922

2023

24+
#[derive(Debug,Deserialize,Serialize,PartialEq)]
25+
struct FetchOptions {
26+
#[serde(rename="retrieveType")]
27+
retrieve_type: bool,
28+
#[serde(rename="retrieveValue")]
29+
retrieve_value: bool,
30+
#[serde(rename="retrieveTags")]
31+
retrieve_tags: bool,
32+
}
33+
34+
35+
impl FetchOptions {
36+
fn new(fetch_type: bool, fetch_value: bool, fetch_tags: bool) -> FetchOptions {
37+
FetchOptions {
38+
retrieve_type: fetch_type,
39+
retrieve_value: fetch_value,
40+
retrieve_tags: fetch_tags,
41+
}
42+
}
43+
}
44+
45+
46+
impl Default for FetchOptions {
47+
fn default() -> FetchOptions {
48+
FetchOptions {
49+
retrieve_type: false,
50+
retrieve_value: true,
51+
retrieve_tags: false,
52+
}
53+
}
54+
}
55+
56+
57+
impl JsonEncodable for FetchOptions {}
58+
59+
60+
impl<'a> JsonDecodable<'a> for FetchOptions {}
61+
62+
2163
#[derive(Clone, Debug)]
2264
pub struct StorageEntity {
2365
pub name: Vec<u8>,
@@ -40,6 +82,7 @@ impl StorageEntity {
4082

4183
pub trait StorageIterator {
4284
fn next(&mut self) -> Result<Option<StorageEntity>, WalletStorageError>;
85+
fn get_total_count(&self) -> Result<Option<usize>, WalletStorageError>;
4386
}
4487

4588

0 commit comments

Comments
 (0)