#[macro_export]
macro_rules! define_model {
($struct:ident,
$table_name:expr,
$(
$(#[$field_attr:meta])*
$column:ident : $type:ty
),* $(,)?
) => {
#[allow(unused_attributes)]
#[derive(Debug, $crate::serde::Serialize, $crate::serde::Deserialize, $crate::db_proc_macro::ToFields, $crate::db_proc_macro::ToOption, Clone)] #[cfg_attr(any(feature = "postgres", feature = "mysql", feature = "sqlite"), derive($crate::sqlx::FromRow))]
pub struct $struct {
$(
$(#[$field_attr])*
pub $column: $type,
)*
}
impl $struct {
#[allow(dead_code)]
pub const NAME: &'static str = $table_name;
#[allow(dead_code)]
pub fn update_time(&mut self) {
let now = $crate::utlis::_utc_ms_option();
$( if stringify!($column) == "updated_at" {
self.updated_at = now;
} )*
}
#[allow(dead_code)]
pub fn pg_table(schema:&str)->String{
if !schema.is_empty() {
format!("\"{}\".\"{}\"" , schema, Self::NAME)
} else {
format!("\"{}\"" , Self::NAME)
}
}
}
}
}
#[macro_export]
macro_rules! define_enum {
(
$(#[$enum_attr:meta])*
$vis:vis enum $name:ident {
$(
$(#[$variant_attr:meta])*
$variant:ident = $value:expr
),* $(,)?
}
) => {
$(#[$enum_attr])*
$vis enum $name {
$(
$(#[$variant_attr])*
$variant,
)*
}
impl $name {
pub fn to_str(&self) -> &'static str {
match self {
$(
$name::$variant => $value,
)*
}
}
}
impl ::std::str::FromStr for $name {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
$(
$value => Ok($name::$variant),
)*
_ => Err(format!("Invalid value for {}: {}", stringify!($name), s)),
}
}
}
impl $crate::serde::Serialize for $name { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::serde::Serializer,
{
let value = match self {
$(
$name::$variant => $value,
)*
};
serializer.serialize_str(value)
}
}
impl<'de> $crate::serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: $crate::serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
match s.as_str() {
$(
$value => Ok($name::$variant),
)*
_ => Err(::serde::de::Error::custom(
format!(concat!("Invalid value for ", stringify!($name), ": {}"), s))),
}
}
}
#[cfg(feature = "sqlite")]
impl<'r> $crate::sqlx::Decode<'r, $crate::sqlx::Sqlite> for $name {
fn decode(value: $crate::sqlx::sqlite::SqliteValueRef<'r>) -> Result<Self, $crate::sqlx::error::BoxDynError> {
let value_str = <String as $crate::sqlx::Decode<$crate::sqlx::Sqlite>>::decode(value)?;
$name::from_str(&value_str).map_err(|e| e.into()) }
}
#[cfg(feature = "mysql")]
impl<'r> $crate::sqlx::Decode<'r, $crate::sqlx::MySql> for $name {
fn decode(value: $crate::sqlx::mysql::MySqlValueRef<'r>) -> Result<Self, $crate::sqlx::error::BoxDynError> {
let value_str = <String as $crate::sqlx::Decode<$crate::sqlx::MySql>>::decode(value)?;
$name::from_str(&value_str).map_err(|e| e.into())
}
}
#[cfg(feature = "postgres")]
impl<'r> $crate::sqlx::Decode<'r, $crate::sqlx::Postgres> for $name {
fn decode(value: $crate::sqlx::postgres::PgValueRef<'r>) -> Result<Self, $crate::sqlx::error::BoxDynError> {
let value_str = <String as $crate::sqlx::Decode<$crate::sqlx::Postgres>>::decode(value)?;
$name::from_str(&value_str).map_err(|e| e.into())
}
}
#[cfg(feature = "sqlite")]
impl $crate::sqlx::Type<$crate::sqlx::Sqlite> for $name {
fn type_info() -> $crate::sqlx::sqlite::SqliteTypeInfo {
<String as $crate::sqlx::Type<$crate::sqlx::Sqlite>>::type_info()
}
}
#[cfg(feature = "postgres")]
impl $crate::sqlx::Type<$crate::sqlx::Postgres> for $name {
fn type_info() -> $crate::sqlx::postgres::PgTypeInfo {
<String as $crate::sqlx::Type<$crate::sqlx::Postgres>>::type_info()
}
}
#[cfg(feature = "mysql")]
impl $crate::sqlx::Type<$crate::sqlx::MySql> for $name {
fn type_info() -> $crate::sqlx::mysql::MySqlTypeInfo{
<String as $crate::sqlx::Type<$crate::sqlx::MySql>>::type_info()
}
}
};
}
#[cfg(feature = "postgres")]
#[macro_export]
macro_rules! pg_builder {
($sql:expr, [$($param:expr),* $(,)?]) => {{
use ::regex::Regex;
use ::sqlx::QueryBuilder;
let sql_str = $sql.as_ref();
let re = Regex::new(r"(\?|\$\d+)").unwrap();
let parts: Vec<&str> = re.split(sql_str).collect();
let param_count = 0 $( + { let _ = &$param; 1 } )*;
if parts.len() != param_count + 1 {panic!("参数数量与 SQL 占位符数量不匹配: 发现 {} 个占位符, 提供了 {} 个参数",parts.len() - 1, param_count ); }
let mut builder: QueryBuilder<'_, ::sqlx::postgres::Postgres> = QueryBuilder::new("");
let mut _i = 0;
$(
builder.push(parts[_i]);
builder.push_bind(&$param);
_i += 1;
)*
builder.push(parts[_i]);
builder
}};
($sql:expr, $params:expr) => {{
use ::regex::Regex;
use ::sqlx::QueryBuilder;
let sql_str = $sql.as_ref(); let re = Regex::new(r"(\?|\$\d+)").unwrap();
let parts: Vec<&str> = re.split(sql_str).collect();
let params_ref = &$params; let param_count = params_ref.len();
if parts.len() != param_count + 1 {
panic!( "参数数量与 SQL 占位符数量不匹配: 发现 {} 个占位符, 提供了 {} 个参数", parts.len() - 1, param_count);
}
let mut builder: QueryBuilder<'_, ::sqlx::postgres::Postgres> = QueryBuilder::new("");
for (i, value) in params_ref.iter().enumerate() {
builder.push(parts[i]);
builder.push_bind(&*value);
}
builder.push(parts[param_count]);
builder
}};
}
#[cfg(feature = "postgres")]
#[test]
fn dev() {
let sql = "select * from talbe where id=$1 and stre=$2";
let _b = 34;
let _aa = "adsb".to_string();
let veca = [34, 3434];
let a = pg_builder!(sql, veca);
let a = a.sql();
println!("asfd {a}");
}