mirror of
https://gitee.com/openharmony/security_asset
synced 2024-12-02 13:18:28 +00:00
remove sqlite struct
Change-Id: I35df78132ffe29dff71b0b5051c688f49ea0116b Match-id-f8cc7945e6fc6501ddcb786cb5bb11571b6c15fa
This commit is contained in:
parent
e9c9527ee4
commit
b4c6e140fd
@ -63,7 +63,6 @@ ohos_rust_shared_ffi("asset_sdk_ffi") {
|
||||
"$COMPONENT_DIR/frameworks/os_dependency/log:asset_log",
|
||||
"$COMPONENT_DIR/frameworks/os_dependency/memory:asset_mem",
|
||||
"$COMPONENT_DIR/interfaces/inner_api/rs:asset_sdk",
|
||||
"//third_party/rust/crates/libc:lib",
|
||||
]
|
||||
crate_name = "asset_sdk_ffi"
|
||||
subsystem_name = "security"
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
//! This module implements the function of Asset SDK from C to RUST.
|
||||
|
||||
use core::ffi::c_void;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
mem::{size_of, ManuallyDrop},
|
||||
@ -27,7 +28,7 @@ use asset_sdk::{AssetMap, DataType, ErrCode, IntoValue, Manager, Tag, Value, Ver
|
||||
|
||||
const RESULT_CODE_SUCCESS: i32 = 0;
|
||||
extern "C" {
|
||||
fn AssetMalloc(size: u32) -> *mut ::libc::c_void;
|
||||
fn AssetMalloc(size: u32) -> *mut c_void;
|
||||
}
|
||||
|
||||
fn into_map(attributes: *const Asset_Attr, attr_cnt: u32) -> Option<AssetMap> {
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
//! This module is used to adapt to the crypto manager.
|
||||
|
||||
use asset_crypto_manager::crypto::{Crypto, CryptoManager, SecretKey, construct_alias};
|
||||
use asset_crypto_manager::crypto::{construct_alias, Crypto, CryptoManager, SecretKey};
|
||||
use asset_db_operator::{
|
||||
database_table_helper::{
|
||||
COLUMN_ACCESSIBILITY, COLUMN_ALIAS, COLUMN_AUTH_TYPE, COLUMN_CRITICAL1, COLUMN_CRITICAL2, COLUMN_CRITICAL3,
|
||||
@ -141,8 +141,12 @@ pub(crate) fn decrypt(calling_info: &CallingInfo, db_data: &mut DbMap) -> Result
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn exec_crypto(calling_info: &CallingInfo, db_data: &mut DbMap, challenge: &Vec<u8>, _auth_token: &[u8])
|
||||
-> Result<()> {
|
||||
pub(crate) fn exec_crypto(
|
||||
calling_info: &CallingInfo,
|
||||
db_data: &mut DbMap,
|
||||
challenge: &Vec<u8>,
|
||||
_auth_token: &[u8],
|
||||
) -> Result<()> {
|
||||
let identity = ipc_rust::reset_calling_identity().map_err(|e| {
|
||||
loge!("Execute reset_calling_identity failed, error is [{}].", e);
|
||||
ErrCode::IpcError
|
||||
@ -157,16 +161,15 @@ pub(crate) fn exec_crypto(calling_info: &CallingInfo, db_data: &mut DbMap, chall
|
||||
let crypto_manager = CryptoManager::new();
|
||||
|
||||
// todo challenge_pos 改用 alias
|
||||
let _alias = construct_alias(
|
||||
calling_info.user_id(), &sha256(calling_info.owner_info()), auth_type, access_type);
|
||||
let _alias = construct_alias(calling_info.user_id(), &sha256(calling_info.owner_info()), auth_type, access_type);
|
||||
match crypto_manager.find(0, challenge) {
|
||||
Some(crypto) => {
|
||||
// todo 添加auth_token
|
||||
let secret = crypto.exec_crypto(secret, &construct_aad(db_data))?;
|
||||
loge!("get secret {} success!!!!", String::from_utf8_lossy(&secret)); // todo delete
|
||||
loge!("get secret {} success!!!!", String::from_utf8_lossy(&secret)); // todo delete
|
||||
db_data.insert(COLUMN_SECRET, Value::Bytes(secret));
|
||||
},
|
||||
None => return Err(ErrCode::CryptoError)
|
||||
None => return Err(ErrCode::CryptoError),
|
||||
}
|
||||
|
||||
if !ipc_rust::set_calling_identity(identity) {
|
||||
@ -174,4 +177,4 @@ pub(crate) fn exec_crypto(calling_info: &CallingInfo, db_data: &mut DbMap, chall
|
||||
return Err(ErrCode::IpcError);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +110,6 @@ pub(crate) fn pre_query(query: &AssetMap, calling_info: &CallingInfo) -> Result<
|
||||
for crypto in cryptos {
|
||||
crypto_manager.add(crypto)?;
|
||||
}
|
||||
logi!("get challenge successful!"); // todo delete
|
||||
logi!("get challenge successful!"); // todo delete
|
||||
Ok(challenge)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ fn query_all(calling_info: &CallingInfo, db_data: &mut DbMap, query: &AssetMap)
|
||||
let Some(Value::Bytes(ref auth_token)) =
|
||||
query.get(&Tag::AuthToken) else { return Err(ErrCode::InvalidArgument) };
|
||||
common::exec_crypto(calling_info, &mut results[0], challenge, auth_token)?;
|
||||
loge!("enter secdond query 4"); // todo delete
|
||||
loge!("enter secdond query 4"); // todo delete
|
||||
into_asset_maps(&results)
|
||||
},
|
||||
_ => {
|
||||
|
@ -16,17 +16,12 @@ import("//build/ohos.gni")
|
||||
COMPONENT_DIR = "//base/security/asset"
|
||||
|
||||
ohos_static_library("crypto_manager_wrapper") {
|
||||
include_dirs = [ "inc" ]
|
||||
sources = [
|
||||
"src/crypto_wrapper.cpp",
|
||||
"src/hks_key_wrapper.cpp",
|
||||
]
|
||||
|
||||
include_dirs = [ "inc" ]
|
||||
|
||||
deps = [
|
||||
"$COMPONENT_DIR/frameworks/os_dependency/memory:asset_mem",
|
||||
"//third_party/bounds_checking_function:libsec_shared",
|
||||
]
|
||||
deps = [ "$COMPONENT_DIR/frameworks/os_dependency/memory:asset_mem" ]
|
||||
|
||||
external_deps = [
|
||||
"hilog:libhilog",
|
||||
|
@ -14,10 +14,11 @@
|
||||
*/
|
||||
|
||||
#include "crypto_wrapper.h"
|
||||
#include <securec.h>
|
||||
|
||||
#include "hks_api.h"
|
||||
#include "hks_param.h"
|
||||
#include "hks_type.h"
|
||||
|
||||
#include "asset_log.h"
|
||||
#include "hks_key_wrapper.h"
|
||||
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
#include "hks_key_wrapper.h"
|
||||
#include "hks_param.h"
|
||||
|
||||
#include "asset_log.h"
|
||||
#include "asset_mem.h"
|
||||
|
||||
const int HEX_RETIO = 2;
|
||||
|
||||
static struct HksParam g_genParams[] = {
|
||||
|
@ -32,8 +32,7 @@ pub struct SecretKey {
|
||||
const MAX_ALIAS_SIZE: u32 = 64;
|
||||
|
||||
/// construct alias
|
||||
pub fn construct_alias(user_id: i32, owner: &Vec<u8>, auth_type: AuthType, access_type: Accessibility)
|
||||
-> Vec<u8> {
|
||||
pub fn construct_alias(user_id: i32, owner: &Vec<u8>, auth_type: AuthType, access_type: Accessibility) -> Vec<u8> {
|
||||
let mut alias: Vec<u8> = Vec::with_capacity(MAX_ALIAS_SIZE as usize);
|
||||
alias.extend_from_slice(&user_id.to_le_bytes());
|
||||
alias.push(b'_');
|
||||
@ -216,7 +215,7 @@ impl Crypto {
|
||||
pub fn encrypt(key: &SecretKey, msg: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>, ErrCode> {
|
||||
// out param
|
||||
let mut cipher: Vec<u8> = vec![0; msg.len() + AEAD_SIZE as usize]; // todo : zdy 加上nonce的长度
|
||||
// in param
|
||||
// in param
|
||||
let data = CryptParam {
|
||||
key_len: key.alias.len() as u32,
|
||||
key_data: key.alias.as_ptr(),
|
||||
|
@ -20,16 +20,15 @@ ohos_rust_static_library("asset_db_operator") {
|
||||
"src/database.rs",
|
||||
"src/database_table_helper.rs",
|
||||
"src/lib.rs",
|
||||
"src/sqlite3_ffi.rs",
|
||||
"src/statement.rs",
|
||||
"src/table.rs",
|
||||
"src/transaction.rs",
|
||||
"src/types.rs",
|
||||
]
|
||||
deps = [
|
||||
":asset_sqlite3_wrapper",
|
||||
"$COMPONENT_DIR/frameworks/definition:asset_definition",
|
||||
"$COMPONENT_DIR/frameworks/os_dependency/log:asset_log",
|
||||
"//third_party/sqlite:sqlite",
|
||||
]
|
||||
|
||||
crate_name = "asset_db_operator"
|
||||
@ -37,3 +36,10 @@ ohos_rust_static_library("asset_db_operator") {
|
||||
subsystem_name = "security"
|
||||
part_name = "asset"
|
||||
}
|
||||
|
||||
ohos_static_library("asset_sqlite3_wrapper") {
|
||||
sources = [ "src/sqlite3_wrapper.c" ]
|
||||
deps = [ "//third_party/sqlite:sqlite" ]
|
||||
subsystem_name = "security"
|
||||
part_name = "asset"
|
||||
}
|
@ -17,38 +17,58 @@
|
||||
//! each user have a db, each db have a db file and a lock, the lock is mutex
|
||||
//! db link is auto drop by RAII
|
||||
|
||||
use core::ffi::c_void;
|
||||
use std::{ffi::CStr, fs, path::Path, ptr::null_mut, sync::Mutex};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
statement::Statement,
|
||||
table::Table,
|
||||
types::{from_data_type_to_str, ColumnInfo, Sqlite3ErrMsg},
|
||||
types::{
|
||||
from_data_type_to_str, ColumnInfo, Sqlite3Callback, Sqlite3ErrMsg, SqliteErrCode, SQLITE_DONE, SQLITE_ERROR,
|
||||
SQLITE_OK, SQLITE_ROW,
|
||||
},
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
fn SqliteOpen(file_name: *const u8, pp_db: *mut *mut c_void) -> i32;
|
||||
fn SqliteCloseV2(db: *mut c_void) -> i32;
|
||||
fn SqliteExec(
|
||||
db: *mut c_void,
|
||||
sql: *const u8,
|
||||
callback: Option<Sqlite3Callback>,
|
||||
data: *mut c_void,
|
||||
msg: *mut *mut u8,
|
||||
) -> i32;
|
||||
fn SqliteFree(data: *mut c_void);
|
||||
fn SqliteErrMsg(db: *mut c_void) -> *const u8;
|
||||
}
|
||||
|
||||
const SQLITE_CORRUPT: i32 = 11;
|
||||
const SQLITE_NOTADB: i32 = 26;
|
||||
|
||||
/// each user have a Database file
|
||||
pub struct UseridFileLock {
|
||||
/// userid
|
||||
pub(crate) userid: i32,
|
||||
pub struct UserIdFileLock {
|
||||
/// user_id
|
||||
pub(crate) user_id: i32,
|
||||
/// file lock
|
||||
pub(crate) mtx: Mutex<i32>,
|
||||
}
|
||||
|
||||
/// save all the userid file locks
|
||||
static G_USER_DB_LOCK_LIST: Mutex<Vec<&'static UseridFileLock>> = Mutex::new(Vec::new());
|
||||
/// save all the user_id file locks
|
||||
static G_USER_DB_LOCK_LIST: Mutex<Vec<&'static UserIdFileLock>> = Mutex::new(Vec::new());
|
||||
|
||||
/// if userid exists, return reference, or create a new lock, insert into list and return reference
|
||||
fn get_file_lock_by_userid(userid: i32) -> &'static UseridFileLock {
|
||||
/// if user_id exists, return reference, or create a new lock, insert into list and return reference
|
||||
fn get_file_lock_by_user_id(user_id: i32) -> &'static UserIdFileLock {
|
||||
let mut list = G_USER_DB_LOCK_LIST.lock().unwrap();
|
||||
for f in list.iter() {
|
||||
if f.userid == userid {
|
||||
if f.user_id == user_id {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
let nf = Box::new(UseridFileLock { userid, mtx: Mutex::new(userid) });
|
||||
let nf = Box::new(UserIdFileLock { user_id, mtx: Mutex::new(user_id) });
|
||||
// SAFETY: We just push item into G_USER_FILE_LOCK_LIST, never remove item or modify item,
|
||||
// so return a reference of leak item is safe.
|
||||
let nf: &'static UseridFileLock = Box::leak(nf);
|
||||
let nf: &'static UserIdFileLock = Box::leak(nf);
|
||||
list.push(nf);
|
||||
list[list.len() - 1]
|
||||
}
|
||||
@ -60,16 +80,10 @@ pub struct Database<'a> {
|
||||
pub(crate) path: String,
|
||||
/// database file string
|
||||
pub(crate) back_path: String,
|
||||
/// is opened with sqlite3_open_v2
|
||||
pub(crate) v2: bool,
|
||||
/// open flags
|
||||
pub(crate) flags: i32,
|
||||
/// vfs
|
||||
pub(crate) vfs: Option<&'a [u8]>,
|
||||
/// raw pointer
|
||||
pub(crate) handle: usize,
|
||||
/// db file
|
||||
pub(crate) file: &'a UseridFileLock,
|
||||
pub(crate) file: &'a UserIdFileLock,
|
||||
}
|
||||
|
||||
/// update func callback
|
||||
@ -91,8 +105,8 @@ pub fn default_update_database_func(db: &Database, old_ver: u32, new_ver: u32) -
|
||||
|
||||
/// format database path
|
||||
#[inline(always)]
|
||||
fn fmt_db_path(userid: i32) -> String {
|
||||
format!("/data/service/el1/public/asset_service/{}/asset.db", userid)
|
||||
fn fmt_db_path(user_id: i32) -> String {
|
||||
format!("/data/service/el1/public/asset_service/{}/asset.db", user_id)
|
||||
}
|
||||
|
||||
/// get backup path
|
||||
@ -123,12 +137,8 @@ pub fn copy_db_file(db: &Database, master_or_backup: bool) -> Result<u64, std::i
|
||||
|
||||
/// wrap sqlite open
|
||||
#[inline(always)]
|
||||
fn sqlite3_open_wrap(file: &str, handle: &mut usize, flag: i32, vfs: Option<&[u8]>, v2: bool) -> SqliteErrCode {
|
||||
if v2 {
|
||||
sqlite3_open_v2_func(file, handle, flag, vfs)
|
||||
} else {
|
||||
sqlite3_open_func(file, handle)
|
||||
}
|
||||
fn sqlite3_open_wrap(file: &str, handle: &mut usize) -> SqliteErrCode {
|
||||
unsafe { SqliteOpen(file.as_ptr(), handle as *mut usize as _) }
|
||||
}
|
||||
|
||||
/// is corrupt
|
||||
@ -138,24 +148,18 @@ pub fn is_db_corrupt(ret: SqliteErrCode) -> bool {
|
||||
}
|
||||
|
||||
/// open db, will recovery wrong db file
|
||||
fn open_db(
|
||||
db: &mut Database,
|
||||
path: String,
|
||||
back_path: String,
|
||||
flag: i32,
|
||||
vfs: Option<&[u8]>,
|
||||
) -> Result<(), SqliteErrCode> {
|
||||
fn open_db(db: &mut Database, path: String, back_path: String) -> Result<(), SqliteErrCode> {
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
let mut ret = sqlite3_open_wrap(&path, &mut db.handle, flag, vfs, db.v2);
|
||||
let mut ret = sqlite3_open_wrap(&path, &mut db.handle);
|
||||
if is_db_corrupt(ret) {
|
||||
// recovery master db
|
||||
let mut back_handle = 0usize;
|
||||
let back_ret = sqlite3_open_wrap(&back_path, &mut back_handle, flag, vfs, db.v2);
|
||||
let back_ret = sqlite3_open_wrap(&back_path, &mut back_handle);
|
||||
if back_ret != SQLITE_OK {
|
||||
asset_log::loge!("both master backup db fail: {} {} {}", path, ret, back_ret);
|
||||
return Err(ret);
|
||||
}
|
||||
let close_ret = sqlite3_close_wrap(db.v2, back_handle);
|
||||
let close_ret = sqlite3_close_wrap(back_handle);
|
||||
if close_ret != SQLITE_OK {
|
||||
asset_log::loge!("close back fail {}", close_ret);
|
||||
}
|
||||
@ -165,7 +169,7 @@ fn open_db(
|
||||
return Err(ret);
|
||||
}
|
||||
asset_log::logi!("recovery master db {} succ", path);
|
||||
ret = sqlite3_open_wrap(&path, &mut db.handle, flag, vfs, db.v2);
|
||||
ret = sqlite3_open_wrap(&path, &mut db.handle);
|
||||
if ret != SQLITE_OK {
|
||||
asset_log::loge!("reopen master db {} fail {}", path, ret);
|
||||
return Err(ret);
|
||||
@ -186,7 +190,7 @@ impl<'a> Database<'a> {
|
||||
}
|
||||
let mut path_c = self.path.clone();
|
||||
path_c.push('\0');
|
||||
let ret = sqlite3_open_wrap(&path_c, &mut self.handle, self.flags, self.vfs, self.v2);
|
||||
let ret = sqlite3_open_wrap(&path_c, &mut self.handle);
|
||||
if ret != SQLITE_OK {
|
||||
asset_log::loge!("re open handle {} fail {}", self.path, ret);
|
||||
return Err(ret);
|
||||
@ -203,35 +207,29 @@ impl<'a> Database<'a> {
|
||||
// user - mutex
|
||||
path: path_c.clone(),
|
||||
back_path: back_path_c.clone(),
|
||||
v2: false,
|
||||
flags: 0,
|
||||
vfs: None,
|
||||
handle: 0,
|
||||
file: get_file_lock_by_userid(i32::MAX),
|
||||
file: get_file_lock_by_user_id(i32::MAX),
|
||||
};
|
||||
path_c.push('\0');
|
||||
back_path_c.push('\0');
|
||||
open_db(&mut db, path_c, back_path_c, 0, None)?;
|
||||
open_db(&mut db, path_c, back_path_c)?;
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
/// create default database
|
||||
pub fn default_new(userid: i32) -> Result<Database<'a>, SqliteErrCode> {
|
||||
let path = fmt_db_path(userid);
|
||||
pub fn default_new(user_id: i32) -> Result<Database<'a>, SqliteErrCode> {
|
||||
let path = fmt_db_path(user_id);
|
||||
let mut path_c = path.clone();
|
||||
let mut back_path_c = fmt_backup_path(path.as_str());
|
||||
let mut db = Database {
|
||||
path: path_c.clone(),
|
||||
back_path: back_path_c.clone(),
|
||||
v2: false,
|
||||
flags: 0,
|
||||
vfs: None,
|
||||
handle: 0,
|
||||
file: get_file_lock_by_userid(userid),
|
||||
file: get_file_lock_by_user_id(user_id),
|
||||
};
|
||||
path_c.push('\0');
|
||||
back_path_c.push('\0');
|
||||
open_db(&mut db, path_c, back_path_c, 0, None)?;
|
||||
open_db(&mut db, path_c, back_path_c)?;
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
@ -269,11 +267,11 @@ impl<'a> Database<'a> {
|
||||
|
||||
/// open database with version update callback
|
||||
pub fn default_new_with_version_update(
|
||||
userid: i32,
|
||||
user_id: i32,
|
||||
ver: u32,
|
||||
callback: UpdateDatabaseCallbackFunc,
|
||||
) -> Result<Database<'a>, SqliteErrCode> {
|
||||
let db = Database::default_new(userid)?;
|
||||
let db = Database::default_new(user_id)?;
|
||||
let version_old = db.get_version()?;
|
||||
#[cfg(test)]
|
||||
{
|
||||
@ -287,26 +285,6 @@ impl<'a> Database<'a> {
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
/// open database file
|
||||
/// use sqlite3_open_v2 instead of sqlite3_open
|
||||
pub fn new_v2(path: &str, flags: i32, vfs: Option<&'a [u8]>) -> Result<Database<'a>, SqliteErrCode> {
|
||||
let mut path_c = path.to_string();
|
||||
let mut back_path_c = fmt_backup_path(path);
|
||||
let mut db = Database {
|
||||
path: path_c.clone(),
|
||||
back_path: back_path_c.clone(),
|
||||
v2: true,
|
||||
flags,
|
||||
vfs,
|
||||
handle: 0,
|
||||
file: get_file_lock_by_userid(i32::MAX),
|
||||
};
|
||||
path_c.push('\0');
|
||||
back_path_c.push('\0');
|
||||
open_db(&mut db, path_c, back_path_c, flags, vfs)?;
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
/// delete database with delete the file
|
||||
pub fn drop_database(path: &str) -> std::io::Result<()> {
|
||||
let name = String::from_utf8(path.as_bytes().to_vec()).unwrap();
|
||||
@ -329,14 +307,14 @@ impl<'a> Database<'a> {
|
||||
}
|
||||
|
||||
/// delete default database
|
||||
pub fn drop_default_database(userid: i32) -> std::io::Result<()> {
|
||||
let path = fmt_db_path(userid);
|
||||
pub fn drop_default_database(user_id: i32) -> std::io::Result<()> {
|
||||
let path = fmt_db_path(user_id);
|
||||
Database::drop_database(path.as_str())
|
||||
}
|
||||
|
||||
/// delete default database and backup db
|
||||
pub fn drop_default_database_and_backup(userid: i32) -> std::io::Result<()> {
|
||||
let path = fmt_db_path(userid);
|
||||
pub fn drop_default_database_and_backup(user_id: i32) -> std::io::Result<()> {
|
||||
let path = fmt_db_path(user_id);
|
||||
let back_path = fmt_backup_path(path.as_str());
|
||||
let ret = Database::drop_database(path.as_str());
|
||||
let back_ret = Database::drop_database(back_path.as_str());
|
||||
@ -348,7 +326,7 @@ impl<'a> Database<'a> {
|
||||
/// return None if no error.
|
||||
/// You do NOT need to free err msg, it's auto freed.
|
||||
pub fn get_err_msg(&self) -> Option<Sqlite3ErrMsg> {
|
||||
let msg = sqlite3_err_msg_func(self.handle);
|
||||
let msg = unsafe { SqliteErrMsg(self.handle as _) };
|
||||
if !msg.is_null() {
|
||||
let s = unsafe { CStr::from_ptr(msg as _) };
|
||||
let se = Sqlite3ErrMsg { s: s.to_str().unwrap(), db: self };
|
||||
@ -369,11 +347,11 @@ impl<'a> Database<'a> {
|
||||
/// callback function for process result set.
|
||||
/// the final param data will be passed into callback function.
|
||||
pub fn exec(&self, stmt: &Statement<false>, callback: Option<Sqlite3Callback>, data: usize) -> SqliteErrCode {
|
||||
let mut msg = null_mut();
|
||||
let ret = sqlite3_exec_func(self.handle, &stmt.sql, callback, data, &mut msg);
|
||||
let mut msg: *mut u8 = null_mut();
|
||||
let ret = unsafe { SqliteExec(self.handle as _, stmt.sql.as_ptr(), callback, data as _, &mut msg as _) };
|
||||
if !msg.is_null() {
|
||||
self.print_err_msg(msg);
|
||||
sqlite3_free_func(msg as _);
|
||||
unsafe { SqliteFree(msg as _) };
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
ret
|
||||
@ -483,18 +461,14 @@ impl<'a> Database<'a> {
|
||||
}
|
||||
|
||||
/// wrap close func
|
||||
pub(crate) fn sqlite3_close_wrap(v2: bool, handle: usize) -> SqliteErrCode {
|
||||
if v2 {
|
||||
sqlite3_close_v2_func(handle)
|
||||
} else {
|
||||
sqlite3_close_func(handle)
|
||||
}
|
||||
pub(crate) fn sqlite3_close_wrap(handle: usize) -> SqliteErrCode {
|
||||
unsafe { SqliteCloseV2(handle as _) }
|
||||
}
|
||||
|
||||
impl<'a> Drop for Database<'a> {
|
||||
fn drop(&mut self) {
|
||||
if self.handle != 0 {
|
||||
let ret = sqlite3_close_wrap(self.v2, self.handle);
|
||||
let ret = sqlite3_close_wrap(self.handle);
|
||||
if ret != SQLITE_OK {
|
||||
asset_log::loge!("close db fail ret {}", ret);
|
||||
}
|
||||
|
@ -23,11 +23,9 @@ use crate::{
|
||||
database::{
|
||||
copy_db_file, copy_db_file_inner, is_db_corrupt, sqlite3_close_wrap, Database, UpdateDatabaseCallbackFunc,
|
||||
},
|
||||
from_sqlite_code_to_asset_code,
|
||||
table::Table,
|
||||
transaction::Transaction,
|
||||
types::{ColumnInfo, Condition, DbMap, QueryOptions, ResultSet},
|
||||
SqliteErrCode, SQLITE_OK,
|
||||
types::{ColumnInfo, Condition, DbMap, QueryOptions, ResultSet, SqliteErrCode, SQLITE_DONE, SQLITE_OK},
|
||||
};
|
||||
|
||||
/// just use database
|
||||
@ -112,6 +110,14 @@ pub const COLUMN_INFO: &[ColumnInfo] = &[
|
||||
ColumnInfo { name: COLUMN_NORMAL4, data_type: DataType::Bytes, is_primary_key: false, not_null: false },
|
||||
];
|
||||
|
||||
/// change sqlite err code to asset err code
|
||||
fn from_sqlite_code_to_asset_code(value: SqliteErrCode) -> ErrCode {
|
||||
if value != SQLITE_OK && value != SQLITE_DONE {
|
||||
asset_log::loge!("error ret {}", value);
|
||||
}
|
||||
ErrCode::SqliteError
|
||||
}
|
||||
|
||||
/// do same operation in backup database when do something in master db
|
||||
/// TODO backup every success operation or only when charge idle?
|
||||
fn back_db_when_succ<T, F: Fn(&Table) -> Result<T, SqliteErrCode>>(
|
||||
@ -359,7 +365,7 @@ fn open_default_table<'a>(db: &'a mut Database) -> Result<Option<Table<'a>>, Err
|
||||
},
|
||||
Err(e) => {
|
||||
if is_db_corrupt(e) {
|
||||
let _ = sqlite3_close_wrap(db.v2, db.handle);
|
||||
let _ = sqlite3_close_wrap(db.handle);
|
||||
// recovery master db
|
||||
let r_ret = copy_db_file(db, true);
|
||||
if r_ret.is_err() {
|
||||
@ -454,8 +460,8 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
|
||||
impl<'a> DefaultDatabaseHelper<'a> {
|
||||
/// open default database and table
|
||||
pub fn open_default_database_table(userid: i32) -> Result<DefaultDatabaseHelper<'a>, ErrCode> {
|
||||
let mut db = Database::default_new(userid).map_err(from_sqlite_code_to_asset_code)?;
|
||||
pub fn open_default_database_table(user_id: i32) -> Result<DefaultDatabaseHelper<'a>, ErrCode> {
|
||||
let mut db = Database::default_new(user_id).map_err(from_sqlite_code_to_asset_code)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
match open_default_table(&mut db) {
|
||||
Ok(o) => {
|
||||
@ -472,11 +478,11 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
|
||||
/// open default database and table, if need update db version, input callback
|
||||
pub fn open_default_database_table_with_version_update(
|
||||
userid: i32,
|
||||
user_id: i32,
|
||||
version_new: u32,
|
||||
callback: UpdateDatabaseCallbackFunc,
|
||||
) -> Result<DefaultDatabaseHelper<'a>, ErrCode> {
|
||||
let mut db = Database::default_new_with_version_update(userid, version_new, callback)
|
||||
let mut db = Database::default_new_with_version_update(user_id, version_new, callback)
|
||||
.map_err(from_sqlite_code_to_asset_code)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
match open_default_table(&mut db) {
|
||||
@ -494,16 +500,16 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn update_datas_default_once(userid: i32, condition: &Condition, datas: &DbMap) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
pub fn update_datas_default_once(user_id: i32, condition: &Condition, datas: &DbMap) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.update_datas_default(condition, datas)
|
||||
}
|
||||
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn insert_datas_default_once(userid: i32, datas: &DbMap) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
pub fn insert_datas_default_once(user_id: i32, datas: &DbMap) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.insert_datas_default(datas)
|
||||
}
|
||||
@ -511,35 +517,35 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn insert_multi_datas_default_once(
|
||||
userid: i32,
|
||||
user_id: i32,
|
||||
columns: &Vec<&'static str>,
|
||||
datas: &Vec<Vec<Value>>,
|
||||
) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.insert_multi_datas_default(columns, datas)
|
||||
}
|
||||
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn delete_datas_default_once(userid: i32, cond: &Condition) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
pub fn delete_datas_default_once(user_id: i32, cond: &Condition) -> Result<i32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.delete_datas_default(cond)
|
||||
}
|
||||
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn is_data_exists_default_once(userid: i32, condition: &Condition) -> Result<bool, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
pub fn is_data_exists_default_once(user_id: i32, condition: &Condition) -> Result<bool, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.is_data_exists_default(condition)
|
||||
}
|
||||
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn select_count_default_once(userid: i32, condition: &Condition) -> Result<u32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
pub fn select_count_default_once(user_id: i32, condition: &Condition) -> Result<u32, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.select_count_default(condition)
|
||||
}
|
||||
@ -547,11 +553,11 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn query_datas_default_once(
|
||||
userid: i32,
|
||||
user_id: i32,
|
||||
condition: &Condition,
|
||||
query_options: Option<&QueryOptions>,
|
||||
) -> Result<ResultSet, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.query_datas_default(condition, query_options)
|
||||
}
|
||||
@ -559,12 +565,12 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
/// see TableHelper
|
||||
#[inline(always)]
|
||||
pub fn query_columns_default_once(
|
||||
userid: i32,
|
||||
user_id: i32,
|
||||
columns: &Vec<&'static str>,
|
||||
condition: &Condition,
|
||||
query_options: Option<&QueryOptions>,
|
||||
) -> Result<Vec<DbMap>, ErrCode> {
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(userid)?;
|
||||
let db = DefaultDatabaseHelper::open_default_database_table(user_id)?;
|
||||
let _lock = db.file.mtx.lock().unwrap();
|
||||
db.query_columns_default(columns, condition, query_options)
|
||||
}
|
||||
@ -578,8 +584,8 @@ impl<'a> DefaultDatabaseHelper<'a> {
|
||||
/// do transaction
|
||||
/// if commit, return true
|
||||
/// if rollback, return false
|
||||
pub fn do_transaction<F: Fn(&Database) -> bool>(userid: i32, callback: F) -> Result<bool, ErrCode> {
|
||||
let db = match DefaultDatabaseHelper::open_default_database_table(userid) {
|
||||
pub fn do_transaction<F: Fn(&Database) -> bool>(user_id: i32, callback: F) -> Result<bool, ErrCode> {
|
||||
let db = match DefaultDatabaseHelper::open_default_database_table(user_id) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
loge!("transaction open db fail");
|
||||
|
@ -19,9 +19,6 @@
|
||||
pub mod database;
|
||||
#[path = "database_table_helper.rs"]
|
||||
pub mod database_table_helper;
|
||||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
#[path = "sqlite3_ffi.rs"]
|
||||
mod sqlite3_ffi;
|
||||
#[path = "statement.rs"]
|
||||
pub mod statement;
|
||||
#[path = "table.rs"]
|
||||
@ -30,4 +27,3 @@ pub mod table;
|
||||
pub mod transaction;
|
||||
#[path = "types.rs"]
|
||||
pub mod types;
|
||||
pub use sqlite3_ffi::*;
|
||||
|
File diff suppressed because it is too large
Load Diff
123
services/db_operator/src/sqlite3_wrapper.c
Normal file
123
services/db_operator/src/sqlite3_wrapper.c
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sqlite3sym.h"
|
||||
|
||||
int SqliteOpen(const char *fileName, void **ppDb)
|
||||
{
|
||||
return sqlite3_open(fileName, (sqlite3 **)ppDb);
|
||||
}
|
||||
|
||||
int SqliteCloseV2(void *db)
|
||||
{
|
||||
return sqlite3_close_v2((sqlite3 *)db);
|
||||
}
|
||||
|
||||
int SqliteExec(void *db, const char *zSql, sqlite3_callback xCallback, void *pArg, char **pzErrMsg)
|
||||
{
|
||||
return sqlite3_exec((sqlite3 *)db, zSql, xCallback, pArg, pzErrMsg);
|
||||
}
|
||||
|
||||
int SqliteFinalize(void *pStmt)
|
||||
{
|
||||
return sqlite3_finalize((sqlite3_stmt *)pStmt);
|
||||
}
|
||||
|
||||
void SqliteFree(void *p)
|
||||
{
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
int SqliteChanges(void *db)
|
||||
{
|
||||
return sqlite3_changes((sqlite3 *)db);
|
||||
}
|
||||
|
||||
int SqlitePrepareV2(void *db, const char *zSql, int nByte, void **ppStmt, const char **pzTail)
|
||||
{
|
||||
return sqlite3_prepare_v2((sqlite3 *)db, zSql, nByte, (sqlite3_stmt **)ppStmt, pzTail);
|
||||
}
|
||||
|
||||
int SqliteBindBlob(void *pStmt, int index, const void *zData, int nData, void(*xDel)(void*))
|
||||
{
|
||||
return sqlite3_bind_blob((sqlite3_stmt *)pStmt, index, zData, nData, xDel);
|
||||
}
|
||||
|
||||
int SqliteBindInt64(void *pStmt, int index, int64_t iValue)
|
||||
{
|
||||
return sqlite3_bind_int64((sqlite3_stmt *)pStmt, index, iValue);
|
||||
}
|
||||
|
||||
const char *SqliteErrMsg(void *db)
|
||||
{
|
||||
return sqlite3_errmsg((sqlite3 *)db);
|
||||
}
|
||||
|
||||
int SqliteStep(void *pStmt)
|
||||
{
|
||||
return sqlite3_step((sqlite3_stmt *)pStmt);
|
||||
}
|
||||
|
||||
int SqliteColumnCount(void *pStmt)
|
||||
{
|
||||
return sqlite3_column_count((sqlite3_stmt *)pStmt);
|
||||
}
|
||||
|
||||
const char *SqliteColumnName(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_name((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
int SqliteDataCount(void *pStmt)
|
||||
{
|
||||
return sqlite3_data_count((sqlite3_stmt *)pStmt);
|
||||
}
|
||||
|
||||
const void *SqliteColumnBlob(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_blob((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
int SqliteColumnInt(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_int((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
int64_t SqliteColumnInt64(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_int64((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
const unsigned char *SqliteColumnText(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_text((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
int SqliteColumnBytes(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_bytes((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
int SqliteColumnType(void *pStmt, int col)
|
||||
{
|
||||
return sqlite3_column_type((sqlite3_stmt *)pStmt, col);
|
||||
}
|
||||
|
||||
int SqliteReset(void *pStmt)
|
||||
{
|
||||
return sqlite3_reset((sqlite3_stmt *)pStmt);
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
//! sqlite statement impl, support two types of statement: exec and prepare
|
||||
//! statement is auto drop by RAII
|
||||
|
||||
use core::ffi::c_void;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::Write;
|
||||
|
||||
@ -23,13 +24,38 @@ use asset_definition::{DataType, Value};
|
||||
use asset_log::loge;
|
||||
|
||||
use crate::{
|
||||
database::Database, sqlite3_bind_blob_func, sqlite3_bind_int64_func, sqlite3_column_blob_func,
|
||||
sqlite3_column_bytes_func, sqlite3_column_count_func, sqlite3_column_double_func, sqlite3_column_int64_func,
|
||||
sqlite3_column_name_func, sqlite3_column_text_func, sqlite3_column_type_func, sqlite3_data_count_func,
|
||||
sqlite3_finalize_func, sqlite3_prepare_v2_func, sqlite3_reset_func, sqlite3_step_func, Sqlite3Callback,
|
||||
SqliteErrCode, SQLITE_BLOB, SQLITE_ERROR, SQLITE_INTEGER, SQLITE_NULL, SQLITE_OK,
|
||||
database::Database,
|
||||
types::{Sqlite3Callback, SqliteErrCode, SQLITE_ERROR, SQLITE_OK},
|
||||
};
|
||||
|
||||
type BindCallback = extern "C" fn(p: *mut c_void);
|
||||
extern "C" {
|
||||
fn SqliteFinalize(stmt: *mut c_void) -> i32;
|
||||
fn SqlitePrepareV2(
|
||||
db: *mut c_void,
|
||||
z_sql: *const u8,
|
||||
n_byte: i32,
|
||||
pp_stmt: *mut *mut c_void,
|
||||
pz_tail: *mut *mut u8,
|
||||
) -> i32;
|
||||
fn SqliteBindBlob(stmt: *mut c_void, index: i32, blob: *const u8, n: i32, callback: Option<BindCallback>) -> i32;
|
||||
fn SqliteBindInt64(stmt: *mut c_void, index: i32, value: i64) -> i32;
|
||||
fn SqliteStep(stmt: *mut c_void) -> i32;
|
||||
fn SqliteColumnCount(stmt: *mut c_void) -> i32;
|
||||
fn SqliteColumnName(stmt: *mut c_void, n: i32) -> *const u8;
|
||||
fn SqliteDataCount(stmt: *mut c_void) -> i32;
|
||||
fn SqliteColumnBlob(stmt: *mut c_void, i_col: i32) -> *const u8;
|
||||
fn SqliteColumnInt64(stmt: *mut c_void, i_col: i32) -> i64;
|
||||
fn SqliteColumnText(stmt: *mut c_void, i_col: i32) -> *const u8;
|
||||
fn SqliteColumnBytes(stmt: *mut c_void, i_col: i32) -> i32;
|
||||
fn SqliteColumnType(stmt: *mut c_void, i_col: i32) -> i32;
|
||||
fn SqliteReset(stmt: *mut c_void) -> i32;
|
||||
}
|
||||
|
||||
const SQLITE_INTEGER: i32 = 1;
|
||||
const SQLITE_BLOB: i32 = 4;
|
||||
const SQLITE_NULL: i32 = 5;
|
||||
|
||||
/// sql statement
|
||||
#[repr(C)]
|
||||
pub struct Statement<'b, const PREPARE: bool> {
|
||||
@ -61,7 +87,7 @@ impl<'b> Statement<'b, true> {
|
||||
/// wrap for sqlite3_step,
|
||||
/// if step succ, will return SQLITE_DONE for update,insert,delete or SQLITE_ROW for select
|
||||
pub fn step(&self) -> SqliteErrCode {
|
||||
sqlite3_step_func(self.handle)
|
||||
unsafe { SqliteStep(self.handle as _) }
|
||||
}
|
||||
|
||||
/// prepare a sql, you can use '?' for datas and bind datas later
|
||||
@ -70,7 +96,15 @@ impl<'b> Statement<'b, true> {
|
||||
let mut sql_s = sql.to_string();
|
||||
sql_s.push('\0');
|
||||
let mut stmt = Statement { sql: sql_s, db, handle: 0 };
|
||||
let ret = sqlite3_prepare_v2_func(db.handle, &stmt.sql, -1, &mut stmt.handle, &mut tail);
|
||||
let ret = unsafe {
|
||||
SqlitePrepareV2(
|
||||
db.handle as _,
|
||||
stmt.sql.as_ptr(),
|
||||
-1,
|
||||
&mut stmt.handle as *mut usize as _,
|
||||
&mut tail as *mut usize as _,
|
||||
)
|
||||
};
|
||||
if ret == 0 {
|
||||
Ok(stmt)
|
||||
} else {
|
||||
@ -94,32 +128,32 @@ impl<'b> Statement<'b, true> {
|
||||
match data {
|
||||
Value::Bytes(b) => {
|
||||
Self::print_vec(index, b);
|
||||
sqlite3_bind_blob_func(self.handle, index, b, b.len() as _, None)
|
||||
unsafe { SqliteBindBlob(self.handle as _, index, b.as_ptr(), b.len() as _, None) }
|
||||
},
|
||||
Value::Number(i) => {
|
||||
loge!("[YZT] index = {}, bind integer = {}", index, i);
|
||||
sqlite3_bind_int64_func(self.handle, index, *i as _)
|
||||
unsafe { SqliteBindInt64(self.handle as _, index, *i as _) }
|
||||
},
|
||||
Value::Bool(b) => {
|
||||
loge!("[YZT] index = {}, bind bool = {}", index, b);
|
||||
sqlite3_bind_int64_func(self.handle, index, *b as _)
|
||||
unsafe { SqliteBindInt64(self.handle as _, index, *b as _) }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// you should reset statement before bind data for insert statement
|
||||
pub fn reset(&self) -> SqliteErrCode {
|
||||
sqlite3_reset_func(self.handle)
|
||||
unsafe { SqliteReset(self.handle as _) }
|
||||
}
|
||||
|
||||
/// get column count for select statement
|
||||
pub fn column_count(&self) -> i32 {
|
||||
sqlite3_column_count_func(self.handle)
|
||||
unsafe { SqliteColumnCount(self.handle as _) }
|
||||
}
|
||||
|
||||
/// return the column name
|
||||
pub fn query_column_name(&self, n: i32) -> Result<&str, SqliteErrCode> {
|
||||
let s = sqlite3_column_name_func(self.handle, n);
|
||||
let s = unsafe { SqliteColumnName(self.handle as _, n) };
|
||||
if !s.is_null() {
|
||||
let name = unsafe { CStr::from_ptr(s as _) };
|
||||
return Ok(name.to_str().unwrap());
|
||||
@ -129,7 +163,7 @@ impl<'b> Statement<'b, true> {
|
||||
|
||||
/// data count
|
||||
pub fn data_count(&self) -> i32 {
|
||||
sqlite3_data_count_func(self.handle)
|
||||
unsafe { SqliteDataCount(self.handle as _) }
|
||||
}
|
||||
|
||||
/// query column datas in result set
|
||||
@ -172,27 +206,21 @@ impl<'b> Statement<'b, true> {
|
||||
/// query column datas in result set for blob data
|
||||
/// the index is start with 0
|
||||
pub fn query_column_blob(&self, index: i32) -> &'b [u8] {
|
||||
let blob = sqlite3_column_blob_func(self.handle, index);
|
||||
let blob = unsafe { SqliteColumnBlob(self.handle as _, index) };
|
||||
let len = self.column_bytes(index);
|
||||
unsafe { core::slice::from_raw_parts(blob, len as _) }
|
||||
}
|
||||
|
||||
/// query column datas in result set for double data
|
||||
/// the index is start with 0
|
||||
pub fn query_column_double(&self, index: i32) -> f64 {
|
||||
sqlite3_column_double_func(self.handle, index)
|
||||
}
|
||||
|
||||
/// query column datas in result set for int data
|
||||
/// the index is start with 0
|
||||
pub fn query_column_int(&self, index: i32) -> u32 {
|
||||
sqlite3_column_int64_func(self.handle, index) as u32
|
||||
unsafe { SqliteColumnInt64(self.handle as _, index) as u32 }
|
||||
}
|
||||
|
||||
/// query column datas in result set for text data
|
||||
/// the index is start with 0
|
||||
pub fn query_column_text(&self, index: i32) -> &'b [u8] {
|
||||
let text = sqlite3_column_text_func(self.handle, index);
|
||||
let text = unsafe { SqliteColumnText(self.handle as _, index) };
|
||||
let len = self.column_bytes(index);
|
||||
unsafe { core::slice::from_raw_parts(text, len as _) }
|
||||
}
|
||||
@ -200,12 +228,12 @@ impl<'b> Statement<'b, true> {
|
||||
/// return the bytes of data, you should first call query_column_text or query_column_blob,
|
||||
/// then call column_bytes.
|
||||
pub fn column_bytes(&self, index: i32) -> i32 {
|
||||
sqlite3_column_bytes_func(self.handle, index)
|
||||
unsafe { SqliteColumnBytes(self.handle as _, index) }
|
||||
}
|
||||
|
||||
/// return column data_type
|
||||
pub fn column_type(&self, index: i32) -> i32 {
|
||||
sqlite3_column_type_func(self.handle, index)
|
||||
unsafe { SqliteColumnType(self.handle as _, index) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +243,7 @@ impl<'b, const PREPARE: bool> Drop for Statement<'b, PREPARE> {
|
||||
return;
|
||||
}
|
||||
if self.handle != 0 {
|
||||
let ret = sqlite3_finalize_func(self.handle);
|
||||
let ret = unsafe { SqliteFinalize(self.handle as _) };
|
||||
if ret != SQLITE_OK {
|
||||
loge!("sqlite3 finalize fail ret {}", ret);
|
||||
}
|
||||
|
@ -18,20 +18,24 @@
|
||||
//! the data can be from user input, we will prepare and bind data.
|
||||
//! table is auto drop by RAII
|
||||
|
||||
use core::ffi::c_void;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::{
|
||||
database::Database,
|
||||
sqlite3_changes_func,
|
||||
statement::Statement,
|
||||
types::{
|
||||
from_data_type_to_str, from_data_value_to_str_value, ColumnInfo, Condition, DbMap, QueryOptions, ResultSet,
|
||||
SqliteErrCode, SQLITE_DONE, SQLITE_ERROR, SQLITE_OK, SQLITE_ROW,
|
||||
},
|
||||
SqliteErrCode, SQLITE_DONE, SQLITE_ERROR, SQLITE_OK, SQLITE_ROW,
|
||||
};
|
||||
|
||||
use asset_definition::{DataType, Value};
|
||||
|
||||
extern "C" {
|
||||
fn SqliteChanges(db: *mut c_void) -> i32;
|
||||
}
|
||||
|
||||
/// a database table
|
||||
#[repr(C)]
|
||||
pub struct Table<'a> {
|
||||
@ -206,7 +210,7 @@ impl<'a> Table<'a> {
|
||||
if ret != SQLITE_DONE {
|
||||
return Err(ret);
|
||||
}
|
||||
let count = sqlite3_changes_func(self.db.handle);
|
||||
let count = unsafe { SqliteChanges(self.db.handle as _) };
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
@ -240,7 +244,7 @@ impl<'a> Table<'a> {
|
||||
if ret != SQLITE_DONE {
|
||||
return Err(ret);
|
||||
}
|
||||
let count = sqlite3_changes_func(self.db.handle);
|
||||
let count = unsafe { SqliteChanges(self.db.handle as _) };
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
@ -269,7 +273,7 @@ impl<'a> Table<'a> {
|
||||
if ret != SQLITE_DONE {
|
||||
return Err(ret);
|
||||
}
|
||||
let count = sqlite3_changes_func(self.db.handle);
|
||||
let count = unsafe { SqliteChanges(self.db.handle as _) };
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
@ -291,7 +295,7 @@ impl<'a> Table<'a> {
|
||||
if ret != SQLITE_DONE {
|
||||
return Err(ret);
|
||||
}
|
||||
let count = sqlite3_changes_func(self.db.handle);
|
||||
let count = unsafe { SqliteChanges(self.db.handle as _) };
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,11 @@
|
||||
//! for db transaction, support closure.
|
||||
//! transaction is auto rollback if not commit by RAII.
|
||||
|
||||
use super::*;
|
||||
use crate::{database::Database, statement::Statement};
|
||||
use crate::{
|
||||
database::Database,
|
||||
statement::Statement,
|
||||
types::{SqliteErrCode, SQLITE_ERROR, SQLITE_OK},
|
||||
};
|
||||
|
||||
/// Transaction for sqlite db
|
||||
#[repr(C)]
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
//! struct types for db
|
||||
|
||||
use core::ffi::c_void;
|
||||
use std::{cmp::Ordering, collections::HashMap};
|
||||
|
||||
use asset_definition::{DataType, Value};
|
||||
@ -84,3 +85,20 @@ pub struct QueryOptions {
|
||||
/// order by columns
|
||||
pub order_by: Option<Vec<&'static str>>,
|
||||
}
|
||||
|
||||
/// sqlite error type
|
||||
pub type SqliteErrCode = i32;
|
||||
/// Successful result
|
||||
pub const SQLITE_OK: i32 = 0;
|
||||
/// Generic error
|
||||
pub const SQLITE_ERROR: i32 = 1;
|
||||
/// sqlite3_step() has another row ready
|
||||
pub const SQLITE_ROW: i32 = 100;
|
||||
/// sqlite3_step() has finished executing
|
||||
pub const SQLITE_DONE: i32 = 101;
|
||||
/// data: pointer passed by sqlite3_exec
|
||||
/// argc: count of ResultSet
|
||||
/// argv: Result
|
||||
/// az_col_name: Column names
|
||||
pub(crate) type Sqlite3Callback =
|
||||
extern "C" fn(data: *mut c_void, argc: i32, argv: *const *const u8, az_col_name: *const *const u8) -> SqliteErrCode;
|
||||
|
@ -154,7 +154,6 @@ fn test_hukkey_decrypt() {
|
||||
let _ = secret_key.delete();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn test_crypto_init() {
|
||||
@ -180,4 +179,4 @@ fn test_crypto_init() {
|
||||
},
|
||||
};
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
@ -23,8 +23,7 @@ use asset_db_operator::{
|
||||
database::*,
|
||||
database_table_helper::{do_transaction, DefaultDatabaseHelper, ASSET_TABLE_NAME, COLUMN_ALIAS, COLUMN_OWNER},
|
||||
statement::Statement,
|
||||
types::{from_data_value_to_str_value, ColumnInfo, DbMap, QueryOptions},
|
||||
SQLITE_DONE, SQLITE_OK, SQLITE_OPEN_CREATE, SQLITE_OPEN_READWRITE, SQLITE_ROW,
|
||||
types::{from_data_value_to_str_value, ColumnInfo, DbMap, QueryOptions, SQLITE_DONE, SQLITE_OK, SQLITE_ROW},
|
||||
};
|
||||
use asset_definition::{DataType, Value};
|
||||
|
||||
@ -46,32 +45,6 @@ pub fn test_for_sqlite3_open() {
|
||||
},
|
||||
};
|
||||
let _ = fs::create_dir("db");
|
||||
|
||||
let _ = match Database::new_v2("db/test.db", SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, None) {
|
||||
Ok(o) => o,
|
||||
Err(ret) => {
|
||||
panic!("test sqlite3 open fail ret {}", ret);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_for_sqlite3_v2_open() {
|
||||
let _ = match Database::new_v2("test_v2.db", SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, None) {
|
||||
Ok(o) => o,
|
||||
Err(ret) => {
|
||||
panic!("test sqlite3 open fail ret {}", ret);
|
||||
},
|
||||
};
|
||||
|
||||
match Database::new_v2("/root/test_v2.db", SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, Some(b"unix-dotfile")) {
|
||||
Ok(_) => {
|
||||
panic!("read root");
|
||||
},
|
||||
Err(ret) => {
|
||||
println!("expected fault {}", ret);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1004,8 +977,8 @@ pub fn test_for_update_ver() {
|
||||
assert!(db4.is_err());
|
||||
}
|
||||
|
||||
pub fn test_for_default_asset(userid: i32) {
|
||||
// let _ = Database::drop_default_database(userid);
|
||||
pub fn test_for_default_asset(user_id: i32) {
|
||||
// let _ = Database::drop_default_database(user_id);
|
||||
let mut def = DbMap::from([
|
||||
("Secret", Value::Bytes(b"blob".to_vec())),
|
||||
("OwnerType", Value::Number(1)),
|
||||
@ -1021,17 +994,17 @@ pub fn test_for_default_asset(userid: i32) {
|
||||
(COLUMN_ALIAS, Value::Bytes(b"Alias1".to_vec())),
|
||||
]);
|
||||
|
||||
let count = DefaultDatabaseHelper::insert_datas_default_once(userid, &def).unwrap();
|
||||
let count = DefaultDatabaseHelper::insert_datas_default_once(user_id, &def).unwrap();
|
||||
assert_eq!(count, 1);
|
||||
|
||||
def.remove(COLUMN_ALIAS);
|
||||
def.insert(COLUMN_ALIAS, Value::Bytes(b"Alias2".to_vec()));
|
||||
|
||||
let count = DefaultDatabaseHelper::insert_datas_default_once(userid, &def).unwrap();
|
||||
let count = DefaultDatabaseHelper::insert_datas_default_once(user_id, &def).unwrap();
|
||||
assert_eq!(count, 1);
|
||||
|
||||
let count = DefaultDatabaseHelper::update_datas_default_once(
|
||||
userid,
|
||||
user_id,
|
||||
&DbMap::from([("Owner", Value::Bytes(b"owner1".to_vec())), ("Alias", Value::Bytes(b"Alias1".to_vec()))]),
|
||||
&DbMap::from([("UpdateTime", Value::Number(1))]),
|
||||
)
|
||||
@ -1039,13 +1012,13 @@ pub fn test_for_default_asset(userid: i32) {
|
||||
assert!(count >= 0);
|
||||
|
||||
let _count = DefaultDatabaseHelper::select_count_default_once(
|
||||
userid,
|
||||
user_id,
|
||||
&DbMap::from([(COLUMN_OWNER, Value::Bytes(b"owner1".to_vec()))]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let _ret = DefaultDatabaseHelper::is_data_exists_default_once(
|
||||
userid,
|
||||
user_id,
|
||||
&DbMap::from([
|
||||
(COLUMN_OWNER, Value::Bytes(b"owner1".to_vec())),
|
||||
(COLUMN_ALIAS, Value::Bytes(b"Alias2".to_vec())),
|
||||
@ -1054,7 +1027,7 @@ pub fn test_for_default_asset(userid: i32) {
|
||||
.unwrap();
|
||||
|
||||
let count = DefaultDatabaseHelper::delete_datas_default_once(
|
||||
userid,
|
||||
user_id,
|
||||
&DbMap::from([
|
||||
(COLUMN_OWNER, Value::Bytes(b"owner1".to_vec())),
|
||||
(COLUMN_ALIAS, Value::Bytes(b"Alias1".to_vec())),
|
||||
@ -1071,7 +1044,7 @@ pub fn test_for_default_asset(userid: i32) {
|
||||
};
|
||||
|
||||
let result = DefaultDatabaseHelper::query_datas_default_once(
|
||||
userid,
|
||||
user_id,
|
||||
&DbMap::from([
|
||||
(COLUMN_OWNER, Value::Bytes(b"owner1".to_vec())),
|
||||
(COLUMN_ALIAS, Value::Bytes(b"Alias2".to_vec())),
|
||||
@ -1088,7 +1061,7 @@ pub fn test_for_default_asset(userid: i32) {
|
||||
}
|
||||
|
||||
let result = DefaultDatabaseHelper::query_columns_default_once(
|
||||
userid,
|
||||
user_id,
|
||||
&vec!["Id", "Alias"],
|
||||
&DbMap::from([
|
||||
(COLUMN_OWNER, Value::Bytes(b"owner1".to_vec())),
|
||||
@ -1103,7 +1076,7 @@ pub fn test_for_default_asset(userid: i32) {
|
||||
}
|
||||
println!();
|
||||
}
|
||||
// let db = DefaultDatabaseHelper::open_default_database_table(userid).unwrap();
|
||||
// let db = DefaultDatabaseHelper::open_default_database_table(user_id).unwrap();
|
||||
// let _ = db.drop_database_and_backup();
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use asset_sdk::{
|
||||
AssetMap, AuthType, ConflictResolution, Insert, Tag, Value, ErrCode
|
||||
};
|
||||
use asset_sdk::{AssetMap, AuthType, ConflictResolution, ErrCode, Insert, Tag, Value};
|
||||
|
||||
use crate::common::{get_bytes, get_number, remove_by_alias, query_attr_by_alias};
|
||||
use crate::common::{get_bytes, get_number, query_attr_by_alias, remove_by_alias};
|
||||
|
||||
#[test]
|
||||
fn add_values_match_query() {
|
||||
@ -47,10 +45,8 @@ fn add_conflict_throw_error() {
|
||||
let alias = "add_conflict_throw_error".as_bytes();
|
||||
let secret = "add_conflict_throw_error_secret".as_bytes();
|
||||
|
||||
let mut add_throw_error = AssetMap::from([
|
||||
(Tag::Alias, Value::Bytes(alias.to_owned())),
|
||||
(Tag::Secret, Value::Bytes(secret.to_owned())),
|
||||
]);
|
||||
let mut add_throw_error =
|
||||
AssetMap::from([(Tag::Alias, Value::Bytes(alias.to_owned())), (Tag::Secret, Value::Bytes(secret.to_owned()))]);
|
||||
asset_sdk::Manager::build().unwrap().add(&add_throw_error).unwrap();
|
||||
|
||||
assert_eq!(Err(ErrCode::Duplicated), asset_sdk::Manager::build().unwrap().add(&add_throw_error));
|
||||
@ -86,4 +82,4 @@ fn add_conflict_over_write() {
|
||||
assert_eq!(label_normal_1, *get_bytes(&res[0], Tag::DataLabelNormal1).unwrap());
|
||||
|
||||
remove_by_alias(alias).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -13,20 +13,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use asset_sdk::{
|
||||
AssetMap, Tag, Value, ErrCode, Result, ReturnType
|
||||
};
|
||||
use asset_sdk::{AssetMap, ErrCode, Result, ReturnType, Tag, Value};
|
||||
|
||||
pub(crate) fn get_bytes(input: &AssetMap, tag: Tag) -> Result<&Vec<u8>> {
|
||||
if let Some(Value::Bytes(bytes)) = input.get(&tag) {
|
||||
return Ok(bytes)
|
||||
return Ok(bytes);
|
||||
}
|
||||
Err(ErrCode::NotFound)
|
||||
}
|
||||
|
||||
pub(crate) fn get_number(input: &AssetMap, tag: Tag) -> Result<u32> {
|
||||
if let Some(Value::Number(num)) = input.get(&tag) {
|
||||
return Ok(*num)
|
||||
return Ok(*num);
|
||||
}
|
||||
Err(ErrCode::NotFound)
|
||||
}
|
||||
@ -61,4 +59,4 @@ pub(crate) fn add_default_asset(alias: &[u8], secret: &[u8]) -> Result<()> {
|
||||
(Tag::Alias, Value::Bytes(alias.to_vec())),
|
||||
(Tag::Secret, Value::Bytes(secret.to_vec())),
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use asset_sdk::{
|
||||
AssetMap, Tag, ErrCode, Value
|
||||
};
|
||||
use asset_sdk::{AssetMap, ErrCode, Tag, Value};
|
||||
|
||||
use crate::common::remove_by_alias;
|
||||
|
||||
@ -26,9 +24,8 @@ fn remove_alias_non_exist() {
|
||||
|
||||
#[test]
|
||||
fn remove_condition_non_exist() {
|
||||
let delete_condition = AssetMap::from([
|
||||
(Tag::DataLabelCritical1, Value::Bytes("remove_condition_non_exist".as_bytes().to_vec())),
|
||||
]);
|
||||
let delete_condition =
|
||||
AssetMap::from([(Tag::DataLabelCritical1, Value::Bytes("remove_condition_non_exist".as_bytes().to_vec()))]);
|
||||
assert_eq!(Err(ErrCode::NotFound), asset_sdk::Manager::build().unwrap().remove(&delete_condition));
|
||||
}
|
||||
|
||||
@ -53,11 +50,9 @@ fn remove_condition_exist_and_query() {
|
||||
fn remove_condition_with_secret() {
|
||||
let alias = "remove_condition_with_secret".as_bytes();
|
||||
let secret = "remove_condition_with_secret".as_bytes();
|
||||
let condition = AssetMap::from([
|
||||
(Tag::Alias, Value::Bytes(alias.to_owned())),
|
||||
(Tag::Secret, Value::Bytes(secret.to_owned())),
|
||||
]);
|
||||
let condition =
|
||||
AssetMap::from([(Tag::Alias, Value::Bytes(alias.to_owned())), (Tag::Secret, Value::Bytes(secret.to_owned()))]);
|
||||
asset_sdk::Manager::build().unwrap().add(&condition).unwrap();
|
||||
assert!(asset_sdk::Manager::build().unwrap().remove(&condition).is_err());
|
||||
remove_by_alias(alias).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,9 @@
|
||||
|
||||
use core::panic;
|
||||
|
||||
use asset_sdk::{
|
||||
AssetMap, Tag, Value, Insert
|
||||
};
|
||||
use asset_sdk::{AssetMap, Insert, Tag, Value};
|
||||
|
||||
use crate::common::{remove_by_alias, query_all_by_alias, add_default_asset, query_attr_by_alias};
|
||||
use crate::common::{add_default_asset, query_all_by_alias, query_attr_by_alias, remove_by_alias};
|
||||
|
||||
#[test]
|
||||
fn update_same_secret() {
|
||||
@ -153,4 +151,4 @@ fn update_alias() {
|
||||
assert!(asset_sdk::Manager::build().unwrap().update(&query, &update).is_err());
|
||||
|
||||
remove_by_alias(alias).unwrap();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user