From a1d9183af1c98d4fd5f87e3145287ee690e853fa Mon Sep 17 00:00:00 2001 From: silverqx Date: Tue, 6 Jul 2021 10:57:02 +0200 Subject: [PATCH] added new joinSub() overload With the callback for join on clause. --- include/orm/query/querybuilder.hpp | 44 ++++++++++++++++++ include/orm/tiny/model.hpp | 59 +++++++++++++++++++++++++ include/orm/tiny/relations/relation.hpp | 53 ++++++++++++++++++++++ include/orm/tiny/tinybuilder.hpp | 44 ++++++++++++++++++ src/orm/query/querybuilder.cpp | 14 ++++++ 5 files changed, 214 insertions(+) diff --git a/include/orm/query/querybuilder.hpp b/include/orm/query/querybuilder.hpp index 4eb4e233c..4ff9b1cd8 100644 --- a/include/orm/query/querybuilder.hpp +++ b/include/orm/query/querybuilder.hpp @@ -203,14 +203,27 @@ namespace Query Builder &joinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second, const QString &type = "inner", bool where = false); + /*! Add a subquery join clause to the query. */ + template + Builder &joinSub(T &&query, const QString &as, + const std::function &callback, + const QString &type = "inner"); /*! Add a subquery left join to the query. */ template Builder &leftJoinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second); + /*! Add a subquery left join to the query. */ + template + Builder &leftJoinSub(T &&query, const QString &as, + const std::function &callback); /*! Add a subquery right join to the query. */ template Builder &rightJoinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second); + /*! Add a subquery right join to the query. */ + template + Builder &rightJoinSub(T &&query, const QString &as, + const std::function &callback); /*! Add a basic where clause to the query. */ Builder &where(const Column &column, const QString &comparison, @@ -525,6 +538,11 @@ namespace Query std::pair> &&subQuery, const QString &as, const QString &first, const QString &comparison, const QVariant &second, const QString &type, bool where); + /*! Add a subquery join clause to the query, common code. */ + Builder &joinSubInternal( + std::pair> &&subQuery, const QString &as, + const std::function &callback, + const QString &type); /*! All of the available clause operators. */ const QVector m_operators { @@ -673,6 +691,7 @@ namespace Query first, comparison, second, where); } + // FUTURE joinSub, missing where param, also in joinSub silverqx template inline Builder & Builder::join(T &&table, const std::function &callback, @@ -767,6 +786,15 @@ namespace Query as, first, comparison, second, type, where); } + template + inline Builder & + Builder::joinSub(T &&query, const QString &as, + const std::function &callback, + const QString &type) + { + return joinSubInternal(createSub(std::forward(query)), as, callback, type); + } + template inline Builder & Builder::leftJoinSub(T &&query, const QString &as, const QString &first, @@ -776,6 +804,14 @@ namespace Query QStringLiteral("left")); } + template + inline Builder & + Builder::leftJoinSub(T &&query, const QString &as, + const std::function &callback) + { + return joinSub(std::forward(query), as, callback, QStringLiteral("left")); + } + template inline Builder & Builder::rightJoinSub(T &&query, const QString &as, const QString &first, @@ -785,6 +821,14 @@ namespace Query QStringLiteral("right")); } + template + inline Builder & + Builder::rightJoinSub(T &&query, const QString &as, + const std::function &callback) + { + return joinSub(std::forward(query), as, callback, QStringLiteral("right")); + } + template inline Builder &Builder::groupBy(Args &&...groups) { diff --git a/include/orm/tiny/model.hpp b/include/orm/tiny/model.hpp index 9e5cbade6..f0823af52 100644 --- a/include/orm/tiny/model.hpp +++ b/include/orm/tiny/model.hpp @@ -373,16 +373,32 @@ namespace Relations { joinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second, const QString &type = "inner", bool where = false); + /*! Add a subquery join clause to the query. */ + template + static std::unique_ptr> + joinSub(T &&query, const QString &as, + const std::function &callback, + const QString &type = "inner"); /*! Add a subquery left join to the query. */ template static std::unique_ptr> leftJoinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second); + /*! Add a subquery left join to the query. */ + template + static std::unique_ptr> + leftJoinSub(T &&query, const QString &as, + const std::function &callback); /*! Add a subquery right join to the query. */ template static std::unique_ptr> rightJoinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second); + /*! Add a subquery right join to the query. */ + template + static std::unique_ptr> + rightJoinSub(T &&query, const QString &as, + const std::function &callback); /*! Add a basic where clause to the query. */ static std::unique_ptr> @@ -1978,6 +1994,21 @@ namespace Relations { return builder; } + template + template + std::unique_ptr> + Model::joinSub( + T &&query, const QString &as, + const std::function &callback, + const QString &type) + { + auto builder = Derived::query(); + + builder->joinSub(std::forward(query), as, callback, type); + + return builder; + } + template template std::unique_ptr> @@ -1992,6 +2023,20 @@ namespace Relations { return builder; } + template + template + std::unique_ptr> + Model::leftJoinSub( + T &&query, const QString &as, + const std::function &callback) + { + auto builder = Derived::query(); + + builder->joinSub(std::forward(query), as, callback, QStringLiteral("left")); + + return builder; + } + template template std::unique_ptr> @@ -2006,6 +2051,20 @@ namespace Relations { return builder; } + template + template + std::unique_ptr> + Model::rightJoinSub( + T &&query, const QString &as, + const std::function &callback) + { + auto builder = Derived::query(); + + builder->joinSub(std::forward(query), as, callback, QStringLiteral("right")); + + return builder; + } + template std::unique_ptr> Model::where( diff --git a/include/orm/tiny/relations/relation.hpp b/include/orm/tiny/relations/relation.hpp index d09e88236..2b23efc59 100644 --- a/include/orm/tiny/relations/relation.hpp +++ b/include/orm/tiny/relations/relation.hpp @@ -331,16 +331,32 @@ namespace Relations T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second, const QString &type = "inner", bool where = false) const; + /*! Add a subquery join clause to the query. */ + template + const Relation &joinSub( + T &&query, const QString &as, + const std::function &callback, + const QString &type = "inner") const; /*! Add a subquery left join to the query. */ template const Relation &leftJoinSub( T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second) const; + /*! Add a subquery left join to the query. */ + template + const Relation &leftJoinSub( + T &&query, const QString &as, + const std::function &callback) const; /*! Add a subquery right join to the query. */ template const Relation &rightJoinSub( T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second) const; + /*! Add a subquery right join to the query. */ + template + const Relation &rightJoinSub( + T &&query, const QString &as, + const std::function &callback) const; /*! Add a basic where clause to the query. */ const Relation &where( @@ -1130,6 +1146,19 @@ namespace Relations return *this; } + template + template + const Relation & + Relation::joinSub( + T &&query, const QString &as, + const std::function &callback, + const QString &type) const + { + m_query->joinSub(std::forward(query), as, callback, type); + + return *this; + } + template template const Relation & @@ -1142,6 +1171,18 @@ namespace Relations return *this; } + template + template + const Relation & + Relation::leftJoinSub( + T &&query, const QString &as, + const std::function &callback) const + { + m_query->joinSub(std::forward(query), as, callback, QStringLiteral("left")); + + return *this; + } + template template const Relation & @@ -1154,6 +1195,18 @@ namespace Relations return *this; } + template + template + const Relation & + Relation::rightJoinSub( + T &&query, const QString &as, + const std::function &callback) const + { + m_query->joinSub(std::forward(query), as, callback, QStringLiteral("right")); + + return *this; + } + template const Relation & Relation::where(const Column &column, const QString &comparison, diff --git a/include/orm/tiny/tinybuilder.hpp b/include/orm/tiny/tinybuilder.hpp index 88152eb34..4a1b0304b 100644 --- a/include/orm/tiny/tinybuilder.hpp +++ b/include/orm/tiny/tinybuilder.hpp @@ -246,14 +246,27 @@ namespace Relations Builder &joinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second, const QString &type = "inner", bool where = false); + /*! Add a subquery join clause to the query. */ + template + Builder &joinSub(T &&query, const QString &as, + const std::function &callback, + const QString &type = "inner"); /*! Add a subquery left join to the query. */ template Builder &leftJoinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second); + /*! Add a subquery left join to the query. */ + template + Builder &leftJoinSub(T &&query, const QString &as, + const std::function &callback); /*! Add a subquery right join to the query. */ template Builder &rightJoinSub(T &&query, const QString &as, const QString &first, const QString &comparison, const QVariant &second); + /*! Add a subquery right join to the query. */ + template + Builder &rightJoinSub(T &&query, const QString &as, + const std::function &callback); /*! Add a basic where clause to the query. */ Builder &where(const Column &column, const QString &comparison, @@ -1095,6 +1108,17 @@ namespace Relations return *this; } + template + template + Builder & + Builder::joinSub(T &&query, const QString &as, + const std::function &callback, + const QString &type) + { + toBase().joinSub(std::forward(query), as, callback, type); + return *this; + } + template template Builder & @@ -1105,6 +1129,16 @@ namespace Relations return *this; } + template + template + Builder & + Builder::leftJoinSub(T &&query, const QString &as, + const std::function &callback) + { + toBase().joinSub(std::forward(query), as, callback, QStringLiteral("left")); + return *this; + } + template template Builder & @@ -1115,6 +1149,16 @@ namespace Relations return *this; } + template + template + Builder & + Builder::rightJoinSub(T &&query, const QString &as, + const std::function &callback) + { + toBase().joinSub(std::forward(query), as, callback, QStringLiteral("right")); + return *this; + } + template Builder & Builder::where(const Column &column, const QString &comparison, diff --git a/src/orm/query/querybuilder.cpp b/src/orm/query/querybuilder.cpp index 371d41316..227d188a0 100644 --- a/src/orm/query/querybuilder.cpp +++ b/src/orm/query/querybuilder.cpp @@ -944,6 +944,20 @@ Builder &Builder::joinSubInternal( first, comparison, second, type, where); } +Builder &Builder::joinSubInternal( + std::pair> &&subQuery, const QString &as, + const std::function &callback, + const QString &type) +{ + auto &[queryString, bindings] = subQuery; + + addBinding(std::move(bindings), BindingType::JOIN); + + return join(Expression(QStringLiteral("(%1) as %2").arg(queryString, + m_grammar.wrapTable(as))), + callback, type); +} + } // namespace Orm #ifdef TINYORM_COMMON_NAMESPACE } // namespace TINYORM_COMMON_NAMESPACE