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