#[macro_export]
macro_rules! crud {
($table:ty{}) => {
$crate::crud!($table {}, "");
};
($table:ty{},$table_name:expr) => {
impl $table {
pub async fn insert_batch(
executor: &dyn $crate::executor::Executor,
tables: &[$table],
batch_size: u64,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error> {
use $crate::crud_traits::ColumnSet;
#[$crate::py_sql(
"`insert into ${table_name} `
trim ',':
bind columns = tables.column_sets():
for idx,table in tables:
if idx == 0:
`(`
trim ',':
for _,v in columns:
${v},
`) VALUES `
(
trim ',':
for _,v in columns:
#{table[v]},
),
"
)]
async fn insert_batch(
executor: &dyn $crate::executor::Executor,
tables: &[$table],
table_name: &str,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error>
{
impled!()
}
if tables.is_empty() {
return Err($crate::rbdc::Error::from(
"insert can not insert empty array tables!",
));
}
let mut table_name = $table_name.to_string();
if table_name.is_empty() {
#[$crate::snake_name($table)]
fn snake_name() {}
table_name = snake_name();
}
let mut result = $crate::rbdc::db::ExecResult {
rows_affected: 0,
last_insert_id: rbs::Value::Null,
};
let ranges =
$crate::plugin::Page::<()>::make_ranges(tables.len() as u64, batch_size);
for (offset, limit) in ranges {
let exec_result = insert_batch(
executor,
&tables[offset as usize..limit as usize],
table_name.as_str(),
)
.await?;
result.rows_affected += exec_result.rows_affected;
result.last_insert_id = exec_result.last_insert_id;
}
Ok(result)
}
pub async fn insert(
executor: &dyn $crate::executor::Executor,
table: &$table,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error> {
<$table>::insert_batch(executor, std::slice::from_ref(table), 1).await
}
}
impl $table {
pub async fn select_by_map(
executor: &dyn $crate::executor::Executor,
mut condition: rbs::Value,
) -> std::result::Result<Vec<$table>, $crate::rbdc::Error> {
use rbatis::crud_traits::ValueOperatorSql;
let table_column = {
let mut columns = String::new();
let mut clean_map = rbs::value::map::ValueMap::with_capacity(condition.len());
for (k, v) in condition {
match k.as_str() {
Some("column") => {
columns = match v {
rbs::Value::String(s) => s.clone(),
rbs::Value::Array(arr) => {
let cols: Vec<&str> =
arr.iter().filter_map(|v| v.as_str()).collect();
if cols.is_empty() {
"*".to_string()
} else {
cols.join(", ")
}
}
_ => "*".to_string(),
};
}
_ => {
clean_map.insert(k.clone(), v.clone());
}
}
}
if columns.is_empty() {
columns = "*".to_string();
}
condition = rbs::Value::Map(clean_map);
columns
};
#[$crate::py_sql(
"`select ${table_column} from ${table_name}`
trim end=' where ':
` where `
trim ' and ': for key,item in condition:
if item == null:
continue:
if !item.is_array():
` and ${key.operator_sql()}#{item}`
if item.is_array():
` and ${key} in (`
trim ',': for _,item_array in item:
#{item_array},
`)`
"
)]
async fn select_by_map(
executor: &dyn $crate::executor::Executor,
table_name: String,
table_column: &str,
condition: &rbs::Value,
) -> std::result::Result<Vec<$table>, $crate::rbdc::Error> {
for (_, v) in condition {
if v.is_array() && v.is_empty() {
return Ok(vec![]);
}
}
impled!()
}
let mut table_name = $table_name.to_string();
if table_name.is_empty() {
#[$crate::snake_name($table)]
fn snake_name() {}
table_name = snake_name();
}
select_by_map(executor, table_name, &table_column, &condition).await
}
}
impl $table {
pub async fn update_by_map(
executor: &dyn $crate::executor::Executor,
table: &$table,
mut condition: rbs::Value,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error> {
use rbatis::crud_traits::{FilterByColumns, ValueOperatorSql};
let set_columns = {
let mut columns = rbs::Value::Null;
let mut clean_map = rbs::value::map::ValueMap::with_capacity(condition.len());
for (k, v) in condition {
match k.as_str() {
Some("column") => {
columns = match v {
rbs::Value::String(s) => {
rbs::Value::Array(vec![rbs::Value::String(s.clone())])
}
rbs::Value::Array(arr) => {
let filtered_array: Vec<rbs::Value> = arr
.iter()
.filter(|v| v.as_str().is_some())
.cloned()
.collect();
if filtered_array.is_empty() {
rbs::Value::Null
} else {
rbs::Value::Array(filtered_array)
}
}
_ => rbs::Value::Null,
};
}
_ => {
clean_map.insert(k.clone(), v.clone());
}
}
}
condition = rbs::Value::Map(clean_map);
columns
};
#[$crate::py_sql(
"`update ${table_name}
if skip_null == false:
set collection='table',skips='id',skip_null=false:
if skip_null == true:
set collection='table',skips='id':
trim end=' where ':
` where `
trim ' and ': for key,item in condition:
if item == null:
continue:
if !item.is_array():
` and ${key.operator_sql()}#{item}`
if item.is_array():
` and ${key} in (`
trim ',': for _,item_array in item:
#{item_array},
`)`
"
)]
async fn update_by_map_internal(
executor: &dyn $crate::executor::Executor,
table_name: String,
table: &rbs::Value,
condition: &rbs::Value,
skip_null: bool,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error>
{
for (_, v) in condition {
if v.is_array() && v.is_empty() {
return Ok($crate::rbdc::db::ExecResult::default());
}
}
impled!()
}
let mut table_name = $table_name.to_string();
if table_name.is_empty() {
#[$crate::snake_name($table)]
fn snake_name() {}
table_name = snake_name();
}
let table_value = rbs::value!(table);
let mut skip_null = true;
let table = if set_columns != rbs::Value::Null {
skip_null = false;
table_value.filter_by_columns(&set_columns)
} else {
table_value
};
update_by_map_internal(executor, table_name, &table, &condition, skip_null).await
}
}
impl $table {
pub async fn delete_by_map(
executor: &dyn $crate::executor::Executor,
condition: rbs::Value,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error> {
use rbatis::crud_traits::ValueOperatorSql;
#[$crate::py_sql(
"`delete from ${table_name}`
trim end=' where ':
` where `
trim ' and ': for key,item in condition:
if item == null:
continue:
if !item.is_array():
` and ${key.operator_sql()}#{item}`
if item.is_array():
` and ${key} in (`
trim ',': for _,item_array in item:
#{item_array},
`)`
"
)]
async fn delete_by_map(
executor: &dyn $crate::executor::Executor,
table_name: String,
condition: &rbs::Value,
) -> std::result::Result<$crate::rbdc::db::ExecResult, $crate::rbdc::Error>
{
for (_, v) in condition {
if v.is_array() && v.is_empty() {
return Ok($crate::rbdc::db::ExecResult::default());
}
}
impled!()
}
let mut table_name = $table_name.to_string();
if table_name.is_empty() {
#[$crate::snake_name($table)]
fn snake_name() {}
table_name = snake_name();
}
delete_by_map(executor, table_name, &condition).await
}
}
};
}
#[macro_export]
macro_rules! htmlsql_select_page {
($fn_name:ident($($param_key:ident:$param_type:ty$(,)?)*) -> $table:ty => $($html_file:expr$(,)?)*) => {
pub async fn $fn_name(executor: &dyn $crate::executor::Executor, page_request: &dyn $crate::plugin::IPageRequest, $($param_key:$param_type,)*) -> std::result::Result<$crate::plugin::Page<$table>, $crate::rbdc::Error> {
#[$crate::html_sql($($html_file,)*)]
pub async fn $fn_name(executor: &dyn $crate::executor::Executor,do_count:bool,page_no:u64,page_size:u64,$($param_key: &$param_type,)*) -> std::result::Result<rbs::Value, $crate::rbdc::Error>{
$crate::impled!()
}
let mut executor = executor;
let mut conn = None;
if executor.name().eq($crate::executor::Executor::name(executor.rb_ref())){
conn = Some(executor.rb_ref().acquire().await?);
match &conn {
Some(c) => {
executor = c;
}
None => {}
}
}
let mut total = 0;
let mut intercept = executor.rb_ref().get_intercept::<$crate::plugin::intercept_page::PageIntercept>().ok_or_else(|| $crate::rbdc::Error::from("PageIntercept not found"))?;
if page_request.do_count() {
intercept.count_ids.insert(executor.id(),$crate::plugin::PageRequest::new(page_request.page_no(), page_request.page_size()));
let total_value = $fn_name(executor, true, page_request.offset(), page_request.page_size(), $(&$param_key,)*).await?;
total = $crate::decode(total_value).unwrap_or(0);
}
intercept.select_ids.insert(executor.id(),$crate::plugin::PageRequest::new(page_request.page_no(), page_request.page_size()));
let mut page = $crate::plugin::Page::<$table>::new(page_request.page_no(), page_request.page_size(), total,vec![]);
let records_value = $fn_name(executor, false, page_request.offset(), page_request.page_size(), $(&$param_key,)*).await?;
page.records = rbs::from_value(records_value)?;
Ok(page)
}
}
}
#[macro_export]
macro_rules! pysql_select_page {
($fn_name:ident($($param_key:ident:$param_type:ty$(,)?)*) -> $table:ty => $($py_file:expr$(,)?)*) => {
pub async fn $fn_name(executor: &dyn $crate::executor::Executor, page_request: &dyn $crate::plugin::IPageRequest, $($param_key:$param_type,)*) -> std::result::Result<$crate::plugin::Page<$table>, $crate::rbdc::Error> {
#[$crate::py_sql($($py_file,)*)]
pub async fn $fn_name(executor: &dyn $crate::executor::Executor,do_count:bool,page_no:u64,page_size:u64,$($param_key: &$param_type,)*) -> std::result::Result<rbs::Value, $crate::rbdc::Error>{
$crate::impled!()
}
let mut executor = executor;
let mut conn = None;
if executor.name().eq($crate::executor::Executor::name(executor.rb_ref())){
conn = Some(executor.rb_ref().acquire().await?);
match &conn {
Some(c) => {
executor = c;
}
None => {}
}
}
let mut intercept = executor.rb_ref().get_intercept::<$crate::plugin::intercept_page::PageIntercept>().ok_or_else(|| $crate::rbdc::Error::from("PageIntercept not found"))?;
let mut total = 0;
if page_request.do_count() {
intercept.count_ids.insert(executor.id(),$crate::plugin::PageRequest::new(page_request.page_no(), page_request.page_size()));
let total_value = $fn_name(executor, true, page_request.offset(), page_request.page_size(), $(&$param_key,)*).await?;
total = $crate::decode(total_value).unwrap_or(0);
}
intercept.select_ids.insert(executor.id(),$crate::plugin::PageRequest::new(page_request.page_no(), page_request.page_size()));
let mut page = $crate::plugin::Page::<$table>::new(page_request.page_no(), page_request.page_size(), total,vec![]);
let records_value = $fn_name(executor, false, page_request.offset(), page_request.page_size(), $(&$param_key,)*).await?;
page.records = rbs::from_value(records_value)?;
Ok(page)
}
}
}
#[macro_export]
macro_rules! raw_sql {
($fn_name:ident($($param_key:ident:$param_type:ty$(,)?)*) -> $return_type:ty => $sql_file:expr) => {
#[$crate::sql($sql_file)]
pub async fn $fn_name($($param_key: $param_type,)*) -> $return_type{
impled!()
}
}
}
#[macro_export]
macro_rules! pysql {
($fn_name:ident($($param_key:ident:$param_type:ty$(,)?)*) -> $return_type:ty => $py_file:expr) => {
#[$crate::py_sql($py_file)]
pub async fn $fn_name($($param_key: $param_type,)*) -> $return_type{
impled!()
}
}
}
#[macro_export]
macro_rules! htmlsql {
($fn_name:ident($($param_key:ident:$param_type:ty$(,)?)*) -> $return_type:ty => $html_file:expr) => {
#[$crate::html_sql($html_file)]
pub async fn $fn_name($($param_key: $param_type,)*) -> $return_type{
impled!()
}
}
}