2021-05-21 02:09:54 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright(C) 2021 hikyuu.org
|
|
|
|
|
*
|
|
|
|
|
* Create on: 2021-05-20
|
|
|
|
|
* Author: fasiondog
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <string>
|
2021-05-22 01:51:10 +08:00
|
|
|
|
#include <ostream>
|
2021-05-22 21:06:08 +08:00
|
|
|
|
#include <sstream>
|
2021-05-22 01:51:10 +08:00
|
|
|
|
#include <vector>
|
2021-05-21 02:09:54 +08:00
|
|
|
|
#include <fmt/format.h>
|
2021-05-22 01:51:10 +08:00
|
|
|
|
#include <fmt/ranges.h>
|
2021-05-22 21:06:08 +08:00
|
|
|
|
#include "../../Log.h"
|
2021-05-21 02:09:54 +08:00
|
|
|
|
|
|
|
|
|
#ifndef HKU_API
|
|
|
|
|
#define HKU_API
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace hku {
|
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
struct ASC {
|
2023-10-22 04:27:04 +08:00
|
|
|
|
explicit ASC(const char* name) : name(name) {}
|
|
|
|
|
explicit ASC(const std::string& name) : name(name) {}
|
2021-05-22 01:51:10 +08:00
|
|
|
|
std::string name;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct DESC {
|
2023-10-22 04:27:04 +08:00
|
|
|
|
explicit DESC(const char* name) : name(name) {}
|
|
|
|
|
explicit DESC(const std::string& name) : name(name) {}
|
2021-05-22 01:51:10 +08:00
|
|
|
|
std::string name;
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-22 04:27:04 +08:00
|
|
|
|
struct LIMIT {
|
|
|
|
|
explicit LIMIT(int limit) : limit(limit) {}
|
|
|
|
|
int limit = 1;
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-21 02:09:54 +08:00
|
|
|
|
class HKU_API DBCondition {
|
|
|
|
|
public:
|
2021-05-24 02:04:57 +08:00
|
|
|
|
DBCondition() = default;
|
|
|
|
|
DBCondition(const DBCondition&) = default;
|
|
|
|
|
DBCondition(DBCondition&& rv) : m_condition(std::move(rv.m_condition)) {}
|
2021-05-21 02:09:54 +08:00
|
|
|
|
|
2021-05-24 02:04:57 +08:00
|
|
|
|
explicit DBCondition(const char* cond) : m_condition(cond) {}
|
|
|
|
|
explicit DBCondition(const std::string& cond) : m_condition(cond) {}
|
|
|
|
|
|
|
|
|
|
DBCondition& operator=(const DBCondition&) = default;
|
|
|
|
|
DBCondition& operator=(DBCondition&& rv) {
|
|
|
|
|
if (this != &rv) {
|
|
|
|
|
m_condition = std::move(rv.m_condition);
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2021-05-21 02:09:54 +08:00
|
|
|
|
|
|
|
|
|
DBCondition& operator&(const DBCondition& other);
|
|
|
|
|
DBCondition& operator|(const DBCondition& other);
|
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
enum ORDERBY { ORDER_ASC, ORDER_DESC };
|
2021-05-21 02:09:54 +08:00
|
|
|
|
|
|
|
|
|
void orderBy(const std::string& field, ORDERBY order) {
|
2021-05-22 01:51:10 +08:00
|
|
|
|
m_condition = order == ORDERBY::ORDER_ASC
|
2021-05-21 02:09:54 +08:00
|
|
|
|
? fmt::format("{} order by {} ASC", m_condition, field)
|
|
|
|
|
: fmt::format("{} order by {} DESC", m_condition, field);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
DBCondition& operator+(const ASC& asc) {
|
|
|
|
|
orderBy(asc.name, ORDER_ASC);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBCondition& operator+(const DESC& desc) {
|
2023-10-22 04:27:04 +08:00
|
|
|
|
orderBy(desc.name, ORDER_DESC);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBCondition& operator+(const LIMIT& limit) {
|
|
|
|
|
m_condition = fmt::format("{} limit {}", m_condition, limit.limit);
|
2021-05-22 01:51:10 +08:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 02:09:54 +08:00
|
|
|
|
const std::string& str() const {
|
|
|
|
|
return m_condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::string m_condition;
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
struct Field {
|
2023-10-22 04:27:04 +08:00
|
|
|
|
explicit Field(const char* name) : name(name) {}
|
|
|
|
|
explicit Field(const std::string& name) : name(name) {}
|
2021-05-22 01:51:10 +08:00
|
|
|
|
|
|
|
|
|
// in 和 not_in 不支持 字符串,一般不会用到 in ("stra", "strb") 的 SQL 操作
|
|
|
|
|
template <typename T>
|
2021-05-26 01:51:49 +08:00
|
|
|
|
DBCondition in(const std::vector<T>& vals) {
|
|
|
|
|
HKU_CHECK(!vals.empty(), "input vals can't be empty!");
|
|
|
|
|
return DBCondition(fmt::format("({} in ({}))", name, fmt::join(vals, ",")));
|
|
|
|
|
}
|
2021-05-22 21:06:08 +08:00
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
template <typename T>
|
2021-05-26 01:51:49 +08:00
|
|
|
|
DBCondition not_in(const std::vector<T>& vals) {
|
|
|
|
|
HKU_CHECK(!vals.empty(), "input vals can't be empty!");
|
|
|
|
|
return DBCondition(fmt::format("({} not in ({}))", name, fmt::join(vals, ",")));
|
|
|
|
|
}
|
2021-05-22 21:06:08 +08:00
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
DBCondition like(const std::string& pattern) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({} like "{}"))", name, pattern));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBCondition like(const char* pattern) {
|
|
|
|
|
return DBCondition(fmt::format(R"(({} like "{}"))", name, pattern));
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-26 01:02:13 +08:00
|
|
|
|
// linux下类成员函数模板特化必须放在类外实现
|
|
|
|
|
// 否则编译时会报:explicit specialization in non-namespace scope
|
2021-05-23 02:15:55 +08:00
|
|
|
|
template <>
|
2021-05-26 01:51:49 +08:00
|
|
|
|
inline DBCondition Field::in<std::string>(const std::vector<std::string>& vals) {
|
2021-05-23 02:15:55 +08:00
|
|
|
|
HKU_CHECK(!vals.empty(), "input vals can't be empty!");
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << name << " in (";
|
|
|
|
|
size_t total = vals.size();
|
|
|
|
|
for (size_t i = 0; i < total - 1; i++) {
|
|
|
|
|
out << "\"" << vals[i] << "\",";
|
|
|
|
|
}
|
|
|
|
|
out << "\"" << vals[total - 1] << "\"))";
|
|
|
|
|
return DBCondition(out.str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-05-26 01:51:49 +08:00
|
|
|
|
inline DBCondition Field::not_in<std::string>(const std::vector<std::string>& vals) {
|
2021-05-23 02:15:55 +08:00
|
|
|
|
HKU_CHECK(!vals.empty(), "input vals can't be empty!");
|
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << name << " not in (";
|
|
|
|
|
size_t total = vals.size();
|
|
|
|
|
for (size_t i = 0; i < total - 1; i++) {
|
|
|
|
|
out << "\"" << vals[i] << "\",";
|
|
|
|
|
}
|
|
|
|
|
out << "\"" << vals[total - 1] << "\"))";
|
|
|
|
|
return DBCondition(out.str());
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-22 01:51:10 +08:00
|
|
|
|
inline std::ostream& operator<<(std::ostream& out, const DBCondition& d) {
|
|
|
|
|
out << d.str();
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
inline DBCondition operator==(const Field& field, T val) {
|
2023-07-28 23:50:26 +08:00
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << field.name << "=" << val << ")";
|
|
|
|
|
return DBCondition(out.str());
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
inline DBCondition operator!=(const Field& field, T val) {
|
2023-07-28 23:50:26 +08:00
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << field.name << "<>" << val << ")";
|
|
|
|
|
return DBCondition(out.str());
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
inline DBCondition operator>(const Field& field, T val) {
|
2023-07-28 23:50:26 +08:00
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << field.name << ">" << val << ")";
|
|
|
|
|
return DBCondition(out.str());
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
inline DBCondition operator>=(const Field& field, T val) {
|
2023-07-28 23:50:26 +08:00
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << field.name << ">=" << val << ")";
|
|
|
|
|
return DBCondition(out.str());
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
inline DBCondition operator<(const Field& field, T val) {
|
2023-07-28 23:50:26 +08:00
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << field.name << "<" << val << ")";
|
|
|
|
|
return DBCondition(out.str());
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
inline DBCondition operator<=(const Field& field, T val) {
|
2023-07-28 23:50:26 +08:00
|
|
|
|
std::ostringstream out;
|
|
|
|
|
out << "(" << field.name << "<=" << val << ")";
|
|
|
|
|
return DBCondition(out.str());
|
2021-05-22 01:51:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator!=(const Field& field, const char* val) {
|
2021-05-22 01:51:10 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}<>"{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator>(const Field& field, const char* val) {
|
2021-05-22 01:51:10 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}>"{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator<(const Field& field, const char* val) {
|
2021-05-22 01:51:10 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}<"{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator>=(const Field& field, const char* val) {
|
2021-05-22 01:51:10 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}>="{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator<=(const Field& field, const char* val) {
|
2021-05-22 01:51:10 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}<="{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator==(const Field& field, const std::string& val) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}="{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator!=(const Field& field, const std::string& val) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}<>"{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator>(const Field& field, const std::string& val) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}>"{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator<(const Field& field, const std::string& val) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}<"{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator>=(const Field& field, const std::string& val) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}>="{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator<=(const Field& field, const std::string& val) {
|
2021-05-22 21:06:08 +08:00
|
|
|
|
return DBCondition(fmt::format(R"(({}<="{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 23:16:04 +08:00
|
|
|
|
inline DBCondition operator==(const Field& field, const char* val) {
|
|
|
|
|
return DBCondition(fmt::format(R"(({}="{}"))", field.name, val));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 02:09:54 +08:00
|
|
|
|
} // namespace hku
|