• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 //! This module provides data operation management on database tables.
17 //! The managed data can be user input. Because we will prepare and bind data.
18 
19 use core::ffi::c_void;
20 use std::cmp::Ordering;
21 
22 use asset_definition::{log_throw_error, Conversion, DataType, ErrCode, Result, SyncType, Value};
23 use asset_log::logi;
24 
25 use crate::{
26     database::Database,
27     statement::Statement,
28     transaction::Transaction,
29     types::{adapt_column, column, ColumnInfo, DbMap, QueryOptions, UpgradeColumnInfo, ADAPT_CLOUD_TABLE, COLUMN_INFO, DB_UPGRADE_VERSION, SQLITE_ROW},
30 };
31 
32 extern "C" {
SqliteChanges(db: *mut c_void) -> i3233     fn SqliteChanges(db: *mut c_void) -> i32;
34 }
35 
36 #[repr(C)]
37 pub(crate) struct Table<'a> {
38     pub(crate) table_name: String,
39     pub(crate) db: &'a Database,
40 }
41 
42 #[inline(always)]
bind_datas(datas: &DbMap, stmt: &Statement, index: &mut i32) -> Result<()>43 fn bind_datas(datas: &DbMap, stmt: &Statement, index: &mut i32) -> Result<()> {
44     for (_, value) in datas.iter() {
45         stmt.bind_data(*index, value)?;
46         *index += 1;
47     }
48     Ok(())
49 }
50 
bind_where_datas(datas: &DbMap, stmt: &Statement, index: &mut i32) -> Result<()>51 fn bind_where_datas(datas: &DbMap, stmt: &Statement, index: &mut i32) -> Result<()> {
52     for (key, value) in datas.iter() {
53         if *key == "SyncType" {
54             stmt.bind_data(*index, value)?;
55             *index += 1;
56         }
57         stmt.bind_data(*index, value)?;
58         *index += 1;
59     }
60     Ok(())
61 }
62 
bind_alias_list(aliases: &[Value], stmt: &Statement, index: &mut i32) -> Result<()>63 fn bind_alias_list(aliases: &[Value], stmt: &Statement, index: &mut i32) -> Result<()> {
64     for alias in aliases {
65         stmt.bind_data(*index, alias)?;
66         *index += 1;
67     }
68     Ok(())
69 }
70 
bind_sync(stmt: &Statement, value: &Value, index: &mut i32) -> Result<()>71 fn bind_sync(stmt: &Statement, value: &Value, index: &mut i32) -> Result<()> {
72     stmt.bind_data(*index, value)?;
73     *index += 1;
74     stmt.bind_data(*index, value)?;
75     *index += 1;
76     Ok(())
77 }
78 
bind_not_sync(stmt: &Statement, value: &Value, index: &mut i32) -> Result<()>79 fn bind_not_sync(stmt: &Statement, value: &Value, index: &mut i32) -> Result<()> {
80     stmt.bind_data(*index, value)?;
81     *index += 1;
82     Ok(())
83 }
84 
bind_where_with_specific_condifion(datas: &[Value], stmt: &Statement, index: &mut i32) -> Result<()>85 fn bind_where_with_specific_condifion(datas: &[Value], stmt: &Statement, index: &mut i32) -> Result<()> {
86     for value in datas.iter() {
87         stmt.bind_data(*index, value)?;
88         *index += 1;
89     }
90     Ok(())
91 }
92 
93 #[inline(always)]
build_sql_columns_not_empty(columns: &Vec<&str>, sql: &mut String)94 fn build_sql_columns_not_empty(columns: &Vec<&str>, sql: &mut String) {
95     for i in 0..columns.len() {
96         let column = &columns[i];
97         sql.push_str(column);
98         if i != columns.len() - 1 {
99             sql.push(',');
100         }
101     }
102 }
103 
104 #[inline(always)]
build_sql_columns(columns: &Vec<&str>, sql: &mut String)105 fn build_sql_columns(columns: &Vec<&str>, sql: &mut String) {
106     if !columns.is_empty() {
107         build_sql_columns_not_empty(columns, sql);
108     } else {
109         sql.push('*');
110     }
111 }
112 
113 #[inline(always)]
build_sql_where(conditions: &DbMap, filter: bool, sql: &mut String)114 fn build_sql_where(conditions: &DbMap, filter: bool, sql: &mut String) {
115     if !conditions.is_empty() || filter {
116         sql.push_str(" where ");
117         if filter {
118             sql.push_str("SyncStatus <> 2");
119             if !conditions.is_empty() {
120                 sql.push_str(" and ");
121             }
122         }
123         if !conditions.is_empty() {
124             for (i, column_name) in conditions.keys().enumerate() {
125                 if *column_name == "SyncType" {
126                     sql.push_str("(SyncType & ?) = ?");
127                 } else {
128                     sql.push_str(column_name);
129                     sql.push_str("=?");
130                 }
131                 if i != conditions.len() - 1 {
132                     sql.push_str(" and ")
133                 }
134             }
135         }
136     }
137 }
138 
139 #[inline(always)]
build_sql_alias_list(len: usize, sql: &mut String)140 fn build_sql_alias_list(len: usize, sql: &mut String) {
141     sql.push_str(" and Alias in (");
142     build_sql_values(len, sql);
143     sql.push_str(") ");
144 }
145 
146 #[inline(always)]
build_sql_values(len: usize, sql: &mut String)147 fn build_sql_values(len: usize, sql: &mut String) {
148     for i in 0..len {
149         sql.push('?');
150         if i != len - 1 {
151             sql.push(',');
152         }
153     }
154 }
155 
156 #[inline(always)]
build_sql_sync(sql: &mut String)157 fn build_sql_sync(sql: &mut String) {
158     sql.push_str(" and (SyncType & ?) = ?");
159 }
160 
161 #[inline(always)]
build_sql_not_sync(sql: &mut String)162 fn build_sql_not_sync(sql: &mut String) {
163     sql.push_str(" and (SyncType & ?) = 0");
164 }
165 
from_data_type_to_str(value: &DataType) -> &'static str166 fn from_data_type_to_str(value: &DataType) -> &'static str {
167     match *value {
168         DataType::Bytes => "BLOB",
169         DataType::Number => "INTEGER",
170         DataType::Bool => "INTEGER",
171     }
172 }
173 
from_data_value_to_str_value(value: &Value) -> String174 fn from_data_value_to_str_value(value: &Value) -> String {
175     match *value {
176         Value::Number(i) => format!("{}", i),
177         Value::Bytes(_) => String::from("NOT SUPPORTED"),
178         Value::Bool(b) => format!("{}", b),
179     }
180 }
181 
build_sql_query_options(query_options: Option<&QueryOptions>, sql: &mut String)182 fn build_sql_query_options(query_options: Option<&QueryOptions>, sql: &mut String) {
183     if let Some(option) = query_options {
184         if let Some(sql_where) = &option.amend {
185             sql.push_str(sql_where);
186         }
187         if let Some(order_by) = &option.order_by {
188             if !order_by.is_empty() {
189                 sql.push_str(" order by ");
190                 build_sql_columns_not_empty(order_by, sql);
191             }
192         }
193         if let Some(order) = option.order {
194             let str = if order == Ordering::Greater {
195                 "ASC"
196             } else if order == Ordering::Less {
197                 "DESC"
198             } else {
199                 ""
200             };
201             sql.push_str(format!(" {}", str).as_str());
202         }
203         if let Some(limit) = option.limit {
204             sql.push_str(format!(" limit {}", limit).as_str());
205             if let Some(offset) = option.offset {
206                 sql.push_str(format!(" offset {}", offset).as_str());
207             }
208         } else if let Some(offset) = option.offset {
209             sql.push_str(format!(" limit -1 offset {}", offset).as_str());
210         }
211     }
212 }
213 
build_sql_reverse_condition(condition: &DbMap, reverse_condition: Option<&DbMap>, sql: &mut String)214 fn build_sql_reverse_condition(condition: &DbMap, reverse_condition: Option<&DbMap>, sql: &mut String) {
215     if let Some(conditions) = reverse_condition {
216         if !conditions.is_empty() {
217             if !condition.is_empty() {
218                 sql.push_str(" and ");
219             } else {
220                 sql.push_str(" where ");
221             }
222             for (i, column_name) in conditions.keys().enumerate() {
223                 if *column_name == "SyncType" {
224                     sql.push_str("(SyncType & ?) == 0");
225                 } else {
226                     sql.push_str(column_name);
227                     sql.push_str("<>?");
228                 }
229                 if i != conditions.len() - 1 {
230                     sql.push_str(" and ")
231                 }
232             }
233         }
234     }
235 }
236 
get_column_info(columns: &'static [ColumnInfo], db_column: &str) -> Result<&'static ColumnInfo>237 fn get_column_info(columns: &'static [ColumnInfo], db_column: &str) -> Result<&'static ColumnInfo> {
238     for column in columns.iter() {
239         if column.name.eq(db_column) {
240             return Ok(column);
241         }
242     }
243     log_throw_error!(ErrCode::DataCorrupted, "Database is corrupted.")
244 }
245 
246 impl<'a> Table<'a> {
new(table_name: &str, db: &'a Database) -> Table<'a>247     pub(crate) fn new(table_name: &str, db: &'a Database) -> Table<'a> {
248         Table { table_name: table_name.to_string(), db }
249     }
250 
exist(&self) -> Result<bool>251     pub(crate) fn exist(&self) -> Result<bool> {
252         let sql = format!("select * from sqlite_master where type ='table' and name = '{}'", self.table_name);
253         let stmt = Statement::prepare(sql.as_str(), self.db)?;
254         let ret = stmt.step()?;
255         if ret == SQLITE_ROW {
256             Ok(true)
257         } else {
258             Ok(false)
259         }
260     }
261 
262     #[allow(dead_code)]
delete(&self) -> Result<()>263     pub(crate) fn delete(&self) -> Result<()> {
264         let sql = format!("DROP TABLE {}", self.table_name);
265         self.db.exec(&sql)
266     }
267 
268     /// Create a table with name 'table_name' at specific version.
269     /// The columns is descriptions for each column.
create_with_version(&self, columns: &[ColumnInfo], version: u32) -> Result<()>270     pub(crate) fn create_with_version(&self, columns: &[ColumnInfo], version: u32) -> Result<()> {
271         let is_exist = self.exist()?;
272         if is_exist {
273             return Ok(());
274         }
275         let mut sql = format!("CREATE TABLE IF NOT EXISTS {}(", self.table_name);
276         for i in 0..columns.len() {
277             let column = &columns[i];
278             sql.push_str(column.name);
279             sql.push(' ');
280             sql.push_str(from_data_type_to_str(&column.data_type));
281             if column.is_primary_key {
282                 sql.push_str(" PRIMARY KEY");
283             }
284             if column.not_null {
285                 sql.push_str(" NOT NULL");
286             }
287             if i != columns.len() - 1 {
288                 sql.push(',')
289             };
290         }
291         sql.push_str(");");
292         let mut trans = Transaction::new(self.db);
293         trans.begin()?;
294         if let Err(e) = self.db.exec(sql.as_str()) {
295             trans.rollback()?;
296             return Err(e);
297         }
298         if let Err(e) = self.db.set_version(version) {
299             trans.rollback()?;
300             Err(e)
301         } else {
302             trans.commit()
303         }
304     }
305 
306     /// Create a table with name 'table_name'.
307     /// The columns is descriptions for each column.
create(&self, columns: &[ColumnInfo]) -> Result<()>308     pub(crate) fn create(&self, columns: &[ColumnInfo]) -> Result<()> {
309         self.create_with_version(columns, DB_UPGRADE_VERSION)
310     }
311 
is_column_exist(&self, column: &'static str) -> bool312     fn is_column_exist(&self, column: &'static str) -> bool {
313         let query_option = QueryOptions {
314             offset: None,
315             limit: Some(1),
316             order: None,
317             order_by: None,
318             amend: None
319         };
320         self.query_row(&vec![column], &DbMap::new(), Some(&query_option), false, COLUMN_INFO).is_ok()
321     }
322 
upgrade(&self, ver: u32, columns: &[UpgradeColumnInfo]) -> Result<()>323     pub(crate) fn upgrade(&self, ver: u32, columns: &[UpgradeColumnInfo]) -> Result<()> {
324         let is_exist = self.exist()?;
325         if !is_exist {
326             return Ok(());
327         }
328         let mut trans = Transaction::new(self.db);
329         trans.begin()?;
330         for item in columns {
331             if let Err(e) = self.add_column(&item.base_info, &item.default_value) {
332                 if self.is_column_exist(item.base_info.name) {
333                     continue;
334                 }
335                 trans.rollback()?;
336                 return Err(e);
337             }
338         }
339         if let Err(e) = self.db.set_version(ver) {
340             trans.rollback()?;
341             Err(e)
342         } else {
343             trans.commit()
344         }
345     }
346 
347     /// Insert a row into table, and datas is the value to be insert.
348     ///
349     /// # Examples
350     ///
351     /// ```
352     /// // SQL: insert into table_name(id,alias) values (3,'alias1')
353     /// let datas = &DbMap::from([("id", Value::Number(3), ("alias", Value::Bytes(b"alias1"))]);
354     /// let ret = table.insert_row(datas);
355     /// ```
insert_row(&self, datas: &DbMap) -> Result<i32>356     pub(crate) fn insert_row(&self, datas: &DbMap) -> Result<i32> {
357         self.insert_row_with_table_name(datas, &self.table_name)
358     }
359 
insert_row_with_table_name(&self, datas: &DbMap, table_name: &str) -> Result<i32>360     pub(crate) fn insert_row_with_table_name(&self, datas: &DbMap, table_name: &str) -> Result<i32> {
361         let mut sql = format!("insert into {} (", table_name);
362         for (i, column_name) in datas.keys().enumerate() {
363             sql.push_str(column_name);
364             if i != datas.len() - 1 {
365                 sql.push(',');
366             }
367         }
368 
369         sql.push_str(") values (");
370         build_sql_values(datas.len(), &mut sql);
371         sql.push(')');
372         let stmt = Statement::prepare(&sql, self.db)?;
373         let mut index = 1;
374         bind_datas(datas, &stmt, &mut index)?;
375         stmt.step()?;
376         let count = unsafe { SqliteChanges(self.db.handle as _) };
377         Ok(count)
378     }
379 
380     // insert adapt data
insert_adapt_data_row(&self, datas: &DbMap, adapt_attributes: &DbMap) -> Result<i32>381     pub(crate) fn insert_adapt_data_row(&self, datas: &DbMap, adapt_attributes: &DbMap) -> Result<i32> {
382         let mut trans = Transaction::new(self.db);
383         trans.begin()?;
384         if let Ok(insert_num) = self.insert_row(datas) {
385             if adapt_attributes.is_empty() || self.insert_row_with_table_name(adapt_attributes, ADAPT_CLOUD_TABLE).is_ok() {
386                 trans.commit()?;
387                 return Ok(insert_num)
388             }
389         }
390         trans.rollback()?;
391         log_throw_error!(ErrCode::DatabaseError, "insert adapt data failed!")
392     }
393 
394     /// Delete row from table.
395     ///
396     /// # Examples
397     ///
398     /// ```
399     /// // SQL: delete from table_name where id=2
400     /// let condition = &DbMap::from([("id", Value::Number(2)]);
401     /// let ret = table.delete_row(condition, None, false);
402     /// ```
delete_row( &self, condition: &DbMap, reverse_condition: Option<&DbMap>, is_filter_sync: bool, ) -> Result<i32>403     pub(crate) fn delete_row(
404         &self,
405         condition: &DbMap,
406         reverse_condition: Option<&DbMap>,
407         is_filter_sync: bool,
408     ) -> Result<i32> {
409         self.delete_row_with_table_name(condition, reverse_condition, is_filter_sync, &self.table_name)
410     }
411 
412     // Delete row from table with table name.
delete_row_with_table_name( &self, condition: &DbMap, reverse_condition: Option<&DbMap>, is_filter_sync: bool, table_name: &str ) -> Result<i32>413     pub(crate) fn delete_row_with_table_name(
414         &self,
415         condition: &DbMap,
416         reverse_condition: Option<&DbMap>,
417         is_filter_sync: bool,
418         table_name: &str
419     ) -> Result<i32> {
420         let mut sql = format!("delete from {}", table_name);
421         build_sql_where(condition, is_filter_sync, &mut sql);
422         build_sql_reverse_condition(condition, reverse_condition, &mut sql);
423         let stmt = Statement::prepare(&sql, self.db)?;
424         let mut index = 1;
425         bind_where_datas(condition, &stmt, &mut index)?;
426         if let Some(datas) = reverse_condition {
427             bind_datas(datas, &stmt, &mut index)?;
428         }
429         stmt.step()?;
430         let count = unsafe { SqliteChanges(self.db.handle as _) };
431         Ok(count)
432     }
433 
434     // delete adapt data
delete_adapt_data_row( &self, datas: Option<&DbMap>, adapt_attributes: Option<&DbMap> ) -> Result<i32>435     pub(crate) fn delete_adapt_data_row(
436         &self,
437         datas: Option<&DbMap>,
438         adapt_attributes: Option<&DbMap>
439     ) -> Result<i32> {
440         let mut trans = Transaction::new(self.db);
441         trans.begin()?;
442         // if datas is empty do not delete data in it.
443         let mut delete_num = 0;
444         if let Some(data) = datas {
445             delete_num = match self.delete_row(data, None, false) {
446                 Ok(num) => num,
447                 Err(_e) => {
448                     trans.rollback()?;
449                     return log_throw_error!(ErrCode::DatabaseError, "delete adapt data failed!")
450                 }
451             }
452         }
453 
454         // if adapt_attributes is empty do not delete data in adapt table.
455         if let Some(adapt_attribute) = adapt_attributes {
456             delete_num = match self.delete_row_with_table_name(adapt_attribute, None, false, ADAPT_CLOUD_TABLE) {
457                 Ok(num) => num,
458                 Err(_e) => {
459                     trans.rollback()?;
460                     return log_throw_error!(ErrCode::DatabaseError, "delete adapt data failed!")
461                 }
462             }
463         }
464         trans.commit()?;
465         Ok(delete_num)
466     }
467 
468     /// Delete row from table with specific condition.
469     ///
470     /// # Examples
471     ///
472     /// ```
473     /// // SQL: delete from table_name where id=2
474     /// let specific_cond = "id".to_string();
475     /// let condition_value = Value::Number(2);
476     /// let ret = table.delete_with_specific_cond(specific_cond, condition_value);
477     /// ```
delete_with_specific_cond(&self, specific_cond: &str, condition_value: &[Value]) -> Result<i32>478     pub(crate) fn delete_with_specific_cond(&self, specific_cond: &str, condition_value: &[Value]) -> Result<i32> {
479         let sql: String = format!("delete from {} where {}", self.table_name, specific_cond);
480         let stmt = Statement::prepare(&sql, self.db)?;
481         let mut index = 1;
482         bind_where_with_specific_condifion(condition_value, &stmt, &mut index)?;
483         stmt.step()?;
484         let count = unsafe { SqliteChanges(self.db.handle as _) };
485         Ok(count)
486     }
487 
update_sync_datas_by_aliases(&self, condition: &DbMap, datas: &DbMap, aliases: &[Value]) -> Result<i32>488     fn update_sync_datas_by_aliases(&self, condition: &DbMap, datas: &DbMap, aliases: &[Value]) -> Result<i32> {
489         let mut sql = format!("update {} set ", self.table_name);
490         for (i, column_name) in datas.keys().enumerate() {
491             sql.push_str(column_name);
492             sql.push_str("=?");
493             if i != datas.len() - 1 {
494                 sql.push(',');
495             }
496         }
497         build_sql_where(condition, true, &mut sql);
498         build_sql_alias_list(aliases.len(), &mut sql);
499         build_sql_sync(&mut sql);
500         let stmt = Statement::prepare(&sql, self.db)?;
501         let mut index = 1;
502         bind_datas(datas, &stmt, &mut index)?;
503         bind_where_datas(condition, &stmt, &mut index)?;
504         bind_alias_list(aliases, &stmt, &mut index)?;
505         let sync_type = Value::Number(SyncType::TrustedAccount as u32);
506         bind_sync(&stmt, &sync_type, &mut index)?;
507         stmt.step()?;
508         let count = unsafe { SqliteChanges(self.db.handle as _) };
509         logi!("update sync data count = {}", count);
510         Ok(count)
511     }
512 
delete_local_datas_by_aliases(&self, condition: &DbMap, aliases: &[Value]) -> Result<i32>513     fn delete_local_datas_by_aliases(&self, condition: &DbMap, aliases: &[Value]) -> Result<i32> {
514         let mut sql = format!("delete from {}", self.table_name);
515         build_sql_where(condition, true, &mut sql);
516         build_sql_alias_list(aliases.len(), &mut sql);
517         build_sql_not_sync(&mut sql);
518         let mut index = 1;
519         let stmt = Statement::prepare(&sql, self.db)?;
520         bind_datas(condition, &stmt, &mut index)?;
521         bind_alias_list(aliases, &stmt, &mut index)?;
522         let sync_type = Value::Number(SyncType::TrustedAccount as u32);
523         bind_not_sync(&stmt, &sync_type, &mut index)?;
524         stmt.step()?;
525         let count = unsafe { SqliteChanges(self.db.handle as _) };
526         logi!("delete local data count = {}", count);
527         Ok(count)
528     }
529 
local_delete_batch_datas( &self, condition: &DbMap, datas: &DbMap, aliases: &[Vec<u8>], ) -> Result<i32>530     pub(crate) fn local_delete_batch_datas(
531         &self,
532         condition: &DbMap,
533         datas: &DbMap,
534         aliases: &[Vec<u8>],
535     ) -> Result<i32> {
536         let mut alias_values = Vec::with_capacity(aliases.len());
537         for alias in aliases {
538             alias_values.push(Value::Bytes(alias.to_vec()));
539         }
540         let mut trans = Transaction::new(self.db);
541         trans.begin()?;
542         let mut count = match self.update_sync_datas_by_aliases(condition, datas, &alias_values) {
543             Ok(count) => count,
544             Err(e) => return Err(e),
545         };
546 
547         count += match self.delete_local_datas_by_aliases(condition, &alias_values) {
548             Ok(count) => count,
549             Err(e) => {
550                 trans.rollback()?;
551                 return Err(e);
552             },
553         };
554 
555         trans.commit()?;
556         Ok(count)
557     }
558 
559     /// Update a row in table.
560     ///
561     /// # Examples
562     ///
563     /// ```
564     /// // SQL: update table_name set alias='update_value' where id=2
565     /// let condition = &DbMap::from([("id", Value::Number(2)]);
566     /// let datas = &DbMap::from([("alias", Value::Bytes(b"update_value")]);
567     /// let ret = table.update_row(conditions, false, datas);
568     /// ```
update_row(&self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<i32>569     pub(crate) fn update_row(&self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<i32> {
570         let mut sql = format!("update {} set ", self.table_name);
571         for (i, column_name) in datas.keys().enumerate() {
572             sql.push_str(column_name);
573             sql.push_str("=?");
574             if i != datas.len() - 1 {
575                 sql.push(',');
576             }
577         }
578         build_sql_where(condition, is_filter_sync, &mut sql);
579         let stmt = Statement::prepare(&sql, self.db)?;
580         let mut index = 1;
581         bind_datas(datas, &stmt, &mut index)?;
582         bind_where_datas(condition, &stmt, &mut index)?;
583         stmt.step()?;
584         let count = unsafe { SqliteChanges(self.db.handle as _) };
585         Ok(count)
586     }
587 
588     /// Query row from table.
589     /// If length of columns is 0, all table columns are queried. (eg. select * xxx)
590     /// If length of condition is 0, all data in the table is queried.
591     ///
592     /// # Examples
593     ///
594     /// ```
595     /// // SQL: select alias,blobs from table_name
596     /// let result_set = table.query_datas_with_key_value(&vec!["alias", "blobs"], false, &vec![]);
597     /// ```
query_row( &self, columns: &Vec<&'static str>, condition: &DbMap, query_options: Option<&QueryOptions>, is_filter_sync: bool, column_info: &'static [ColumnInfo], ) -> Result<Vec<DbMap>>598     pub(crate) fn query_row(
599         &self,
600         columns: &Vec<&'static str>,
601         condition: &DbMap,
602         query_options: Option<&QueryOptions>,
603         is_filter_sync: bool,
604         column_info: &'static [ColumnInfo],
605     ) -> Result<Vec<DbMap>> {
606         let mut sql = String::from("select ");
607         if !columns.is_empty() {
608             sql.push_str("distinct ");
609         }
610         build_sql_columns(columns, &mut sql);
611         sql.push_str(" from ");
612         sql.push_str(self.table_name.as_str());
613         build_sql_where(condition, is_filter_sync, &mut sql);
614         build_sql_query_options(query_options, &mut sql);
615         let stmt = Statement::prepare(&sql, self.db)?;
616         let mut index = 1;
617         bind_where_datas(condition, &stmt, &mut index)?;
618         let mut result = vec![];
619         while stmt.step()? == SQLITE_ROW {
620             let mut record = DbMap::new();
621             let n = stmt.data_count();
622             for i in 0..n {
623                 let column_name = stmt.query_column_name(i)?;
624                 let column_info = get_column_info(column_info, column_name)?;
625                 match stmt.query_column_auto_type(i)? {
626                     Some(Value::Number(n)) if column_info.data_type == DataType::Bool => {
627                         record.insert(column_info.name, Value::Bool(n != 0))
628                     },
629                     Some(n) if n.data_type() == column_info.data_type => record.insert(column_info.name, n),
630                     Some(_) => {
631                         return log_throw_error!(ErrCode::DataCorrupted, "The data in DB has been tampered with.")
632                     },
633                     None => continue,
634                 };
635             }
636             result.push(record);
637         }
638         Ok(result)
639     }
640 
641     /// Query row from table.
642     /// If length of columns is 0, all table columns are queried. (eg. select * xxx)
643     /// If length of condition is 0, all data in the table is queried.
644     ///
645     /// # Examples
646     ///
647     /// ```
648     /// // SQL: select alias,blobs from table_name
649     /// let result_set = table.query_datas_with_key_value(&vec!["alias", "blobs"], false, &vec![]);
650     /// ```
query_connect_table_row( &self, columns: &Vec<&'static str>, condition: &DbMap, query_options: Option<&QueryOptions>, is_filter_sync: bool, column_info: &'static [ColumnInfo], ) -> Result<Vec<DbMap>>651     pub(crate) fn query_connect_table_row(
652         &self,
653         columns: &Vec<&'static str>,
654         condition: &DbMap,
655         query_options: Option<&QueryOptions>,
656         is_filter_sync: bool,
657         column_info: &'static [ColumnInfo],
658     ) -> Result<Vec<DbMap>> {
659         let mut sql = String::from("select ");
660         if !columns.is_empty() {
661             sql.push_str("distinct ");
662         }
663         build_sql_columns(columns, &mut sql);
664         sql.push_str(" from ");
665         sql.push_str(self.table_name.as_str());
666         sql.push_str(format!(
667             " LEFT JOIN {} ON {}.{} = {}.{}",
668             ADAPT_CLOUD_TABLE, self.table_name.as_str(),
669             column::GLOBAL_ID, ADAPT_CLOUD_TABLE, adapt_column::OLD_GLOBAL_ID).as_str()
670         );
671         build_sql_where(condition, is_filter_sync, &mut sql);
672         build_sql_query_options(query_options, &mut sql);
673         let stmt = Statement::prepare(&sql, self.db)?;
674         let mut index = 1;
675         bind_where_datas(condition, &stmt, &mut index)?;
676         let mut result = vec![];
677         while stmt.step()? == SQLITE_ROW {
678             let mut record = DbMap::new();
679             let n = stmt.data_count();
680             for i in 0..n {
681                 let column_name = stmt.query_column_name(i)?;
682                 let column_info = get_column_info(column_info, column_name)?;
683                 match stmt.query_column_auto_type(i)? {
684                     Some(Value::Number(n)) if column_info.data_type == DataType::Bool => {
685                         record.insert(column_info.name, Value::Bool(n != 0))
686                     },
687                     Some(n) if n.data_type() == column_info.data_type => record.insert(column_info.name, n),
688                     Some(_) => {
689                         return log_throw_error!(ErrCode::DataCorrupted, "The data in DB has been tampered with.")
690                     },
691                     None => continue,
692                 };
693             }
694             result.push(record);
695         }
696         Ok(result)
697     }
698 
699     /// Count the number of datas with query condition(can be empty).
700     ///
701     /// # Examples
702     ///
703     /// ```
704     /// // SQL: select count(*) as count from table_name where id=3
705     /// let count = table.count_datas(&DbMap::from([("id", Value::Number(3))]), false);
706     /// ```
count_datas(&self, condition: &DbMap, is_filter_sync: bool) -> Result<u32>707     pub(crate) fn count_datas(&self, condition: &DbMap, is_filter_sync: bool) -> Result<u32> {
708         let mut sql = format!("select count(*) as count from {}", self.table_name);
709         build_sql_where(condition, is_filter_sync, &mut sql);
710         let stmt = Statement::prepare(&sql, self.db)?;
711         let mut index = 1;
712         bind_where_datas(condition, &stmt, &mut index)?;
713         stmt.step()?;
714         let count = stmt.query_column_int(0);
715         Ok(count)
716     }
717 
718     /// Check whether data exists in the database table.
719     ///
720     /// # Examples
721     ///
722     /// ```
723     /// // SQL: select count(*) as count from table_name where id=3 and alias='alias'
724     /// let exits = table
725     ///     .is_data_exists(&DbMap::from([("id", Value::Number(3)), ("alias", Value::Bytes(b"alias"))]), false);
726     /// ```
is_data_exists(&self, cond: &DbMap, is_filter_sync: bool) -> Result<bool>727     pub(crate) fn is_data_exists(&self, cond: &DbMap, is_filter_sync: bool) -> Result<bool> {
728         let ret = self.count_datas(cond, is_filter_sync);
729         match ret {
730             Ok(count) => Ok(count > 0),
731             Err(e) => Err(e),
732         }
733     }
734 
735     /// Add new column tp table.
736     /// 1. Primary key cannot be added.
737     /// 2. Cannot add a non-null column with no default value
738     /// 3. Only the integer and blob types support the default value, and the default value of the blob type is null.
739     ///
740     /// # Examples
741     ///
742     /// ```
743     /// // SQL: alter table table_name add cloumn id integer not null
744     /// let ret = table.add_column(
745     ///     ColumnInfo {
746     ///         name: "id",
747     ///         data_type: DataType::INTEGER,
748     ///         is_primary_key: false,
749     ///         not_null: true,
750     ///     },
751     ///     Some(Value::Number(0)),
752     /// );
753     /// ```
add_column(&self, column: &ColumnInfo, default_value: &Option<Value>) -> Result<()>754     pub(crate) fn add_column(&self, column: &ColumnInfo, default_value: &Option<Value>) -> Result<()> {
755         if column.is_primary_key {
756             return log_throw_error!(ErrCode::InvalidArgument, "The primary key already exists in the table.");
757         }
758         if column.not_null && default_value.is_none() {
759             return log_throw_error!(ErrCode::InvalidArgument, "A default value is required for a non-null column.");
760         }
761         let data_type = from_data_type_to_str(&column.data_type);
762         let mut sql = format!("ALTER TABLE {} ADD COLUMN {} {}", self.table_name, column.name, data_type);
763         if let Some(data) = default_value {
764             sql.push_str(" DEFAULT ");
765             sql.push_str(&from_data_value_to_str_value(data));
766         }
767         if column.not_null {
768             sql.push_str(" NOT NULL");
769         }
770         self.db.exec(sql.as_str())
771     }
772 
replace_row(&self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<()>773     pub(crate) fn replace_row(&self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<()> {
774         let mut trans = Transaction::new(self.db);
775         trans.begin()?;
776         if let Err(e) = self.delete_row(condition, None, is_filter_sync) {
777             trans.rollback()?;
778             return Err(e);
779         }
780         if let Err(e) = self.insert_row(datas) {
781             trans.rollback()?;
782             Err(e)
783         } else {
784             trans.commit()
785         }
786     }
787 }
788