From ceeccf653da7ec14807df66471fed627122f9fa1 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 27 Nov 2024 15:06:43 +0300 Subject: [PATCH 01/35] add and beautify files --- sql.h | 1482 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 1250 insertions(+), 232 deletions(-) diff --git a/sql.h b/sql.h index aa4acc0..5761d37 100644 --- a/sql.h +++ b/sql.h @@ -3,15 +3,29 @@ #include #include +#include + +namespace { + +const std::string& quotes("\""); + +} + + namespace sql { class column; +class column_value; +class SelectModel; + class Param { public: - Param (const std::string ¶m) : _param(param) {} - Param (const char *param) : _param(param) {} + Param(const std::string& param) : + _param(param) {} + Param(const char* param) : + _param(param) {} public: std::string operator()() const { return param(); } @@ -21,46 +35,56 @@ class Param const std::string _param; }; -template -inline std::string to_value(const T& data) { +template +inline std::string to_value(const T& data) +{ return std::to_string(data); } -template -inline std::string to_value(char const(&data)[N]) { +template +inline std::string to_value(char const (&data)[N]) +{ std::string str("'"); + str.append(data); str.append("'"); return str; } -template <> -inline std::string to_value(const std::string& data) { +template<> +inline std::string to_value(const std::string& data) +{ std::string str("'"); + str.append(data); str.append("'"); return str; } -template <> -inline std::string to_value(const char* const& data) { +template<> +inline std::string to_value(const char* const& data) +{ std::string str("'"); + str.append(data); str.append("'"); return str; } -template <> -inline std::string to_value(const Param& data) { +template<> +inline std::string to_value(const Param& data) +{ return data(); } -template <> +template<> inline std::string to_value(const column& data); +template<> +inline std::string to_value(const column_value& data); /* -template <> -static std::string sql::to_value(const time_t& data) { + template <> + static std::string sql::to_value(const time_t& data) { char buff[128] = {0}; struct tm* ttime = localtime(&data); strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", ttime); @@ -68,17 +92,23 @@ static std::string sql::to_value(const time_t& data) { str.append(buff); str.append("'"); return str; -} -*/ + } + */ -template -void join_vector(std::string& result, const std::vector& vec, const char* sep) { +template +void join_vector(std::string& result, const std::vector& vec, const char* sep) +{ size_t size = vec.size(); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { result.append(vec[i]); result.append(sep); - } else { + } + else + { result.append(vec[i]); } } @@ -87,61 +117,150 @@ void join_vector(std::string& result, const std::vector& vec, const char* sep class column { public: - column(const std::string& column) { - _cond = column; + + + column() {} + // alias + column(const std::string& column_name, const std::string& alias = "", const std::string& as = "", const std::string& to_type = "") + { + if (!alias.empty()) + _cond.append(alias + "."); + + + + _cond.append(quotes + column_name + quotes); + + if (!to_type.empty()) + _cond.append("::" + to_type); + + if (!as.empty()) + _cond.append(" AS " + as); } - virtual ~column() {} - column& as(const std::string& s) { - _cond.append(" as "); - _cond.append(s); + column(const column& column_name, const std::string& alias = "", const std::string& as = "", const std::string& to_type = "") + { + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(column_name.str()); + + if (!to_type.empty()) + _cond.append("::" + to_type); + + if (!as.empty()) + _cond.append(" AS " + as); + } + + column& operator()(const std::string& column_name, const std::string& alias = "", const std::string& as = "") + { + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(quotes + column_name + quotes); + + if (!as.empty()) + _cond.append(" AS " + as); + return *this; } - column& is_null() { + virtual ~column() {} + + + column& is_null() + { _cond.append(" is null"); return *this; } - column& is_not_null() { + column& is_not_null() + { _cond.append(" is not null"); return *this; } - template - column& in(const std::vector& args) { + template + column& in (const std::vector& args) { size_t size = args.size(); - if(size == 1) { - _cond.append(" = "); - _cond.append(to_value(args[0])); - } else { - _cond.append(" in ("); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { - _cond.append(to_value(args[i])); - _cond.append(", "); - } else { - _cond.append(to_value(args[i])); - } + + + + _cond.append(" in ("); + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { + _cond.append(to_value(args[i])); + _cond.append(", "); + } + else + { + _cond.append(to_value(args[i])); } - _cond.append(")"); } + _cond.append(")"); + + return *this; + } + + column& in (const std::string& in_column) { + _cond.append(" in ("); + + _cond.append(in_column); + _cond.append(" ) "); + return *this; + } + + + column& append(const std::string& data) + { + _cond.append(" || '" + data + "' "); + return *this; + } + + column& prepend(const std::string& data) + { + _cond.insert(0, " '" + data + "' || "); + return *this; + } + + // special characters such as %,_ must contains in like_condition + // template<> + column& like(const std::string& like_condition) + { + if (like_condition.size() <= 0) + return *this; + + _cond.append(" LIKE '"); + _cond.append(like_condition); + _cond.append("' "); + + return *this; } - template - column& not_in(const std::vector& args) { + template + column& not_in(const std::vector& args) + { size_t size = args.size(); - if(size == 1) { + + if (size == 1) + { _cond.append(" != "); _cond.append(to_value(args[0])); - } else { + } + else + { _cond.append(" not in ("); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { _cond.append(to_value(args[i])); _cond.append(", "); - } else { + } + else + { _cond.append(to_value(args[i])); } } @@ -150,8 +269,10 @@ class column return *this; } - column& operator &&(column& condition) { + column& operator&&(column& condition) + { std::string str("("); + str.append(_cond); str.append(") and ("); str.append(condition._cond); @@ -160,8 +281,10 @@ class column return condition; } - column& operator ||(column& condition) { + column& operator||(column& condition) + { std::string str("("); + str.append(_cond); str.append(") or ("); str.append(condition._cond); @@ -170,102 +293,721 @@ class column return condition; } - column& operator &&(const std::string& condition) { + column& operator&&(const std::string& condition) + { _cond.append(" and "); _cond.append(condition); return *this; } - column& operator ||(const std::string& condition) { + column& operator||(const std::string& condition) + { _cond.append(" or "); _cond.append(condition); return *this; } - column& operator &&(const char* condition) { + column& operator&&(const char* condition) + { _cond.append(" and "); _cond.append(condition); return *this; } - column& operator ||(const char* condition) { + column& operator||(const char* condition) + { _cond.append(" or "); _cond.append(condition); return *this; } - template - column& operator ==(const T& data) { + template + column& operator==(const T& data) + { _cond.append(" = "); _cond.append(to_value(data)); return *this; } - template - column& operator !=(const T& data) { + template + column& operator!=(const T& data) + { _cond.append(" != "); _cond.append(to_value(data)); return *this; } - template - column& operator >=(const T& data) { + template + column& operator>=(const T& data) + { _cond.append(" >= "); _cond.append(to_value(data)); return *this; } - template - column& operator <=(const T& data) { + template + column& operator<=(const T& data) + { _cond.append(" <= "); _cond.append(to_value(data)); return *this; } - template - column& operator >(const T& data) { + template + column& operator>(const T& data) + { _cond.append(" > "); _cond.append(to_value(data)); return *this; } - template - column& operator <(const T& data) { + template + column& operator<(const T& data) + { _cond.append(" < "); _cond.append(to_value(data)); return *this; } - const std::string& str() const { + template + column& operator/(const T& data) + { + _cond.append(" / "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator+(const T& data) + { + _cond.append(" + "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator*(const T& data) + { + _cond.append(" * "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator-(const T& data) + { + _cond.append(" - "); + _cond.append(to_value(data)); + return *this; + } + + const std::string& str() const + { return _cond; } operator bool() { return true; } + private: std::string _cond; }; -template <> -inline std::string to_value(const column& data) { + +class table +{ +public: + table(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") + { + if (!tablespace.empty()) + { + table_str_.append(tablespace); + table_str_.append("."); + } + table_str_.append(quotes + table_name + quotes); + + if (!alias.empty()) + table_str_.append(" " + alias + " "); + else + table_str_.append(" "); + } + + const std::string& str() const + {} + +private: + std::string table_str_ = ""; +}; + +class column_value +{ +public: + + column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_value = false) + { + if (!is_value) + _cond.append("'" + column_value + "'"); + else + _cond.append(column_value); + + + if (!to_type.empty()) + _cond.append("::" + to_type); + + if (!as.empty()) + _cond.append(" AS " + as); + } + + const std::string& str() const + { + return _cond; + } + + template + column_value& operator>(const T& data) + { + _cond.append(" > "); + _cond.append(to_value(data)); + return *this; + } + + template + column_value& operator<(const T& data) + { + _cond.append(" < "); + _cond.append(to_value(data)); + return *this; + } + + template + column_value& operator*(const T& data) + { + _cond.append(" * " + to_value(data)); + return *this; + } + +private: + std::string _cond; +}; + +template<> +inline std::string to_value(const column& data) +{ + return data.str(); +} + +inline std::string to_value(const sql::column_value& data) +{ return data.str(); } +inline std::string to_value(const std::string& data) +{ + return data; +} + +class SqlFunction +{ +public: + SqlFunction() : + _sql_func("") {} + virtual ~SqlFunction() {} + + virtual std::string str() const = 0; + +private: + // SqlFunction(const SqlFunction& data) = delete; + SqlFunction& operator=(const SqlFunction& data) = delete; + +protected: + std::string _sql_func; +}; + + +class existsStatement : public SqlFunction +{ +public: + + existsStatement() + {} + + template + existsStatement& exists(T subq, const std::string& as) + { + _sql_func.append("EXISTS ("); + _sql_func.append(to_value(subq)); + _sql_func.append(") "); + + if (as.length() > 2) + _sql_func.append(" AS " + as + " "); + + return *this; + } + + virtual std::string str() const override + { + return _sql_func; + } +}; + +class caseStatement : public SqlFunction +{ +public: + caseStatement() + { + _sql_func.append(" END"); + } + + template + caseStatement& case_sql(std::string as = "", std::string case_else = "", Args&& ... conditionals) + { + if (case_else.length() > 2) + _sql_func.insert(0, " ELSE '" + case_else + "'"); + + if (!as.empty()) + _sql_func.append(" AS " + as); + + case_sql(conditionals ...); + return *this; + } + + template + caseStatement& case_sql(std::pair when, Args&& ... conditionals) + { + std::string pb(" WHEN "); + + pb.append(to_value(when.first)); + pb.append(" THEN "); + pb.append(to_value(when.second)); + + _sql_func.insert(0, pb); + case_sql(conditionals ...); + return *this; + } + + caseStatement& case_sql() + { + _sql_func.insert(0, "CASE "); + return *this; + } + + virtual std::string str() const override + { + return _sql_func; + } + + virtual ~caseStatement() {} +}; + +class SqlWindowFunction : public SqlFunction +{ +public: + SqlWindowFunction() {} + virtual ~SqlWindowFunction() {} + + SqlWindowFunction& row_number(const sql::column& column + , const sql::column&& partition = sql::column() + , const sql::column&& order = sql::column() + , const bool& desc = false + , const std::string& as = "") + { + return w_function("ROW_NUMBER", column.str(), partition.str(), order.str(), desc, as); + } + + SqlWindowFunction& sum_over(const sql::column& column + , const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("SUM", column.str(), partition, order, desc, as); + } + + SqlWindowFunction& count_over(const sql::column& column + , const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("COUNT", column.str(), partition, order, desc, as); + } + + SqlWindowFunction& count(const sql::column& column) + { + _sql_func.clear(); + _sql_func.append("COUNT(" + column.str() + ") "); + + return *this; + } + + SqlWindowFunction& dense_rank( + const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("DENSE_RANK", "", partition, order, desc, as); + } + + SqlWindowFunction& dense_rank( + const sql::column& partition = sql::column() + , const sql::column& order = sql::column() + , const bool& desc = false + , const std::string& as = "") + { + return w_function("DENSE_RANK", "", partition.str(), order.str(), desc, as); + } + + SqlWindowFunction& dense_rank( + const sql::column& partition = sql::column() + , const std::vector> order_by_desc = std::vector> + () + , const std::string& as = "") + { + std::vector> order_by_desc_string; + + for (int i = 0; i < order_by_desc.size(); i++) + { + order_by_desc_string.push_back(std::pair(order_by_desc.at(i).first.str(), order_by_desc.at(i).second)); + } + + // const std::vector> const_order_by_desc_string = order_by_desc_string; + return w_function("DENSE_RANK", "", partition.str(), order_by_desc_string, as); + } + + SqlWindowFunction& dense_rank( + const std::string& partition = std::string() + , const std::vector> order_by_desc = std::vector> + () + , const std::string& as = "") + { + return w_function("DENSE_RANK", "", partition, order_by_desc, as); + } + + SqlWindowFunction& rank( + const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("RANK", "", partition, order, desc, as); + } + + SqlWindowFunction& rank( + const sql::column& partition = sql::column() + , const sql::column& order = sql::column() + , const bool& desc = false + , const std::string& as = "") + { + return w_function("RANK", "", partition.str(), order.str(), desc, as); + } + + virtual std::string str() const override + { + return _sql_func; + } + +private: + + SqlWindowFunction& w_function(const std::string& function_name, + const std::string& column + , const std::string& partition = "" + , const std::string& order_by = "" + , const bool desc = false + , const std::string& as = "") + { + _sql_func.clear(); + + _sql_func.append(function_name); + + _sql_func.append("("); + + if (!column.empty() || (column.length() > 2)) + _sql_func.append(column); + + _sql_func.append(")"); + _sql_func.append(" OVER "); + _sql_func.append("("); + + + if (partition.length() > 2) + { + _sql_func.append("PARTITION BY "); + _sql_func.append(partition); + + _sql_func.append(" "); + } + + if (order_by.length() > 2) + { + _sql_func.append("ORDER BY "); + _sql_func.append(order_by); + _sql_func.append(" "); + desc ? _sql_func.append(" DESC ") + : _sql_func.append(" ASC "); + _sql_func.append(" ) "); + } + + if (!as.empty()) + _sql_func.append(" AS " + as); + + return *this; + } + + SqlWindowFunction& w_function(const std::string& function_name, + const std::string& column + , + const std::string& partition = "" + , + const std::vector> order_by_desc = std::vector> + () + , + const std::string& as = "") + { + _sql_func.clear(); + _sql_func.append(function_name); + + _sql_func.append("("); + + if (!column.empty() || (column.length() > 2)) + _sql_func.append(column); + + _sql_func.append(")"); + _sql_func.append(" OVER "); + _sql_func.append("("); + + + if (partition.length() > 2) + { + _sql_func.append("PARTITION BY "); + _sql_func.append(partition); + + _sql_func.append(" "); + } + + if (order_by_desc.size() > 0) + { + _sql_func.append("ORDER BY "); + + for (int i = 0; i < order_by_desc.size(); i++) + { + if (order_by_desc.at(i).first.length() > 2) + { + _sql_func.append(order_by_desc.at(i).first); + _sql_func.append(" "); + order_by_desc.at(i).second ? _sql_func.append(" DESC , ") + : _sql_func.append(" ASC , "); + } + } + _sql_func = _sql_func.substr(0, _sql_func.size() - 3); + + _sql_func.append(" ) "); + } + + if (!as.empty()) + _sql_func.append(" AS " + as); + + return *this; + } +}; + +class TimeFormatingFunction : public SqlFunction +{ +public: + TimeFormatingFunction() {} + virtual ~TimeFormatingFunction() {} + + + TimeFormatingFunction& to_timestamp(const column& data) + { + return t_function("to_timestamp", data); + } + + virtual std::string str() const override + { + return _sql_func; + } + +private: + TimeFormatingFunction& t_function(const std::string& name, const column& data) + { + _sql_func.append(name + "(" + data.str() + ")"); + return *this; + } +}; + +class CastFunction : public SqlFunction +{ +public: + CastFunction(const column expression, + + const std::string& data_type = "", + const int& length = 30) + { + _sql_func = "CAST("; + _sql_func.append(expression.str() + " AS " + data_type + ") "); + } + + std::string str() const override + { + return _sql_func; + } +}; + + + + +class RoundFunction : public SqlFunction +{ +public: + RoundFunction(const CastFunction expression, + const std::string& as = "", + const int& length = 30) + { + _sql_func = "ROUND("; + _sql_func.append(expression.str() + " , " + std::to_string(length) + ") "); + + if (!as.empty()) + _sql_func.append(" AS " + as); + } + + RoundFunction(const column expression, + const std::string& as = "", + const int& length = 30) + { + _sql_func = "ROUND("; + _sql_func.append(expression.str() + " , " + std::to_string(length) + ") "); + + if (!as.empty()) + _sql_func.append(" AS " + as); + } -class SqlModel + std::string str() const override + { + return _sql_func; + } +}; + + + +class DataTypeFormatingFunction : public SqlFunction +{ +public: + DataTypeFormatingFunction(const std::string& as = "") + { + if (!as.empty()) + _as.append(" AS " + quotes + as + quotes); + } + + std::string str() const override + { + return _sql_func + _as; + } + + virtual ~DataTypeFormatingFunction() {} + + + DataTypeFormatingFunction& to_char(const sql::TimeFormatingFunction& tf_func, + const bool& is_text, + const std::string& format = "") + { + DataTypeFormatingFunction& text = dtf_function("to_char", tf_func.str(), is_text, format); + + + return text; + } + + DataTypeFormatingFunction& to_char(const column& data, + const std::string& format = "") + { + return dtf_function("to_char", data.str(), true, format); + } + + DataTypeFormatingFunction& to_char(const column_value& data, + const std::string& format = "") + { + return dtf_function("to_char", data.str(), false, format); + } + +private: + DataTypeFormatingFunction& dtf_function(const std::string& name, + const std::string& data, + const bool& is_column, + const std::string& format = "") + { + _sql_func.append(name); + + _sql_func.append("("); + _sql_func.append(data); + + if (!format.empty()) + _sql_func.append(", '" + format + "'"); + _sql_func.append(")"); + return *this; + } + + std::string _as; +}; + + + + +class conditional_expressions : public SqlFunction +{ +public: + conditional_expressions(const std::string& as = "") + { + _sql_func.append(" COALESCE ( "); + + if (!as.empty()) + _as.append(" AS " + as); + } + + virtual std::string str() const override + { + return _sql_func + _as; + } + + virtual ~conditional_expressions() {} + + template + conditional_expressions& coalesce(const T& col, Args&& ... cols) + { + _sql_func.append(to_value(col) + " , "); + coalesce(cols ...); + return *this; + } + +private: + conditional_expressions& coalesce() + { + // remove last comma + if (_sql_func.size() > 4) + _sql_func = _sql_func.substr(0, _sql_func.size() - 3); + _sql_func.append(" ) "); + return *this; + } + + std::string _as = ""; +}; + +class SqlModel { public: SqlModel() {} virtual ~SqlModel() {} virtual const std::string& str() = 0; - const std::string& last_sql() { + const std::string& last_sql() + { return _sql; } + private: - SqlModel(const SqlModel& m) = delete; - SqlModel& operator =(const SqlModel& data) = delete; + // SqlModel(const SqlModel& m) = delete; + SqlModel& operator=(const SqlModel& data) = delete; + protected: std::string _sql; }; @@ -273,203 +1015,408 @@ class SqlModel class SelectModel : public SqlModel { public: - SelectModel() : _distinct(false) {} + SelectModel() : + _distinct(false) {} virtual ~SelectModel() {} - template - SelectModel& select(const std::string& str, Args&&... columns) { - _select_columns.push_back(str); - select(columns...); + template + SelectModel& select(const std::string& str, Args&& ... columns) + { + const std::string& pb(quotes + str + quotes); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + + template + SelectModel& select(const SqlFunction& sql_function, Args&& ... columns) + { + const std::string& pb = sql_function.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + + template + SelectModel& select(std::pair subquery, Args&& ... columns) + { + std::string pb(" ( "); + + pb.append(subquery.first.str()); + pb.append(" ) "); + + if (!subquery.second.empty()) + { + pb.append(" AS "); + pb.append(subquery.second); + } + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + + template + SelectModel& select(const column column_struct, Args&& ... columns) + { + const std::string& pb = column_struct.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + + template + SelectModel& select(const column_value data, Args&& ... columns) + { + const std::string& pb = data.str(); + + _select_columns.push_back(pb); + select(columns ...); return *this; } // for recursion - SelectModel& select() { + SelectModel& select() + { return *this; } - SelectModel& distinct() { + SelectModel& distinct() + { _distinct = true; return *this; } - template - SelectModel& from(const std::string& table_name, Args&&... tables) { - if(_table_name.empty()) { - _table_name = table_name; - } else { - _table_name.append(", "); - _table_name.append(table_name); + // template + SelectModel& from(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") + { + if (!tablespace.empty()) + { + _table_name.append(tablespace); + _table_name.append("."); } - from(tables...); + _table_name.append(quotes + table_name + quotes); + + if (!alias.empty()) + _table_name.append(" " + alias + " "); + else + _table_name.append(" "); + + return *this; } - - // for recursion - SelectModel& from() { + + SelectModel& from_subquery(const std::string& table_name, const std::string& alias = "") + { + _table_name.append(table_name); + + if (!alias.empty()) + _table_name.append(" " + alias + " "); + else + _table_name.append(" "); + + return *this; } - SelectModel& join(const std::string& table_name) { - _join_type = "join"; - _join_table = table_name; + SelectModel& from(std::vector selects, const std::string& alias = "") + { + for (int i = 0; i < selects.size(); i++) + { + std::string subs_q = selects[i].str(); + + _table_name.append(" ( " + subs_q + " )"); + + if (i != selects.size()) + _table_name.append(" UNION ALL "); + } + + if (!alias.empty()) + _table_name.append(" " + alias + " "); + else + _table_name.append(" "); + return *this; } - SelectModel& left_join(const std::string& table_name) { - _join_type = "left join"; - _join_table = table_name; + SelectModel& join_statement(const std::string& join_type, + const std::string& table_name, + const std::string& tablespace, + const std::string& alias, + const std::string& on_conditions) + { + // std::vector>> type; + + std::string join_type_and_table(" " + join_type + " "); + + if (!tablespace.empty()) + join_type_and_table.append(tablespace + "."); + + join_type_and_table.append(quotes + table_name + quotes); + + if (!alias.empty()) + join_type_and_table.append(" " + alias + " "); + + join_type_and_table.append("ON " + on_conditions); + + _join_type.push_back(join_type_and_table); + return *this; } - SelectModel& left_outer_join(const std::string& table_name) { - _join_type = "left outer join"; - _join_table = table_name; + SelectModel& left_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "" + ) + { + join_statement("LEFT JOIN", table_name, tablespace, alias, on_conditions.str()); + return *this; } - SelectModel& right_join(const std::string& table_name) { - _join_type = "right join"; - _join_table = table_name; + SelectModel& left_outer_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") + { + join_statement("left outer join", table_name, tablespace, alias, on_conditions.str()); + return *this; } - SelectModel& right_outer_join(const std::string& table_name) { - _join_type = "right outer join"; - _join_table = table_name; + SelectModel& right_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "" + ) + { + join_statement(" right join ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& full_join(const std::string& table_name) { - _join_type = "full join"; - _join_table = table_name; + SelectModel& right_outer_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") + { + join_statement(" RIGHT OUTER JOIN ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& full_outer_join(const std::string& table_name) { - _join_type = "full outer join"; - _join_table = table_name; + SelectModel& full_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") + { + join_statement(" full join ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& on(const std::string& condition) { - _join_on_condition.push_back(condition); + SelectModel& full_outer_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") + { + join_statement(" FULL OUTER JOIN ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& on(const column& condition) { - _join_on_condition.push_back(condition.str()); + SelectModel& where(const std::string& condition) + { + _where_condition.push_back(condition); return *this; } - SelectModel& where(const std::string& condition) { - _where_condition.push_back(condition); + SelectModel& where(const column& condition) + { + _where_condition.push_back(condition.str()); return *this; } - SelectModel& where(const column& condition) { + SelectModel& where(const column_value& condition) + { _where_condition.push_back(condition.str()); return *this; } - template - SelectModel& group_by(const std::string& str, Args&&...columns) { + SelectModel& where_exists(std::vector data) + { + std::string where_c; + + for (int i = 0; i < data.size(); i++) + { + where_c.append("(EXISTS ("); + where_c.append(data[i].str()); + where_c.append(" ) ) OR "); + } + where_c = where_c.substr(0, where_c.length() - 3); + + _where_condition.push_back(where_c); + return *this; + } + + SelectModel& where_not_exists(std::vector data) + { + std::string where_c; + + for (int i = 0; i < data.size(); i++) + { + where_c.append("( NOT EXISTS ("); + where_c.append(data[i].str()); + where_c.append(" ) ) OR "); + } + where_c = where_c.substr(0, where_c.length() - 3); + _where_condition.push_back(where_c); + return *this; + } + + template + SelectModel& where_between(const column& cond, const T& begin_val, const T& end_val) + { + std::string where_val; + + where_val.append(cond.str()); + std::string begin = std::to_string(begin_val); + std::string end = std::to_string(end_val); + where_val.append(" BETWEEN " + begin + " AND " + end); + _where_condition.push_back(where_val); + return *this; + } + + template + SelectModel& group_by(const std::string& str, Args&& ... columns) + { _groupby_columns.push_back(str); - group_by(columns...); + group_by(columns ...); return *this; } // for recursion - SelectModel& group_by() { + SelectModel& group_by() + { return *this; } - SelectModel& having(const std::string& condition) { + SelectModel& having(const std::string& condition) + { _having_condition.push_back(condition); return *this; } - SelectModel& having(const column& condition) { + SelectModel& having(const column& condition) + { _having_condition.push_back(condition.str()); return *this; } - SelectModel& order_by(const std::string& order_by) { - _order_by = order_by; + SelectModel& order_by(const std::string& order_by, const bool desc = false) + { + _order_by = order_by; + _order_by_desc = desc; return *this; } - template - SelectModel& limit(const T& limit) { + SelectModel& order_by(const column& order_by, const bool desc = false) + { + _order_by = to_value(order_by); + _order_by_desc = desc; + return *this; + } + + template + SelectModel& limit(const T& limit) + { _limit = std::to_string(limit); return *this; } - template - SelectModel& limit(const T& offset, const T& limit) { + + template + SelectModel& limit(const T& offset, const T& limit) + { _offset = std::to_string(offset); - _limit = std::to_string(limit); + _limit = std::to_string(limit); return *this; } - template - SelectModel& offset(const T& offset) { + + template + SelectModel& offset(const T& offset) + { _offset = std::to_string(offset); return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); - _sql.append("select "); - if(_distinct) { - _sql.append("distinct "); - } + _sql.append(" SELECT "); + + if (_distinct) + _sql.append(" DISTINCT "); join_vector(_sql, _select_columns, ", "); - _sql.append(" from "); + _sql.append(" FROM "); _sql.append(_table_name); - if(!_join_type.empty()) { - _sql.append(" "); - _sql.append(_join_type); - _sql.append(" "); - _sql.append(_join_table); - } - if(!_join_on_condition.empty()) { - _sql.append(" on "); - join_vector(_sql, _join_on_condition, " and "); + + if (!_join_type.empty()) + { + for (std::string join :_join_type) + { + _sql.append(" " + join + " "); + } } - if(!_where_condition.empty()) { - _sql.append(" where "); - join_vector(_sql, _where_condition, " and "); + + if (!_where_condition.empty()) + { + _sql.append(" WHERE "); + join_vector(_sql, _where_condition, " AND "); } - if(!_groupby_columns.empty()) { + + if (!_groupby_columns.empty()) + { _sql.append(" group by "); join_vector(_sql, _groupby_columns, ", "); } - if(!_having_condition.empty()) { + + if (!_having_condition.empty()) + { _sql.append(" having "); join_vector(_sql, _having_condition, " and "); } - if(!_order_by.empty()) { - _sql.append(" order by "); + + if (!_order_by.empty()) + { + _sql.append(" ORDER BY "); _sql.append(_order_by); + + if (_order_by_desc) + _sql.append(" DESC "); } - if(!_limit.empty()) { + + if (!_limit.empty()) + { _sql.append(" limit "); _sql.append(_limit); } - if(!_offset.empty()) { + + if (!_offset.empty()) + { _sql.append(" offset "); _sql.append(_offset); } return _sql; } - SelectModel& reset() { + SelectModel& reset() + { _select_columns.clear(); _distinct = false; _groupby_columns.clear(); _table_name.clear(); _join_type.clear(); - _join_table.clear(); - _join_on_condition.clear(); + // 64_join_on_condition.clear(); _where_condition.clear(); _having_condition.clear(); _order_by.clear(); @@ -477,8 +1424,10 @@ class SelectModel : public SqlModel _offset.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, SelectModel& mod) { - out< _groupby_columns; std::string _table_name; - std::string _join_type; - std::string _join_table; - std::vector _join_on_condition; + std::vector _join_type; + + // std::vector _join_on_condition; std::vector _where_condition; std::vector _having_condition; std::string _order_by; + bool _order_by_desc = false; std::string _limit; std::string _offset; }; - +inline std::string to_value(SelectModel& data) +{ + return data.str(); +} class InsertModel : public SqlModel { @@ -505,49 +1458,93 @@ class InsertModel : public SqlModel InsertModel() {} virtual ~InsertModel() {} - template - InsertModel& insert(const std::string& c, const T& data) { - _columns.push_back(c); - _values.push_back(to_value(data)); + template + InsertModel& insert(const std::string& c, const T& data) + { + if constexpr + (std::is_same::value) + { + _columns.push_back(quotes + c + quotes); + std::string v_data = "FALSE"; + + if (data) v_data = "TRUE"; + _values.push_back(v_data); + } + else + if constexpr (std::is_same::value) + { + _columns.push_back(quotes + c + quotes); + + _values.push_back(std::to_string(data)); + } + else + { + _columns.push_back(quotes + c + quotes); + _values.push_back("'" + to_value(data) + "'"); + } + return *this; + } + + InsertModel& insert(const std::string& c) + { + _columns.push_back(quotes + c + quotes); + _values.push_back(" ? "); return *this; } - template - InsertModel& operator()(const std::string& c, const T& data) { + template + InsertModel& operator()(const std::string& c, const T& data) + { return insert(c, data); } - InsertModel& into(const std::string& table_name) { - _table_name = table_name; + InsertModel& operator()(const std::string& c) + { + return insert(c); + } + + InsertModel& into(const std::string& table_name, const std::string& tablespace = "") + { + _table_name.clear(); + + if (!tablespace.empty()) + _table_name.append(tablespace + "."); + _table_name.append(quotes + table_name + quotes); return *this; } - InsertModel& replace(bool var) { + InsertModel& replace(bool var) + { _replace = var; return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); std::string v_ss; - if (_replace) { + if (_replace) _sql.append("insert or replace into "); - }else { + else _sql.append("insert into "); - } _sql.append(_table_name); _sql.append("("); v_ss.append(" values("); size_t size = _columns.size(); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { _sql.append(_columns[i]); _sql.append(", "); v_ss.append(_values[i]); v_ss.append(", "); - } else { + } + else + { _sql.append(_columns[i]); _sql.append(")"); v_ss.append(_values[i]); @@ -558,15 +1555,17 @@ class InsertModel : public SqlModel return _sql; } - InsertModel& reset() { + InsertModel& reset() + { _table_name.clear(); _columns.clear(); _values.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, InsertModel& mod) { - out< _values; }; -template <> -inline InsertModel& InsertModel::insert(const std::string& c, const std::nullptr_t&) { +template<> +inline InsertModel& InsertModel::insert(const std::string& c, const std::nullptr_t&) +{ _columns.push_back(c); _values.push_back("null"); return *this; } - class UpdateModel : public SqlModel { public: UpdateModel() {} virtual ~UpdateModel() {} - UpdateModel& update(const std::string& table_name) { + UpdateModel& update(const std::string& table_name) + { _table_name = table_name; return *this; } - template - UpdateModel& set(const std::string& c, const T& data) { + template + UpdateModel& set(const std::string& c, const T& data) + { std::string str(c); + str.append(" = "); str.append(to_value(data)); _set_columns.push_back(str); return *this; } - template - UpdateModel& operator()(const std::string& c, const T& data) { + template + UpdateModel& operator()(const std::string& c, const T& data) + { return set(c, data); } - UpdateModel& where(const std::string& condition) { + UpdateModel& where(const std::string& condition) + { _where_condition.push_back(condition); return *this; } - UpdateModel& where(const column& condition) { + UpdateModel& where(const column& condition) + { _where_condition.push_back(condition.str()); return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); _sql.append("update "); _sql.append(_table_name); _sql.append(" set "); join_vector(_sql, _set_columns, ", "); size_t size = _where_condition.size(); - if(size > 0) { - _sql.append(" where "); + + if (size > 0) + { + _sql.append(" WHERE "); join_vector(_sql, _where_condition, " and "); } return _sql; } - UpdateModel& reset() { + UpdateModel& reset() + { _table_name.clear(); _set_columns.clear(); _where_condition.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, UpdateModel& mod) { - out< _where_condition; }; -template <> -inline UpdateModel& UpdateModel::set(const std::string& c, const std::nullptr_t&) { +template<> +inline UpdateModel& UpdateModel::set(const std::string& c, const std::nullptr_t&) +{ std::string str(c); + str.append(" = null"); _set_columns.push_back(str); return *this; } - class DeleteModel : public SqlModel { public: DeleteModel() {} virtual ~DeleteModel() {} - DeleteModel& _delete() { + DeleteModel& _delete() + { return *this; } - template - DeleteModel& from(const std::string& table_name, Args&&... tables) { - if(_table_name.empty()) { - _table_name = table_name; - } else { - _table_name.append(", "); - _table_name.append(table_name); + template + DeleteModel& from(const std::string& table_name, const std::string& tablespace = "") + { + if (!tablespace.empty()) + { + _table_name.append(tablespace); + _table_name.append("."); } - from(tables...); - return *this; - } - - // for recursion - DeleteModel& from() { + _table_name.append(quotes + table_name + quotes); + _table_name.append(" "); + return *this; } - DeleteModel& where(const std::string& condition) { + DeleteModel& where(const std::string& condition) + { _where_condition.push_back(condition); return *this; } - DeleteModel& where(const column& condition) { + DeleteModel& where(const column& condition) + { _where_condition.push_back(condition.str()); return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); _sql.append("delete from "); _sql.append(_table_name); size_t size = _where_condition.size(); - if(size > 0) { - _sql.append(" where "); - join_vector(_sql, _where_condition, " and "); + + if (size > 0) + { + _sql.append(" WHERE "); + join_vector(_sql, _where_condition, " AND "); } return _sql; } - DeleteModel& reset() { + DeleteModel& reset() + { _table_name.clear(); _where_condition.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, DeleteModel& mod) { - out< Date: Wed, 27 Nov 2024 15:10:22 +0300 Subject: [PATCH 02/35] Inifinitive sql-builder --- sql.h | 1482 +++++++++------------------------------------------------ 1 file changed, 232 insertions(+), 1250 deletions(-) diff --git a/sql.h b/sql.h index 5761d37..aa4acc0 100644 --- a/sql.h +++ b/sql.h @@ -3,29 +3,15 @@ #include #include -#include - -namespace { - -const std::string& quotes("\""); - -} - - namespace sql { class column; -class column_value; -class SelectModel; - class Param { public: - Param(const std::string& param) : - _param(param) {} - Param(const char* param) : - _param(param) {} + Param (const std::string ¶m) : _param(param) {} + Param (const char *param) : _param(param) {} public: std::string operator()() const { return param(); } @@ -35,56 +21,46 @@ class Param const std::string _param; }; -template -inline std::string to_value(const T& data) -{ +template +inline std::string to_value(const T& data) { return std::to_string(data); } -template -inline std::string to_value(char const (&data)[N]) -{ +template +inline std::string to_value(char const(&data)[N]) { std::string str("'"); - str.append(data); str.append("'"); return str; } -template<> -inline std::string to_value(const std::string& data) -{ +template <> +inline std::string to_value(const std::string& data) { std::string str("'"); - str.append(data); str.append("'"); return str; } -template<> -inline std::string to_value(const char* const& data) -{ +template <> +inline std::string to_value(const char* const& data) { std::string str("'"); - str.append(data); str.append("'"); return str; } -template<> -inline std::string to_value(const Param& data) -{ +template <> +inline std::string to_value(const Param& data) { return data(); } -template<> +template <> inline std::string to_value(const column& data); -template<> -inline std::string to_value(const column_value& data); /* - template <> - static std::string sql::to_value(const time_t& data) { +template <> +static std::string sql::to_value(const time_t& data) { char buff[128] = {0}; struct tm* ttime = localtime(&data); strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", ttime); @@ -92,23 +68,17 @@ inline std::string to_value(const column_value& data); str.append(buff); str.append("'"); return str; - } - */ +} +*/ -template -void join_vector(std::string& result, const std::vector& vec, const char* sep) -{ +template +void join_vector(std::string& result, const std::vector& vec, const char* sep) { size_t size = vec.size(); - - for (size_t i = 0; i < size; ++i) - { - if (i < size - 1) - { + for(size_t i = 0; i < size; ++i) { + if(i < size - 1) { result.append(vec[i]); result.append(sep); - } - else - { + } else { result.append(vec[i]); } } @@ -117,150 +87,61 @@ void join_vector(std::string& result, const std::vector& vec, const char* sep class column { public: - - - column() {} - // alias - column(const std::string& column_name, const std::string& alias = "", const std::string& as = "", const std::string& to_type = "") - { - if (!alias.empty()) - _cond.append(alias + "."); - - - - _cond.append(quotes + column_name + quotes); - - if (!to_type.empty()) - _cond.append("::" + to_type); - - if (!as.empty()) - _cond.append(" AS " + as); + column(const std::string& column) { + _cond = column; } + virtual ~column() {} - column(const column& column_name, const std::string& alias = "", const std::string& as = "", const std::string& to_type = "") - { - if (!alias.empty()) - _cond.append(alias + "."); - _cond.append(column_name.str()); - - if (!to_type.empty()) - _cond.append("::" + to_type); - - if (!as.empty()) - _cond.append(" AS " + as); - } - - column& operator()(const std::string& column_name, const std::string& alias = "", const std::string& as = "") - { - if (!alias.empty()) - _cond.append(alias + "."); - _cond.append(quotes + column_name + quotes); - - if (!as.empty()) - _cond.append(" AS " + as); - + column& as(const std::string& s) { + _cond.append(" as "); + _cond.append(s); return *this; } - virtual ~column() {} - - - column& is_null() - { + column& is_null() { _cond.append(" is null"); return *this; } - column& is_not_null() - { + column& is_not_null() { _cond.append(" is not null"); return *this; } - template - column& in (const std::vector& args) { + template + column& in(const std::vector& args) { size_t size = args.size(); - - - - _cond.append(" in ("); - - for (size_t i = 0; i < size; ++i) - { - if (i < size - 1) - { - _cond.append(to_value(args[i])); - _cond.append(", "); - } - else - { - _cond.append(to_value(args[i])); + if(size == 1) { + _cond.append(" = "); + _cond.append(to_value(args[0])); + } else { + _cond.append(" in ("); + for(size_t i = 0; i < size; ++i) { + if(i < size - 1) { + _cond.append(to_value(args[i])); + _cond.append(", "); + } else { + _cond.append(to_value(args[i])); + } } + _cond.append(")"); } - _cond.append(")"); - - return *this; - } - - column& in (const std::string& in_column) { - _cond.append(" in ("); - - _cond.append(in_column); - _cond.append(" ) "); - return *this; - } - - - column& append(const std::string& data) - { - _cond.append(" || '" + data + "' "); - return *this; - } - - column& prepend(const std::string& data) - { - _cond.insert(0, " '" + data + "' || "); - return *this; - } - - // special characters such as %,_ must contains in like_condition - // template<> - column& like(const std::string& like_condition) - { - if (like_condition.size() <= 0) - return *this; - - _cond.append(" LIKE '"); - _cond.append(like_condition); - _cond.append("' "); - - return *this; } - template - column& not_in(const std::vector& args) - { + template + column& not_in(const std::vector& args) { size_t size = args.size(); - - if (size == 1) - { + if(size == 1) { _cond.append(" != "); _cond.append(to_value(args[0])); - } - else - { + } else { _cond.append(" not in ("); - - for (size_t i = 0; i < size; ++i) - { - if (i < size - 1) - { + for(size_t i = 0; i < size; ++i) { + if(i < size - 1) { _cond.append(to_value(args[i])); _cond.append(", "); - } - else - { + } else { _cond.append(to_value(args[i])); } } @@ -269,10 +150,8 @@ class column return *this; } - column& operator&&(column& condition) - { + column& operator &&(column& condition) { std::string str("("); - str.append(_cond); str.append(") and ("); str.append(condition._cond); @@ -281,10 +160,8 @@ class column return condition; } - column& operator||(column& condition) - { + column& operator ||(column& condition) { std::string str("("); - str.append(_cond); str.append(") or ("); str.append(condition._cond); @@ -293,721 +170,102 @@ class column return condition; } - column& operator&&(const std::string& condition) - { + column& operator &&(const std::string& condition) { _cond.append(" and "); _cond.append(condition); return *this; } - column& operator||(const std::string& condition) - { + column& operator ||(const std::string& condition) { _cond.append(" or "); _cond.append(condition); return *this; } - column& operator&&(const char* condition) - { + column& operator &&(const char* condition) { _cond.append(" and "); _cond.append(condition); return *this; } - column& operator||(const char* condition) - { + column& operator ||(const char* condition) { _cond.append(" or "); _cond.append(condition); return *this; } - template - column& operator==(const T& data) - { + template + column& operator ==(const T& data) { _cond.append(" = "); _cond.append(to_value(data)); return *this; } - template - column& operator!=(const T& data) - { + template + column& operator !=(const T& data) { _cond.append(" != "); _cond.append(to_value(data)); return *this; } - template - column& operator>=(const T& data) - { + template + column& operator >=(const T& data) { _cond.append(" >= "); _cond.append(to_value(data)); return *this; } - template - column& operator<=(const T& data) - { + template + column& operator <=(const T& data) { _cond.append(" <= "); _cond.append(to_value(data)); return *this; } - template - column& operator>(const T& data) - { + template + column& operator >(const T& data) { _cond.append(" > "); _cond.append(to_value(data)); return *this; } - template - column& operator<(const T& data) - { + template + column& operator <(const T& data) { _cond.append(" < "); _cond.append(to_value(data)); return *this; } - template - column& operator/(const T& data) - { - _cond.append(" / "); - _cond.append(to_value(data)); - return *this; - } - - template - column& operator+(const T& data) - { - _cond.append(" + "); - _cond.append(to_value(data)); - return *this; - } - - template - column& operator*(const T& data) - { - _cond.append(" * "); - _cond.append(to_value(data)); - return *this; - } - - template - column& operator-(const T& data) - { - _cond.append(" - "); - _cond.append(to_value(data)); - return *this; - } - - const std::string& str() const - { + const std::string& str() const { return _cond; } operator bool() { return true; } - private: std::string _cond; }; - -class table -{ -public: - table(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") - { - if (!tablespace.empty()) - { - table_str_.append(tablespace); - table_str_.append("."); - } - table_str_.append(quotes + table_name + quotes); - - if (!alias.empty()) - table_str_.append(" " + alias + " "); - else - table_str_.append(" "); - } - - const std::string& str() const - {} - -private: - std::string table_str_ = ""; -}; - -class column_value -{ -public: - - column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_value = false) - { - if (!is_value) - _cond.append("'" + column_value + "'"); - else - _cond.append(column_value); - - - if (!to_type.empty()) - _cond.append("::" + to_type); - - if (!as.empty()) - _cond.append(" AS " + as); - } - - const std::string& str() const - { - return _cond; - } - - template - column_value& operator>(const T& data) - { - _cond.append(" > "); - _cond.append(to_value(data)); - return *this; - } - - template - column_value& operator<(const T& data) - { - _cond.append(" < "); - _cond.append(to_value(data)); - return *this; - } - - template - column_value& operator*(const T& data) - { - _cond.append(" * " + to_value(data)); - return *this; - } - -private: - std::string _cond; -}; - -template<> -inline std::string to_value(const column& data) -{ - return data.str(); -} - -inline std::string to_value(const sql::column_value& data) -{ +template <> +inline std::string to_value(const column& data) { return data.str(); } -inline std::string to_value(const std::string& data) -{ - return data; -} - -class SqlFunction -{ -public: - SqlFunction() : - _sql_func("") {} - virtual ~SqlFunction() {} - - virtual std::string str() const = 0; - -private: - // SqlFunction(const SqlFunction& data) = delete; - SqlFunction& operator=(const SqlFunction& data) = delete; - -protected: - std::string _sql_func; -}; - - -class existsStatement : public SqlFunction -{ -public: - - existsStatement() - {} - - template - existsStatement& exists(T subq, const std::string& as) - { - _sql_func.append("EXISTS ("); - _sql_func.append(to_value(subq)); - _sql_func.append(") "); - - if (as.length() > 2) - _sql_func.append(" AS " + as + " "); - - return *this; - } - - virtual std::string str() const override - { - return _sql_func; - } -}; - -class caseStatement : public SqlFunction -{ -public: - caseStatement() - { - _sql_func.append(" END"); - } - - template - caseStatement& case_sql(std::string as = "", std::string case_else = "", Args&& ... conditionals) - { - if (case_else.length() > 2) - _sql_func.insert(0, " ELSE '" + case_else + "'"); - - if (!as.empty()) - _sql_func.append(" AS " + as); - - case_sql(conditionals ...); - return *this; - } - - template - caseStatement& case_sql(std::pair when, Args&& ... conditionals) - { - std::string pb(" WHEN "); - - pb.append(to_value(when.first)); - pb.append(" THEN "); - pb.append(to_value(when.second)); - - _sql_func.insert(0, pb); - case_sql(conditionals ...); - return *this; - } - - caseStatement& case_sql() - { - _sql_func.insert(0, "CASE "); - return *this; - } - - virtual std::string str() const override - { - return _sql_func; - } - - virtual ~caseStatement() {} -}; - -class SqlWindowFunction : public SqlFunction -{ -public: - SqlWindowFunction() {} - virtual ~SqlWindowFunction() {} - - SqlWindowFunction& row_number(const sql::column& column - , const sql::column&& partition = sql::column() - , const sql::column&& order = sql::column() - , const bool& desc = false - , const std::string& as = "") - { - return w_function("ROW_NUMBER", column.str(), partition.str(), order.str(), desc, as); - } - - SqlWindowFunction& sum_over(const sql::column& column - , const std::string& partition = "" - , const std::string& order = "" - , const bool& desc = false - , const std::string& as = "") - { - return w_function("SUM", column.str(), partition, order, desc, as); - } - - SqlWindowFunction& count_over(const sql::column& column - , const std::string& partition = "" - , const std::string& order = "" - , const bool& desc = false - , const std::string& as = "") - { - return w_function("COUNT", column.str(), partition, order, desc, as); - } - - SqlWindowFunction& count(const sql::column& column) - { - _sql_func.clear(); - _sql_func.append("COUNT(" + column.str() + ") "); - - return *this; - } - - SqlWindowFunction& dense_rank( - const std::string& partition = "" - , const std::string& order = "" - , const bool& desc = false - , const std::string& as = "") - { - return w_function("DENSE_RANK", "", partition, order, desc, as); - } - - SqlWindowFunction& dense_rank( - const sql::column& partition = sql::column() - , const sql::column& order = sql::column() - , const bool& desc = false - , const std::string& as = "") - { - return w_function("DENSE_RANK", "", partition.str(), order.str(), desc, as); - } - - SqlWindowFunction& dense_rank( - const sql::column& partition = sql::column() - , const std::vector> order_by_desc = std::vector> - () - , const std::string& as = "") - { - std::vector> order_by_desc_string; - - for (int i = 0; i < order_by_desc.size(); i++) - { - order_by_desc_string.push_back(std::pair(order_by_desc.at(i).first.str(), order_by_desc.at(i).second)); - } - - // const std::vector> const_order_by_desc_string = order_by_desc_string; - return w_function("DENSE_RANK", "", partition.str(), order_by_desc_string, as); - } - - SqlWindowFunction& dense_rank( - const std::string& partition = std::string() - , const std::vector> order_by_desc = std::vector> - () - , const std::string& as = "") - { - return w_function("DENSE_RANK", "", partition, order_by_desc, as); - } - - SqlWindowFunction& rank( - const std::string& partition = "" - , const std::string& order = "" - , const bool& desc = false - , const std::string& as = "") - { - return w_function("RANK", "", partition, order, desc, as); - } - - SqlWindowFunction& rank( - const sql::column& partition = sql::column() - , const sql::column& order = sql::column() - , const bool& desc = false - , const std::string& as = "") - { - return w_function("RANK", "", partition.str(), order.str(), desc, as); - } - - virtual std::string str() const override - { - return _sql_func; - } - -private: - - SqlWindowFunction& w_function(const std::string& function_name, - const std::string& column - , const std::string& partition = "" - , const std::string& order_by = "" - , const bool desc = false - , const std::string& as = "") - { - _sql_func.clear(); - - _sql_func.append(function_name); - - _sql_func.append("("); - - if (!column.empty() || (column.length() > 2)) - _sql_func.append(column); - - _sql_func.append(")"); - _sql_func.append(" OVER "); - _sql_func.append("("); - - - if (partition.length() > 2) - { - _sql_func.append("PARTITION BY "); - _sql_func.append(partition); - - _sql_func.append(" "); - } - - if (order_by.length() > 2) - { - _sql_func.append("ORDER BY "); - _sql_func.append(order_by); - _sql_func.append(" "); - desc ? _sql_func.append(" DESC ") - : _sql_func.append(" ASC "); - _sql_func.append(" ) "); - } - - if (!as.empty()) - _sql_func.append(" AS " + as); - - return *this; - } - - SqlWindowFunction& w_function(const std::string& function_name, - const std::string& column - , - const std::string& partition = "" - , - const std::vector> order_by_desc = std::vector> - () - , - const std::string& as = "") - { - _sql_func.clear(); - _sql_func.append(function_name); - - _sql_func.append("("); - - if (!column.empty() || (column.length() > 2)) - _sql_func.append(column); - - _sql_func.append(")"); - _sql_func.append(" OVER "); - _sql_func.append("("); - - - if (partition.length() > 2) - { - _sql_func.append("PARTITION BY "); - _sql_func.append(partition); - - _sql_func.append(" "); - } - - if (order_by_desc.size() > 0) - { - _sql_func.append("ORDER BY "); - - for (int i = 0; i < order_by_desc.size(); i++) - { - if (order_by_desc.at(i).first.length() > 2) - { - _sql_func.append(order_by_desc.at(i).first); - _sql_func.append(" "); - order_by_desc.at(i).second ? _sql_func.append(" DESC , ") - : _sql_func.append(" ASC , "); - } - } - _sql_func = _sql_func.substr(0, _sql_func.size() - 3); - - _sql_func.append(" ) "); - } - - if (!as.empty()) - _sql_func.append(" AS " + as); - - return *this; - } -}; - -class TimeFormatingFunction : public SqlFunction -{ -public: - TimeFormatingFunction() {} - virtual ~TimeFormatingFunction() {} - - - TimeFormatingFunction& to_timestamp(const column& data) - { - return t_function("to_timestamp", data); - } - - virtual std::string str() const override - { - return _sql_func; - } - -private: - TimeFormatingFunction& t_function(const std::string& name, const column& data) - { - _sql_func.append(name + "(" + data.str() + ")"); - return *this; - } -}; - -class CastFunction : public SqlFunction -{ -public: - CastFunction(const column expression, - - const std::string& data_type = "", - const int& length = 30) - { - _sql_func = "CAST("; - _sql_func.append(expression.str() + " AS " + data_type + ") "); - } - - std::string str() const override - { - return _sql_func; - } -}; - - - - -class RoundFunction : public SqlFunction -{ -public: - RoundFunction(const CastFunction expression, - const std::string& as = "", - const int& length = 30) - { - _sql_func = "ROUND("; - _sql_func.append(expression.str() + " , " + std::to_string(length) + ") "); - - if (!as.empty()) - _sql_func.append(" AS " + as); - } - - RoundFunction(const column expression, - const std::string& as = "", - const int& length = 30) - { - _sql_func = "ROUND("; - _sql_func.append(expression.str() + " , " + std::to_string(length) + ") "); - - if (!as.empty()) - _sql_func.append(" AS " + as); - } - std::string str() const override - { - return _sql_func; - } -}; - - - -class DataTypeFormatingFunction : public SqlFunction -{ -public: - DataTypeFormatingFunction(const std::string& as = "") - { - if (!as.empty()) - _as.append(" AS " + quotes + as + quotes); - } - - std::string str() const override - { - return _sql_func + _as; - } - - virtual ~DataTypeFormatingFunction() {} - - - DataTypeFormatingFunction& to_char(const sql::TimeFormatingFunction& tf_func, - const bool& is_text, - const std::string& format = "") - { - DataTypeFormatingFunction& text = dtf_function("to_char", tf_func.str(), is_text, format); - - - return text; - } - - DataTypeFormatingFunction& to_char(const column& data, - const std::string& format = "") - { - return dtf_function("to_char", data.str(), true, format); - } - - DataTypeFormatingFunction& to_char(const column_value& data, - const std::string& format = "") - { - return dtf_function("to_char", data.str(), false, format); - } - -private: - DataTypeFormatingFunction& dtf_function(const std::string& name, - const std::string& data, - const bool& is_column, - const std::string& format = "") - { - _sql_func.append(name); - - _sql_func.append("("); - _sql_func.append(data); - - if (!format.empty()) - _sql_func.append(", '" + format + "'"); - _sql_func.append(")"); - return *this; - } - - std::string _as; -}; - - - - -class conditional_expressions : public SqlFunction -{ -public: - conditional_expressions(const std::string& as = "") - { - _sql_func.append(" COALESCE ( "); - - if (!as.empty()) - _as.append(" AS " + as); - } - - virtual std::string str() const override - { - return _sql_func + _as; - } - - virtual ~conditional_expressions() {} - - template - conditional_expressions& coalesce(const T& col, Args&& ... cols) - { - _sql_func.append(to_value(col) + " , "); - coalesce(cols ...); - return *this; - } - -private: - conditional_expressions& coalesce() - { - // remove last comma - if (_sql_func.size() > 4) - _sql_func = _sql_func.substr(0, _sql_func.size() - 3); - _sql_func.append(" ) "); - return *this; - } - - std::string _as = ""; -}; - -class SqlModel +class SqlModel { public: SqlModel() {} virtual ~SqlModel() {} virtual const std::string& str() = 0; - const std::string& last_sql() - { + const std::string& last_sql() { return _sql; } - private: - // SqlModel(const SqlModel& m) = delete; - SqlModel& operator=(const SqlModel& data) = delete; - + SqlModel(const SqlModel& m) = delete; + SqlModel& operator =(const SqlModel& data) = delete; protected: std::string _sql; }; @@ -1015,408 +273,203 @@ class SqlModel class SelectModel : public SqlModel { public: - SelectModel() : - _distinct(false) {} + SelectModel() : _distinct(false) {} virtual ~SelectModel() {} - template - SelectModel& select(const std::string& str, Args&& ... columns) - { - const std::string& pb(quotes + str + quotes); - - _select_columns.push_back(pb); - select(columns ...); - return *this; - } - - template - SelectModel& select(const SqlFunction& sql_function, Args&& ... columns) - { - const std::string& pb = sql_function.str(); - - _select_columns.push_back(pb); - select(columns ...); - return *this; - } - - template - SelectModel& select(std::pair subquery, Args&& ... columns) - { - std::string pb(" ( "); - - pb.append(subquery.first.str()); - pb.append(" ) "); - - if (!subquery.second.empty()) - { - pb.append(" AS "); - pb.append(subquery.second); - } - - _select_columns.push_back(pb); - select(columns ...); - return *this; - } - - template - SelectModel& select(const column column_struct, Args&& ... columns) - { - const std::string& pb = column_struct.str(); - - _select_columns.push_back(pb); - select(columns ...); - return *this; - } - - template - SelectModel& select(const column_value data, Args&& ... columns) - { - const std::string& pb = data.str(); - - _select_columns.push_back(pb); - select(columns ...); + template + SelectModel& select(const std::string& str, Args&&... columns) { + _select_columns.push_back(str); + select(columns...); return *this; } // for recursion - SelectModel& select() - { + SelectModel& select() { return *this; } - SelectModel& distinct() - { + SelectModel& distinct() { _distinct = true; return *this; } - // template - SelectModel& from(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") - { - if (!tablespace.empty()) - { - _table_name.append(tablespace); - _table_name.append("."); + template + SelectModel& from(const std::string& table_name, Args&&... tables) { + if(_table_name.empty()) { + _table_name = table_name; + } else { + _table_name.append(", "); + _table_name.append(table_name); } - _table_name.append(quotes + table_name + quotes); - - if (!alias.empty()) - _table_name.append(" " + alias + " "); - else - _table_name.append(" "); - - + from(tables...); return *this; } - - SelectModel& from_subquery(const std::string& table_name, const std::string& alias = "") - { - _table_name.append(table_name); - - if (!alias.empty()) - _table_name.append(" " + alias + " "); - else - _table_name.append(" "); - - + + // for recursion + SelectModel& from() { return *this; } - SelectModel& from(std::vector selects, const std::string& alias = "") - { - for (int i = 0; i < selects.size(); i++) - { - std::string subs_q = selects[i].str(); - - _table_name.append(" ( " + subs_q + " )"); - - if (i != selects.size()) - _table_name.append(" UNION ALL "); - } - - if (!alias.empty()) - _table_name.append(" " + alias + " "); - else - _table_name.append(" "); - + SelectModel& join(const std::string& table_name) { + _join_type = "join"; + _join_table = table_name; return *this; } - SelectModel& join_statement(const std::string& join_type, - const std::string& table_name, - const std::string& tablespace, - const std::string& alias, - const std::string& on_conditions) - { - // std::vector>> type; - - std::string join_type_and_table(" " + join_type + " "); - - if (!tablespace.empty()) - join_type_and_table.append(tablespace + "."); - - join_type_and_table.append(quotes + table_name + quotes); - - if (!alias.empty()) - join_type_and_table.append(" " + alias + " "); - - join_type_and_table.append("ON " + on_conditions); - - _join_type.push_back(join_type_and_table); - + SelectModel& left_join(const std::string& table_name) { + _join_type = "left join"; + _join_table = table_name; return *this; } - SelectModel& left_join(const std::string& table_name, - const column& on_conditions, - const std::string& tablespace = "", - const std::string& alias = "" - ) - { - join_statement("LEFT JOIN", table_name, tablespace, alias, on_conditions.str()); - + SelectModel& left_outer_join(const std::string& table_name) { + _join_type = "left outer join"; + _join_table = table_name; return *this; } - SelectModel& left_outer_join(const std::string& table_name, - const column& on_conditions, - const std::string& tablespace = "", - const std::string& alias = "") - { - join_statement("left outer join", table_name, tablespace, alias, on_conditions.str()); - + SelectModel& right_join(const std::string& table_name) { + _join_type = "right join"; + _join_table = table_name; return *this; } - SelectModel& right_join(const std::string& table_name, - const column& on_conditions, - const std::string& tablespace = "", - const std::string& alias = "" - ) - { - join_statement(" right join ", table_name, tablespace, alias, on_conditions.str()); + SelectModel& right_outer_join(const std::string& table_name) { + _join_type = "right outer join"; + _join_table = table_name; return *this; } - SelectModel& right_outer_join(const std::string& table_name, - const column& on_conditions, - const std::string& tablespace = "", - const std::string& alias = "") - { - join_statement(" RIGHT OUTER JOIN ", table_name, tablespace, alias, on_conditions.str()); + SelectModel& full_join(const std::string& table_name) { + _join_type = "full join"; + _join_table = table_name; return *this; } - SelectModel& full_join(const std::string& table_name, - const column& on_conditions, - const std::string& tablespace = "", - const std::string& alias = "") - { - join_statement(" full join ", table_name, tablespace, alias, on_conditions.str()); + SelectModel& full_outer_join(const std::string& table_name) { + _join_type = "full outer join"; + _join_table = table_name; return *this; } - SelectModel& full_outer_join(const std::string& table_name, - const column& on_conditions, - const std::string& tablespace = "", - const std::string& alias = "") - { - join_statement(" FULL OUTER JOIN ", table_name, tablespace, alias, on_conditions.str()); + SelectModel& on(const std::string& condition) { + _join_on_condition.push_back(condition); return *this; } - SelectModel& where(const std::string& condition) - { - _where_condition.push_back(condition); + SelectModel& on(const column& condition) { + _join_on_condition.push_back(condition.str()); return *this; } - SelectModel& where(const column& condition) - { - _where_condition.push_back(condition.str()); + SelectModel& where(const std::string& condition) { + _where_condition.push_back(condition); return *this; } - SelectModel& where(const column_value& condition) - { + SelectModel& where(const column& condition) { _where_condition.push_back(condition.str()); return *this; } - SelectModel& where_exists(std::vector data) - { - std::string where_c; - - for (int i = 0; i < data.size(); i++) - { - where_c.append("(EXISTS ("); - where_c.append(data[i].str()); - where_c.append(" ) ) OR "); - } - where_c = where_c.substr(0, where_c.length() - 3); - - _where_condition.push_back(where_c); - return *this; - } - - SelectModel& where_not_exists(std::vector data) - { - std::string where_c; - - for (int i = 0; i < data.size(); i++) - { - where_c.append("( NOT EXISTS ("); - where_c.append(data[i].str()); - where_c.append(" ) ) OR "); - } - where_c = where_c.substr(0, where_c.length() - 3); - _where_condition.push_back(where_c); - return *this; - } - - template - SelectModel& where_between(const column& cond, const T& begin_val, const T& end_val) - { - std::string where_val; - - where_val.append(cond.str()); - std::string begin = std::to_string(begin_val); - std::string end = std::to_string(end_val); - where_val.append(" BETWEEN " + begin + " AND " + end); - _where_condition.push_back(where_val); - return *this; - } - - template - SelectModel& group_by(const std::string& str, Args&& ... columns) - { + template + SelectModel& group_by(const std::string& str, Args&&...columns) { _groupby_columns.push_back(str); - group_by(columns ...); + group_by(columns...); return *this; } // for recursion - SelectModel& group_by() - { + SelectModel& group_by() { return *this; } - SelectModel& having(const std::string& condition) - { + SelectModel& having(const std::string& condition) { _having_condition.push_back(condition); return *this; } - SelectModel& having(const column& condition) - { + SelectModel& having(const column& condition) { _having_condition.push_back(condition.str()); return *this; } - SelectModel& order_by(const std::string& order_by, const bool desc = false) - { - _order_by = order_by; - _order_by_desc = desc; + SelectModel& order_by(const std::string& order_by) { + _order_by = order_by; return *this; } - SelectModel& order_by(const column& order_by, const bool desc = false) - { - _order_by = to_value(order_by); - _order_by_desc = desc; - return *this; - } - - template - SelectModel& limit(const T& limit) - { + template + SelectModel& limit(const T& limit) { _limit = std::to_string(limit); return *this; } - - template - SelectModel& limit(const T& offset, const T& limit) - { + template + SelectModel& limit(const T& offset, const T& limit) { _offset = std::to_string(offset); - _limit = std::to_string(limit); + _limit = std::to_string(limit); return *this; } - - template - SelectModel& offset(const T& offset) - { + template + SelectModel& offset(const T& offset) { _offset = std::to_string(offset); return *this; } - virtual const std::string& str() override - { + virtual const std::string& str() override { _sql.clear(); - _sql.append(" SELECT "); - - if (_distinct) - _sql.append(" DISTINCT "); + _sql.append("select "); + if(_distinct) { + _sql.append("distinct "); + } join_vector(_sql, _select_columns, ", "); - _sql.append(" FROM "); + _sql.append(" from "); _sql.append(_table_name); - - if (!_join_type.empty()) - { - for (std::string join :_join_type) - { - _sql.append(" " + join + " "); - } + if(!_join_type.empty()) { + _sql.append(" "); + _sql.append(_join_type); + _sql.append(" "); + _sql.append(_join_table); } - - if (!_where_condition.empty()) - { - _sql.append(" WHERE "); - join_vector(_sql, _where_condition, " AND "); + if(!_join_on_condition.empty()) { + _sql.append(" on "); + join_vector(_sql, _join_on_condition, " and "); } - - if (!_groupby_columns.empty()) - { + if(!_where_condition.empty()) { + _sql.append(" where "); + join_vector(_sql, _where_condition, " and "); + } + if(!_groupby_columns.empty()) { _sql.append(" group by "); join_vector(_sql, _groupby_columns, ", "); } - - if (!_having_condition.empty()) - { + if(!_having_condition.empty()) { _sql.append(" having "); join_vector(_sql, _having_condition, " and "); } - - if (!_order_by.empty()) - { - _sql.append(" ORDER BY "); + if(!_order_by.empty()) { + _sql.append(" order by "); _sql.append(_order_by); - - if (_order_by_desc) - _sql.append(" DESC "); } - - if (!_limit.empty()) - { + if(!_limit.empty()) { _sql.append(" limit "); _sql.append(_limit); } - - if (!_offset.empty()) - { + if(!_offset.empty()) { _sql.append(" offset "); _sql.append(_offset); } return _sql; } - SelectModel& reset() - { + SelectModel& reset() { _select_columns.clear(); _distinct = false; _groupby_columns.clear(); _table_name.clear(); _join_type.clear(); - // 64_join_on_condition.clear(); + _join_table.clear(); + _join_on_condition.clear(); _where_condition.clear(); _having_condition.clear(); _order_by.clear(); @@ -1424,10 +477,8 @@ class SelectModel : public SqlModel _offset.clear(); return *this; } - - friend inline std::ostream& operator<<(std::ostream& out, SelectModel& mod) - { - out << mod.str(); + friend inline std::ostream& operator<< (std::ostream& out, SelectModel& mod) { + out< _groupby_columns; std::string _table_name; - std::vector _join_type; - - // std::vector _join_on_condition; + std::string _join_type; + std::string _join_table; + std::vector _join_on_condition; std::vector _where_condition; std::vector _having_condition; std::string _order_by; - bool _order_by_desc = false; std::string _limit; std::string _offset; }; -inline std::string to_value(SelectModel& data) -{ - return data.str(); -} + class InsertModel : public SqlModel { @@ -1458,93 +505,49 @@ class InsertModel : public SqlModel InsertModel() {} virtual ~InsertModel() {} - template - InsertModel& insert(const std::string& c, const T& data) - { - if constexpr - (std::is_same::value) - { - _columns.push_back(quotes + c + quotes); - std::string v_data = "FALSE"; - - if (data) v_data = "TRUE"; - _values.push_back(v_data); - } - else - if constexpr (std::is_same::value) - { - _columns.push_back(quotes + c + quotes); - - _values.push_back(std::to_string(data)); - } - else - { - _columns.push_back(quotes + c + quotes); - _values.push_back("'" + to_value(data) + "'"); - } - return *this; - } - - InsertModel& insert(const std::string& c) - { - _columns.push_back(quotes + c + quotes); - _values.push_back(" ? "); + template + InsertModel& insert(const std::string& c, const T& data) { + _columns.push_back(c); + _values.push_back(to_value(data)); return *this; } - template - InsertModel& operator()(const std::string& c, const T& data) - { + template + InsertModel& operator()(const std::string& c, const T& data) { return insert(c, data); } - InsertModel& operator()(const std::string& c) - { - return insert(c); - } - - InsertModel& into(const std::string& table_name, const std::string& tablespace = "") - { - _table_name.clear(); - - if (!tablespace.empty()) - _table_name.append(tablespace + "."); - _table_name.append(quotes + table_name + quotes); + InsertModel& into(const std::string& table_name) { + _table_name = table_name; return *this; } - InsertModel& replace(bool var) - { + InsertModel& replace(bool var) { _replace = var; return *this; } - virtual const std::string& str() override - { + virtual const std::string& str() override { _sql.clear(); std::string v_ss; - if (_replace) + if (_replace) { _sql.append("insert or replace into "); - else + }else { _sql.append("insert into "); + } _sql.append(_table_name); _sql.append("("); v_ss.append(" values("); size_t size = _columns.size(); - - for (size_t i = 0; i < size; ++i) - { - if (i < size - 1) - { + for(size_t i = 0; i < size; ++i) { + if(i < size - 1) { _sql.append(_columns[i]); _sql.append(", "); v_ss.append(_values[i]); v_ss.append(", "); - } - else - { + } else { _sql.append(_columns[i]); _sql.append(")"); v_ss.append(_values[i]); @@ -1555,17 +558,15 @@ class InsertModel : public SqlModel return _sql; } - InsertModel& reset() - { + InsertModel& reset() { _table_name.clear(); _columns.clear(); _values.clear(); return *this; } - friend inline std::ostream& operator<<(std::ostream& out, InsertModel& mod) - { - out << mod.str(); + friend inline std::ostream& operator<< (std::ostream& out, InsertModel& mod) { + out< _values; }; -template<> -inline InsertModel& InsertModel::insert(const std::string& c, const std::nullptr_t&) -{ +template <> +inline InsertModel& InsertModel::insert(const std::string& c, const std::nullptr_t&) { _columns.push_back(c); _values.push_back("null"); return *this; } + class UpdateModel : public SqlModel { public: UpdateModel() {} virtual ~UpdateModel() {} - UpdateModel& update(const std::string& table_name) - { + UpdateModel& update(const std::string& table_name) { _table_name = table_name; return *this; } - template - UpdateModel& set(const std::string& c, const T& data) - { + template + UpdateModel& set(const std::string& c, const T& data) { std::string str(c); - str.append(" = "); str.append(to_value(data)); _set_columns.push_back(str); return *this; } - template - UpdateModel& operator()(const std::string& c, const T& data) - { + template + UpdateModel& operator()(const std::string& c, const T& data) { return set(c, data); } - UpdateModel& where(const std::string& condition) - { + UpdateModel& where(const std::string& condition) { _where_condition.push_back(condition); return *this; } - UpdateModel& where(const column& condition) - { + UpdateModel& where(const column& condition) { _where_condition.push_back(condition.str()); return *this; } - virtual const std::string& str() override - { + virtual const std::string& str() override { _sql.clear(); _sql.append("update "); _sql.append(_table_name); _sql.append(" set "); join_vector(_sql, _set_columns, ", "); size_t size = _where_condition.size(); - - if (size > 0) - { - _sql.append(" WHERE "); + if(size > 0) { + _sql.append(" where "); join_vector(_sql, _where_condition, " and "); } return _sql; } - UpdateModel& reset() - { + UpdateModel& reset() { _table_name.clear(); _set_columns.clear(); _where_condition.clear(); return *this; } - - friend inline std::ostream& operator<<(std::ostream& out, UpdateModel& mod) - { - out << mod.str(); + friend inline std::ostream& operator<< (std::ostream& out, UpdateModel& mod) { + out< _where_condition; }; -template<> -inline UpdateModel& UpdateModel::set(const std::string& c, const std::nullptr_t&) -{ +template <> +inline UpdateModel& UpdateModel::set(const std::string& c, const std::nullptr_t&) { std::string str(c); - str.append(" = null"); _set_columns.push_back(str); return *this; } + class DeleteModel : public SqlModel { public: DeleteModel() {} virtual ~DeleteModel() {} - DeleteModel& _delete() - { + DeleteModel& _delete() { return *this; } - template - DeleteModel& from(const std::string& table_name, const std::string& tablespace = "") - { - if (!tablespace.empty()) - { - _table_name.append(tablespace); - _table_name.append("."); + template + DeleteModel& from(const std::string& table_name, Args&&... tables) { + if(_table_name.empty()) { + _table_name = table_name; + } else { + _table_name.append(", "); + _table_name.append(table_name); } - _table_name.append(quotes + table_name + quotes); - _table_name.append(" "); - + from(tables...); + return *this; + } + + // for recursion + DeleteModel& from() { return *this; } - DeleteModel& where(const std::string& condition) - { + DeleteModel& where(const std::string& condition) { _where_condition.push_back(condition); return *this; } - DeleteModel& where(const column& condition) - { + DeleteModel& where(const column& condition) { _where_condition.push_back(condition.str()); return *this; } - virtual const std::string& str() override - { + virtual const std::string& str() override { _sql.clear(); _sql.append("delete from "); _sql.append(_table_name); size_t size = _where_condition.size(); - - if (size > 0) - { - _sql.append(" WHERE "); - join_vector(_sql, _where_condition, " AND "); + if(size > 0) { + _sql.append(" where "); + join_vector(_sql, _where_condition, " and "); } return _sql; } - DeleteModel& reset() - { + DeleteModel& reset() { _table_name.clear(); _where_condition.clear(); return *this; } - - friend inline std::ostream& operator<<(std::ostream& out, DeleteModel& mod) - { - out << mod.str(); + friend inline std::ostream& operator<< (std::ostream& out, DeleteModel& mod) { + out< Date: Wed, 27 Nov 2024 15:11:45 +0300 Subject: [PATCH 03/35] update sqlbuilder --- sql.h | 509 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 329 insertions(+), 180 deletions(-) diff --git a/sql.h b/sql.h index aa4acc0..a8802a3 100644 --- a/sql.h +++ b/sql.h @@ -10,8 +10,10 @@ class column; class Param { public: - Param (const std::string ¶m) : _param(param) {} - Param (const char *param) : _param(param) {} + Param(const std::string& param) : + _param(param) {} + Param(const char* param) : + _param(param) {} public: std::string operator()() const { return param(); } @@ -21,46 +23,54 @@ class Param const std::string _param; }; -template -inline std::string to_value(const T& data) { +template +inline std::string to_value(const T& data) +{ return std::to_string(data); } -template -inline std::string to_value(char const(&data)[N]) { +template +inline std::string to_value(char const (&data)[N]) +{ std::string str("'"); + str.append(data); str.append("'"); return str; } -template <> -inline std::string to_value(const std::string& data) { +template<> +inline std::string to_value(const std::string& data) +{ std::string str("'"); + str.append(data); str.append("'"); return str; } -template <> -inline std::string to_value(const char* const& data) { +template<> +inline std::string to_value(const char* const& data) +{ std::string str("'"); + str.append(data); str.append("'"); return str; } -template <> -inline std::string to_value(const Param& data) { +template<> +inline std::string to_value(const Param& data) +{ return data(); } -template <> +template<> inline std::string to_value(const column& data); /* -template <> -static std::string sql::to_value(const time_t& data) { + template <> + static std::string sql::to_value(const time_t& data) { char buff[128] = {0}; struct tm* ttime = localtime(&data); strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", ttime); @@ -68,17 +78,23 @@ static std::string sql::to_value(const time_t& data) { str.append(buff); str.append("'"); return str; -} -*/ + } + */ -template -void join_vector(std::string& result, const std::vector& vec, const char* sep) { +template +void join_vector(std::string& result, const std::vector& vec, const char* sep) +{ size_t size = vec.size(); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { result.append(vec[i]); result.append(sep); - } else { + } + else + { result.append(vec[i]); } } @@ -87,40 +103,54 @@ void join_vector(std::string& result, const std::vector& vec, const char* sep class column { public: - column(const std::string& column) { + column(const std::string& column) + { _cond = column; } + virtual ~column() {} - column& as(const std::string& s) { + column& as(const std::string& s) + { _cond.append(" as "); _cond.append(s); return *this; } - column& is_null() { + column& is_null() + { _cond.append(" is null"); return *this; } - column& is_not_null() { + column& is_not_null() + { _cond.append(" is not null"); return *this; } - template - column& in(const std::vector& args) { + template + column& in (const std::vector& args) { size_t size = args.size(); - if(size == 1) { + + if (size == 1) + { _cond.append(" = "); _cond.append(to_value(args[0])); - } else { + } + else + { _cond.append(" in ("); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { _cond.append(to_value(args[i])); _cond.append(", "); - } else { + } + else + { _cond.append(to_value(args[i])); } } @@ -129,19 +159,29 @@ class column return *this; } - template - column& not_in(const std::vector& args) { + template + column& not_in(const std::vector& args) + { size_t size = args.size(); - if(size == 1) { + + if (size == 1) + { _cond.append(" != "); _cond.append(to_value(args[0])); - } else { + } + else + { _cond.append(" not in ("); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { _cond.append(to_value(args[i])); _cond.append(", "); - } else { + } + else + { _cond.append(to_value(args[i])); } } @@ -150,8 +190,10 @@ class column return *this; } - column& operator &&(column& condition) { + column& operator&&(column& condition) + { std::string str("("); + str.append(_cond); str.append(") and ("); str.append(condition._cond); @@ -160,8 +202,10 @@ class column return condition; } - column& operator ||(column& condition) { + column& operator||(column& condition) + { std::string str("("); + str.append(_cond); str.append(") or ("); str.append(condition._cond); @@ -170,102 +214,117 @@ class column return condition; } - column& operator &&(const std::string& condition) { + column& operator&&(const std::string& condition) + { _cond.append(" and "); _cond.append(condition); return *this; } - column& operator ||(const std::string& condition) { + column& operator||(const std::string& condition) + { _cond.append(" or "); _cond.append(condition); return *this; } - column& operator &&(const char* condition) { + column& operator&&(const char* condition) + { _cond.append(" and "); _cond.append(condition); return *this; } - column& operator ||(const char* condition) { + column& operator||(const char* condition) + { _cond.append(" or "); _cond.append(condition); return *this; } - template - column& operator ==(const T& data) { + template + column& operator==(const T& data) + { _cond.append(" = "); _cond.append(to_value(data)); return *this; } - template - column& operator !=(const T& data) { + template + column& operator!=(const T& data) + { _cond.append(" != "); _cond.append(to_value(data)); return *this; } - template - column& operator >=(const T& data) { + template + column& operator>=(const T& data) + { _cond.append(" >= "); _cond.append(to_value(data)); return *this; } - template - column& operator <=(const T& data) { + template + column& operator<=(const T& data) + { _cond.append(" <= "); _cond.append(to_value(data)); return *this; } - template - column& operator >(const T& data) { + template + column& operator>(const T& data) + { _cond.append(" > "); _cond.append(to_value(data)); return *this; } - template - column& operator <(const T& data) { + template + column& operator<(const T& data) + { _cond.append(" < "); _cond.append(to_value(data)); return *this; } - const std::string& str() const { + const std::string& str() const + { return _cond; } operator bool() { return true; } + private: std::string _cond; }; -template <> -inline std::string to_value(const column& data) { +template<> +inline std::string to_value(const column& data) +{ return data.str(); } - -class SqlModel +class SqlModel { public: SqlModel() {} virtual ~SqlModel() {} virtual const std::string& str() = 0; - const std::string& last_sql() { + const std::string& last_sql() + { return _sql; } + private: - SqlModel(const SqlModel& m) = delete; - SqlModel& operator =(const SqlModel& data) = delete; + SqlModel(const SqlModel& m) = delete; + SqlModel& operator=(const SqlModel& data) = delete; + protected: std::string _sql; }; @@ -273,196 +332,246 @@ class SqlModel class SelectModel : public SqlModel { public: - SelectModel() : _distinct(false) {} + SelectModel() : + _distinct(false) {} virtual ~SelectModel() {} - template - SelectModel& select(const std::string& str, Args&&... columns) { + template + SelectModel& select(const std::string& str, Args&& ... columns) + { _select_columns.push_back(str); - select(columns...); + select(columns ...); return *this; } // for recursion - SelectModel& select() { + SelectModel& select() + { return *this; } - SelectModel& distinct() { + SelectModel& distinct() + { _distinct = true; return *this; } - template - SelectModel& from(const std::string& table_name, Args&&... tables) { - if(_table_name.empty()) { - _table_name = table_name; - } else { - _table_name.append(", "); - _table_name.append(table_name); + // template + SelectModel& from(const std::string& tablespace, const std::string& table_name) + { + assert(table_name.empty()); + assert(!_table_name.empty()); + + + if (!tablespace.empty()) + { + _table_name.append(tablespace); + _table_name.append("."); } - from(tables...); - return *this; - } - - // for recursion - SelectModel& from() { + _table_name.append("\\\""); + _table_name.append(table_name); + _table_name.append("\"\\"); + return *this; } - SelectModel& join(const std::string& table_name) { - _join_type = "join"; + // // for recursion + // SelectModel& from() { + // return *this; + // } + + SelectModel& join(const std::string& table_name) + { + _join_type = "join"; _join_table = table_name; return *this; } - SelectModel& left_join(const std::string& table_name) { - _join_type = "left join"; + SelectModel& left_join(const std::string& table_name) + { + _join_type = "left join"; _join_table = table_name; return *this; } - SelectModel& left_outer_join(const std::string& table_name) { - _join_type = "left outer join"; + SelectModel& left_outer_join(const std::string& table_name) + { + _join_type = "left outer join"; _join_table = table_name; return *this; } - SelectModel& right_join(const std::string& table_name) { - _join_type = "right join"; + SelectModel& right_join(const std::string& table_name) + { + _join_type = "right join"; _join_table = table_name; return *this; } - SelectModel& right_outer_join(const std::string& table_name) { - _join_type = "right outer join"; + SelectModel& right_outer_join(const std::string& table_name) + { + _join_type = "right outer join"; _join_table = table_name; return *this; } - SelectModel& full_join(const std::string& table_name) { - _join_type = "full join"; + SelectModel& full_join(const std::string& table_name) + { + _join_type = "full join"; _join_table = table_name; return *this; } - SelectModel& full_outer_join(const std::string& table_name) { - _join_type = "full outer join"; + SelectModel& full_outer_join(const std::string& table_name) + { + _join_type = "full outer join"; _join_table = table_name; return *this; } - SelectModel& on(const std::string& condition) { + SelectModel& on(const std::string& condition) + { _join_on_condition.push_back(condition); return *this; } - SelectModel& on(const column& condition) { + SelectModel& on(const column& condition) + { _join_on_condition.push_back(condition.str()); return *this; } - SelectModel& where(const std::string& condition) { + SelectModel& where(const std::string& condition) + { _where_condition.push_back(condition); return *this; } - SelectModel& where(const column& condition) { + SelectModel& where(const column& condition) + { _where_condition.push_back(condition.str()); return *this; } - template - SelectModel& group_by(const std::string& str, Args&&...columns) { + template + SelectModel& group_by(const std::string& str, Args&& ... columns) + { _groupby_columns.push_back(str); - group_by(columns...); + group_by(columns ...); return *this; } // for recursion - SelectModel& group_by() { + SelectModel& group_by() + { return *this; } - SelectModel& having(const std::string& condition) { + SelectModel& having(const std::string& condition) + { _having_condition.push_back(condition); return *this; } - SelectModel& having(const column& condition) { + SelectModel& having(const column& condition) + { _having_condition.push_back(condition.str()); return *this; } - SelectModel& order_by(const std::string& order_by) { + SelectModel& order_by(const std::string& order_by) + { _order_by = order_by; return *this; } - template - SelectModel& limit(const T& limit) { + template + SelectModel& limit(const T& limit) + { _limit = std::to_string(limit); return *this; } - template - SelectModel& limit(const T& offset, const T& limit) { + + template + SelectModel& limit(const T& offset, const T& limit) + { _offset = std::to_string(offset); - _limit = std::to_string(limit); + _limit = std::to_string(limit); return *this; } - template - SelectModel& offset(const T& offset) { + + template + SelectModel& offset(const T& offset) + { _offset = std::to_string(offset); return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); _sql.append("select "); - if(_distinct) { + + if (_distinct) _sql.append("distinct "); - } join_vector(_sql, _select_columns, ", "); _sql.append(" from "); _sql.append(_table_name); - if(!_join_type.empty()) { + + if (!_join_type.empty()) + { _sql.append(" "); _sql.append(_join_type); _sql.append(" "); _sql.append(_join_table); } - if(!_join_on_condition.empty()) { + + if (!_join_on_condition.empty()) + { _sql.append(" on "); join_vector(_sql, _join_on_condition, " and "); } - if(!_where_condition.empty()) { + + if (!_where_condition.empty()) + { _sql.append(" where "); join_vector(_sql, _where_condition, " and "); } - if(!_groupby_columns.empty()) { + + if (!_groupby_columns.empty()) + { _sql.append(" group by "); join_vector(_sql, _groupby_columns, ", "); } - if(!_having_condition.empty()) { + + if (!_having_condition.empty()) + { _sql.append(" having "); join_vector(_sql, _having_condition, " and "); } - if(!_order_by.empty()) { + + if (!_order_by.empty()) + { _sql.append(" order by "); _sql.append(_order_by); } - if(!_limit.empty()) { + + if (!_limit.empty()) + { _sql.append(" limit "); _sql.append(_limit); } - if(!_offset.empty()) { + + if (!_offset.empty()) + { _sql.append(" offset "); _sql.append(_offset); } return _sql; } - SelectModel& reset() { + SelectModel& reset() + { _select_columns.clear(); _distinct = false; _groupby_columns.clear(); @@ -477,8 +586,10 @@ class SelectModel : public SqlModel _offset.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, SelectModel& mod) { - out< - InsertModel& insert(const std::string& c, const T& data) { + template + InsertModel& insert(const std::string& c, const T& data) + { _columns.push_back(c); _values.push_back(to_value(data)); return *this; } - template - InsertModel& operator()(const std::string& c, const T& data) { + template + InsertModel& operator()(const std::string& c, const T& data) + { return insert(c, data); } - InsertModel& into(const std::string& table_name) { + InsertModel& into(const std::string& table_name) + { _table_name = table_name; return *this; } - InsertModel& replace(bool var) { + InsertModel& replace(bool var) + { _replace = var; return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); std::string v_ss; - if (_replace) { + if (_replace) _sql.append("insert or replace into "); - }else { + else _sql.append("insert into "); - } _sql.append(_table_name); _sql.append("("); v_ss.append(" values("); size_t size = _columns.size(); - for(size_t i = 0; i < size; ++i) { - if(i < size - 1) { + + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) + { _sql.append(_columns[i]); _sql.append(", "); v_ss.append(_values[i]); v_ss.append(", "); - } else { + } + else + { _sql.append(_columns[i]); _sql.append(")"); v_ss.append(_values[i]); @@ -558,15 +678,17 @@ class InsertModel : public SqlModel return _sql; } - InsertModel& reset() { + InsertModel& reset() + { _table_name.clear(); _columns.clear(); _values.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, InsertModel& mod) { - out< _values; }; -template <> -inline InsertModel& InsertModel::insert(const std::string& c, const std::nullptr_t&) { +template<> +inline InsertModel& InsertModel::insert(const std::string& c, const std::nullptr_t&) +{ _columns.push_back(c); _values.push_back("null"); return *this; } - class UpdateModel : public SqlModel { public: UpdateModel() {} virtual ~UpdateModel() {} - UpdateModel& update(const std::string& table_name) { + UpdateModel& update(const std::string& table_name) + { _table_name = table_name; return *this; } - template - UpdateModel& set(const std::string& c, const T& data) { + template + UpdateModel& set(const std::string& c, const T& data) + { std::string str(c); + str.append(" = "); str.append(to_value(data)); _set_columns.push_back(str); return *this; } - template - UpdateModel& operator()(const std::string& c, const T& data) { + template + UpdateModel& operator()(const std::string& c, const T& data) + { return set(c, data); } - UpdateModel& where(const std::string& condition) { + UpdateModel& where(const std::string& condition) + { _where_condition.push_back(condition); return *this; } - UpdateModel& where(const column& condition) { + UpdateModel& where(const column& condition) + { _where_condition.push_back(condition.str()); return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); _sql.append("update "); _sql.append(_table_name); _sql.append(" set "); join_vector(_sql, _set_columns, ", "); size_t size = _where_condition.size(); - if(size > 0) { + + if (size > 0) + { _sql.append(" where "); join_vector(_sql, _where_condition, " and "); } return _sql; } - UpdateModel& reset() { + UpdateModel& reset() + { _table_name.clear(); _set_columns.clear(); _where_condition.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, UpdateModel& mod) { - out< _where_condition; }; -template <> -inline UpdateModel& UpdateModel::set(const std::string& c, const std::nullptr_t&) { +template<> +inline UpdateModel& UpdateModel::set(const std::string& c, const std::nullptr_t&) +{ std::string str(c); + str.append(" = null"); _set_columns.push_back(str); return *this; } - class DeleteModel : public SqlModel { public: DeleteModel() {} virtual ~DeleteModel() {} - DeleteModel& _delete() { + DeleteModel& _delete() + { return *this; } - template - DeleteModel& from(const std::string& table_name, Args&&... tables) { - if(_table_name.empty()) { + template + DeleteModel& from(const std::string& table_name, Args&& ... tables) + { + if (_table_name.empty()) + { _table_name = table_name; - } else { + } + else + { _table_name.append(", "); _table_name.append(table_name); } - from(tables...); + from(tables ...); return *this; } - + // for recursion - DeleteModel& from() { + DeleteModel& from() + { return *this; } - DeleteModel& where(const std::string& condition) { + DeleteModel& where(const std::string& condition) + { _where_condition.push_back(condition); return *this; } - DeleteModel& where(const column& condition) { + DeleteModel& where(const column& condition) + { _where_condition.push_back(condition.str()); return *this; } - virtual const std::string& str() override { + virtual const std::string& str() override + { _sql.clear(); _sql.append("delete from "); _sql.append(_table_name); size_t size = _where_condition.size(); - if(size > 0) { + + if (size > 0) + { _sql.append(" where "); join_vector(_sql, _where_condition, " and "); } return _sql; } - DeleteModel& reset() { + DeleteModel& reset() + { _table_name.clear(); _where_condition.clear(); return *this; } - friend inline std::ostream& operator<< (std::ostream& out, DeleteModel& mod) { - out< Date: Wed, 27 Nov 2024 15:14:17 +0300 Subject: [PATCH 04/35] sql-builder: fix coma erorr in from() function --- sql.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql.h b/sql.h index a8802a3..183f4ee 100644 --- a/sql.h +++ b/sql.h @@ -370,7 +370,8 @@ class SelectModel : public SqlModel } _table_name.append("\\\""); _table_name.append(table_name); - _table_name.append("\"\\"); + _table_name.append("\\\""); + _table_name.append(" "); return *this; } From 30c5fdc9217de25c606a4c708b23cfbf81d21878 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 27 Nov 2024 15:16:20 +0300 Subject: [PATCH 05/35] Add window functions. Add first window function row_number() --- sql.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/sql.h b/sql.h index 183f4ee..958f967 100644 --- a/sql.h +++ b/sql.h @@ -309,6 +309,85 @@ inline std::string to_value(const column& data) return data.str(); } +class SqlFunction +{ +public: + SqlFunction() {} + virtual ~SqlFunction() {} + + virtual const std::string& str() const = 0; + +private: + SqlFunction(const SqlFunction& data) = delete; + SqlFunction& operator=(const SqlFunction& data) = delete; + +protected: + std::string _sql_func; +}; + +class SqlWindowFunction : public SqlFunction +{ +public: + SqlWindowFunction() {} + virtual ~SqlWindowFunction() {} + + SqlWindowFunction& row_number(const std::string& column + , const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false) + { + _sql_func.clear(); + + + _sql_func.append("ROW_NUMBER"); + + + _sql_func.append("("); + + if (!column.empty()) + { + _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(column); + _sql_func.append("\\\""); // + \" + } + _sql_func.append(")"); + _sql_func.append(" OVER "); + _sql_func.append("("); + + + if (!partition.empty()) + { + _sql_func.append("PARTITION BY "); + _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(partition); + _sql_func.append("\\\""); // + \" + _sql_func.append(" "); + } + + if (!order.empty()) + { + _sql_func.append("ORDER BY "); + _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(order); + _sql_func.append("\\\""); + _sql_func.append(" "); + } + + if (!partition.empty() || !order.empty()) + desc ? _sql_func.append(" DESC ") + : _sql_func.append(" ASC "); + _sql_func.append(")"); + return *this; + } + + virtual const std::string& str() const override + { + return _sql_func; + } + +private: +}; + class SqlModel { public: From 78c6e580adb46e97e518aad5d9aaa2c1089bf674 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 27 Nov 2024 15:59:31 +0300 Subject: [PATCH 06/35] Add opportunity to add window function into select statement --- sql.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sql.h b/sql.h index 958f967..00208ff 100644 --- a/sql.h +++ b/sql.h @@ -423,6 +423,16 @@ class SelectModel : public SqlModel return *this; } + template + SelectModel& select(const SqlFunction& sql_function, Args&& ... columns) + { + const std::string& pb = sql_function.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + // for recursion SelectModel& select() { @@ -436,10 +446,10 @@ class SelectModel : public SqlModel } // template - SelectModel& from(const std::string& tablespace, const std::string& table_name) + SelectModel& from(const std::string& table_name, const std::string& tablespace = "") { - assert(table_name.empty()); - assert(!_table_name.empty()); + // assert(table_name.empty()); + // assert(!_table_name.empty()); if (!tablespace.empty()) From e79404b5ac8ee2f8288d990c6e704c7982c74d14 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Sat, 30 Nov 2024 01:13:39 +0300 Subject: [PATCH 07/35] fix quotes --- sql.h | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/sql.h b/sql.h index 00208ff..205b4a2 100644 --- a/sql.h +++ b/sql.h @@ -3,6 +3,13 @@ #include #include +namespace { + +const std::string& quotes("\""); + +} + + namespace sql { class column; @@ -346,9 +353,9 @@ class SqlWindowFunction : public SqlFunction if (!column.empty()) { - _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(quotes); // ROW_NUMBER(+ \" _sql_func.append(column); - _sql_func.append("\\\""); // + \" + _sql_func.append(quotes); // + \" } _sql_func.append(")"); _sql_func.append(" OVER "); @@ -358,18 +365,18 @@ class SqlWindowFunction : public SqlFunction if (!partition.empty()) { _sql_func.append("PARTITION BY "); - _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(quotes); // ROW_NUMBER(+ \" _sql_func.append(partition); - _sql_func.append("\\\""); // + \" + _sql_func.append(quotes); // + \" _sql_func.append(" "); } if (!order.empty()) { _sql_func.append("ORDER BY "); - _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(quotes); // ROW_NUMBER(+ \" _sql_func.append(order); - _sql_func.append("\\\""); + _sql_func.append(quotes); _sql_func.append(" "); } @@ -418,7 +425,9 @@ class SelectModel : public SqlModel template SelectModel& select(const std::string& str, Args&& ... columns) { - _select_columns.push_back(str); + const std::string& pb(quotes + str + quotes); + + _select_columns.push_back(pb); select(columns ...); return *this; } @@ -457,9 +466,9 @@ class SelectModel : public SqlModel _table_name.append(tablespace); _table_name.append("."); } - _table_name.append("\\\""); + _table_name.append(quotes); _table_name.append(table_name); - _table_name.append("\\\""); + _table_name.append(quotes); _table_name.append(" "); return *this; From 5f1390558a97eaae24efdf98f45dd2b99d472555 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Sat, 30 Nov 2024 01:18:15 +0300 Subject: [PATCH 08/35] unification window function --- sql.h | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/sql.h b/sql.h index 205b4a2..99ded7d 100644 --- a/sql.h +++ b/sql.h @@ -319,7 +319,8 @@ inline std::string to_value(const column& data) class SqlFunction { public: - SqlFunction() {} + SqlFunction() : + _sql_func("") {} virtual ~SqlFunction() {} virtual const std::string& str() const = 0; @@ -335,28 +336,40 @@ class SqlFunction class SqlWindowFunction : public SqlFunction { public: - SqlWindowFunction() {} + SqlWindowFunction() {} virtual ~SqlWindowFunction() {} SqlWindowFunction& row_number(const std::string& column , const std::string& partition = "" , const std::string& order = "" , const bool& desc = false) + { + return w_function("ROW_NUMBER", column, partition, order, desc); + } + + virtual const std::string& str() const override + { + return _sql_func; + } + +private: + + SqlWindowFunction& w_function(const std::string& function_name, const std::string& column + , const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false) { _sql_func.clear(); - _sql_func.append("ROW_NUMBER"); + _sql_func.append(function_name); _sql_func.append("("); if (!column.empty()) - { - _sql_func.append(quotes); // ROW_NUMBER(+ \" - _sql_func.append(column); - _sql_func.append(quotes); // + \" - } + _sql_func.append(quotes + column + quotes); + _sql_func.append(")"); _sql_func.append(" OVER "); _sql_func.append("("); @@ -365,18 +378,16 @@ class SqlWindowFunction : public SqlFunction if (!partition.empty()) { _sql_func.append("PARTITION BY "); - _sql_func.append(quotes); // ROW_NUMBER(+ \" - _sql_func.append(partition); - _sql_func.append(quotes); // + \" + _sql_func.append(quotes + partition + quotes); + _sql_func.append(" "); } if (!order.empty()) { _sql_func.append("ORDER BY "); - _sql_func.append(quotes); // ROW_NUMBER(+ \" - _sql_func.append(order); - _sql_func.append(quotes); + _sql_func.append(quotes + order + quotes); + . _sql_func.append(" "); } @@ -386,13 +397,6 @@ class SqlWindowFunction : public SqlFunction _sql_func.append(")"); return *this; } - - virtual const std::string& str() const override - { - return _sql_func; - } - -private: }; class SqlModel From 0da768503eeedce24b09d5aa6ecb6b4627729077 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Sat, 30 Nov 2024 01:20:57 +0300 Subject: [PATCH 09/35] update from function in delete statement --- sql.h | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/sql.h b/sql.h index 99ded7d..0c9431c 100644 --- a/sql.h +++ b/sql.h @@ -387,7 +387,6 @@ class SqlWindowFunction : public SqlFunction { _sql_func.append("ORDER BY "); _sql_func.append(quotes + order + quotes); - . _sql_func.append(" "); } @@ -470,16 +469,14 @@ class SelectModel : public SqlModel _table_name.append(tablespace); _table_name.append("."); } - _table_name.append(quotes); - _table_name.append(table_name); - _table_name.append(quotes); + _table_name.append(quotes + table_name + quotes); _table_name.append(" "); return *this; } // // for recursion - // SelectModel& from() { + // DeleteModel& from() { // return *this; // } @@ -910,27 +907,28 @@ class DeleteModel : public SqlModel } template - DeleteModel& from(const std::string& table_name, Args&& ... tables) + DeleteModel& from(const std::string& table_name, const std::string& tablespace = "") { - if (_table_name.empty()) - { - _table_name = table_name; - } - else + // assert(table_name.empty()); + // assert(!_table_name.empty()); + + + if (!tablespace.empty()) { - _table_name.append(", "); - _table_name.append(table_name); + _table_name.append(tablespace); + _table_name.append("."); } - from(tables ...); - return *this; - } + _table_name.append(quotes + table_name + quotes); + _table_name.append(" "); - // for recursion - DeleteModel& from() - { return *this; } + // // for recursion + // SelectModel& from() { + // return *this; + // } + DeleteModel& where(const std::string& condition) { _where_condition.push_back(condition); From 0467fef286e9b5a1916146b2509137547c053964 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Sat, 30 Nov 2024 01:23:32 +0300 Subject: [PATCH 10/35] fix qoutes from delete model statement --- sql.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sql.h b/sql.h index 0c9431c..b8f9032 100644 --- a/sql.h +++ b/sql.h @@ -112,7 +112,7 @@ class column public: column(const std::string& column) { - _cond = column; + _cond = quotes + column + quotes; } virtual ~column() {} @@ -924,11 +924,6 @@ class DeleteModel : public SqlModel return *this; } - // // for recursion - // SelectModel& from() { - // return *this; - // } - DeleteModel& where(const std::string& condition) { _where_condition.push_back(condition); From 17ad9da8eeaac86d6d99a13aa23f9ca730e50b51 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:46:48 +0300 Subject: [PATCH 11/35] Updagte function "into" in InsertModel class --- sql.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sql.h b/sql.h index b8f9032..bbc2195 100644 --- a/sql.h +++ b/sql.h @@ -732,7 +732,16 @@ class InsertModel : public SqlModel InsertModel& into(const std::string& table_name) { - _table_name = table_name; + return insert(c); + } + + InsertModel& into(const std::string& table_name, const std::string& tablespace = "") + { + _table_name.clear(); + + if (!tablespace.empty()) + _table_name.append(tablespace + "."); + _table_name.append(quotes + table_name + quotes); return *this; } From 27ac2f614fcb520dfeb2877f2ef122eb6ecce017 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:47:55 +0300 Subject: [PATCH 12/35] Add insert unknown value of columns, Add quotes to insert columns --- sql.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sql.h b/sql.h index bbc2195..596335c 100644 --- a/sql.h +++ b/sql.h @@ -719,18 +719,25 @@ class InsertModel : public SqlModel template InsertModel& insert(const std::string& c, const T& data) { - _columns.push_back(c); + _columns.push_back(quotes + c + quotes); _values.push_back(to_value(data)); return *this; } + InsertModel& insert(const std::string& c) + { + _columns.push_back(quotes + c + quotes); + _values.push_back(" ? "); + return *this; + } + template InsertModel& operator()(const std::string& c, const T& data) { return insert(c, data); } - InsertModel& into(const std::string& table_name) + InsertModel& operator()(const std::string& c) { return insert(c); } From d7e372fc5780685c60059ab89ad8088b8d926bc0 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:49:17 +0300 Subject: [PATCH 13/35] builder: add alias to column --- sql.h | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/sql.h b/sql.h index 596335c..5041d2e 100644 --- a/sql.h +++ b/sql.h @@ -110,9 +110,28 @@ void join_vector(std::string& result, const std::vector& vec, const char* sep class column { public: - column(const std::string& column) + + // alias + column(const std::string& column_name, const std::string& alias = "", const std::string& as = "") + { + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(quotes + column_name + quotes); + + if (!as.empty()) + _cond.append(" as " + as); + } + + column& operator()(const std::string& column_name, const std::string& alias = "", const std::string& as = "") { - _cond = quotes + column + quotes; + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(quotes + column_name + quotes); + + if (!as.empty()) + _cond.append(" as " + as); + + return *this; } virtual ~column() {} @@ -140,6 +159,7 @@ class column column& in (const std::vector& args) { size_t size = args.size(); + if (size == 1) { _cond.append(" = "); @@ -166,6 +186,7 @@ class column return *this; } + template column& not_in(const std::vector& args) { @@ -445,6 +466,16 @@ class SelectModel : public SqlModel return *this; } + template + SelectModel& select(const column column_struct, Args&& ... columns) + { + const std::string& pb = column_struct.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + // for recursion SelectModel& select() { @@ -475,11 +506,6 @@ class SelectModel : public SqlModel return *this; } - // // for recursion - // DeleteModel& from() { - // return *this; - // } - SelectModel& join(const std::string& table_name) { _join_type = "join"; From eb4c42bcfb6f6fe30b353b31f206739152d1a46c Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:50:06 +0300 Subject: [PATCH 14/35] builder: Add column_value --- sql.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sql.h b/sql.h index 5041d2e..b5730dc 100644 --- a/sql.h +++ b/sql.h @@ -14,6 +14,8 @@ namespace sql { class column; + + class Param { public: @@ -331,6 +333,27 @@ class column std::string _cond; }; +class column_value +{ +public: + + column_value(const std::string& column_value, const std::string& as = "") + { + _cond.append("'" + column_value + "'"); + + if (!as.empty()) + _cond.append(" as " + as); + } + + const std::string& str() const + { + return _cond; + } + +private: + std::string _cond; +}; + template<> inline std::string to_value(const column& data) { @@ -476,6 +499,12 @@ class SelectModel : public SqlModel return *this; } + template + SelectModel& select(const column_value, Args&& ... columns) + { + const std::string& + } + // for recursion SelectModel& select() { From 24633487d417afb02ecef0abedabae01dd327725 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:51:06 +0300 Subject: [PATCH 15/35] add date_type format function --- sql.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/sql.h b/sql.h index b5730dc..5c9bfc1 100644 --- a/sql.h +++ b/sql.h @@ -442,6 +442,43 @@ class SqlWindowFunction : public SqlFunction } }; +class DateTypeFormatingFunction : public SqlFunction +{ +public: + DateTypeFormatingFunction() {} + virtual ~DateTypeFormatingFunction() {} + + virtual const std::string& str() const override + { + return _sql_func; + } + + DateTypeFormatingFunction& to_char(const std::string& name, + const std::string& data, + const bool& is_text, + const std::string& format = "") + { + return dtf_function(name, data, is_text, format) + } + +private: + DateTypeFormatingFunction& dtf_function(const std::string& name, + const std::string& data, + const bool& is_column, + const std::string& format = "") + { + _sql_func.append(name); + + _sql_func.append("("); + _sql_func.append(data); + + if (!format.empty()) + _sql_func.append("," + format); + _sql_func.append(")"); + } +}; + + class SqlModel { public: From 5d26b527a39a5d34438df6d6828b45f4853085af Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:51:47 +0300 Subject: [PATCH 16/35] add to_char --- sql.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sql.h b/sql.h index 5c9bfc1..cdf228d 100644 --- a/sql.h +++ b/sql.h @@ -458,7 +458,7 @@ class DateTypeFormatingFunction : public SqlFunction const bool& is_text, const std::string& format = "") { - return dtf_function(name, data, is_text, format) + return dtf_function(name, data, is_text, format); } private: @@ -536,10 +536,16 @@ class SelectModel : public SqlModel return *this; } + // #define + template - SelectModel& select(const column_value, Args&& ... columns) + SelectModel& select(const column_value data, Args&& ... columns) { - const std::string& + const std::string& pb = data.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; } // for recursion From 34a5caf4c9e0a636711dd21530910e34992a01f0 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 10:58:01 +0300 Subject: [PATCH 17/35] add date_type_format function --- sql.h | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/sql.h b/sql.h index cdf228d..4b2bee2 100644 --- a/sql.h +++ b/sql.h @@ -445,20 +445,35 @@ class SqlWindowFunction : public SqlFunction class DateTypeFormatingFunction : public SqlFunction { public: - DateTypeFormatingFunction() {} - virtual ~DateTypeFormatingFunction() {} - - virtual const std::string& str() const override + DateTypeFormatingFunction(/*const std::string& data, + const bool& is_text*/ + ) { - return _sql_func; + /* if (is_text) + _sql_func.append("'" + data + "'"); + else + _sql_func.append("\"" + data + "\"");*/ } - DateTypeFormatingFunction& to_char(const std::string& name, - const std::string& data, + virtual ~DateTypeFormatingFunction() {} + + + DateTypeFormatingFunction& to_char(const std::string& data, const bool& is_text, const std::string& format = "") { - return dtf_function(name, data, is_text, format); + return dtf_function("to_char", data, is_text, format); + } + + DateTypeFormatingFunction& to_char(const column& data, + const std::string& format = "") + { + return dtf_function("to_char", data.str(), false, format); + } + + virtual const std::string& str() const override + { + return _sql_func; } private: @@ -473,8 +488,9 @@ class DateTypeFormatingFunction : public SqlFunction _sql_func.append(data); if (!format.empty()) - _sql_func.append("," + format); + _sql_func.append(", '" + format + "'"); _sql_func.append(")"); + return *this; } }; @@ -536,8 +552,6 @@ class SelectModel : public SqlModel return *this; } - // #define - template SelectModel& select(const column_value data, Args&& ... columns) { @@ -1084,3 +1098,4 @@ class DeleteModel : public SqlModel }; } + From 03a916188bf08fe399f7a2a6a0799fa449c6b7a8 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 11:02:17 +0300 Subject: [PATCH 18/35] TimeFormatingFunction --- sql.h | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/sql.h b/sql.h index 4b2bee2..469c3b5 100644 --- a/sql.h +++ b/sql.h @@ -445,17 +445,35 @@ class SqlWindowFunction : public SqlFunction class DateTypeFormatingFunction : public SqlFunction { public: - DateTypeFormatingFunction(/*const std::string& data, - const bool& is_text*/ - ) + TimeFormatingFunction() {} + virtual ~TimeFormatingFunction() {} + + + TimeFormatingFunction& to_timestamp(const column& data) { - /* if (is_text) - _sql_func.append("'" + data + "'"); - else - _sql_func.append("\"" + data + "\"");*/ + return t_function("to_timestamp", data); } - virtual ~DateTypeFormatingFunction() {} + virtual const std::string& str() const override + { + return _sql_func; + } + +private: + TimeFormatingFunction& t_function(const std::string& name, const column& data) + { + _sql_func.append(name + "(" + data.str() + ")"); + return *this; + } +}; + +class DataTypeFormatingFunction : public SqlFunction +{ +public: + DataTypeFormatingFunction() + {} + + virtual ~DataTypeFormatingFunction() {} DateTypeFormatingFunction& to_char(const std::string& data, @@ -1098,4 +1116,3 @@ class DeleteModel : public SqlModel }; } - From 9c9778b677ac5af6d85bc3cfef8a609edd3cf292 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 11:06:03 +0300 Subject: [PATCH 19/35] add math operator to columns --- sql.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sql.h b/sql.h index 469c3b5..9acaa2b 100644 --- a/sql.h +++ b/sql.h @@ -320,6 +320,38 @@ class column return *this; } + template + column& operator/(const T& data) + { + _cond.append(" / "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator+(const T& data) + { + _cond.append(" + "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator*(const T& data) + { + _cond.append(" * "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator-(const T& data) + { + _cond.append(" - "); + _cond.append(to_value(data)); + return *this; + } + const std::string& str() const { return _cond; From 78fa6076b782a7cbc50498a2df8fe1a3341aae3e Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 11:07:49 +0300 Subject: [PATCH 20/35] remove standard "as" for column --- sql.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sql.h b/sql.h index 9acaa2b..f8f69ea 100644 --- a/sql.h +++ b/sql.h @@ -138,12 +138,6 @@ class column virtual ~column() {} - column& as(const std::string& s) - { - _cond.append(" as "); - _cond.append(s); - return *this; - } column& is_null() { @@ -1148,3 +1142,4 @@ class DeleteModel : public SqlModel }; } + \ No newline at end of file From 6d09ea97c2995002202e74c94b8f1dfe7d45c3d2 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 11:13:02 +0300 Subject: [PATCH 21/35] Add "AS" to function constructor --- sql.h | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/sql.h b/sql.h index f8f69ea..e33bfb2 100644 --- a/sql.h +++ b/sql.h @@ -468,7 +468,7 @@ class SqlWindowFunction : public SqlFunction } }; -class DateTypeFormatingFunction : public SqlFunction +class TimeFormatingFunction : public SqlFunction { public: TimeFormatingFunction() {} @@ -496,32 +496,35 @@ class DateTypeFormatingFunction : public SqlFunction class DataTypeFormatingFunction : public SqlFunction { public: - DataTypeFormatingFunction() - {} + DataTypeFormatingFunction(const std::string& as = "") + { + if (!as.empty()) + _as.append(" as " + quotes + as + quotes); + } + + virtual const std::string& str() const override + { + return _sql_func + _as; + } virtual ~DataTypeFormatingFunction() {} - DateTypeFormatingFunction& to_char(const std::string& data, + DataTypeFormatingFunction& to_char(const sql::TimeFormatingFunction& tf_func, const bool& is_text, const std::string& format = "") { - return dtf_function("to_char", data, is_text, format); + return dtf_function("to_char", tf_func.str(), is_text, format); } - DateTypeFormatingFunction& to_char(const column& data, + DataTypeFormatingFunction& to_char(const column& data, const std::string& format = "") { return dtf_function("to_char", data.str(), false, format); } - virtual const std::string& str() const override - { - return _sql_func; - } - private: - DateTypeFormatingFunction& dtf_function(const std::string& name, + DataTypeFormatingFunction& dtf_function(const std::string& name, const std::string& data, const bool& is_column, const std::string& format = "") @@ -536,9 +539,12 @@ class DataTypeFormatingFunction : public SqlFunction _sql_func.append(")"); return *this; } + + std::string _as = ""; }; + class SqlModel { public: From 63483a5faa97c6ec12ceccd6fe19d16441b354b1 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 11:17:55 +0300 Subject: [PATCH 22/35] add conditional expressions --- sql.h | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/sql.h b/sql.h index e33bfb2..3e88d9f 100644 --- a/sql.h +++ b/sql.h @@ -543,7 +543,40 @@ class DataTypeFormatingFunction : public SqlFunction std::string _as = ""; }; +class conditional_expressions : public SqlFunction +{ +public: + conditional_expressions(const std::string& as = "") + { + _sql_func.append(" COALESCE ( "); + if (!as.empty()) + _as.append(" as " + quotes + as + quotes); + } + + virtual const std::string& str() const override + { + return _sql_func + _as; + } + + virtual ~conditional_expressions() {} + + template + conditional_expressions& coalesce(const T& col, Args&& ... cols) + { + _sql_func.append(to_value(col)); + coalesce(cols ...); + return *this; + } + +private: + conditional_expressions& coalesce() + { + return *this; + } + + std::string _as = ""; +}; class SqlModel { @@ -1148,4 +1181,4 @@ class DeleteModel : public SqlModel }; } - \ No newline at end of file + From dfb1d0adddaa9a07524bf4bed686f5493d1374d6 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 4 Dec 2024 11:18:58 +0300 Subject: [PATCH 23/35] fix some errors --- sql.h | 111 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 31 deletions(-) diff --git a/sql.h b/sql.h index 3e88d9f..b6a57ba 100644 --- a/sql.h +++ b/sql.h @@ -14,8 +14,14 @@ namespace sql { class column; +class column_value; +class SqlWindowFunction; +class conditional_expressions; + +class DataTypeFormatingFunction; +class TimeFormatingFunction; class Param { public: @@ -38,6 +44,19 @@ inline std::string to_value(const T& data) return std::to_string(data); } +#define TO_VALUE_FUNCTION(TYPE) \ + inline std::string to_value(const TYPE& data) { \ + return data.str(); \ + } + +TO_VALUE_FUNCTION(SqlWindowFunction); +TO_VALUE_FUNCTION(DataTypeFormatingFunction); +TO_VALUE_FUNCTION(TimeFormatingFunction); +TO_VALUE_FUNCTION(sql::column_value); +TO_VALUE_FUNCTION(sql::column); +TO_VALUE_FUNCTION(sql::conditional_expressions); + + template inline std::string to_value(char const (&data)[N]) { @@ -77,6 +96,13 @@ inline std::string to_value(const Param& data) template<> inline std::string to_value(const column& data); +template<> +inline std::string to_value(const column_value& data); + +template<> +inline std::string to_value(const conditional_expressions& data); + + /* template <> static std::string sql::to_value(const time_t& data) { @@ -359,14 +385,24 @@ class column std::string _cond; }; + +template<> +inline std::string to_value(const column& data) +{ + return data.str(); +} + class column_value { public: - column_value(const std::string& column_value, const std::string& as = "") + column_value(const std::string& column_value, const std::string& convert_to = "", const std::string& as = "") { _cond.append("'" + column_value + "'"); + if (!convert_to.empty()) + _cond.append(" ::" + convert_to); + if (!as.empty()) _cond.append(" as " + as); } @@ -381,7 +417,7 @@ class column_value }; template<> -inline std::string to_value(const column& data) +inline std::string to_value(const column_value& data) { return data.str(); } @@ -393,7 +429,12 @@ class SqlFunction _sql_func("") {} virtual ~SqlFunction() {} - virtual const std::string& str() const = 0; + + + const std::string str() + { + return _sql_func + _as; + } private: SqlFunction(const SqlFunction& data) = delete; @@ -401,12 +442,20 @@ class SqlFunction protected: std::string _sql_func; + std::string _as = ""; }; + + class SqlWindowFunction : public SqlFunction { public: - SqlWindowFunction() {} + SqlWindowFunction(const std::string& as = "") + { + if (!as.empty()) + _as = " as " + as; + } + virtual ~SqlWindowFunction() {} SqlWindowFunction& row_number(const std::string& column @@ -417,11 +466,6 @@ class SqlWindowFunction : public SqlFunction return w_function("ROW_NUMBER", column, partition, order, desc); } - virtual const std::string& str() const override - { - return _sql_func; - } - private: SqlWindowFunction& w_function(const std::string& function_name, const std::string& column @@ -471,7 +515,12 @@ class SqlWindowFunction : public SqlFunction class TimeFormatingFunction : public SqlFunction { public: - TimeFormatingFunction() {} + TimeFormatingFunction(const std::string& as = "") + { + if (!as.empty()) + _as = as; + } + virtual ~TimeFormatingFunction() {} @@ -480,11 +529,6 @@ class TimeFormatingFunction : public SqlFunction return t_function("to_timestamp", data); } - virtual const std::string& str() const override - { - return _sql_func; - } - private: TimeFormatingFunction& t_function(const std::string& name, const column& data) { @@ -502,11 +546,6 @@ class DataTypeFormatingFunction : public SqlFunction _as.append(" as " + quotes + as + quotes); } - virtual const std::string& str() const override - { - return _sql_func + _as; - } - virtual ~DataTypeFormatingFunction() {} @@ -539,13 +578,12 @@ class DataTypeFormatingFunction : public SqlFunction _sql_func.append(")"); return *this; } - - std::string _as = ""; }; class conditional_expressions : public SqlFunction { public: + conditional_expressions(const std::string& as = "") { _sql_func.append(" COALESCE ( "); @@ -554,11 +592,6 @@ class conditional_expressions : public SqlFunction _as.append(" as " + quotes + as + quotes); } - virtual const std::string& str() const override - { - return _sql_func + _as; - } - virtual ~conditional_expressions() {} template @@ -570,14 +603,21 @@ class conditional_expressions : public SqlFunction } private: + conditional_expressions& coalesce() { + _sql_func.append(" ) " + _as); return *this; } - - std::string _as = ""; }; + +template<> +inline std::string to_value(const conditional_expressions& data) +{ + return data.str(); +} + class SqlModel { public: @@ -618,7 +658,7 @@ class SelectModel : public SqlModel template SelectModel& select(const SqlFunction& sql_function, Args&& ... columns) { - const std::string& pb = sql_function.str(); + const std::string& pb = to_value(sql_function); _select_columns.push_back(pb); select(columns ...); @@ -645,6 +685,16 @@ class SelectModel : public SqlModel return *this; } + // template + // SelectModel& select(const T data, Args&& ... columns) + // { + // const std::string& pb = to_value(data); + + // _select_columns.push_back(pb); + // select(columns ...); + // return *this; + // } + // for recursion SelectModel& select() { @@ -1181,4 +1231,3 @@ class DeleteModel : public SqlModel }; } - From 25335f387434f080084ae1551fe34dbfc31d040c Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Mon, 3 Feb 2025 14:33:39 +0300 Subject: [PATCH 24/35] const and ref fix --- sql.h | 369 ++++++++-------------------------------------------------- 1 file changed, 51 insertions(+), 318 deletions(-) diff --git a/sql.h b/sql.h index b6a57ba..00208ff 100644 --- a/sql.h +++ b/sql.h @@ -3,25 +3,10 @@ #include #include -namespace { - -const std::string& quotes("\""); - -} - - namespace sql { class column; -class column_value; - -class SqlWindowFunction; - -class conditional_expressions; - -class DataTypeFormatingFunction; -class TimeFormatingFunction; class Param { public: @@ -44,19 +29,6 @@ inline std::string to_value(const T& data) return std::to_string(data); } -#define TO_VALUE_FUNCTION(TYPE) \ - inline std::string to_value(const TYPE& data) { \ - return data.str(); \ - } - -TO_VALUE_FUNCTION(SqlWindowFunction); -TO_VALUE_FUNCTION(DataTypeFormatingFunction); -TO_VALUE_FUNCTION(TimeFormatingFunction); -TO_VALUE_FUNCTION(sql::column_value); -TO_VALUE_FUNCTION(sql::column); -TO_VALUE_FUNCTION(sql::conditional_expressions); - - template inline std::string to_value(char const (&data)[N]) { @@ -96,13 +68,6 @@ inline std::string to_value(const Param& data) template<> inline std::string to_value(const column& data); -template<> -inline std::string to_value(const column_value& data); - -template<> -inline std::string to_value(const conditional_expressions& data); - - /* template <> static std::string sql::to_value(const time_t& data) { @@ -138,33 +103,20 @@ void join_vector(std::string& result, const std::vector& vec, const char* sep class column { public: - - // alias - column(const std::string& column_name, const std::string& alias = "", const std::string& as = "") + column(const std::string& column) { - if (!alias.empty()) - _cond.append(alias + "."); - _cond.append(quotes + column_name + quotes); - - if (!as.empty()) - _cond.append(" as " + as); + _cond = column; } - column& operator()(const std::string& column_name, const std::string& alias = "", const std::string& as = "") - { - if (!alias.empty()) - _cond.append(alias + "."); - _cond.append(quotes + column_name + quotes); - - if (!as.empty()) - _cond.append(" as " + as); + virtual ~column() {} + column& as(const std::string& s) + { + _cond.append(" as "); + _cond.append(s); return *this; } - virtual ~column() {} - - column& is_null() { _cond.append(" is null"); @@ -181,7 +133,6 @@ class column column& in (const std::vector& args) { size_t size = args.size(); - if (size == 1) { _cond.append(" = "); @@ -208,7 +159,6 @@ class column return *this; } - template column& not_in(const std::vector& args) { @@ -340,38 +290,6 @@ class column return *this; } - template - column& operator/(const T& data) - { - _cond.append(" / "); - _cond.append(to_value(data)); - return *this; - } - - template - column& operator+(const T& data) - { - _cond.append(" + "); - _cond.append(to_value(data)); - return *this; - } - - template - column& operator*(const T& data) - { - _cond.append(" * "); - _cond.append(to_value(data)); - return *this; - } - - template - column& operator-(const T& data) - { - _cond.append(" - "); - _cond.append(to_value(data)); - return *this; - } - const std::string& str() const { return _cond; @@ -385,56 +303,19 @@ class column std::string _cond; }; - template<> inline std::string to_value(const column& data) { return data.str(); } -class column_value -{ -public: - - column_value(const std::string& column_value, const std::string& convert_to = "", const std::string& as = "") - { - _cond.append("'" + column_value + "'"); - - if (!convert_to.empty()) - _cond.append(" ::" + convert_to); - - if (!as.empty()) - _cond.append(" as " + as); - } - - const std::string& str() const - { - return _cond; - } - -private: - std::string _cond; -}; - -template<> -inline std::string to_value(const column_value& data) -{ - return data.str(); -} - class SqlFunction { public: - SqlFunction() : - _sql_func("") {} + SqlFunction() {} virtual ~SqlFunction() {} - - - const std::string str() - { - return _sql_func + _as; - } + virtual const std::string& str() const = 0; private: SqlFunction(const SqlFunction& data) = delete; @@ -442,48 +323,33 @@ class SqlFunction protected: std::string _sql_func; - std::string _as = ""; }; - - class SqlWindowFunction : public SqlFunction { public: - SqlWindowFunction(const std::string& as = "") - { - if (!as.empty()) - _as = " as " + as; - } - + SqlWindowFunction() {} virtual ~SqlWindowFunction() {} SqlWindowFunction& row_number(const std::string& column , const std::string& partition = "" , const std::string& order = "" , const bool& desc = false) - { - return w_function("ROW_NUMBER", column, partition, order, desc); - } - -private: - - SqlWindowFunction& w_function(const std::string& function_name, const std::string& column - , const std::string& partition = "" - , const std::string& order = "" - , const bool& desc = false) { _sql_func.clear(); - _sql_func.append(function_name); + _sql_func.append("ROW_NUMBER"); _sql_func.append("("); if (!column.empty()) - _sql_func.append(quotes + column + quotes); - + { + _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(column); + _sql_func.append("\\\""); // + \" + } _sql_func.append(")"); _sql_func.append(" OVER "); _sql_func.append("("); @@ -492,15 +358,18 @@ class SqlWindowFunction : public SqlFunction if (!partition.empty()) { _sql_func.append("PARTITION BY "); - _sql_func.append(quotes + partition + quotes); - + _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(partition); + _sql_func.append("\\\""); // + \" _sql_func.append(" "); } if (!order.empty()) { _sql_func.append("ORDER BY "); - _sql_func.append(quotes + order + quotes); + _sql_func.append("\\\""); // ROW_NUMBER(+ \" + _sql_func.append(order); + _sql_func.append("\\\""); _sql_func.append(" "); } @@ -510,114 +379,15 @@ class SqlWindowFunction : public SqlFunction _sql_func.append(")"); return *this; } -}; - -class TimeFormatingFunction : public SqlFunction -{ -public: - TimeFormatingFunction(const std::string& as = "") - { - if (!as.empty()) - _as = as; - } - - virtual ~TimeFormatingFunction() {} - - - TimeFormatingFunction& to_timestamp(const column& data) - { - return t_function("to_timestamp", data); - } - -private: - TimeFormatingFunction& t_function(const std::string& name, const column& data) - { - _sql_func.append(name + "(" + data.str() + ")"); - return *this; - } -}; - -class DataTypeFormatingFunction : public SqlFunction -{ -public: - DataTypeFormatingFunction(const std::string& as = "") - { - if (!as.empty()) - _as.append(" as " + quotes + as + quotes); - } - - virtual ~DataTypeFormatingFunction() {} - - - DataTypeFormatingFunction& to_char(const sql::TimeFormatingFunction& tf_func, - const bool& is_text, - const std::string& format = "") - { - return dtf_function("to_char", tf_func.str(), is_text, format); - } - - DataTypeFormatingFunction& to_char(const column& data, - const std::string& format = "") - { - return dtf_function("to_char", data.str(), false, format); - } - -private: - DataTypeFormatingFunction& dtf_function(const std::string& name, - const std::string& data, - const bool& is_column, - const std::string& format = "") - { - _sql_func.append(name); - - _sql_func.append("("); - _sql_func.append(data); - - if (!format.empty()) - _sql_func.append(", '" + format + "'"); - _sql_func.append(")"); - return *this; - } -}; - -class conditional_expressions : public SqlFunction -{ -public: - - conditional_expressions(const std::string& as = "") - { - _sql_func.append(" COALESCE ( "); - - if (!as.empty()) - _as.append(" as " + quotes + as + quotes); - } - - virtual ~conditional_expressions() {} - template - conditional_expressions& coalesce(const T& col, Args&& ... cols) + virtual const std::string& str() const override { - _sql_func.append(to_value(col)); - coalesce(cols ...); - return *this; + return _sql_func; } private: - - conditional_expressions& coalesce() - { - _sql_func.append(" ) " + _as); - return *this; - } }; - -template<> -inline std::string to_value(const conditional_expressions& data) -{ - return data.str(); -} - class SqlModel { public: @@ -648,9 +418,7 @@ class SelectModel : public SqlModel template SelectModel& select(const std::string& str, Args&& ... columns) { - const std::string& pb(quotes + str + quotes); - - _select_columns.push_back(pb); + _select_columns.push_back(str); select(columns ...); return *this; } @@ -658,43 +426,13 @@ class SelectModel : public SqlModel template SelectModel& select(const SqlFunction& sql_function, Args&& ... columns) { - const std::string& pb = to_value(sql_function); - - _select_columns.push_back(pb); - select(columns ...); - return *this; - } - - template - SelectModel& select(const column column_struct, Args&& ... columns) - { - const std::string& pb = column_struct.str(); - - _select_columns.push_back(pb); - select(columns ...); - return *this; - } - - template - SelectModel& select(const column_value data, Args&& ... columns) - { - const std::string& pb = data.str(); + const std::string& pb = sql_function.str(); _select_columns.push_back(pb); select(columns ...); return *this; } - // template - // SelectModel& select(const T data, Args&& ... columns) - // { - // const std::string& pb = to_value(data); - - // _select_columns.push_back(pb); - // select(columns ...); - // return *this; - // } - // for recursion SelectModel& select() { @@ -719,12 +457,19 @@ class SelectModel : public SqlModel _table_name.append(tablespace); _table_name.append("."); } - _table_name.append(quotes + table_name + quotes); + _table_name.append("\\\""); + _table_name.append(table_name); + _table_name.append("\\\""); _table_name.append(" "); return *this; } + // // for recursion + // SelectModel& from() { + // return *this; + // } + SelectModel& join(const std::string& table_name) { _join_type = "join"; @@ -964,36 +709,20 @@ class InsertModel : public SqlModel template InsertModel& insert(const std::string& c, const T& data) { - _columns.push_back(quotes + c + quotes); + _columns.push_back(c); _values.push_back(to_value(data)); return *this; } - InsertModel& insert(const std::string& c) - { - _columns.push_back(quotes + c + quotes); - _values.push_back(" ? "); - return *this; - } - template InsertModel& operator()(const std::string& c, const T& data) { return insert(c, data); } - InsertModel& operator()(const std::string& c) + InsertModel& into(const std::string& table_name) { - return insert(c); - } - - InsertModel& into(const std::string& table_name, const std::string& tablespace = "") - { - _table_name.clear(); - - if (!tablespace.empty()) - _table_name.append(tablespace + "."); - _table_name.append(quotes + table_name + quotes); + _table_name = table_name; return *this; } @@ -1168,20 +897,24 @@ class DeleteModel : public SqlModel } template - DeleteModel& from(const std::string& table_name, const std::string& tablespace = "") + DeleteModel& from(const std::string& table_name, Args&& ... tables) { - // assert(table_name.empty()); - // assert(!_table_name.empty()); - - - if (!tablespace.empty()) + if (_table_name.empty()) { - _table_name.append(tablespace); - _table_name.append("."); + _table_name = table_name; } - _table_name.append(quotes + table_name + quotes); - _table_name.append(" "); + else + { + _table_name.append(", "); + _table_name.append(table_name); + } + from(tables ...); + return *this; + } + // for recursion + DeleteModel& from() + { return *this; } From aa87d310db6682ff8f38beaad48498a420ff8ff4 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Mon, 3 Feb 2025 14:42:19 +0300 Subject: [PATCH 25/35] add to type cast to column with value --- sql.h | 358 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 309 insertions(+), 49 deletions(-) diff --git a/sql.h b/sql.h index 00208ff..3a5f9f4 100644 --- a/sql.h +++ b/sql.h @@ -3,10 +3,19 @@ #include #include +namespace { + +const std::string& quotes("\""); + +} + + namespace sql { class column; + + class Param { public: @@ -103,20 +112,33 @@ void join_vector(std::string& result, const std::vector& vec, const char* sep class column { public: - column(const std::string& column) + + // alias + column(const std::string& column_name, const std::string& alias = "", const std::string& as = "") { - _cond = column; - } + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(quotes + column_name + quotes); - virtual ~column() {} + if (!as.empty()) + _cond.append(" as " + as); + } - column& as(const std::string& s) + column& operator()(const std::string& column_name, const std::string& alias = "", const std::string& as = "") { - _cond.append(" as "); - _cond.append(s); + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(quotes + column_name + quotes); + + if (!as.empty()) + _cond.append(" as " + as); + return *this; } + virtual ~column() {} + + column& is_null() { _cond.append(" is null"); @@ -133,6 +155,7 @@ class column column& in (const std::vector& args) { size_t size = args.size(); + if (size == 1) { _cond.append(" = "); @@ -159,6 +182,7 @@ class column return *this; } + template column& not_in(const std::vector& args) { @@ -290,6 +314,38 @@ class column return *this; } + template + column& operator/(const T& data) + { + _cond.append(" / "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator+(const T& data) + { + _cond.append(" + "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator*(const T& data) + { + _cond.append(" * "); + _cond.append(to_value(data)); + return *this; + } + + template + column& operator-(const T& data) + { + _cond.append(" - "); + _cond.append(to_value(data)); + return *this; + } + const std::string& str() const { return _cond; @@ -303,6 +359,30 @@ class column std::string _cond; }; +class column_value +{ +public: + + column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "") + { + _cond.append("'" + column_value + "'"); + + if (!to_type.empty()) + _cond.append(" ::" + to_type); + + if (!as.empty()) + _cond.append(" as " + as); + } + + const std::string& str() const + { + return _cond; + } + +private: + std::string _cond; +}; + template<> inline std::string to_value(const column& data) { @@ -312,10 +392,11 @@ inline std::string to_value(const column& data) class SqlFunction { public: - SqlFunction() {} + SqlFunction() : + _sql_func("") {} virtual ~SqlFunction() {} - virtual const std::string& str() const = 0; + virtual std::string str() const = 0; private: SqlFunction(const SqlFunction& data) = delete; @@ -328,28 +409,40 @@ class SqlFunction class SqlWindowFunction : public SqlFunction { public: - SqlWindowFunction() {} + SqlWindowFunction() {} virtual ~SqlWindowFunction() {} SqlWindowFunction& row_number(const std::string& column , const std::string& partition = "" , const std::string& order = "" , const bool& desc = false) + { + return w_function("ROW_NUMBER", column, partition, order, desc); + } + + virtual std::string str() const override + { + return _sql_func; + } + +private: + + SqlWindowFunction& w_function(const std::string& function_name, const std::string& column + , const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false) { _sql_func.clear(); - _sql_func.append("ROW_NUMBER"); + _sql_func.append(function_name); _sql_func.append("("); if (!column.empty()) - { - _sql_func.append("\\\""); // ROW_NUMBER(+ \" - _sql_func.append(column); - _sql_func.append("\\\""); // + \" - } + _sql_func.append(quotes + column + quotes); + _sql_func.append(")"); _sql_func.append(" OVER "); _sql_func.append("("); @@ -358,18 +451,15 @@ class SqlWindowFunction : public SqlFunction if (!partition.empty()) { _sql_func.append("PARTITION BY "); - _sql_func.append("\\\""); // ROW_NUMBER(+ \" - _sql_func.append(partition); - _sql_func.append("\\\""); // + \" + _sql_func.append(quotes + partition + quotes); + _sql_func.append(" "); } if (!order.empty()) { _sql_func.append("ORDER BY "); - _sql_func.append("\\\""); // ROW_NUMBER(+ \" - _sql_func.append(order); - _sql_func.append("\\\""); + _sql_func.append(quotes + order + quotes); _sql_func.append(" "); } @@ -379,13 +469,122 @@ class SqlWindowFunction : public SqlFunction _sql_func.append(")"); return *this; } +}; + +class TimeFormatingFunction : public SqlFunction +{ +public: + TimeFormatingFunction() {} + virtual ~TimeFormatingFunction() {} + + + TimeFormatingFunction& to_timestamp(const column& data) + { + return t_function("to_timestamp", data); + } - virtual const std::string& str() const override + virtual std::string str() const override { return _sql_func; } private: + TimeFormatingFunction& t_function(const std::string& name, const column& data) + { + _sql_func.append(name + "(" + data.str() + ")"); + return *this; + } +}; + +class DataTypeFormatingFunction : public SqlFunction +{ +public: + DataTypeFormatingFunction(const std::string& as = "") + { + if (!as.empty()) + _as.append(" as " + quotes + as + quotes); + } + + std::string str() const override + { + // std::string result = _sql_func; + + // result = result.append(_as); + return _sql_func + _as; // CRASHES WTF + } + + virtual ~DataTypeFormatingFunction() {} + + + DataTypeFormatingFunction& to_char(const sql::TimeFormatingFunction& tf_func, + const bool& is_text, + const std::string& format = "") + { + DataTypeFormatingFunction& text = dtf_function("to_char", tf_func.str(), is_text, format); + std::string text_SDF = text.str(); + + return text; + } + + DataTypeFormatingFunction& to_char(const column& data, + const std::string& format = "") + { + return dtf_function("to_char", data.str(), false, format); + } + +private: + DataTypeFormatingFunction& dtf_function(const std::string& name, + const std::string& data, + const bool& is_column, + const std::string& format = "") + { + _sql_func.append(name); + + _sql_func.append("("); + _sql_func.append(data); + + if (!format.empty()) + _sql_func.append(", '" + format + "'"); + _sql_func.append(")"); + return *this; + } + + std::string _as; +}; + +class conditional_expressions : public SqlFunction +{ +public: + conditional_expressions(const std::string& as = "") + { + _sql_func.append(" COALESCE ( "); + + if (!as.empty()) + _as.append(" as " + quotes + as + quotes); + } + + virtual std::string str() const override + { + return _sql_func + _as; + } + + virtual ~conditional_expressions() {} + + template + conditional_expressions& coalesce(const T& col, Args&& ... cols) + { + _sql_func.append(to_value(col)); + coalesce(cols ...); + return *this; + } + +private: + conditional_expressions& coalesce() + { + return *this; + } + + std::string _as = ""; }; class SqlModel @@ -418,7 +617,9 @@ class SelectModel : public SqlModel template SelectModel& select(const std::string& str, Args&& ... columns) { - _select_columns.push_back(str); + const std::string& pb(quotes + str + quotes); + + _select_columns.push_back(pb); select(columns ...); return *this; } @@ -433,6 +634,26 @@ class SelectModel : public SqlModel return *this; } + template + SelectModel& select(const column column_struct, Args&& ... columns) + { + const std::string& pb = column_struct.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + + template + SelectModel& select(const column_value data, Args&& ... columns) + { + const std::string& pb = data.str(); + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + // for recursion SelectModel& select() { @@ -457,19 +678,12 @@ class SelectModel : public SqlModel _table_name.append(tablespace); _table_name.append("."); } - _table_name.append("\\\""); - _table_name.append(table_name); - _table_name.append("\\\""); + _table_name.append(quotes + table_name + quotes); _table_name.append(" "); return *this; } - // // for recursion - // SelectModel& from() { - // return *this; - // } - SelectModel& join(const std::string& table_name) { _join_type = "join"; @@ -709,20 +923,36 @@ class InsertModel : public SqlModel template InsertModel& insert(const std::string& c, const T& data) { - _columns.push_back(c); + _columns.push_back(quotes + c + quotes); _values.push_back(to_value(data)); return *this; } + InsertModel& insert(const std::string& c) + { + _columns.push_back(quotes + c + quotes); + _values.push_back(" ? "); + return *this; + } + template InsertModel& operator()(const std::string& c, const T& data) { return insert(c, data); } - InsertModel& into(const std::string& table_name) + InsertModel& operator()(const std::string& c) { - _table_name = table_name; + return insert(c); + } + + InsertModel& into(const std::string& table_name, const std::string& tablespace = "") + { + _table_name.clear(); + + if (!tablespace.empty()) + _table_name.append(tablespace + "."); + _table_name.append(quotes + table_name + quotes); return *this; } @@ -897,24 +1127,20 @@ class DeleteModel : public SqlModel } template - DeleteModel& from(const std::string& table_name, Args&& ... tables) + DeleteModel& from(const std::string& table_name, const std::string& tablespace = "") { - if (_table_name.empty()) - { - _table_name = table_name; - } - else + // assert(table_name.empty()); + // assert(!_table_name.empty()); + + + if (!tablespace.empty()) { - _table_name.append(", "); - _table_name.append(table_name); + _table_name.append(tablespace); + _table_name.append("."); } - from(tables ...); - return *this; - } + _table_name.append(quotes + table_name + quotes); + _table_name.append(" "); - // for recursion - DeleteModel& from() - { return *this; } @@ -964,3 +1190,37 @@ class DeleteModel : public SqlModel }; } +// #define DIAGNOSIS_FLIGHT(NAME, SUBSYSTEM, FLIGHT_TYPE, TEST_PARAMETERS, TITLE, RESULTS) \ +// ac_menu_ ## SUBSYSTEM ## NAME ## _ = new QAction(TITLE, this); \ +// menu_ ## SUBSYSTEM ## _->addAction(ac_menu_ ## SUBSYSTEM ## NAME ## _); + +// ALL_DIAGNOSIS_FLIGHTS +// #undef DIAGNOSIS_FLIGHT +// #define ALL_DIAGNOSIS_FLIGHTS \ +// DIAGNOSIS_FLIGHT(GeoBinding, PAR, \ +// FlightType::kGeoBinding, \ +// { TestedParameter::pCircleGeoBinding }, \ +// "Определение координат ПАР", \ +// { TestResultsName::kGeoBindingLatitudeResultName COMMA \ +// TestResultsName::kGeoBindingLongitudeResultName COMMA \ +// TestResultsName::kGeoBindingAltitudeResultName COMMA \ +// TestResultsName::kFlightDataIntervalResultName COMMA \ +// TestResultsName::kGeoBindingAzimuthResultName COMMA \ +// TestResultsName::kGeoBindingRollResultName COMMA \ +// TestResultsName::kGeoBindingPitchResultName COMMA \ +// }) \ +// // +// #define DIAGNOSIS_FLIGHT(NAME, SUBSYSTEM, FLIGHT_TYPE, TEST_PARAMETERS, TITLE, RESULTS) \ +// const static DiagnosisFlight f ## SUBSYSTEM ## NAME = DiagnosisFlight(Subsystem::s ## SUBSYSTEM, \ +// FLIGHT_TYPE, \ +// TEST_PARAMETERS, \ +// TITLE, \ +// RESULTS); + +// ALL_DIAGNOSIS_FLIGHTS +// #undef DIAGNOSIS_FLIGHT + + +// #define SELECT_STATEMENT(TYPE) + +// #undef SELECT_STATEMENT(TYPE) From 716faed1c030e50e78766229cd4ba588d03abbb9 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Mon, 3 Feb 2025 14:43:26 +0300 Subject: [PATCH 26/35] column with value to string --- sql.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sql.h b/sql.h index 3a5f9f4..b654383 100644 --- a/sql.h +++ b/sql.h @@ -14,7 +14,7 @@ namespace sql { class column; - +class column_value; class Param { @@ -76,6 +76,8 @@ inline std::string to_value(const Param& data) template<> inline std::string to_value(const column& data); +template<> +inline std::string to_value(const column_value& data); /* template <> @@ -389,6 +391,11 @@ inline std::string to_value(const column& data) return data.str(); } +inline std::string to_value(const sql::column_value& data) +{ + return data.str(); +} + class SqlFunction { public: From 44b7438ddec2301271f16405e3e332043459a39d Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Mon, 3 Feb 2025 14:44:25 +0300 Subject: [PATCH 27/35] fix coalesce last param --- sql.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql.h b/sql.h index b654383..eb9f2eb 100644 --- a/sql.h +++ b/sql.h @@ -580,7 +580,7 @@ class conditional_expressions : public SqlFunction template conditional_expressions& coalesce(const T& col, Args&& ... cols) { - _sql_func.append(to_value(col)); + _sql_func.append(to_value(col) + " , "); coalesce(cols ...); return *this; } @@ -588,6 +588,10 @@ class conditional_expressions : public SqlFunction private: conditional_expressions& coalesce() { + // remove last comma + if (_sql_func.size() > 4) + _sql_func = _sql_func.substr(0, _sql_func.size() - 3); + _sql_func.append(" ) "); return *this; } From d20cadb974c39b0229def7822147d32f5b836781 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Mon, 3 Feb 2025 14:48:49 +0300 Subject: [PATCH 28/35] Add alias to from function --- sql.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sql.h b/sql.h index eb9f2eb..eaaee1b 100644 --- a/sql.h +++ b/sql.h @@ -678,12 +678,8 @@ class SelectModel : public SqlModel } // template - SelectModel& from(const std::string& table_name, const std::string& tablespace = "") + SelectModel& from(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") { - // assert(table_name.empty()); - // assert(!_table_name.empty()); - - if (!tablespace.empty()) { _table_name.append(tablespace); From 69953257fe16da0b9eafb4f0c445c31ea10a30e0 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 19 Feb 2025 18:11:46 +0300 Subject: [PATCH 29/35] small fix --- sql.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql.h b/sql.h index eaaee1b..fa85b64 100644 --- a/sql.h +++ b/sql.h @@ -686,7 +686,12 @@ class SelectModel : public SqlModel _table_name.append("."); } _table_name.append(quotes + table_name + quotes); - _table_name.append(" "); + + if (!alias.empty()) + _table_name.append(" " + alias + " "); + else + _table_name.append(" "); + return *this; } From bfb7e3aef121d678cfea4405a7cc96f3c91aec5f Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 19 Feb 2025 18:12:18 +0300 Subject: [PATCH 30/35] update left join function --- sql.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/sql.h b/sql.h index fa85b64..e693a66 100644 --- a/sql.h +++ b/sql.h @@ -703,10 +703,23 @@ class SelectModel : public SqlModel return *this; } - SelectModel& left_join(const std::string& table_name) + SelectModel& left_join(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") { - _join_type = "left join"; - _join_table = table_name; + _join_type = " left join "; + + if (!tablespace.empty()) + { + _join_type.append(tablespace); + _join_type.append("."); + } + _join_type.append(quotes + table_name + quotes); + + if (!alias.empty()) + _join_type.append(" " + alias + " "); + else + _join_type.append(" "); + + return *this; } From 2d788cfb34095b23240e9a173643dba9d915c684 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Wed, 19 Feb 2025 18:13:10 +0300 Subject: [PATCH 31/35] remove equals instad of in add is_null to clumn value add order_by to clumn_value --- sql.h | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/sql.h b/sql.h index e693a66..a72431e 100644 --- a/sql.h +++ b/sql.h @@ -158,27 +158,27 @@ class column size_t size = args.size(); - if (size == 1) - { - _cond.append(" = "); - _cond.append(to_value(args[0])); - } - else - { - _cond.append(" in ("); + // if (size == 1) + // { + // _cond.append(" = "); + // _cond.append(to_value(args[0])); + // } + // else + // { + _cond.append(" in ("); - for (size_t i = 0; i < size; ++i) + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) { - if (i < size - 1) - { - _cond.append(to_value(args[i])); - _cond.append(", "); - } - else - { - _cond.append(to_value(args[i])); - } + _cond.append(to_value(args[i])); + _cond.append(", "); + } + else + { + _cond.append(to_value(args[i])); } + // } _cond.append(")"); } return *this; @@ -365,9 +365,13 @@ class column_value { public: - column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "") + column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_null = false) { - _cond.append("'" + column_value + "'"); + if (!is_null) + _cond.append("'" + column_value + "'"); + else + _cond.append(column_value); + if (!to_type.empty()) _cond.append(" ::" + to_type); From fa80b5d12511714c8799a07a8e2723ea91d25ec8 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Fri, 7 Mar 2025 15:48:48 +0300 Subject: [PATCH 32/35] update_left_join function --- sql.h | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/sql.h b/sql.h index a72431e..e693a66 100644 --- a/sql.h +++ b/sql.h @@ -158,27 +158,27 @@ class column size_t size = args.size(); - // if (size == 1) - // { - // _cond.append(" = "); - // _cond.append(to_value(args[0])); - // } - // else - // { - _cond.append(" in ("); - - for (size_t i = 0; i < size; ++i) + if (size == 1) { - if (i < size - 1) - { - _cond.append(to_value(args[i])); - _cond.append(", "); - } - else + _cond.append(" = "); + _cond.append(to_value(args[0])); + } + else + { + _cond.append(" in ("); + + for (size_t i = 0; i < size; ++i) { - _cond.append(to_value(args[i])); + if (i < size - 1) + { + _cond.append(to_value(args[i])); + _cond.append(", "); + } + else + { + _cond.append(to_value(args[i])); + } } - // } _cond.append(")"); } return *this; @@ -365,13 +365,9 @@ class column_value { public: - column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_null = false) + column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "") { - if (!is_null) - _cond.append("'" + column_value + "'"); - else - _cond.append(column_value); - + _cond.append("'" + column_value + "'"); if (!to_type.empty()) _cond.append(" ::" + to_type); From e516ee9182f95a25694a1c56c1118c696d5a7f08 Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Fri, 7 Mar 2025 15:50:14 +0300 Subject: [PATCH 33/35] multiple join (left/right) statements --- sql.h | 236 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 128 insertions(+), 108 deletions(-) diff --git a/sql.h b/sql.h index e693a66..7c7bb2b 100644 --- a/sql.h +++ b/sql.h @@ -158,27 +158,27 @@ class column size_t size = args.size(); - if (size == 1) - { - _cond.append(" = "); - _cond.append(to_value(args[0])); - } - else - { - _cond.append(" in ("); + // if (size == 1) + // { + // _cond.append(" = "); + // _cond.append(to_value(args[0])); + // } + // else + // { + _cond.append(" in ("); - for (size_t i = 0; i < size; ++i) + for (size_t i = 0; i < size; ++i) + { + if (i < size - 1) { - if (i < size - 1) - { - _cond.append(to_value(args[i])); - _cond.append(", "); - } - else - { - _cond.append(to_value(args[i])); - } + _cond.append(to_value(args[i])); + _cond.append(", "); + } + else + { + _cond.append(to_value(args[i])); } + // } _cond.append(")"); } return *this; @@ -361,13 +361,43 @@ class column std::string _cond; }; + +class table +{ +public: + table(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") + { + if (!tablespace.empty()) + { + table_str_.append(tablespace); + table_str_.append("."); + } + table_str_.append(quotes + table_name + quotes); + + if (!alias.empty()) + table_str_.append(" " + alias + " "); + else + table_str_.append(" "); + } + + const std::string& str() const + {} + +private: + std::string table_str_ = ""; +}; + class column_value { public: - column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "") + column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_null = false) { - _cond.append("'" + column_value + "'"); + if (!is_null) + _cond.append("'" + column_value + "'"); + else + _cond.append(column_value); + if (!to_type.empty()) _cond.append(" ::" + to_type); @@ -696,77 +726,84 @@ class SelectModel : public SqlModel return *this; } - SelectModel& join(const std::string& table_name) + SelectModel& join_statement(const std::string& join_type, + const std::string& table_name, + const std::string& tablespace, + const std::string& alias, + const std::string& on_conditions) { - _join_type = "join"; - _join_table = table_name; - return *this; - } + // std::vector>> type; - SelectModel& left_join(const std::string& table_name, const std::string& tablespace = "", const std::string& alias = "") - { - _join_type = " left join "; + std::string join_type_and_table(" " + join_type + " "); if (!tablespace.empty()) - { - _join_type.append(tablespace); - _join_type.append("."); - } - _join_type.append(quotes + table_name + quotes); + join_type_and_table.append(tablespace + "."); + + join_type_and_table.append(quotes + table_name + quotes); if (!alias.empty()) - _join_type.append(" " + alias + " "); - else - _join_type.append(" "); + join_type_and_table.append(" " + alias + " "); + _join_type.push_back(std::make_pair(join_type_and_table, on_conditions)); return *this; } - SelectModel& left_outer_join(const std::string& table_name) + SelectModel& left_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "" + ) { - _join_type = "left outer join"; - _join_table = table_name; - return *this; - } + join_statement("LEFT JOIN", table_name, tablespace, alias, on_conditions.str()); - SelectModel& right_join(const std::string& table_name) - { - _join_type = "right join"; - _join_table = table_name; return *this; } - SelectModel& right_outer_join(const std::string& table_name) + SelectModel& left_outer_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") { - _join_type = "right outer join"; - _join_table = table_name; + join_statement("left outer join", table_name, tablespace, alias, on_conditions.str()); + return *this; } - SelectModel& full_join(const std::string& table_name) + SelectModel& right_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "" + ) { - _join_type = "full join"; - _join_table = table_name; + join_statement(" right join ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& full_outer_join(const std::string& table_name) + SelectModel& right_outer_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") { - _join_type = "full outer join"; - _join_table = table_name; + join_statement(" right outer join ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& on(const std::string& condition) + SelectModel& full_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") { - _join_on_condition.push_back(condition); + join_statement(" full join ", table_name, tablespace, alias, on_conditions.str()); return *this; } - SelectModel& on(const column& condition) + SelectModel& full_outer_join(const std::string& table_name, + const column& on_conditions, + const std::string& tablespace = "", + const std::string& alias = "") { - _join_on_condition.push_back(condition.str()); + join_statement(" FULL OUTER JOIN ", table_name, tablespace, alias, on_conditions.str()); return *this; } @@ -814,6 +851,12 @@ class SelectModel : public SqlModel return *this; } + SelectModel& order_by(const column& order_by) + { + _order_by = to_value(order_by); + return *this; + } + template SelectModel& limit(const T& limit) { @@ -842,23 +885,35 @@ class SelectModel : public SqlModel _sql.append("select "); if (_distinct) - _sql.append("distinct "); + _sql.append(" DISTINCT "); join_vector(_sql, _select_columns, ", "); - _sql.append(" from "); + _sql.append(" FROM "); _sql.append(_table_name); + // if (!_join_type.empty()) + // { + // _sql.append(" "); + // _sql.append(_join_type); + // _sql.append(" "); + // _sql.append(_join_table); + // } + + // if (!_join_on_condition.empty()) + // { + // _sql.append(" on "); + // join_vector(_sql, _join_on_condition, " and "); + // } + if (!_join_type.empty()) { - _sql.append(" "); - _sql.append(_join_type); - _sql.append(" "); - _sql.append(_join_table); - } + for (std::pair join :_join_type) + { + _sql.append(" " + join.first + " "); + std::string on = join.second; + _sql.append(" ON "); - if (!_join_on_condition.empty()) - { - _sql.append(" on "); - join_vector(_sql, _join_on_condition, " and "); + _sql.append(join.second); + } } if (!_where_condition.empty()) @@ -906,8 +961,7 @@ class SelectModel : public SqlModel _groupby_columns.clear(); _table_name.clear(); _join_type.clear(); - _join_table.clear(); - _join_on_condition.clear(); + // 64_join_on_condition.clear(); _where_condition.clear(); _having_condition.clear(); _order_by.clear(); @@ -927,9 +981,9 @@ class SelectModel : public SqlModel bool _distinct; std::vector _groupby_columns; std::string _table_name; - std::string _join_type; - std::string _join_table; - std::vector _join_on_condition; + std::vector> _join_type; + + // std::vector _join_on_condition; std::vector _where_condition; std::vector _having_condition; std::string _order_by; @@ -1215,37 +1269,3 @@ class DeleteModel : public SqlModel }; } -// #define DIAGNOSIS_FLIGHT(NAME, SUBSYSTEM, FLIGHT_TYPE, TEST_PARAMETERS, TITLE, RESULTS) \ -// ac_menu_ ## SUBSYSTEM ## NAME ## _ = new QAction(TITLE, this); \ -// menu_ ## SUBSYSTEM ## _->addAction(ac_menu_ ## SUBSYSTEM ## NAME ## _); - -// ALL_DIAGNOSIS_FLIGHTS -// #undef DIAGNOSIS_FLIGHT -// #define ALL_DIAGNOSIS_FLIGHTS \ -// DIAGNOSIS_FLIGHT(GeoBinding, PAR, \ -// FlightType::kGeoBinding, \ -// { TestedParameter::pCircleGeoBinding }, \ -// "Определение координат ПАР", \ -// { TestResultsName::kGeoBindingLatitudeResultName COMMA \ -// TestResultsName::kGeoBindingLongitudeResultName COMMA \ -// TestResultsName::kGeoBindingAltitudeResultName COMMA \ -// TestResultsName::kFlightDataIntervalResultName COMMA \ -// TestResultsName::kGeoBindingAzimuthResultName COMMA \ -// TestResultsName::kGeoBindingRollResultName COMMA \ -// TestResultsName::kGeoBindingPitchResultName COMMA \ -// }) \ -// // -// #define DIAGNOSIS_FLIGHT(NAME, SUBSYSTEM, FLIGHT_TYPE, TEST_PARAMETERS, TITLE, RESULTS) \ -// const static DiagnosisFlight f ## SUBSYSTEM ## NAME = DiagnosisFlight(Subsystem::s ## SUBSYSTEM, \ -// FLIGHT_TYPE, \ -// TEST_PARAMETERS, \ -// TITLE, \ -// RESULTS); - -// ALL_DIAGNOSIS_FLIGHTS -// #undef DIAGNOSIS_FLIGHT - - -// #define SELECT_STATEMENT(TYPE) - -// #undef SELECT_STATEMENT(TYPE) From 617bc734044550998e0e99bce0ef6d48f4d5daed Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Fri, 14 Mar 2025 12:32:20 +0300 Subject: [PATCH 34/35] Add sql window function --- sql.h | 640 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 557 insertions(+), 83 deletions(-) diff --git a/sql.h b/sql.h index 7c7bb2b..5761d37 100644 --- a/sql.h +++ b/sql.h @@ -3,6 +3,8 @@ #include #include +#include + namespace { const std::string& quotes("\""); @@ -15,6 +17,7 @@ namespace sql { class column; class column_value; +class SelectModel; class Param { @@ -115,15 +118,36 @@ class column { public: + + column() {} // alias - column(const std::string& column_name, const std::string& alias = "", const std::string& as = "") + column(const std::string& column_name, const std::string& alias = "", const std::string& as = "", const std::string& to_type = "") { if (!alias.empty()) _cond.append(alias + "."); + + + _cond.append(quotes + column_name + quotes); + if (!to_type.empty()) + _cond.append("::" + to_type); + + if (!as.empty()) + _cond.append(" AS " + as); + } + + column(const column& column_name, const std::string& alias = "", const std::string& as = "", const std::string& to_type = "") + { + if (!alias.empty()) + _cond.append(alias + "."); + _cond.append(column_name.str()); + + if (!to_type.empty()) + _cond.append("::" + to_type); + if (!as.empty()) - _cond.append(" as " + as); + _cond.append(" AS " + as); } column& operator()(const std::string& column_name, const std::string& alias = "", const std::string& as = "") @@ -133,7 +157,7 @@ class column _cond.append(quotes + column_name + quotes); if (!as.empty()) - _cond.append(" as " + as); + _cond.append(" AS " + as); return *this; } @@ -158,13 +182,7 @@ class column size_t size = args.size(); - // if (size == 1) - // { - // _cond.append(" = "); - // _cond.append(to_value(args[0])); - // } - // else - // { + _cond.append(" in ("); for (size_t i = 0; i < size; ++i) @@ -178,12 +196,47 @@ class column { _cond.append(to_value(args[i])); } - // } - _cond.append(")"); } + _cond.append(")"); + + return *this; + } + + column& in (const std::string& in_column) { + _cond.append(" in ("); + + _cond.append(in_column); + _cond.append(" ) "); + return *this; + } + + + column& append(const std::string& data) + { + _cond.append(" || '" + data + "' "); + return *this; + } + + column& prepend(const std::string& data) + { + _cond.insert(0, " '" + data + "' || "); return *this; } + // special characters such as %,_ must contains in like_condition + // template<> + column& like(const std::string& like_condition) + { + if (like_condition.size() <= 0) + return *this; + + _cond.append(" LIKE '"); + _cond.append(like_condition); + _cond.append("' "); + + + return *this; + } template column& not_in(const std::vector& args) @@ -391,19 +444,19 @@ class column_value { public: - column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_null = false) + column_value(const std::string& column_value, const std::string& to_type = "", const std::string& as = "", const bool& is_value = false) { - if (!is_null) + if (!is_value) _cond.append("'" + column_value + "'"); else _cond.append(column_value); if (!to_type.empty()) - _cond.append(" ::" + to_type); + _cond.append("::" + to_type); if (!as.empty()) - _cond.append(" as " + as); + _cond.append(" AS " + as); } const std::string& str() const @@ -411,6 +464,29 @@ class column_value return _cond; } + template + column_value& operator>(const T& data) + { + _cond.append(" > "); + _cond.append(to_value(data)); + return *this; + } + + template + column_value& operator<(const T& data) + { + _cond.append(" < "); + _cond.append(to_value(data)); + return *this; + } + + template + column_value& operator*(const T& data) + { + _cond.append(" * " + to_value(data)); + return *this; + } + private: std::string _cond; }; @@ -426,6 +502,11 @@ inline std::string to_value(const sql::column_value& data) return data.str(); } +inline std::string to_value(const std::string& data) +{ + return data; +} + class SqlFunction { public: @@ -436,25 +517,190 @@ class SqlFunction virtual std::string str() const = 0; private: - SqlFunction(const SqlFunction& data) = delete; + // SqlFunction(const SqlFunction& data) = delete; SqlFunction& operator=(const SqlFunction& data) = delete; protected: std::string _sql_func; }; + +class existsStatement : public SqlFunction +{ +public: + + existsStatement() + {} + + template + existsStatement& exists(T subq, const std::string& as) + { + _sql_func.append("EXISTS ("); + _sql_func.append(to_value(subq)); + _sql_func.append(") "); + + if (as.length() > 2) + _sql_func.append(" AS " + as + " "); + + return *this; + } + + virtual std::string str() const override + { + return _sql_func; + } +}; + +class caseStatement : public SqlFunction +{ +public: + caseStatement() + { + _sql_func.append(" END"); + } + + template + caseStatement& case_sql(std::string as = "", std::string case_else = "", Args&& ... conditionals) + { + if (case_else.length() > 2) + _sql_func.insert(0, " ELSE '" + case_else + "'"); + + if (!as.empty()) + _sql_func.append(" AS " + as); + + case_sql(conditionals ...); + return *this; + } + + template + caseStatement& case_sql(std::pair when, Args&& ... conditionals) + { + std::string pb(" WHEN "); + + pb.append(to_value(when.first)); + pb.append(" THEN "); + pb.append(to_value(when.second)); + + _sql_func.insert(0, pb); + case_sql(conditionals ...); + return *this; + } + + caseStatement& case_sql() + { + _sql_func.insert(0, "CASE "); + return *this; + } + + virtual std::string str() const override + { + return _sql_func; + } + + virtual ~caseStatement() {} +}; + class SqlWindowFunction : public SqlFunction { public: SqlWindowFunction() {} virtual ~SqlWindowFunction() {} - SqlWindowFunction& row_number(const std::string& column + SqlWindowFunction& row_number(const sql::column& column + , const sql::column&& partition = sql::column() + , const sql::column&& order = sql::column() + , const bool& desc = false + , const std::string& as = "") + { + return w_function("ROW_NUMBER", column.str(), partition.str(), order.str(), desc, as); + } + + SqlWindowFunction& sum_over(const sql::column& column + , const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("SUM", column.str(), partition, order, desc, as); + } + + SqlWindowFunction& count_over(const sql::column& column , const std::string& partition = "" , const std::string& order = "" - , const bool& desc = false) + , const bool& desc = false + , const std::string& as = "") { - return w_function("ROW_NUMBER", column, partition, order, desc); + return w_function("COUNT", column.str(), partition, order, desc, as); + } + + SqlWindowFunction& count(const sql::column& column) + { + _sql_func.clear(); + _sql_func.append("COUNT(" + column.str() + ") "); + + return *this; + } + + SqlWindowFunction& dense_rank( + const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("DENSE_RANK", "", partition, order, desc, as); + } + + SqlWindowFunction& dense_rank( + const sql::column& partition = sql::column() + , const sql::column& order = sql::column() + , const bool& desc = false + , const std::string& as = "") + { + return w_function("DENSE_RANK", "", partition.str(), order.str(), desc, as); + } + + SqlWindowFunction& dense_rank( + const sql::column& partition = sql::column() + , const std::vector> order_by_desc = std::vector> + () + , const std::string& as = "") + { + std::vector> order_by_desc_string; + + for (int i = 0; i < order_by_desc.size(); i++) + { + order_by_desc_string.push_back(std::pair(order_by_desc.at(i).first.str(), order_by_desc.at(i).second)); + } + + // const std::vector> const_order_by_desc_string = order_by_desc_string; + return w_function("DENSE_RANK", "", partition.str(), order_by_desc_string, as); + } + + SqlWindowFunction& dense_rank( + const std::string& partition = std::string() + , const std::vector> order_by_desc = std::vector> + () + , const std::string& as = "") + { + return w_function("DENSE_RANK", "", partition, order_by_desc, as); + } + + SqlWindowFunction& rank( + const std::string& partition = "" + , const std::string& order = "" + , const bool& desc = false + , const std::string& as = "") + { + return w_function("RANK", "", partition, order, desc, as); + } + + SqlWindowFunction& rank( + const sql::column& partition = sql::column() + , const sql::column& order = sql::column() + , const bool& desc = false + , const std::string& as = "") + { + return w_function("RANK", "", partition.str(), order.str(), desc, as); } virtual std::string str() const override @@ -464,46 +710,104 @@ class SqlWindowFunction : public SqlFunction private: - SqlWindowFunction& w_function(const std::string& function_name, const std::string& column + SqlWindowFunction& w_function(const std::string& function_name, + const std::string& column , const std::string& partition = "" - , const std::string& order = "" - , const bool& desc = false) + , const std::string& order_by = "" + , const bool desc = false + , const std::string& as = "") { _sql_func.clear(); - _sql_func.append(function_name); - _sql_func.append("("); - if (!column.empty()) - _sql_func.append(quotes + column + quotes); + if (!column.empty() || (column.length() > 2)) + _sql_func.append(column); _sql_func.append(")"); _sql_func.append(" OVER "); _sql_func.append("("); - if (!partition.empty()) + if (partition.length() > 2) { _sql_func.append("PARTITION BY "); - _sql_func.append(quotes + partition + quotes); + _sql_func.append(partition); _sql_func.append(" "); } - if (!order.empty()) + if (order_by.length() > 2) { _sql_func.append("ORDER BY "); - _sql_func.append(quotes + order + quotes); + _sql_func.append(order_by); _sql_func.append(" "); - } - - if (!partition.empty() || !order.empty()) desc ? _sql_func.append(" DESC ") : _sql_func.append(" ASC "); + _sql_func.append(" ) "); + } + + if (!as.empty()) + _sql_func.append(" AS " + as); + + return *this; + } + + SqlWindowFunction& w_function(const std::string& function_name, + const std::string& column + , + const std::string& partition = "" + , + const std::vector> order_by_desc = std::vector> + () + , + const std::string& as = "") + { + _sql_func.clear(); + _sql_func.append(function_name); + + _sql_func.append("("); + + if (!column.empty() || (column.length() > 2)) + _sql_func.append(column); + _sql_func.append(")"); + _sql_func.append(" OVER "); + _sql_func.append("("); + + + if (partition.length() > 2) + { + _sql_func.append("PARTITION BY "); + _sql_func.append(partition); + + _sql_func.append(" "); + } + + if (order_by_desc.size() > 0) + { + _sql_func.append("ORDER BY "); + + for (int i = 0; i < order_by_desc.size(); i++) + { + if (order_by_desc.at(i).first.length() > 2) + { + _sql_func.append(order_by_desc.at(i).first); + _sql_func.append(" "); + order_by_desc.at(i).second ? _sql_func.append(" DESC , ") + : _sql_func.append(" ASC , "); + } + } + _sql_func = _sql_func.substr(0, _sql_func.size() - 3); + + _sql_func.append(" ) "); + } + + if (!as.empty()) + _sql_func.append(" AS " + as); + return *this; } }; @@ -533,21 +837,72 @@ class TimeFormatingFunction : public SqlFunction } }; +class CastFunction : public SqlFunction +{ +public: + CastFunction(const column expression, + + const std::string& data_type = "", + const int& length = 30) + { + _sql_func = "CAST("; + _sql_func.append(expression.str() + " AS " + data_type + ") "); + } + + std::string str() const override + { + return _sql_func; + } +}; + + + + +class RoundFunction : public SqlFunction +{ +public: + RoundFunction(const CastFunction expression, + const std::string& as = "", + const int& length = 30) + { + _sql_func = "ROUND("; + _sql_func.append(expression.str() + " , " + std::to_string(length) + ") "); + + if (!as.empty()) + _sql_func.append(" AS " + as); + } + + RoundFunction(const column expression, + const std::string& as = "", + const int& length = 30) + { + _sql_func = "ROUND("; + _sql_func.append(expression.str() + " , " + std::to_string(length) + ") "); + + if (!as.empty()) + _sql_func.append(" AS " + as); + } + + std::string str() const override + { + return _sql_func; + } +}; + + + class DataTypeFormatingFunction : public SqlFunction { public: DataTypeFormatingFunction(const std::string& as = "") { if (!as.empty()) - _as.append(" as " + quotes + as + quotes); + _as.append(" AS " + quotes + as + quotes); } std::string str() const override { - // std::string result = _sql_func; - - // result = result.append(_as); - return _sql_func + _as; // CRASHES WTF + return _sql_func + _as; } virtual ~DataTypeFormatingFunction() {} @@ -558,13 +913,19 @@ class DataTypeFormatingFunction : public SqlFunction const std::string& format = "") { DataTypeFormatingFunction& text = dtf_function("to_char", tf_func.str(), is_text, format); - std::string text_SDF = text.str(); + return text; } DataTypeFormatingFunction& to_char(const column& data, const std::string& format = "") + { + return dtf_function("to_char", data.str(), true, format); + } + + DataTypeFormatingFunction& to_char(const column_value& data, + const std::string& format = "") { return dtf_function("to_char", data.str(), false, format); } @@ -589,6 +950,9 @@ class DataTypeFormatingFunction : public SqlFunction std::string _as; }; + + + class conditional_expressions : public SqlFunction { public: @@ -597,7 +961,7 @@ class conditional_expressions : public SqlFunction _sql_func.append(" COALESCE ( "); if (!as.empty()) - _as.append(" as " + quotes + as + quotes); + _as.append(" AS " + as); } virtual std::string str() const override @@ -641,7 +1005,7 @@ class SqlModel } private: - SqlModel(const SqlModel& m) = delete; + // SqlModel(const SqlModel& m) = delete; SqlModel& operator=(const SqlModel& data) = delete; protected: @@ -675,6 +1039,25 @@ class SelectModel : public SqlModel return *this; } + template + SelectModel& select(std::pair subquery, Args&& ... columns) + { + std::string pb(" ( "); + + pb.append(subquery.first.str()); + pb.append(" ) "); + + if (!subquery.second.empty()) + { + pb.append(" AS "); + pb.append(subquery.second); + } + + _select_columns.push_back(pb); + select(columns ...); + return *this; + } + template SelectModel& select(const column column_struct, Args&& ... columns) { @@ -726,6 +1109,39 @@ class SelectModel : public SqlModel return *this; } + SelectModel& from_subquery(const std::string& table_name, const std::string& alias = "") + { + _table_name.append(table_name); + + if (!alias.empty()) + _table_name.append(" " + alias + " "); + else + _table_name.append(" "); + + + return *this; + } + + SelectModel& from(std::vector selects, const std::string& alias = "") + { + for (int i = 0; i < selects.size(); i++) + { + std::string subs_q = selects[i].str(); + + _table_name.append(" ( " + subs_q + " )"); + + if (i != selects.size()) + _table_name.append(" UNION ALL "); + } + + if (!alias.empty()) + _table_name.append(" " + alias + " "); + else + _table_name.append(" "); + + return *this; + } + SelectModel& join_statement(const std::string& join_type, const std::string& table_name, const std::string& tablespace, @@ -744,7 +1160,9 @@ class SelectModel : public SqlModel if (!alias.empty()) join_type_and_table.append(" " + alias + " "); - _join_type.push_back(std::make_pair(join_type_and_table, on_conditions)); + join_type_and_table.append("ON " + on_conditions); + + _join_type.push_back(join_type_and_table); return *this; } @@ -785,7 +1203,7 @@ class SelectModel : public SqlModel const std::string& tablespace = "", const std::string& alias = "") { - join_statement(" right outer join ", table_name, tablespace, alias, on_conditions.str()); + join_statement(" RIGHT OUTER JOIN ", table_name, tablespace, alias, on_conditions.str()); return *this; } @@ -819,6 +1237,56 @@ class SelectModel : public SqlModel return *this; } + SelectModel& where(const column_value& condition) + { + _where_condition.push_back(condition.str()); + return *this; + } + + SelectModel& where_exists(std::vector data) + { + std::string where_c; + + for (int i = 0; i < data.size(); i++) + { + where_c.append("(EXISTS ("); + where_c.append(data[i].str()); + where_c.append(" ) ) OR "); + } + where_c = where_c.substr(0, where_c.length() - 3); + + _where_condition.push_back(where_c); + return *this; + } + + SelectModel& where_not_exists(std::vector data) + { + std::string where_c; + + for (int i = 0; i < data.size(); i++) + { + where_c.append("( NOT EXISTS ("); + where_c.append(data[i].str()); + where_c.append(" ) ) OR "); + } + where_c = where_c.substr(0, where_c.length() - 3); + _where_condition.push_back(where_c); + return *this; + } + + template + SelectModel& where_between(const column& cond, const T& begin_val, const T& end_val) + { + std::string where_val; + + where_val.append(cond.str()); + std::string begin = std::to_string(begin_val); + std::string end = std::to_string(end_val); + where_val.append(" BETWEEN " + begin + " AND " + end); + _where_condition.push_back(where_val); + return *this; + } + template SelectModel& group_by(const std::string& str, Args&& ... columns) { @@ -845,15 +1313,17 @@ class SelectModel : public SqlModel return *this; } - SelectModel& order_by(const std::string& order_by) + SelectModel& order_by(const std::string& order_by, const bool desc = false) { - _order_by = order_by; + _order_by = order_by; + _order_by_desc = desc; return *this; } - SelectModel& order_by(const column& order_by) + SelectModel& order_by(const column& order_by, const bool desc = false) { - _order_by = to_value(order_by); + _order_by = to_value(order_by); + _order_by_desc = desc; return *this; } @@ -882,7 +1352,7 @@ class SelectModel : public SqlModel virtual const std::string& str() override { _sql.clear(); - _sql.append("select "); + _sql.append(" SELECT "); if (_distinct) _sql.append(" DISTINCT "); @@ -890,36 +1360,18 @@ class SelectModel : public SqlModel _sql.append(" FROM "); _sql.append(_table_name); - // if (!_join_type.empty()) - // { - // _sql.append(" "); - // _sql.append(_join_type); - // _sql.append(" "); - // _sql.append(_join_table); - // } - - // if (!_join_on_condition.empty()) - // { - // _sql.append(" on "); - // join_vector(_sql, _join_on_condition, " and "); - // } - if (!_join_type.empty()) { - for (std::pair join :_join_type) + for (std::string join :_join_type) { - _sql.append(" " + join.first + " "); - std::string on = join.second; - _sql.append(" ON "); - - _sql.append(join.second); + _sql.append(" " + join + " "); } } if (!_where_condition.empty()) { - _sql.append(" where "); - join_vector(_sql, _where_condition, " and "); + _sql.append(" WHERE "); + join_vector(_sql, _where_condition, " AND "); } if (!_groupby_columns.empty()) @@ -936,8 +1388,11 @@ class SelectModel : public SqlModel if (!_order_by.empty()) { - _sql.append(" order by "); + _sql.append(" ORDER BY "); _sql.append(_order_by); + + if (_order_by_desc) + _sql.append(" DESC "); } if (!_limit.empty()) @@ -981,17 +1436,21 @@ class SelectModel : public SqlModel bool _distinct; std::vector _groupby_columns; std::string _table_name; - std::vector> _join_type; + std::vector _join_type; // std::vector _join_on_condition; std::vector _where_condition; std::vector _having_condition; std::string _order_by; + bool _order_by_desc = false; std::string _limit; std::string _offset; }; - +inline std::string to_value(SelectModel& data) +{ + return data.str(); +} class InsertModel : public SqlModel { @@ -1002,8 +1461,27 @@ class InsertModel : public SqlModel template InsertModel& insert(const std::string& c, const T& data) { - _columns.push_back(quotes + c + quotes); - _values.push_back(to_value(data)); + if constexpr + (std::is_same::value) + { + _columns.push_back(quotes + c + quotes); + std::string v_data = "FALSE"; + + if (data) v_data = "TRUE"; + _values.push_back(v_data); + } + else + if constexpr (std::is_same::value) + { + _columns.push_back(quotes + c + quotes); + + _values.push_back(std::to_string(data)); + } + else + { + _columns.push_back(quotes + c + quotes); + _values.push_back("'" + to_value(data) + "'"); + } return *this; } @@ -1158,7 +1636,7 @@ class UpdateModel : public SqlModel if (size > 0) { - _sql.append(" where "); + _sql.append(" WHERE "); join_vector(_sql, _where_condition, " and "); } return _sql; @@ -1208,10 +1686,6 @@ class DeleteModel : public SqlModel template DeleteModel& from(const std::string& table_name, const std::string& tablespace = "") { - // assert(table_name.empty()); - // assert(!_table_name.empty()); - - if (!tablespace.empty()) { _table_name.append(tablespace); @@ -1244,8 +1718,8 @@ class DeleteModel : public SqlModel if (size > 0) { - _sql.append(" where "); - join_vector(_sql, _where_condition, " and "); + _sql.append(" WHERE "); + join_vector(_sql, _where_condition, " AND "); } return _sql; } From 600e22c65be4a17e405895a65848aff45f49f2fa Mon Sep 17 00:00:00 2001 From: KondratovRoman Date: Fri, 14 Mar 2025 12:34:32 +0300 Subject: [PATCH 35/35] Small fix return value. --- sql.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql.h b/sql.h index 5761d37..1911e32 100644 --- a/sql.h +++ b/sql.h @@ -434,7 +434,7 @@ class table } const std::string& str() const - {} + { return table_str_;} private: std::string table_str_ = "";