• 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 interfaces for database management.
17 //! Databases are isolated based on users and protected by locks.
18 
19 use core::ffi::c_void;
20 use std::{ffi::CStr, fs, ptr::null_mut, sync::Mutex};
21 
22 use asset_common::{CallingInfo, OwnerType};
23 use asset_definition::{log_throw_error, ErrCode, Extension, Result, Value};
24 use asset_crypto_manager::secret_key::rename_key_alias;
25 use asset_log::{loge, logi};
26 
27 use crate::{
28     statement::Statement,
29     table::Table,
30     types::{
31         column, sqlite_err_handle, DbMap, QueryOptions, COLUMN_INFO, DB_UPGRADE_VERSION, DB_UPGRADE_VERSION_V1,
32         DB_UPGRADE_VERSION_V2, DB_UPGRADE_VERSION_V3, SQLITE_OK, TABLE_NAME, UPGRADE_COLUMN_INFO,
33         UPGRADE_COLUMN_INFO_V2, UPGRADE_COLUMN_INFO_V3,
34     },
35 };
36 
37 extern "C" {
SqliteOpen(file_name: *const u8, pp_db: *mut *mut c_void) -> i3238     fn SqliteOpen(file_name: *const u8, pp_db: *mut *mut c_void) -> i32;
SqliteCloseV2(db: *mut c_void) -> i3239     fn SqliteCloseV2(db: *mut c_void) -> i32;
SqliteExec(db: *mut c_void, sql: *const u8, msg: *mut *mut u8) -> i3240     fn SqliteExec(db: *mut c_void, sql: *const u8, msg: *mut *mut u8) -> i32;
SqliteFree(data: *mut c_void)41     fn SqliteFree(data: *mut c_void);
SqliteErrMsg(db: *mut c_void) -> *const u842     fn SqliteErrMsg(db: *mut c_void) -> *const u8;
43 }
44 
45 /// each user have a Database file
46 pub(crate) struct UserDbLock {
47     pub(crate) user_id: i32,
48     pub(crate) mtx: Mutex<i32>,
49 }
50 
51 static USER_DB_LOCK_LIST: Mutex<Vec<&'static UserDbLock>> = Mutex::new(Vec::new());
52 
53 /// If the user exists, the reference to the lock is returned.
54 /// Otherwise, a new lock is created and its reference is returned.
get_file_lock_by_user_id(user_id: i32) -> &'static UserDbLock55 fn get_file_lock_by_user_id(user_id: i32) -> &'static UserDbLock {
56     let mut list = USER_DB_LOCK_LIST.lock().unwrap();
57     for f in list.iter() {
58         if f.user_id == user_id {
59             return f;
60         }
61     }
62     let nf = Box::new(UserDbLock { user_id, mtx: Mutex::new(user_id) });
63     // SAFETY: We just push item into USER_DB_LOCK_LIST, never remove item or modify item,
64     // so return a reference of leak item is safe.
65     let nf: &'static UserDbLock = Box::leak(nf);
66     list.push(nf);
67     list[list.len() - 1]
68 }
69 
70 /// Struct used to store database files and connection information.
71 #[repr(C)]
72 pub struct Database {
73     pub(crate) path: String,
74     pub(crate) backup_path: String,
75     pub(crate) handle: usize, // Pointer to the database connection.
76     pub(crate) db_lock: &'static UserDbLock,
77 }
78 
79 /// Callback for database upgrade.
80 pub type UpgradeDbCallback = fn(db: &Database, old_ver: u32, new_ver: u32) -> Result<()>;
81 
82 #[cfg(not(test))]
83 const ROOT_PATH: &str = "/data/service/el1/public/asset_service";
84 #[cfg(test)]
85 const ROOT_PATH: &str = "/data/asset_test";
86 
87 #[inline(always)]
fmt_db_path(user_id: i32) -> String88 fn fmt_db_path(user_id: i32) -> String {
89     format!("{}/{}/asset.db", ROOT_PATH, user_id)
90 }
91 
92 #[inline(always)]
fmt_backup_path(path: &str) -> String93 fn fmt_backup_path(path: &str) -> String {
94     let mut bp = path.to_string();
95     bp.push_str(".backup");
96     bp
97 }
98 
99 /// Get asset storage path.
get_path() -> String100 pub fn get_path() -> String {
101     ROOT_PATH.to_string()
102 }
103 
104 impl Database {
105     /// Create a database.
build(user_id: i32) -> Result<Database>106     pub fn build(user_id: i32) -> Result<Database> {
107         let path = fmt_db_path(user_id);
108         let backup_path = fmt_backup_path(path.as_str());
109         let lock = get_file_lock_by_user_id(user_id);
110         let mut db = Database { path, backup_path, handle: 0, db_lock: lock };
111         let _lock = db.db_lock.mtx.lock().unwrap();
112         db.open_and_restore()?;
113         db.restore_if_exec_fail(|e: &Table| e.create(COLUMN_INFO))?;
114         db.upgrade(user_id, DB_UPGRADE_VERSION, |_, _, _| Ok(()))?;
115         Ok(db)
116     }
117 
118     /// check is db ok
check_db_accessible(path: String, user_id: i32) -> Result<()>119     pub fn check_db_accessible(path: String, user_id: i32) -> Result<()> {
120         let lock = get_file_lock_by_user_id(user_id);
121         let mut db = Database { path: path.clone(), backup_path: path, handle: 0, db_lock: lock };
122         db.open()?;
123         let table = Table::new(TABLE_NAME, &db);
124         table.create(COLUMN_INFO)
125     }
126 
127     // Open database connection.
open(&mut self) -> Result<()>128     pub(crate) fn open(&mut self) -> Result<()> {
129         let mut path_c = self.path.clone();
130         path_c.push('\0');
131 
132         let ret = unsafe { SqliteOpen(path_c.as_ptr(), &mut self.handle as *mut usize as _) };
133         if ret == SQLITE_OK {
134             Ok(())
135         } else {
136             self.close();
137             log_throw_error!(sqlite_err_handle(ret), "[FATAL][DB]Open database failed, err={}", ret)
138         }
139     }
140 
141     /// Open the database connection and restore the database if the connection fails.
open_and_restore(&mut self) -> Result<()>142     fn open_and_restore(&mut self) -> Result<()> {
143         let result = self.open();
144         let result = match result {
145             Err(ret) if ret.code == ErrCode::DataCorrupted => self.restore(),
146             ret => ret,
147         };
148         result
149     }
150 
151     /// Close database connection.
close(&mut self)152     fn close(&mut self) {
153         if self.handle != 0 {
154             unsafe { SqliteCloseV2(self.handle as _) };
155             self.handle = 0;
156         }
157     }
158 
159     /// Close database connection.
close_db(&mut self)160     pub(crate) fn close_db(&mut self) {
161         let _lock = self.db_lock.mtx.lock().unwrap();
162         self.close()
163     }
164 
165     // Recovery the corrupt database and reopen it.
restore(&mut self) -> Result<()>166     pub(crate) fn restore(&mut self) -> Result<()> {
167         loge!("[WARNING]Database is corrupt, start to restore");
168         self.close();
169         if let Err(e) = fs::copy(&self.backup_path, &self.path) {
170             return log_throw_error!(ErrCode::FileOperationError, "[FATAL][DB]Recovery database failed, err={}", e);
171         }
172         self.open()
173     }
174 
175     /// Get database version, default is 0.
get_db_version(&self) -> Result<u32>176     fn get_db_version(&self) -> Result<u32> {
177         let stmt = Statement::prepare("pragma user_version", self)?;
178         stmt.step()?;
179         let version = stmt.query_column_int(0);
180         Ok(version)
181     }
182 
183     /// Get database version, default is 0.
184     #[allow(dead_code)]
get_version(&self) -> Result<u32>185     pub(crate) fn get_version(&self) -> Result<u32> {
186         let _lock = self.db_lock.mtx.lock().unwrap();
187         self.get_db_version()
188     }
189 
190     /// Update the database version for database upgrade.
191     #[allow(dead_code)]
set_version(&self, ver: u32) -> Result<()>192     pub(crate) fn set_version(&self, ver: u32) -> Result<()> {
193         let sql = format!("pragma user_version = {}", ver);
194         self.exec(sql.as_str())
195     }
196 
197     /// Upgrade database to new version.
198     #[allow(dead_code)]
upgrade(&mut self, user_id: i32, target_ver: u32, callback: UpgradeDbCallback) -> Result<()>199     pub fn upgrade(&mut self, user_id: i32, target_ver: u32, callback: UpgradeDbCallback) -> Result<()> {
200         let mut current_ver = self.get_db_version()?;
201         logi!("current database version: {}", current_ver);
202         if current_ver >= target_ver {
203             return Ok(());
204         }
205         while current_ver < target_ver {
206             match current_ver {
207                 DB_UPGRADE_VERSION_V1 => {
208                     self.restore_if_exec_fail(|e: &Table| e.upgrade(DB_UPGRADE_VERSION_V2, UPGRADE_COLUMN_INFO_V2))?;
209                     current_ver += 1;
210                 },
211                 DB_UPGRADE_VERSION_V2 => {
212                     self.restore_if_exec_fail(|e: &Table| e.upgrade(DB_UPGRADE_VERSION_V3, UPGRADE_COLUMN_INFO_V3))?;
213                     current_ver += 1;
214                 },
215                 DB_UPGRADE_VERSION_V3 => {
216                     if self.upgrade_key_alias(user_id)? {
217                         self.restore_if_exec_fail(|e: &Table| e.upgrade(DB_UPGRADE_VERSION, UPGRADE_COLUMN_INFO))?;
218                         current_ver += 1;
219                     } else {
220                         break;
221                     }
222                 },
223                 _ => break,
224             }
225         }
226 
227         callback(self, current_ver, target_ver)
228     }
229 
upgrade_key_alias(&mut self, user_id: i32) -> Result<bool>230     fn upgrade_key_alias(&mut self, user_id: i32) -> Result<bool> {
231         let query_results = self.query_data_without_lock(
232             &vec![
233                 column::OWNER_TYPE,
234                 column::OWNER,
235                 column::AUTH_TYPE,
236                 column::ACCESSIBILITY,
237                 column::REQUIRE_PASSWORD_SET,
238             ],
239             &DbMap::new(),
240             None,
241             true,
242         )?;
243 
244         let mut upgrade_result = true;
245         for query_result in query_results {
246             let owner_type = query_result.get_enum_attr(&column::OWNER_TYPE)?;
247             let owner_info = query_result.get_bytes_attr(&column::OWNER)?;
248             let calling_info = CallingInfo::new(user_id, owner_type, owner_info.to_vec());
249             let auth_type = query_result.get_enum_attr(&column::AUTH_TYPE)?;
250             let access_type = query_result.get_enum_attr(&column::ACCESSIBILITY)?;
251             let require_password_set = query_result.get_bool_attr(&column::REQUIRE_PASSWORD_SET)?;
252             // upgrade_result is set to false as long as any call in the loop for renaming key alias returned false.
253             upgrade_result &= rename_key_alias(&calling_info, auth_type, access_type, require_password_set);
254         }
255 
256         Ok(upgrade_result)
257     }
258 
259     /// Delete database file.
260     #[allow(dead_code)]
delete(user_id: i32) -> Result<()>261     pub(crate) fn delete(user_id: i32) -> Result<()> {
262         let path = fmt_db_path(user_id);
263         let backup_path = fmt_backup_path(&path);
264         if let Err(e) = fs::remove_file(path) {
265             return log_throw_error!(ErrCode::FileOperationError, "[FATAL][DB]Delete database failed, err={}", e);
266         }
267 
268         if let Err(e) = fs::remove_file(backup_path) {
269             return log_throw_error!(
270                 ErrCode::FileOperationError,
271                 "[FATAL][DB]Delete backup database failed, err={}",
272                 e
273             );
274         }
275         Ok(())
276     }
277 
278     /// Print the error message of database.
print_db_msg(&self)279     pub(crate) fn print_db_msg(&self) {
280         let msg = unsafe { SqliteErrMsg(self.handle as _) };
281         if !msg.is_null() {
282             let s = unsafe { CStr::from_ptr(msg as _) };
283             if let Ok(rs) = s.to_str() {
284                 loge!("[FATAL][DB]Database error message: {}", rs);
285             }
286         }
287     }
288 
289     /// execute sql without prepare
exec(&self, sql: &str) -> Result<()>290     pub fn exec(&self, sql: &str) -> Result<()> {
291         let mut sql_s = sql.to_string();
292         sql_s.push('\0');
293         let mut msg: *mut u8 = null_mut();
294         let ret = unsafe { SqliteExec(self.handle as _, sql_s.as_ptr(), &mut msg as _) };
295         if !msg.is_null() {
296             let s = unsafe { CStr::from_ptr(msg as _) };
297             if let Ok(rs) = s.to_str() {
298                 return log_throw_error!(
299                     sqlite_err_handle(ret),
300                     "[FATAL]Database execute sql failed. error code={}, error msg={}",
301                     ret,
302                     rs
303                 );
304             }
305             unsafe { SqliteFree(msg as _) };
306         }
307         if ret == SQLITE_OK {
308             Ok(())
309         } else {
310             log_throw_error!(sqlite_err_handle(ret), "[FATAL]Database execute sql failed. error code={}", ret)
311         }
312     }
313 
314     /// execute func in db, if failed and error code is data corrupted then restore
restore_if_exec_fail<T, F: Fn(&Table) -> Result<T>>(&mut self, func: F) -> Result<T>315     pub(crate) fn restore_if_exec_fail<T, F: Fn(&Table) -> Result<T>>(&mut self, func: F) -> Result<T> {
316         let table = Table::new(TABLE_NAME, self);
317         let result = func(&table);
318         match result {
319             Err(ret) if ret.code == ErrCode::DataCorrupted => {
320                 self.restore()?;
321                 let table = Table::new(TABLE_NAME, self); // Database handle will be changed.
322                 func(&table)
323             },
324             ret => ret,
325         }
326     }
327 
328     /// Insert datas into database.
329     /// The datas is a map of column-data pair.
330     /// If the operation is successful, the number of inserted data is returned.
331     ///
332     /// # Examples
333     ///
334     /// ```
335     /// use asset_definition::Value;
336     /// use asset_db_operator::{database::Database, types::{column, DbMap}};
337     ///
338     /// // SQL: insert into table_name(Owner,OwnerType,Alias,value) values('owner',1,'alias','insert_value')
339     /// let datas = DbMap::new();
340     /// datas.insert(column::OWNER, Value::Bytes(b"owner".to_ver()));
341     /// datas.insert(column::OWNER_TYPE, Value::Number(OwnerType::Native as u32));
342     /// datas.insert(column::ALIAS, Value::Bytes(b"alias".to_ver()));
343     /// datas.insert("value", Value::Bytes(b"insert_value".to_vec()));
344     /// let user_id = 100;
345     /// let ret = Database::build(user_id)?.insert_datas(&datas);
346     /// ```
347     ///
348     #[inline(always)]
insert_datas(&mut self, datas: &DbMap) -> Result<i32>349     pub fn insert_datas(&mut self, datas: &DbMap) -> Result<i32> {
350         let _lock: std::sync::MutexGuard<'_, i32> = self.db_lock.mtx.lock().unwrap();
351         let closure = |e: &Table| {
352             let mut query = DbMap::new();
353             query.insert_attr(column::ALIAS, datas.get_bytes_attr(&column::ALIAS)?.clone());
354             query.insert_attr(column::OWNER, datas.get_bytes_attr(&column::OWNER)?.clone());
355             query.insert_attr(column::OWNER_TYPE, datas.get_enum_attr::<OwnerType>(&column::OWNER_TYPE)?);
356             if e.is_data_exists(&query, false)? {
357                 log_throw_error!(ErrCode::Duplicated, "[FATAL]The data with the specified alias already exists.")
358             } else {
359                 e.insert_row(datas)
360             }
361         };
362         self.restore_if_exec_fail(closure)
363     }
364 
365     /// Delete datas from database.
366     /// The condition is a map of column-data pair.
367     /// If the operation is successful, the number of deleted data is returned.
368     ///
369     /// # Examples
370     ///
371     /// ```
372     /// use asset_definition::Value;
373     /// use asset_db_operator::{database::Database, types::{column, DbMap}};
374     ///
375     /// // SQL: delete from table_name where Owner='owner' and OwnerType=1 and Alias='alias' and value='delete_value'
376     /// let datas = DbMap::new();
377     /// datas.insert(column::OWNER, Value::Bytes(b"owner".to_ver()));
378     /// datas.insert(column::OWNER_TYPE, Value::Number(OwnerType::Native as u32));
379     /// datas.insert(column::ALIAS, Value::Bytes(b"alias".to_ver()));
380     /// datas.insert("value", Value::Bytes(b"delete_value".to_vec()));
381     /// let user_id = 100;
382     /// let ret = Database::build(user_id)?.delete_datas(&cond, None, false);
383     /// ```
384     ///
385     ///
386     #[inline(always)]
delete_datas( &mut self, condition: &DbMap, reverse_condition: Option<&DbMap>, is_filter_sync: bool, ) -> Result<i32>387     pub fn delete_datas(
388         &mut self,
389         condition: &DbMap,
390         reverse_condition: Option<&DbMap>,
391         is_filter_sync: bool,
392     ) -> Result<i32> {
393         let _lock = self.db_lock.mtx.lock().unwrap();
394         let closure = |e: &Table| e.delete_row(condition, reverse_condition, is_filter_sync);
395         self.restore_if_exec_fail(closure)
396     }
397 
398     /// Delete datas from database with specific condition.
399     /// If the operation is successful, the number of deleted data is returned.
400     #[inline(always)]
delete_specific_condition_datas( &mut self, specific_cond: &str, condition_value: &[Value], ) -> Result<i32>401     pub fn delete_specific_condition_datas(
402         &mut self,
403         specific_cond: &str,
404         condition_value: &[Value],
405     ) -> Result<i32> {
406         let _lock = self.db_lock.mtx.lock().unwrap();
407         let closure = |e: &Table| e.delete_with_specific_cond(specific_cond, condition_value);
408         self.restore_if_exec_fail(closure)
409     }
410 
411     /// Update datas in database.
412     /// The datas is a map of column-data pair.
413     /// If the operation is successful, the number of updated data is returned.
414     ///
415     /// # Examples
416     ///
417     /// ```
418     /// use asset_definition::Value;
419     /// use asset_db_operator::{database::Database, types::{column, DbMap}};
420     ///
421     /// // SQL: update table_name set alias='update_value' where Owner='owner' and OwnerType=1 and Alias='alias'
422     /// let cond = DbMap.new();
423     /// cond.insert(column::OWNER, Value::Bytes(b"owner".to_ver()));
424     /// cond.insert(column::OWNER_TYPE, Value::Number(OwnerType::Native as u32));
425     /// cond.insert(column::ALIAS, Value::Bytes(b"alias".to_ver()));
426     /// let datas = DbMap::from([("alias", Value::Bytes(b"update_value".to_vec()))]);
427     /// let user_id = 100;
428     /// let ret = Database::build(user_id)?.update_datas(&condition, true, &datas);
429     /// ```
430     #[inline(always)]
update_datas(&mut self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<i32>431     pub fn update_datas(&mut self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<i32> {
432         let _lock = self.db_lock.mtx.lock().unwrap();
433         let closure = |e: &Table| e.update_row(condition, is_filter_sync, datas);
434         self.restore_if_exec_fail(closure)
435     }
436 
437     /// Check whether data exists in the database.
438     ///
439     /// # Examples
440     ///
441     /// ```
442     /// use asset_definition::Value;
443     /// use asset_db_operator::{database::Database, types::{column, DbMap}};
444     ///
445     /// // SQL: select count(*) as count from table_name where Owner='owner' and OwnerType=1 and Alias='alias'
446     /// let datas = DbMap::new();
447     /// datas.insert(column::OWNER, Value::Bytes(b"owner".to_ver()));
448     /// datas.insert(column::OWNER_TYPE, Value::Number(OwnerType::Native as u32));
449     /// datas.insert(column::ALIAS, Value::Bytes(b"alias".to_ver()));
450     /// let user_id = 100;
451     /// let exist = Database::build(user_id)?.is_data_exists(&datas, false);
452     /// ```
453     #[inline(always)]
is_data_exists(&mut self, condition: &DbMap, is_filter_sync: bool) -> Result<bool>454     pub fn is_data_exists(&mut self, condition: &DbMap, is_filter_sync: bool) -> Result<bool> {
455         let _lock = self.db_lock.mtx.lock().unwrap();
456         let closure = |e: &Table| e.is_data_exists(condition, is_filter_sync);
457         self.restore_if_exec_fail(closure)
458     }
459 
460     /// Query data that meets specified conditions(can be empty) from the database.
461     /// If the operation is successful, the resultSet is returned.
462     ///
463     /// # Examples
464     ///
465     /// ```
466     /// use asset_definition::Value;
467     /// use asset_db_operator::{database::Database, types::{column, DbMap}};
468     ///
469     /// // SQL: select * from table_name where Owner='owner' and OwnerType=1 and Alias='alias'
470     /// let cond = DbMap::new();
471     /// cond.insert(column::OWNER, Value::Bytes(b"owner".to_ver()));
472     /// cond.insert(column::OWNER_TYPE, Value::Number(OwnerType::Native as u32));
473     /// cond.insert(column::ALIAS, Value::Bytes(b"alias".to_ver()));
474     /// let user_id = 100;
475     /// let ret = Database::build(user_id)?.query_datas(&vec![], &cond, None, false);
476     /// ```
477     #[inline(always)]
query_datas( &mut self, columns: &Vec<&'static str>, condition: &DbMap, query_options: Option<&QueryOptions>, is_filter_sync: bool, ) -> Result<Vec<DbMap>>478     pub fn query_datas(
479         &mut self,
480         columns: &Vec<&'static str>,
481         condition: &DbMap,
482         query_options: Option<&QueryOptions>,
483         is_filter_sync: bool,
484     ) -> Result<Vec<DbMap>> {
485         let _lock = self.db_lock.mtx.lock().unwrap();
486         let closure = |e: &Table| e.query_row(columns, condition, query_options, is_filter_sync, COLUMN_INFO);
487         self.restore_if_exec_fail(closure)
488     }
489 
490     /// Query data that meets specified conditions(can be empty) from the database.
491     /// If the operation is successful, the resultSet is returned.
492     ///
493     /// # Examples
494     ///
495     /// ```
496     /// use asset_definition::Value;
497     /// use asset_db_operator::{database::Database, types::{column, DbMap}};
498     ///
499     /// // SQL: select * from table_name where Owner='owner' and OwnerType=1 and Alias='alias'
500     /// let cond = DbMap::new();
501     /// cond.insert(column::OWNER, Value::Bytes(b"owner".to_ver()));
502     /// cond.insert(column::OWNER_TYPE, Value::Number(OwnerType::Native as u32));
503     /// cond.insert(column::ALIAS, Value::Bytes(b"alias".to_ver()));
504     /// let user_id = 100;
505     /// let ret = Database::build(user_id)?.query_data_without_lock(&vec![], &cond, None, false);
506     /// ```
query_data_without_lock( &mut self, columns: &Vec<&'static str>, condition: &DbMap, query_options: Option<&QueryOptions>, is_filter_sync: bool, ) -> Result<Vec<DbMap>>507     pub fn query_data_without_lock(
508         &mut self,
509         columns: &Vec<&'static str>,
510         condition: &DbMap,
511         query_options: Option<&QueryOptions>,
512         is_filter_sync: bool,
513     ) -> Result<Vec<DbMap>> {
514         let closure = |e: &Table| e.query_row(columns, condition, query_options, is_filter_sync, COLUMN_INFO);
515         self.restore_if_exec_fail(closure)
516     }
517 
518     /// Delete old data and insert new data.
replace_datas(&mut self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<()>519     pub fn replace_datas(&mut self, condition: &DbMap, is_filter_sync: bool, datas: &DbMap) -> Result<()> {
520         let _lock = self.db_lock.mtx.lock().unwrap();
521         let closure = |e: &Table| e.replace_row(condition, is_filter_sync, datas);
522         self.restore_if_exec_fail(closure)
523     }
524 }
525 
526 impl Drop for Database {
drop(&mut self)527     fn drop(&mut self) {
528         self.close_db()
529     }
530 }
531