LCOV - code coverage report
Current view: top level - core/sql - SPSqlWhere.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 97 126 77.0 %
Date: 2024-05-12 00:16:13 Functions: 73 121 60.3 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : // Excluded from documentation/codegen tool
      25             : ///@ SP_EXCLUDE
      26             : 
      27             : #ifndef STAPPLER_SQL_SPSQLWHERE_HPP_
      28             : #define STAPPLER_SQL_SPSQLWHERE_HPP_
      29             : 
      30             : #include "SPSql.h"
      31             : 
      32             : namespace STAPPLER_VERSIONIZED stappler::sql {
      33             : 
      34             : template <typename Stream>
      35        2950 : static inline void Query_writeOperator(Stream &stream, Operator op) {
      36        2950 :         switch (op) {
      37        2825 :         case Operator::And: stream << "AND"; break;
      38         125 :         case Operator::Or: stream << "OR"; break;
      39             :         }
      40        2950 : }
      41             : 
      42             : template <typename Interface>
      43       18025 : static inline auto Query_writeFieldName(typename Interface::StringStreamType &stream, const StringView &cmp, bool plain)
      44             :         -> typename Interface::StringStreamType & {
      45       18025 :         if (!plain) { stream << '"'; }
      46       18025 :         stream << cmp;
      47       18025 :         if (!plain) { stream << '"'; }
      48       18025 :         return stream;
      49             : }
      50             : 
      51             : template <typename Binder, typename Interface, typename Value1>
      52       17275 : static inline void Query_writeComparationStr(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
      53             :                 const typename Query<Binder, Interface>::Field &f, const StringView &cmp, Value1 &&v1) {
      54       17275 :         stream << "(";
      55       17275 :         if (!f.source.empty()) { stream << "\"" << f.source << "\"."; }
      56       17275 :         Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp;
      57       17275 :         q.writeBind(forward<Value1>(v1));
      58       17275 :         stream << ")";
      59       17275 : }
      60             : 
      61             : template <typename Binder, typename Interface, typename Value1>
      62          25 : static inline void Query_writeComparationStrArray(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
      63             :                 const typename Query<Binder, Interface>::Field &f, const StringView &cmp, Value1 &&v1) {
      64          25 :         stream << "(";
      65          25 :         if (!f.source.empty()) { stream << "\"" << f.source << "\"."; }
      66          25 :         Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp;
      67          25 :         q.writeBindArray(forward<Value1>(v1));
      68          25 :         stream << ")";
      69          25 : }
      70             : 
      71             : template <typename Binder, typename Interface, typename Value1, typename Value2>
      72          50 : static inline void Query_writeComparationStr(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
      73             :                 const typename Query<Binder, Interface>::Field &f, const StringView &cmp1, Value1 &&v1, const StringView &cmp2, Value2 &&v2, const StringView &op) {
      74          50 :         stream << "(";
      75          50 :         if (!f.source.empty()) { stream << f.source << "."; }
      76          50 :         Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp1;
      77          50 :         q.writeBind(forward<Value1>(v1));
      78          50 :         stream << " " << op << " ";
      79          50 :         if (!f.source.empty()) { stream << f.source << "."; }
      80          50 :         Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp2;
      81          50 :         q.writeBind(forward<Value2>(v2));
      82          50 :         stream << ")";
      83          50 : }
      84             : 
      85             : template <typename Binder, typename Interface, typename Value1, typename Value2>
      86           0 : static inline void Query_writeComparationBetween(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
      87             :                 const typename Query<Binder, Interface>::Field &f, Value1 &&v1, Value2 &&v2) {
      88           0 :         if (!f.source.empty()) { stream << f.source << "."; }
      89           0 :         Query_writeFieldName<Interface>(stream, f.name, f.plain) << " BETWEEN ";
      90           0 :         q.writeBind(forward<Value1>(v1));
      91           0 :         stream << " AND ";
      92           0 :         q.writeBind(forward<Value2>(v2));
      93           0 : }
      94             : 
      95             : template <typename Binder, typename Interface>
      96         625 : static inline void Query_writeComparationStrNoArg(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
      97             :                 const typename Query<Binder, Interface>::Field &f, const StringView &cmp) {
      98         625 :         stream << "(";
      99         625 :         if (!f.source.empty()) { stream << f.source << "."; }
     100         625 :         Query_writeFieldName<Interface>(stream, f.name, f.plain) << cmp << ")";
     101         625 : }
     102             : 
     103             : template <typename Binder, typename Interface, typename Value1>
     104       16725 : inline void Query_writeComparation(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
     105             :                 const typename Query<Binder, Interface>::Field &f, Comparation cmp, Value1 &&v1) {
     106       16725 :         switch (cmp) {
     107         125 :         case Comparation::LessThen:                     Query_writeComparationStr(q, stream, f, "<",  std::forward<Value1>(v1)); break;
     108           0 :         case Comparation::LessOrEqual:          Query_writeComparationStr(q, stream, f, "<=", std::forward<Value1>(v1)); break;
     109       14925 :         case Comparation::Equal:                        Query_writeComparationStr(q, stream, f, "=",  std::forward<Value1>(v1)); break;
     110          75 :         case Comparation::NotEqual:                     Query_writeComparationStr(q, stream, f, "!=", std::forward<Value1>(v1)); break;
     111           0 :         case Comparation::GreatherOrEqual:      Query_writeComparationStr(q, stream, f, ">=", std::forward<Value1>(v1)); break;
     112        1425 :         case Comparation::GreatherThen:         Query_writeComparationStr(q, stream, f, ">",  std::forward<Value1>(v1)); break;
     113          50 :         case Comparation::Includes:                     Query_writeComparationStr(q, stream, f, "@@", std::forward<Value1>(v1)); break;
     114         125 :         case Comparation::In:                           Query_writeComparationStr(q, stream, f, " IN ", std::forward<Value1>(v1)); break;
     115           0 :         case Comparation::NotIn:                        Query_writeComparationStr(q, stream, f, " NOT IN ", std::forward<Value1>(v1)); break;
     116           0 :         case Comparation::IsNull:                       Query_writeComparationStrNoArg(q, stream, f, " IS NULL"); break;
     117           0 :         case Comparation::IsNotNull:            Query_writeComparationStrNoArg(q, stream, f, " IS NOT NULL"); break;
     118           0 :         default: break;
     119             :         }
     120       16725 : }
     121             : 
     122             : template <typename T>
     123           0 : auto makePatternComparator(Comparation cmp, T &&value) -> PatternComparator<T> {
     124           0 :         return PatternComparator<T>{cmp, &value};
     125             : }
     126             : 
     127             : template <typename Binder, typename Interface, typename Value1, typename Value2>
     128        1150 : inline void Query_writeComparation(Query<Binder, Interface> &q, typename Interface::StringStreamType &stream,
     129             :                 const typename Query<Binder, Interface>::Field &f, Comparation cmp, Value1 &&v1, Value2 &&v2) {
     130        1150 :         stream << "(";
     131        1150 :         switch (cmp) {
     132           0 :         case Comparation::Invalid:                      break;
     133          50 :         case Comparation::LessThen:                     Query_writeComparationStr(q, stream, f, "<",  std::forward<Value1>(v1)); break;
     134           0 :         case Comparation::LessOrEqual:          Query_writeComparationStr(q, stream, f, "<=", std::forward<Value1>(v1)); break;
     135         375 :         case Comparation::Equal:                        Query_writeComparationStr(q, stream, f, "=",  std::forward<Value1>(v1)); break;
     136           0 :         case Comparation::NotEqual:                     Query_writeComparationStr(q, stream, f, "!=", std::forward<Value1>(v1)); break;
     137           0 :         case Comparation::GreatherOrEqual:      Query_writeComparationStr(q, stream, f, ">=", std::forward<Value1>(v1)); break;
     138          25 :         case Comparation::GreatherThen:         Query_writeComparationStr(q, stream, f, ">",  std::forward<Value1>(v1)); break;
     139          50 :         case Comparation::BetweenValues:        Query_writeComparationStr(q, stream, f, ">",  std::forward<Value1>(v1), "<",  std::forward<Value2>(v2), "AND"); break;
     140           0 :         case Comparation::BetweenEquals:        Query_writeComparationStr(q, stream, f, ">=", std::forward<Value1>(v1), "<=", std::forward<Value2>(v2), "AND"); break;
     141           0 :         case Comparation::NotBetweenValues:     Query_writeComparationStr(q, stream, f, "<=", std::forward<Value1>(v1), ">=", std::forward<Value2>(v2), "OR"); break;
     142           0 :         case Comparation::NotBetweenEquals:     Query_writeComparationStr(q, stream, f, "<",  std::forward<Value1>(v1), ">",  std::forward<Value2>(v2), "OR"); break;
     143           0 :         case Comparation::Includes:                     Query_writeComparationStr(q, stream, f, "@@", std::forward<Value1>(v1)); break;
     144           0 :         case Comparation::Between:                      Query_writeComparationBetween(q, stream, f, std::forward<Value1>(v1), std::forward<Value2>(v2)); break;
     145          25 :         case Comparation::In:                           Query_writeComparationStrArray(q, stream, f, " IN ", std::forward<Value1>(v1)); break;
     146           0 :         case Comparation::NotIn:                        Query_writeComparationStrArray(q, stream, f, " NOT IN ", std::forward<Value1>(v1)); break;
     147           0 :         case Comparation::IsNull:                       Query_writeComparationStrNoArg(q, stream, f, " IS NULL"); break;
     148         625 :         case Comparation::IsNotNull:            Query_writeComparationStrNoArg(q, stream, f, " IS NOT NULL"); break;
     149           0 :         case Comparation::Prefix:                       Query_writeComparationStr(q, stream, f, " LIKE ", makePatternComparator(cmp, std::forward<Value1>(v1))); break;
     150           0 :         case Comparation::Suffix:                       Query_writeComparationStr(q, stream, f, " LIKE ", makePatternComparator(cmp, std::forward<Value1>(v1))); break;
     151           0 :         case Comparation::WordPart:                     Query_writeComparationStr(q, stream, f, " LIKE ", makePatternComparator(cmp, std::forward<Value1>(v1))); break;
     152             :         }
     153        1150 :         stream << ")";
     154        1150 : }
     155             : 
     156             : template <typename Binder, typename Interface>
     157             : template <typename Clause>
     158             : template <typename Value>
     159       16725 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, Comparation cmp, Value &&val) -> Clause & {
     160       16725 :         if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
     161       16725 :         Query_writeComparation(*(this->query), this->query->stream, field, cmp, std::forward<Value>(val));
     162       16725 :         return (Clause &)*this;
     163             : }
     164             : 
     165             : template <typename Binder, typename Interface>
     166             : template <typename Clause>
     167             : template <typename Value>
     168         100 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, const StringView &cmp, Value &&val) -> Clause & {
     169         100 :         if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
     170         100 :         Query_writeComparationStr(*(this->query), this->query->stream, field, cmp, std::forward<Value>(val));
     171         100 :         return (Clause &)*this;
     172             : }
     173             : 
     174             : template <typename Binder, typename Interface>
     175             : template <typename Clause>
     176             : template <typename Value>
     177        1150 : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, Comparation cmp, Value &&val1, Value &&val2) -> Clause & {
     178        1150 :         if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
     179        1150 :         Query_writeComparation(*(this->query), this->query->stream, field, cmp, std::forward<Value>(val1), std::forward<Value>(val2));
     180        1150 :         return (Clause &)*this;
     181             : }
     182             : 
     183             : template <typename Binder, typename Interface>
     184             : template <typename Clause>
     185             : template <typename Value>
     186             : auto Query<Binder, Interface>::WhereClause<Clause>::where(Operator op, const Field &field, const StringView &cmp1, Value &&val1, const StringView &cmp2, Value &&val2) -> Clause & {
     187             :         if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
     188             :         Query_writeComparationStr(*(this->query), this->query->stream, field, cmp1, std::forward<Value>(val1), cmp2, std::forward<Value>(val2));
     189             :         return (Clause &)*this;
     190             : }
     191             : 
     192             : template <typename Binder, typename Interface>
     193             : template <typename Clause>
     194             : template <typename Callback>
     195        1800 : auto Query<Binder, Interface>::WhereClause<Clause>::parenthesis(Operator op, const Callback &cb) -> Clause & {
     196        1800 :         if (this->state == State::None) { this->state = State::Some; } else { Query_writeOperator(this->query->stream, op); }
     197        1800 :         this->query->stream << "(";
     198        1800 :         auto state = this->state;
     199        1800 :         this->state = State::None;
     200        1800 :         WhereBegin tmp(this->query);
     201        1800 :         cb(tmp);
     202        1800 :         this->state = state;
     203        1800 :         this->query->stream << ")";
     204        1800 :         return (Clause &)*this;
     205             : }
     206             : 
     207             : template <typename Binder, typename Interface>
     208             : template <typename ... Args>
     209        1625 : auto Query<Binder, Interface>::WhereBegin::where(Args && ... args) -> WhereContinue {
     210        1625 :         WhereContinue q(this->query);
     211        1625 :         q.where(sql::Operator::And, std::forward<Args>(args)...);
     212        1625 :         return q;
     213             : }
     214             : 
     215             : template <typename Binder, typename Interface>
     216        1775 : auto Query<Binder, Interface>::WhereBegin::where() -> WhereContinue {
     217        1775 :         return WhereContinue(this->query);
     218             : }
     219             : 
     220             : template <typename Binder, typename Interface>
     221             : template <typename Callback>
     222             : auto Query<Binder, Interface>::WhereBegin::whereParentesis(const Callback &cb) -> WhereContinue {
     223             :         WhereContinue q(this->query);
     224             :         q.parenthesis(sql::Operator::And, cb);
     225             :         return q;
     226             : }
     227             : 
     228             : template <typename Binder, typename Interface>
     229             : template <typename Clause>
     230             : template <typename Value>
     231        6100 : auto Query<Binder, Interface>::SetClause<Clause>::set(const StringView &f, Value &&v) -> Clause & {
     232        6100 :         if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
     233        6100 :         this->query->stream << " \"" << f << "\"=";
     234        6100 :         this->query->writeBind(forward<Value>(v));
     235        6100 :         return (Clause &)*this;
     236             : }
     237             : 
     238             : template <typename Binder, typename Interface>
     239             : template <typename Clause>
     240             : template <typename Value>
     241             : auto Query<Binder, Interface>::SetClause<Clause>::set(const StringView &t, const StringView &f, Value && v) -> Clause & {
     242             :         if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
     243             :         this->query->stream << " " << t << ".\"" << f << "\"=";
     244             :         this->query->writeBind(forward<Value>(v));
     245             :         return (Clause &)*this;
     246             : }
     247             : 
     248             : template <typename Binder, typename Interface>
     249             : template <typename Clause>
     250          25 : auto Query<Binder, Interface>::SetClause<Clause>::def(const StringView &f) -> Clause & {
     251          25 :         if (this->state == State::None) { this->state = State::Some; } else { this->query->stream << ","; }
     252          25 :         this->query->stream << " \"" << f << "\"=DEFAULT";
     253          25 :         return (Clause &)*this;
     254             : }
     255             : 
     256             : }
     257             : 
     258             : #endif /* STAPPLER_SQL_SPSQLWHERE_HPP_ */

Generated by: LCOV version 1.14