2026年第一天完成purecpp社区规划的一项任务--ormpp支持链式调用了!
安全的orm链式调用API用起来与行云流水那样丝滑!
没有串拼装,编译期反射,自动拼装sql脚本,自带编译期检查,安全可靠!
ormpp已支持链式调用了!
简单查询
先根据业务实例创建数据表,然后插入两条数据,以mysql``数据库为例:
cpp
struct test_optional {
int id;
std::optional<std::string> name;
std::optional<int> age;
std::optional<int> empty;
};
dbng<mysql> mysql;
if (mysql.connect(ip, username, password, db)) {
mysql.create_datatable<test_optional>(ormpp_auto_key{col(&test_optional::id)});
mysql.insert<test_optional>({0, "purecpp", 1});
mysql.insert<test_optional>({0, "test", 2});
}
简单查询
cpp
//查询所有
auto l = sqlite.select(all).from<test_optional>().collect();
//查询部分列
auto l1 =
sqlite.select(col(&test_optional::id), col(&test_optional::name))
.from<test_optional>()
.collect();
//条件查询
auto l2 = sqlite.select(all)
.from<test_optional>()
.where(col(&test_optional::id).in(1, 2))
.order_by(col(&test_optional::id).desc(),
col(&test_optional::name).desc())
.limit(5)
.offset(0)
.collect();
绑定参数
cpp
//调用`param()`表示它是一个`占位符`'?'`,调用`collect(2)`表示绑定对应的参数
auto l0 = sqlite.select(all)
.from<test_optional>()
.where(col(&test_optional::id).param())
.collect(2);
auto l = sqlite.select(all)
.from<test_optional>()
.where(col(&test_optional::name).param())
.collect(std::string("test"));
CHECK(l0.size() == 1);
CHECK(l.size() == 1);
简单聚集查询
cpp
//常见的聚集函数`count,sum,avg,min,max`
auto l = sqlite.select(count()).from<test_optional>().collect();
auto l2 = sqlite.select(count(col(&test_optional::id)))
.from<test_optional>()
.collect();
auto l3 = sqlite.select(count_distinct(col(&test_optional::id)))
.from<test_optional>()
.collect();
CHECK(l == 2);
CHECK(l2 == 2);
CHECK(l3 == 2);
auto l4 = sqlite.select(sum(col(&test_optional::id)))
.from<test_optional>()
.collect();
auto l5 = sqlite.select(avg(col(&test_optional::id)))
.from<test_optional>()
.collect();
auto l6 = sqlite.select(min(col(&test_optional::id)))
.from<test_optional>()
.collect();
auto l7 = sqlite.select(max(col(&test_optional::id)))
.from<test_optional>()
.collect();
聚集加group by查询
cpp
//`group_by,having`
auto l =
sqlite.select(count(col(&test_optional::id)), col(&test_optional::id))
.from<test_optional>()
.group_by(col(&test_optional::id))
.collect();
auto l1 =
sqlite.select(sum(col(&test_optional::id)), col(&test_optional::id))
.from<test_optional>()
.group_by(col(&test_optional::id))
.collect();
auto l2 =
sqlite.select(sum(col(&test_optional::id)), col(&test_optional::id))
.from<test_optional>()
.group_by(col(&test_optional::id))
.collect();
auto l3 =
sqlite.select(sum(col(&test_optional::id)), col(&test_optional::id))
.from<test_optional>()
.where(col(&test_optional::id) > 0)
.group_by(col(&test_optional::id))
.collect();
auto l4 =
sqlite.select(sum(col(&test_optional::age)), col(&test_optional::id))
.from<test_optional>()
.where(col(&test_optional::id) > 0)
.group_by(col(&test_optional::id))
.having(sum(col(&test_optional::age)) > 0 && count() > 0)
.collect();
合并查询
cpp
auto l2 = sqlite.select(col(&test_optional::name), col(&person::name))
.from<test_optional>()
.inner_join(col(&test_optional::id), col(&person::id))
.where(col(&person::id) > 0 || col(&person::id) == 1)
.collect();
按链式调用转换下面的比较复杂的sql脚本:
cpp
std::string sql =
"select a.title, a.content, u.user_name as author_name, t.name as "
"tag_name, a.created_at, a.updated_at, a.views_count, a.comments_count "
"from articles a INNER JOIN users u ON a.author_id = u.id INNER JOIN "
"tags t ON a.tag_id = t.tag_id WHERE a.slug = and a.is_deleted=0;";
auto results =
conn->select(col(&articles_t::title), col(&articles_t::content),
col(&users_t::user_name), col(&tags_t::name),
col(&articles_t::created_at), col(&articles_t::updated_at),
col(&articles_t::views_count),
col(&articles_t::comments_count))
.from<articles_t>()
.inner_join(col(&articles_t::author_id), col(&users_t::id))
.inner_join(col(&articles_t::tag_id), col(&tags_t::tag_id))
.where(col(&articles_t::slug).param() &&
col(&articles_t::is_deleted) == 0).collect(slug);
至此,无需多言,只有三个词来形容ormpp的链式API:安全,流畅,丝滑!