use pgbatis::pgmacro::PGCRUD;
use pgbatis::Wrapper;
use pgbatis::ColumnExt;
use pgbatis::Parameters;
use pgbatis::tokio_postgres::types::ToSql;
use pgbatis::tokio_postgres::Row;
use serde::{Deserialize, Serialize};
#[derive(PGCRUD, Serialize, Deserialize, Clone, Debug, Default)]
pub struct User {
pub id: Option<String>,
pub name: Option<String>,
pub age: Option<i32>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
pgbatis::link("127.0.0.1", 5432, "postgres", "password", "mydb", 10).await?;
println!("✅ 数据库连接成功");
pgbatis::ping().await?;
println!("✅ ping 成功");
let user = User {
id: Some("u1".into()),
name: Some("Alice".into()),
age: Some(30),
};
let rows = pgbatis::save(user.clone(), None, None).await?;
println!("✅ save 成功,影响行数: {rows}");
let users = vec![
User { id: Some("u2".into()), name: Some("Bob".into()), age: Some(25) },
User { id: Some("u3".into()), name: Some("Charlie".into()), age: Some(35) },
User { id: Some("u4".into()), name: Some("Diana".into()), age: Some(28) },
User { id: Some("u5".into()), name: Some("Eve".into()), age: Some(22) },
];
for u in &users {
pgbatis::save(u.clone(), None, None).await?;
}
println!("✅ 批量 save 成功");
let update_data = User {
name: Some("Alice Updated".into()),
..Default::default()
};
let rows = pgbatis::update(
update_data,
Wrapper::new().eq(&UserColumn::Id, &"u1"),
None,
None,
)
.await?;
println!("✅ update 成功,影响行数: {rows}");
let all_users: Vec<User> = pgbatis::fetch(Wrapper::new(), None, None).await?;
println!("✅ fetch 全部用户: {} 条", all_users.len());
let adults: Vec<User> = pgbatis::fetch(
Wrapper::new().gt(&UserColumn::Age, &18),
None,
None,
)
.await?;
println!("✅ fetch 成年用户: {} 条", adults.len());
let alice: User = pgbatis::fetch_one(
Wrapper::new().eq(&UserColumn::Id, &"u1"),
None,
None,
)
.await?;
println!("✅ fetch_one: {:?}", alice);
let names: Vec<std::collections::HashMap<String, serde_json::Value>> = pgbatis::fetch_with_recoder_field::<User>(
Wrapper::new()
.set_recoder_field(&UserColumn::Id)
.set_recoder_field(&UserColumn::Name),
None,
None,
)
.await?;
println!("✅ fetch_with_recoder_field(仅 id+name): {names:?}");
let page = pgbatis::fetch_page::<User>(
Wrapper::new()
.set_pages(1, 2) .set_order_by_column_ext(&UserColumn::Id, false), None,
None,
)
.await?;
println!(
"✅ fetch_page: 第{}/{}页,总{}条",
page.current_page, page.pages, page.total
);
for u in &page.records {
println!(" - {:?}", u);
}
let keyword = pgbatis::format_like(&Some("li".into()));
let matched: Vec<User> = pgbatis::fetch(
Wrapper::new().like(&UserColumn::Name, &keyword),
None,
None,
)
.await?;
println!("✅ LIKE 查询(含 'li'): {matched:?}");
let rows = pgbatis::query(
"SELECT name, age FROM users WHERE age > $1 ORDER BY age DESC",
&[&20],
)
.await?;
println!("✅ query: {rows:?}");
let stat = pgbatis::query_one("SELECT count(*) as cnt, avg(age) as avg_age FROM users", &[])
.await?;
println!("✅ query_one: {stat:?}");
let page = pgbatis::query_page(
"SELECT id, name, age FROM users",
&[],
"age",
true, 1,
3,
)
.await?;
println!("✅ query_page: 总{}条,当前页{}条", page.total, page.records.len());
let typed_users: Vec<User> = pgbatis::query_t::<User>(
"SELECT id, name, age FROM users WHERE age < $1",
&[&30],
)
.await?;
println!("✅ query_t: {} 条", typed_users.len());
let rows = pgbatis::execute(
&"UPDATE users SET age = $1 WHERE id = $2".to_string(),
&[&99, &"u1"],
)
.await?;
println!("✅ execute: {rows} 行");
let exists = pgbatis::check_row_by_column("users", &UserColumn::Name, "Alice Updated").await?;
println!("✅ check_row_by_column: Alice 存在? {exists}");
let exists = pgbatis::check_row_wrap::<User>(
Wrapper::new().eq(&UserColumn::Id, &"u99"),
None,
None,
)
.await?;
println!("✅ check_row_wrap: u99 存在? {exists}");
let mid_age: Vec<User> = pgbatis::fetch(
Wrapper::new()
.between(&UserColumn::Age, &25, &35)
.set_order_by_column_ext(&UserColumn::Age, false),
None,
None,
)
.await?;
println!("✅ between 25~35: {mid_age:?}");
let targets: Vec<User> = pgbatis::fetch(
Wrapper::new().in_array_string(
&UserColumn::Id,
&vec!["u2".into(), "u3".into(), "u4".into()],
),
None,
None,
)
.await?;
println!("✅ in_array_string: {targets:?}");
let rows = pgbatis::remove::<User>(
Wrapper::new().eq(&UserColumn::Id, &"u5"),
None,
None,
)
.await?;
println!("✅ remove(软删除)u5,影响: {rows} 行");
let after_delete: Vec<User> = pgbatis::fetch(Wrapper::new(), None, None).await?;
println!(" 删除后剩余: {} 条(u5 已被过滤)", after_delete.len());
let rows = pgbatis::permanent_deletion::<User>(
Wrapper::new().eq(&UserColumn::Id, &"u4"),
None,
None,
)
.await?;
println!("✅ permanent_deletion u4,影响: {rows} 行");
pgbatis::set_unlogic_delete_table("sys_log");
let new_users = vec![
User { id: Some("t1".into()), name: Some("Tx1".into()), age: Some(10) },
User { id: Some("t2".into()), name: Some("Tx2".into()), age: Some(20) },
];
pgbatis::transaction_delete_and_save(
&UserColumn::Id,
&"u1",
new_users,
None,
None,
)
.await?;
println!("✅ transaction_delete_and_save 成功");
use pgbatis::TransactionBatchParam;
let params = vec![
TransactionBatchParam {
statement_sql: "UPDATE users SET age = $1 WHERE id = $2",
params: vec![&50, &"t1"],
},
TransactionBatchParam {
statement_sql: "UPDATE users SET age = $1 WHERE id = $2",
params: vec![&60, &"t2"],
},
];
pgbatis::transaction_batch(params).await?;
println!("✅ transaction_batch 成功");
let final_users: Vec<User> = pgbatis::fetch(
Wrapper::new().set_order_by_column_ext(&UserColumn::Id, false),
None,
None,
)
.await?;
println!("\n🎉 最终用户列表:");
for u in &final_users {
println!(" {:?}", u);
}
Ok(())
}