diff --git a/demo/work.cpp b/demo/work.cpp index aae003d..3140da0 100644 --- a/demo/work.cpp +++ b/demo/work.cpp @@ -164,5 +164,58 @@ int main() { in( iPT.payload_id, query::query::select({ temp_id_col }).from( temporary ) ) ) .str( conn->dialect() ); + + // const QString statement = QString( "SELECT %5 FROM %1 " + // "LEFT JOIN (SELECT %2, MAX(%3) AS lastSuccessfulLogin FROM %1 WHERE %4 = ? GROUP BY %2) ll " + // "ON %1.%2 = ll.%2 " + // "WHERE (lastSuccessfulLogin IS NULL OR %3 <= lastSuccessfulLogin) AND %3 < ?" ) + // .arg( LoginHistory::staticSqlMetaInfo().tableName() ) + // .arg( LoginHistory::staticSqlMetaInfo().columnName( LoginHistory::Attributes::userAttributeId() ) ) + // .arg( LoginHistory::staticSqlMetaInfo().columnName( LoginHistory::Attributes::timestampAttributeId() ) ) + // .arg( LoginHistory::staticSqlMetaInfo().columnName( LoginHistory::Attributes::failReasonSqlAttributeId() ) ) + // .arg( LoginHistory::staticSqlMetaInfo().columnName( LoginHistory::Attributes::idAttributeId() ) ); + + const auto q = query::query::select({LOGIN_HISTORY.client, query::max(LOGIN_HISTORY.login_time).as( "lastSuccessfulLogin" ) } ) + .from( LOGIN_HISTORY ) + .where( LOGIN_HISTORY.fail_reason == _ ) + .group_by( LOGIN_HISTORY.client ); + // .as_table("ll"); + + const auto stmt3 = query::query::select({ LOGIN_HISTORY.client }) + .from( LOGIN_HISTORY ) + .join_left(q/*, "ll"*/ ) + .on( LOGIN_HISTORY.client == "ll.client" ) + .where( query::is_null("lastSuccessfulLogin") && LOGIN_HISTORY.login_time < "ll.lastSuccessfulLogin" ) + .str( conn->dialect() ); + + std::cout << stmt1 << std::endl; + std::cout << stmt2 << std::endl; + std::cout << stmt3 << std::endl; + + // const QString subQuery = QString( "SELECT MAX(%1) AS lastSuccessfulLogin, %3 FROM %2 " + // "WHERE(%4 = ? OR %4 = ? OR %4 = ?) AND %3 = ? GROUP BY %3 " ); + // + // const QString statement = QString( "SELECT MAX(t1.%1) AS LAST_FAILED_LOGIN FROM %2 t1 LEFT JOIN" + // "(%0) t2 " + // "ON t1.%3 = t2.%3 " + // "WHERE(t2.lastSuccessfulLogin IS NULL OR t2.lastSuccessfulLogin < t1.%1) " + // "AND (t1.%4 = ? OR t1.%4 = ?) " + // "AND t1.%3 = ?" ) + // .arg( subQuery ) + // .arg( LoginHistory::staticSqlMetaInfo().columnName( LoginHistory::Attributes::timestampAttributeId() ) ) + // .arg( LoginHistory::staticSqlMetaInfo().tableName() ) + // .arg( columnFilterName ) + // .arg( LoginHistory::staticSqlMetaInfo().columnName( LoginHistory::Attributes::failReasonSqlAttributeId() ) ); + // + // QSqlQuery query( sqlDatabase() ); + // if ( query.prepare( statement ) ) { + // query.addBindValue( LoginHistory::FailReason::NoFailReason ); + // query.addBindValue( LoginHistory::FailReason::NoScenarioForUser ); + // query.addBindValue( LoginHistory::FailReason::UserLockedByAdmin ); + // query.addBindValue( columnFilterValue ); + // query.addBindValue( LoginHistory::FailReason::WrongPassword ); + // query.addBindValue( LoginHistory::FailReason::UnknownUserName ); + // query.addBindValue( columnFilterValue ); + return 0; } \ No newline at end of file diff --git a/demo/work/admin/LoginHistory.hpp b/demo/work/admin/LoginHistory.hpp index 0e68ae5..4cd32ed 100644 --- a/demo/work/admin/LoginHistory.hpp +++ b/demo/work/admin/LoginHistory.hpp @@ -9,6 +9,8 @@ #include "matador/object/object_ptr.hpp" +#include "matador/query/meta_table_macro.hpp" + #include "matador/utils/base_class.hpp" #include "matador/utils/enum_mapper.hpp" #include "matador/utils/foreign_attributes.hpp" @@ -59,6 +61,9 @@ struct LoginHistory : core::Model { field::attribute( op, "login_time", login_time ); } }; + } +META_TABLE( login_histories, LOGIN_HISTORY, id, version, client, scenario, collection_center, login_name, fail_reason, login_time ) + #endif //LOGIN_HISTORY_HPP diff --git a/demo/work/admin/User.hpp b/demo/work/admin/User.hpp index ef257ba..9f83748 100644 --- a/demo/work/admin/User.hpp +++ b/demo/work/admin/User.hpp @@ -7,6 +7,8 @@ #include "matador/object/object_ptr.hpp" +#include "matador/query/meta_table_macro.hpp" + #include "matador/utils/base_class.hpp" #include "matador/utils/foreign_attributes.hpp" #include "matador/utils/types.hpp" @@ -42,4 +44,7 @@ struct User : core::Model { }; } + +META_TABLE(users, USER, id, version, name, symbol, salt, password, lock_type, locked_at, lock_reason, role, user_directory) + #endif //USER_HPP diff --git a/include/matador/query/criteria.hpp b/include/matador/query/criteria.hpp index f58ce6e..eff9286 100644 --- a/include/matador/query/criteria.hpp +++ b/include/matador/query/criteria.hpp @@ -3,6 +3,7 @@ #include "matador/query/criteria/between_criteria.hpp" #include "matador/query/criteria/binary_criteria.hpp" +#include "matador/query/criteria/check_null_criteria.hpp" #include "matador/query/criteria/collection_criteria.hpp" #include "matador/query/criteria/like_criteria.hpp" #include "matador/query/criteria/logical_criteria.hpp" diff --git a/include/matador/query/criteria/check_null_criteria.hpp b/include/matador/query/criteria/check_null_criteria.hpp new file mode 100644 index 0000000..e66417c --- /dev/null +++ b/include/matador/query/criteria/check_null_criteria.hpp @@ -0,0 +1,26 @@ +#ifndef MATADOR_IS_NULL_CRITERIA_HPP +#define MATADOR_IS_NULL_CRITERIA_HPP + +#include "matador/query/criteria/abstract_column_criteria.hpp" + +namespace matador::query { +enum class check_null_operator { + IsNull, + IsNotNull, +}; + +class check_null_criteria final : public abstract_column_criteria { +public: + check_null_criteria() = delete; + check_null_criteria(const table_column& col, check_null_operator op); + + void accept(criteria_visitor& visitor) const override; + + [[nodiscard]] check_null_operator operand() const; + +private: + check_null_operator operator_{}; +}; + +} +#endif // MATADOR_IS_NULL_CRITERIA_HPP diff --git a/include/matador/query/criteria/criteria_operators.hpp b/include/matador/query/criteria/criteria_operators.hpp index f9f6403..9da0479 100644 --- a/include/matador/query/criteria/criteria_operators.hpp +++ b/include/matador/query/criteria/criteria_operators.hpp @@ -104,5 +104,8 @@ criteria_ptr between(const table_column &col, utils::placeholder min, utils::pla criteria_ptr like(const table_column &col, const std::string &pattern); +criteria_ptr is_null(const table_column &col); +criteria_ptr is_not_null(const table_column &col); + } #endif //CRITERIA_CRITERIA_OPERATORS_HPP \ No newline at end of file diff --git a/include/matador/query/criteria/criteria_visitor.hpp b/include/matador/query/criteria/criteria_visitor.hpp index 5b6d00e..e269aed 100644 --- a/include/matador/query/criteria/criteria_visitor.hpp +++ b/include/matador/query/criteria/criteria_visitor.hpp @@ -5,6 +5,7 @@ namespace matador::query { class between_criteria; class binary_criteria; class binary_column_criteria; +class check_null_criteria; class like_criteria; class logical_criteria; class not_criteria; @@ -18,6 +19,7 @@ public: virtual void visit(const between_criteria &node) = 0; virtual void visit(const binary_criteria &node) = 0; virtual void visit(const binary_column_criteria &node) = 0; + virtual void visit(const check_null_criteria &node) = 0; virtual void visit(const collection_criteria &node) = 0; virtual void visit(const collection_query_criteria &node) = 0; virtual void visit(const like_criteria &node) = 0; diff --git a/include/matador/query/criteria_evaluator.hpp b/include/matador/query/criteria_evaluator.hpp index 423de59..d2e32ea 100644 --- a/include/matador/query/criteria_evaluator.hpp +++ b/include/matador/query/criteria_evaluator.hpp @@ -23,6 +23,7 @@ public: void visit(const between_criteria &node) override; void visit(const binary_criteria &node) override; void visit(const binary_column_criteria &node) override; + void visit(const check_null_criteria &node) override; void visit(const collection_criteria &node) override; void visit(const collection_query_criteria &node) override; void visit(const like_criteria &node) override; diff --git a/include/matador/query/intermediates/query_from_intermediate.hpp b/include/matador/query/intermediates/query_from_intermediate.hpp index 222457c..6320bc8 100644 --- a/include/matador/query/intermediates/query_from_intermediate.hpp +++ b/include/matador/query/intermediates/query_from_intermediate.hpp @@ -16,6 +16,7 @@ public: using fetchable_query::fetchable_query; query_join_intermediate join_left(const table &t); + query_join_intermediate join_left(const fetchable_query &q); query_from_intermediate join_left(join_data &data); query_from_intermediate join_left(std::vector &data_vector); diff --git a/include/matador/query/internal/query_parts.hpp b/include/matador/query/internal/query_parts.hpp index 59fb64e..9bc9d5a 100644 --- a/include/matador/query/internal/query_parts.hpp +++ b/include/matador/query/internal/query_parts.hpp @@ -143,10 +143,10 @@ private: std::vector tables_; }; -class query_join_part final : public query_part +class query_join_table_part final : public query_part { public: - explicit query_join_part(class table tab); + explicit query_join_table_part(class table tab); [[nodiscard]] const class table& table() const; @@ -157,6 +157,20 @@ private: class table table_; }; +class query_join_query_part final : public query_part +{ +public: + explicit query_join_query_part(fetchable_query q); + + [[nodiscard]] const fetchable_query& query() const; + +private: + void accept(query_part_visitor &visitor) override; + +private: + fetchable_query query_; +}; + class query_on_part final : public query_part { public: diff --git a/include/matador/query/meta_table_macro.hpp b/include/matador/query/meta_table_macro.hpp index 0b58c03..d5d445d 100644 --- a/include/matador/query/meta_table_macro.hpp +++ b/include/matador/query/meta_table_macro.hpp @@ -3,7 +3,6 @@ #include "matador/utils/macro_map.hpp" -#include "matador/query/table_column.hpp" #include "matador/query/table.hpp" #define FIELD(FIELD_NAME) const matador::query::table_column& FIELD_NAME; diff --git a/include/matador/query/query.hpp b/include/matador/query/query.hpp index 5f640d6..5595a54 100644 --- a/include/matador/query/query.hpp +++ b/include/matador/query/query.hpp @@ -10,10 +10,12 @@ class connection; } namespace matador::query { class schema; -table_column alias(const std::string &column, const std::string &as); -table_column alias(table_column &&col, const std::string &as); table_column count(const std::string &column); table_column count_all(); +table_column sum(const std::string &column); +table_column avg(const std::string &column); +table_column max(const std::string &column); +table_column min(const std::string &column); class query { diff --git a/include/matador/query/query_builder.hpp b/include/matador/query/query_builder.hpp index a3134d5..d2e7a54 100644 --- a/include/matador/query/query_builder.hpp +++ b/include/matador/query/query_builder.hpp @@ -37,6 +37,7 @@ public: void visit( const binary_criteria& node ) override; void visit( const binary_column_criteria& node ) override; void visit( const collection_criteria& node ) override; + void visit( const check_null_criteria& node ) override; void visit( const collection_query_criteria& node ) override; void visit( const like_criteria& node ) override; void visit( const logical_criteria& node ) override; diff --git a/include/matador/query/query_compiler.hpp b/include/matador/query/query_compiler.hpp index ec0e814..baa2a9a 100644 --- a/include/matador/query/query_compiler.hpp +++ b/include/matador/query/query_compiler.hpp @@ -47,7 +47,8 @@ protected: protected: void visit(internal::query_select_part &part) override; void visit(internal::query_from_part &part) override; - void visit(internal::query_join_part &part) override; + void visit(internal::query_join_table_part &part) override; + void visit(internal::query_join_query_part &part) override; void visit(internal::query_on_part &part) override; void visit(internal::query_where_part &part) override; void visit(internal::query_group_by_part &part) override; diff --git a/include/matador/query/query_part_visitor.hpp b/include/matador/query/query_part_visitor.hpp index e0d2bbc..758a763 100644 --- a/include/matador/query/query_part_visitor.hpp +++ b/include/matador/query/query_part_visitor.hpp @@ -15,7 +15,8 @@ class query_add_foreign_key_reference_part; class query_add_primary_key_constraint_part; class query_select_part; class query_from_part; -class query_join_part; +class query_join_table_part; +class query_join_query_part; class query_on_part; class query_where_part; class query_group_by_part; @@ -57,7 +58,8 @@ public: virtual void visit(internal::query_select_part &part) = 0; virtual void visit(internal::query_from_part &part) = 0; - virtual void visit(internal::query_join_part &part) = 0; + virtual void visit(internal::query_join_table_part &part) = 0; + virtual void visit(internal::query_join_query_part &part) = 0; virtual void visit(internal::query_on_part &part) = 0; virtual void visit(internal::query_where_part &part) = 0; virtual void visit(internal::query_group_by_part &part) = 0; diff --git a/include/matador/query/table_column.hpp b/include/matador/query/table_column.hpp index 61c37be..c3b37c8 100644 --- a/include/matador/query/table_column.hpp +++ b/include/matador/query/table_column.hpp @@ -30,7 +30,7 @@ public: [[nodiscard]] bool equals(const table_column &x) const; - table_column as(std::string a); + table_column as(const std::string& alias) const; [[nodiscard]] const std::string& name() const; [[nodiscard]] std::string canonical_name() const; diff --git a/include/matador/sql/dialect.hpp b/include/matador/sql/dialect.hpp index 7f9ea8a..dcbb26b 100644 --- a/include/matador/sql/dialect.hpp +++ b/include/matador/sql/dialect.hpp @@ -152,6 +152,8 @@ public: [[nodiscard]] const std::string& in() const; [[nodiscard]] const std::string& insert() const; [[nodiscard]] const std::string& into() const; + [[nodiscard]] const std::string& is_null() const; + [[nodiscard]] const std::string& is_not_null() const; [[nodiscard]] const std::string& join() const; [[nodiscard]] const std::string& like() const; [[nodiscard]] const std::string& limit() const; @@ -218,6 +220,8 @@ private: {dialect_token::In, "IN"}, {dialect_token::Insert, "INSERT"}, {dialect_token::Into, "INTO"}, + {dialect_token::IsNull, "IS NULL"}, + {dialect_token::IsNotNull, "IS NOT NULL"}, {dialect_token::Join, "LEFT JOIN"}, {dialect_token::Like, "LIKE"}, {dialect_token::Limit, "LIMIT"}, diff --git a/include/matador/sql/dialect_token.hpp b/include/matador/sql/dialect_token.hpp index f7e7384..f40a523 100644 --- a/include/matador/sql/dialect_token.hpp +++ b/include/matador/sql/dialect_token.hpp @@ -35,6 +35,8 @@ enum class dialect_token : uint8_t { In, Insert, Into, + IsNull, + IsNotNull, Join, Like, Limit, diff --git a/source/orm/CMakeLists.txt b/source/orm/CMakeLists.txt index 462e177..fe0771c 100644 --- a/source/orm/CMakeLists.txt +++ b/source/orm/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(matador-orm STATIC ../../include/matador/query/criteria/abstract_column_criteria.hpp ../../include/matador/query/criteria/abstract_criteria.hpp ../../include/matador/query/criteria/between_criteria.hpp + ../../include/matador/query/criteria/check_null_criteria.hpp ../../include/matador/query/criteria/collection_criteria.hpp ../../include/matador/query/criteria/criteria_operators.hpp ../../include/matador/query/criteria/criteria_utils.hpp @@ -102,6 +103,7 @@ add_library(matador-orm STATIC query/criteria/abstract_column_criteria.cpp query/criteria/between_criteria.cpp query/criteria/binary_criteria.cpp + query/criteria/check_null_criteria.cpp query/criteria/collection_criteria.cpp query/criteria/criteria_operators.cpp query/criteria/like_criteria.cpp diff --git a/source/orm/query/criteria/check_null_criteria.cpp b/source/orm/query/criteria/check_null_criteria.cpp new file mode 100644 index 0000000..30dd5af --- /dev/null +++ b/source/orm/query/criteria/check_null_criteria.cpp @@ -0,0 +1,16 @@ +#include "matador/query/criteria/check_null_criteria.hpp" + +#include "matador/query/criteria/criteria_visitor.hpp" + +namespace matador::query { +check_null_criteria::check_null_criteria(const table_column& col, const check_null_operator op) +: abstract_column_criteria(col) +, operator_{op} {} + +void check_null_criteria::accept(criteria_visitor& visitor) const { + visitor.visit(*this); +} +check_null_operator check_null_criteria::operand() const { + return operator_; +} +} // namespace matador::query \ No newline at end of file diff --git a/source/orm/query/criteria/criteria_operators.cpp b/source/orm/query/criteria/criteria_operators.cpp index 94c45cf..24e9c4f 100644 --- a/source/orm/query/criteria/criteria_operators.cpp +++ b/source/orm/query/criteria/criteria_operators.cpp @@ -1,6 +1,7 @@ #include "matador/query/criteria/criteria_operators.hpp" #include "matador/query/criteria/between_criteria.hpp" +#include "matador/query/criteria/check_null_criteria.hpp" #include "matador/query/criteria/like_criteria.hpp" #include "matador/query/criteria/logical_criteria.hpp" #include "matador/query/criteria/not_criteria.hpp" @@ -118,4 +119,11 @@ criteria_ptr between(const table_column &col, utils::placeholder min, utils::pla criteria_ptr like(const table_column &col, const std::string &pattern) { return std::make_unique(col, pattern); } + +criteria_ptr is_null(const table_column &col) { + return std::make_unique(col, check_null_operator::IsNull); } +criteria_ptr is_not_null(const table_column &col) { + return std::make_unique(col, check_null_operator::IsNotNull); +} +} // namespace matador::query diff --git a/source/orm/query/criteria_evaluator.cpp b/source/orm/query/criteria_evaluator.cpp index 7d8ffd2..0c9dcdb 100644 --- a/source/orm/query/criteria_evaluator.cpp +++ b/source/orm/query/criteria_evaluator.cpp @@ -1,18 +1,17 @@ #include "matador/query/criteria_evaluator.hpp" -#include "matador/query/query_utils.hpp" #include "matador/query/criteria/between_criteria.hpp" #include "matador/query/criteria/binary_criteria.hpp" +#include "matador/query/criteria/check_null_criteria.hpp" #include "matador/query/criteria/collection_criteria.hpp" #include "matador/query/criteria/like_criteria.hpp" #include "matador/query/criteria/logical_criteria.hpp" #include "matador/query/criteria/not_criteria.hpp" - +#include "matador/query/query_utils.hpp" #include "matador/sql/dialect.hpp" #include "matador/sql/query_context.hpp" - -#include "matador/utils/value.hpp" #include "matador/utils/enum_mapper.hpp" +#include "matador/utils/value.hpp" namespace matador::query { namespace detail { @@ -61,6 +60,14 @@ void criteria_evaluator::visit( const binary_column_criteria& node ) { clause_ += prepare_criteria(dialect_, node.left_column()) + " " + detail::BinaryOperatorEnum.to_string(node.operand()) + " " + prepare_criteria(dialect_, node.right_column()); } +void criteria_evaluator::visit(const check_null_criteria &node) { + clause_ += prepare_identifier(dialect_, node.col()) + " "; + if (node.operand() == check_null_operator::IsNull) + clause_ += dialect_.is_null(); + else + clause_ += dialect_.is_not_null(); +} + void criteria_evaluator::visit(const collection_criteria &node) { const auto count = node.values().size(); for (size_t i = 0; i < count; ++i) { diff --git a/source/orm/query/intermediates/query_from_intermediate.cpp b/source/orm/query/intermediates/query_from_intermediate.cpp index 08fd85c..91bed05 100644 --- a/source/orm/query/intermediates/query_from_intermediate.cpp +++ b/source/orm/query/intermediates/query_from_intermediate.cpp @@ -10,19 +10,24 @@ namespace matador::query { query_join_intermediate query_from_intermediate::join_left(const table &t) { - context_->parts.push_back(std::make_unique(t)); + context_->parts.push_back(std::make_unique(t)); + return {context_}; +} + +query_join_intermediate query_from_intermediate::join_left(const fetchable_query &q) { + context_->parts.push_back(std::make_unique(q)); return {context_}; } query_from_intermediate query_from_intermediate::join_left(join_data &data) { - context_->parts.push_back(std::make_unique(*data.join_table)); + context_->parts.push_back(std::make_unique(*data.join_table)); context_->parts.push_back(std::make_unique(std::move(data.condition))); return {context_}; } query_from_intermediate query_from_intermediate::join_left(std::vector &data_vector) { for (auto &[join_table, condition] : data_vector) { - context_->parts.push_back(std::make_unique(*join_table)); + context_->parts.push_back(std::make_unique(*join_table)); context_->parts.push_back(std::make_unique(std::move(condition))); } return {context_}; diff --git a/source/orm/query/internal/query_parts.cpp b/source/orm/query/internal/query_parts.cpp index 346571f..3963b1b 100644 --- a/source/orm/query/internal/query_parts.cpp +++ b/source/orm/query/internal/query_parts.cpp @@ -147,16 +147,29 @@ void query_from_part::accept(query_part_visitor &visitor) { visitor.visit(*this); } -query_join_part::query_join_part(class table tab) +query_join_table_part::query_join_table_part(class table tab) : query_part(sql::dialect_token::Join) , table_(std::move(tab)) { } -const table &query_join_part::table() const { +const table &query_join_table_part::table() const { return table_; } -void query_join_part::accept(query_part_visitor &visitor) { +void query_join_table_part::accept(query_part_visitor &visitor) { + visitor.visit(*this); +} + +query_join_query_part::query_join_query_part(fetchable_query q) +: query_part(sql::dialect_token::Join) +, query_(std::move(q)) +{} + +const fetchable_query &query_join_query_part::query() const { + return query_; +} + +void query_join_query_part::accept(query_part_visitor &visitor) { visitor.visit(*this); } diff --git a/source/orm/query/query.cpp b/source/orm/query/query.cpp index ae77362..73629ee 100644 --- a/source/orm/query/query.cpp +++ b/source/orm/query/query.cpp @@ -2,15 +2,6 @@ namespace matador::query { -table_column alias(const std::string &column, const std::string &as) { - return {column, as}; -} - -table_column alias(table_column &&col, const std::string &as) { - col.as(as); - return col; -} - table_column count(const std::string &column) { return {sql::sql_function_t::Count, column}; } @@ -18,6 +9,18 @@ table_column count(const std::string &column) { table_column count_all() { return count("*"); } +table_column sum(const std::string& column) { + return {sql::sql_function_t::Sum, column}; +} +table_column avg(const std::string& column) { + return {sql::sql_function_t::Avg, column}; +} +table_column max(const std::string& column) { + return {sql::sql_function_t::Max, column}; +} +table_column min(const std::string& column) { + return {sql::sql_function_t::Min, column}; +} query_create_intermediate query::create() { diff --git a/source/orm/query/query_builder.cpp b/source/orm/query/query_builder.cpp index 508aaca..9cb0ae2 100644 --- a/source/orm/query/query_builder.cpp +++ b/source/orm/query/query_builder.cpp @@ -15,6 +15,10 @@ void criteria_transformer::visit( const binary_criteria& node ) { void criteria_transformer::visit( const binary_column_criteria& /*node*/ ) {} +void criteria_transformer::visit(const check_null_criteria& node) { + update_criteria_column(node); +} + void criteria_transformer::visit( const collection_criteria& node ) { update_criteria_column(node); } diff --git a/source/orm/query/query_compiler.cpp b/source/orm/query/query_compiler.cpp index 58d374c..7b4ba20 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -174,10 +174,14 @@ void query_compiler::visit(internal::query_from_part &part) { } } -void query_compiler::visit(internal::query_join_part &part) { +void query_compiler::visit(internal::query_join_table_part &part) { query_.sql += " " + build_table_name(part.token(), *dialect_, part.table()); } +void query_compiler::visit(internal::query_join_query_part &part) { + query_.sql += " " + dialect_->join() + " (" + part.query().str(*dialect_) + ")"; +} + void query_compiler::visit(internal::query_on_part &part) { criteria_evaluator evaluator(*dialect_, query_); query_.sql += " " + dialect_->on() + diff --git a/source/orm/query/table_column.cpp b/source/orm/query/table_column.cpp index e0deed0..adc0111 100644 --- a/source/orm/query/table_column.cpp +++ b/source/orm/query/table_column.cpp @@ -91,9 +91,8 @@ bool table_column::equals(const table_column &x) const { function_ == x.function_; } -table_column table_column::as(std::string a) { - alias_ = std::move(a); - return {table_, name_, alias_, type_, attributes_, function_}; +table_column table_column::as(const std::string& alias) const { + return {table_, name_, alias, type_, attributes_, function_}; } const std::string& table_column::name() const { diff --git a/source/orm/sql/dialect.cpp b/source/orm/sql/dialect.cpp index 8477457..318b4c2 100644 --- a/source/orm/sql/dialect.cpp +++ b/source/orm/sql/dialect.cpp @@ -221,6 +221,14 @@ const std::string &dialect::into() const { return token_at(dialect_token::Into); } +const std::string &dialect::is_null() const { + return token_at(dialect_token::IsNull); +} + +const std::string &dialect::is_not_null() const { + return token_at(dialect_token::IsNotNull); +} + const std::string &dialect::join() const { return token_at(dialect_token::Join); }