github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/include/ff/sql/stmt.h (about)

     1  /***********************************************
     2    The MIT License (MIT)
     3  
     4    Copyright (c) 2012 Athrun Arthur <athrunarthur@gmail.com>
     5  
     6    Permission is hereby granted, free of charge, to any person obtaining a copy
     7    of this software and associated documentation files (the "Software"), to deal
     8    in the Software without restriction, including without limitation the rights
     9    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10    copies of the Software, and to permit persons to whom the Software is
    11    furnished to do so, subject to the following conditions:
    12  
    13    The above copyright notice and this permission notice shall be included in
    14    all copies or substantial portions of the Software.
    15  
    16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22    THE SOFTWARE.
    23   *************************************************/
    24  #pragma once
    25  #include "ff/sql/common.h"
    26  #include "ff/sql/rows.h"
    27  #include <sstream>
    28  
    29  namespace ff {
    30  namespace sql {
    31  
    32  struct cond_stmt {
    33  public:
    34    virtual void dump_to_sql_string(std::stringstream &ss) const = 0;
    35      };
    36  
    37  
    38      template<typename T1, typename T2>
    39        struct and_cond_stmt : public cond_stmt{
    40          and_cond_stmt(const T1 & t1, const T2 & t2): stmt1(t1), stmt2(t2){}
    41          T1 stmt1;
    42          T2 stmt2;
    43  
    44          typedef typename util::merge_type_list<
    45              typename T1::cols_type, typename T2::cols_type>::type cols_type;
    46  
    47          void traverse_and_call_back(const std::function<void (cond_stmt *)> & callback){
    48            stmt1.traverse_and_call_back(callback);
    49            callback(this);
    50            stmt2.traverse_and_call_back(callback);
    51          }
    52  
    53          virtual void dump_to_sql_string(std::stringstream &ss) const {
    54            ss<<" (";
    55            stmt1.dump_to_sql_string(ss);
    56            ss<<" and ";
    57            stmt2.dump_to_sql_string(ss);
    58            ss<<") ";
    59          }
    60        };
    61      template< typename T1, typename T2>
    62        struct or_cond_stmt : public cond_stmt{
    63          or_cond_stmt(const T1 & t1, const T2 & t2): stmt1(t1), stmt2(t2){}
    64          void traverse_and_call_back(const std::function<void (cond_stmt *)> & callback){
    65            stmt1.traverse_and_call_back(callback);
    66            callback(this);
    67            stmt2.traverse_and_call_back(callback);
    68          }
    69          T1 stmt1;
    70          T2 stmt2;
    71          typedef typename util::merge_type_list<
    72              typename T1::cols_type, typename T2::cols_type>::type cols_type;
    73          virtual void dump_to_sql_string(std::stringstream &ss) const {
    74            ss<<" (";
    75            stmt1.dump_to_sql_string(ss);
    76            ss<<" or ";
    77            stmt2.dump_to_sql_string(ss);
    78            ss<<") ";
    79          }
    80        };
    81  
    82  
    83      enum sql_cond_type{
    84        eq_cond,
    85        ne_cond,
    86        ge_cond,
    87        le_cond,
    88      };
    89  
    90      template<typename T, sql_cond_type CT>
    91        struct basic_cond_stmt : public cond_stmt{
    92          basic_cond_stmt(const typename T::type & value) : m_value (value){}
    93          void traverse_and_call_back(const std::function<void (cond_stmt *)> & callback){
    94            callback(this);
    95          }
    96          typename T::type m_value;
    97  
    98          typedef util::type_list<T> cols_type;
    99          const static sql_cond_type cond_type = CT;
   100        };
   101  
   102      template<typename T>
   103        struct eq_cond_stmt : public basic_cond_stmt<T, eq_cond>{
   104          eq_cond_stmt(const typename T::type & value): basic_cond_stmt<T, eq_cond>(value){}
   105  
   106          virtual void dump_to_sql_string(std::stringstream &ss) const {
   107            ss << T::name << " = ? ";
   108          }
   109        };
   110      template<typename T>
   111        struct ne_cond_stmt : public basic_cond_stmt<T, ne_cond>{
   112          ne_cond_stmt(const typename T::type & value): basic_cond_stmt<T, ne_cond>(value){}
   113          virtual void dump_to_sql_string(std::stringstream &ss) const {
   114            ss<<T::name<<" != ? ";
   115          }
   116        };
   117      template<typename T>
   118        struct ge_cond_stmt : public basic_cond_stmt<T, ge_cond>{
   119          ge_cond_stmt(const typename T::type & value): basic_cond_stmt<T, ge_cond>(value){}
   120          virtual void dump_to_sql_string(std::stringstream &ss) const {
   121            ss<<T::name<<" >= ? ";
   122          }
   123        };
   124      template<typename T>
   125        struct le_cond_stmt : public basic_cond_stmt<T, le_cond>{
   126          le_cond_stmt(const typename T::type & value): basic_cond_stmt<T, le_cond>(value){}
   127          virtual void dump_to_sql_string(std::stringstream &ss) const {
   128            ss<<T::name<<" <= ? ";
   129          }
   130        };
   131  
   132      template<typename TT, typename... ARGS>
   133        struct statement{
   134          public:
   135            typedef typename TT::engine_type engine_type;
   136            statement(engine_type *engine) : m_engine(engine) {}
   137            virtual row_collection<ARGS...> eval() = 0;
   138          protected:
   139            engine_type *m_engine;
   140        };
   141  
   142  #include "ff/sql/where_stmt_bind.hpp"
   143  
   144        template <typename TT, typename... ARGS>
   145        struct limit_statement : public statement<TT, ARGS...> {
   146        public:
   147          typedef typename TT::engine_type engine_type;
   148          limit_statement(engine_type *engine, const std::string &prev_sql,
   149                          int64_t count)
   150              : statement<TT, ARGS...>(engine), m_prev_sql(prev_sql),
   151                m_count(count) {}
   152  
   153          virtual row_collection<ARGS...> eval() {
   154            std::stringstream ss;
   155            ss << get_eval_sql_string() << ";";
   156            auto ret = m_engine->eval_sql_query_string(ss.str());
   157            return m_engine->template parse_records<ARGS...>(ret);
   158          }
   159  
   160        protected:
   161          std::string get_eval_sql_string() const {
   162            std::stringstream ss;
   163            ss << m_prev_sql << " LIMIT " << m_count;
   164            return ss.str();
   165          }
   166  
   167        protected:
   168          using statement<TT, ARGS...>::m_engine;
   169          std::string m_prev_sql;
   170          int64_t m_count;
   171        };
   172  
   173        struct desc {
   174          constexpr static const char *name = "DESC";
   175        };
   176        struct asc {
   177          constexpr static const char *name = "ASC";
   178        };
   179  
   180        template <typename TT, typename CT, typename ORDER, typename... ARGS>
   181        struct order_statement : public statement<TT, ARGS...> {
   182        public:
   183          typedef typename TT::engine_type engine_type;
   184          order_statement(engine_type *engine, const std::string &prev_sql)
   185              : statement<TT, ARGS...>(engine), m_prev_sql(prev_sql) {}
   186  
   187          limit_statement<TT, ARGS...> limit(int64_t count) {
   188            if (count <= 0) {
   189              throw std::runtime_error("limit count must be larger than 0");
   190            }
   191            return limit_statement<TT, ARGS...>(m_engine, get_eval_sql_string(),
   192                                                count);
   193          }
   194          virtual row_collection<ARGS...> eval() {
   195            std::stringstream ss;
   196            ss << get_eval_sql_string() << ";";
   197            auto ret = m_engine->eval_sql_query_string(ss.str());
   198            return m_engine->template parse_records<ARGS...>(ret);
   199          }
   200  
   201        protected:
   202          std::string get_eval_sql_string() const {
   203            std::stringstream ss;
   204            ss << m_prev_sql << " order by " << CT::name << " " << ORDER::name;
   205            return ss.str();
   206          }
   207  
   208        protected:
   209          using statement<TT, ARGS...>::m_engine;
   210          std::string m_prev_sql;
   211        };
   212  
   213        template <typename TT, typename CST, typename... ARGS>
   214        struct cst_limit_statement : public statement<TT, ARGS...> {
   215        public:
   216          typedef typename TT::engine_type engine_type;
   217          cst_limit_statement(engine_type *engine, const std::string &prev_sql,
   218                              int64_t count, CST cst)
   219              : statement<TT, ARGS...>(engine), m_prev_sql(prev_sql),
   220                m_count(count), m_cst(cst) {}
   221  
   222          virtual row_collection<ARGS...> eval() {
   223            std::stringstream ss;
   224            ss << get_eval_sql_string();
   225            ss << "; ";
   226            auto native_statmenet = m_engine->prepare_sql_with_string(ss.str());
   227            int index = 0;
   228            traverse_cond_for_bind<TT, CST>::run(m_engine, native_statmenet,
   229                                                 m_cst, index);
   230            auto ret = m_engine->eval_native_sql_stmt(native_statmenet);
   231            return m_engine->template parse_records<ARGS...>(ret);
   232          }
   233  
   234        protected:
   235          std::string get_eval_sql_string() const {
   236            std::stringstream ss;
   237            ss << m_prev_sql << " LIMIT " << m_count;
   238            return ss.str();
   239          }
   240  
   241        protected:
   242          using statement<TT, ARGS...>::m_engine;
   243          std::string m_prev_sql;
   244          int64_t m_count;
   245          CST m_cst;
   246        };
   247  
   248        template <typename TT, typename CT, typename ORDER, typename CST,
   249                  typename... ARGS>
   250        struct cst_order_statement : public statement<TT, ARGS...> {
   251        public:
   252          typedef typename TT::engine_type engine_type;
   253          cst_order_statement(engine_type *engine, const std::string &prev_sql,
   254                              CST cst)
   255              : statement<TT, ARGS...>(engine), m_prev_sql(prev_sql), m_cst(cst) {
   256          }
   257  
   258          cst_limit_statement<TT, CST, ARGS...> limit(int64_t count) {
   259            if (count <= 0) {
   260              throw std::runtime_error("limit count must be larger than 0");
   261            }
   262            return cst_limit_statement<TT, CST, ARGS...>(
   263                m_engine, get_eval_sql_string(), count, m_cst);
   264          }
   265          virtual row_collection<ARGS...> eval() {
   266            std::stringstream ss;
   267            ss << get_eval_sql_string();
   268            ss << "; ";
   269            auto native_statmenet = m_engine->prepare_sql_with_string(ss.str());
   270            int index = 0;
   271            traverse_cond_for_bind<TT, CST>::run(m_engine, native_statmenet,
   272                                                 m_cst, index);
   273            auto ret = m_engine->eval_native_sql_stmt(native_statmenet);
   274            return m_engine->template parse_records<ARGS...>(ret);
   275          }
   276  
   277        protected:
   278          std::string get_eval_sql_string() const {
   279            std::stringstream ss;
   280            ss << m_prev_sql << " order by " << CT::name << " " << ORDER::name;
   281            return ss.str();
   282          }
   283  
   284        protected:
   285          using statement<TT, ARGS...>::m_engine;
   286          std::string m_prev_sql;
   287          CST m_cst;
   288        };
   289        template <typename TT, typename CST, typename... ARGS>
   290        struct where_statement : public statement<TT, ARGS...> {
   291        public:
   292          typedef typename TT::engine_type engine_type;
   293          where_statement(engine_type *engine, const std::string &sql,
   294                          const CST &cst)
   295              : statement<TT, ARGS...>(engine), m_prev_sql(sql), m_cst(cst) {}
   296  
   297          virtual row_collection<ARGS...> eval() {
   298            std::stringstream ss;
   299            ss << get_eval_sql_string();
   300            ss << "; ";
   301            auto native_statmenet = m_engine->prepare_sql_with_string(ss.str());
   302            int index = 0;
   303            traverse_cond_for_bind<TT, CST>::run(m_engine, native_statmenet,
   304                                                 m_cst, index);
   305            auto ret = m_engine->eval_native_sql_stmt(native_statmenet);
   306            return m_engine->template parse_records<ARGS...>(ret);
   307          }
   308  
   309          cst_limit_statement<TT, CST, ARGS...> limit(int64_t count) {
   310            if (count <= 0) {
   311              throw std::runtime_error("limit count must be larger than 0");
   312              return;
   313            }
   314            return cst_limit_statement<TT, CST, ARGS...>(
   315                m_engine, get_eval_sql_string(), count, m_cst);
   316          }
   317  
   318          template <typename CT, typename ORDER>
   319          cst_order_statement<TT, CT, ORDER, CST, ARGS...> order_by() {
   320            static_assert(util::is_contain_types<typename TT::cols_type,
   321                                                 util::type_list<CT>>::value,
   322                          "Can't use rows that is not in table for order by");
   323            return cst_order_statement<TT, CT, ORDER, CST, ARGS...>(
   324                m_engine, get_eval_sql_string(), m_cst);
   325          }
   326  
   327        protected:
   328          std::string get_eval_sql_string() const {
   329            std::stringstream ss;
   330            ss << m_prev_sql << " where ";
   331  
   332            m_cst.dump_to_sql_string(ss);
   333            return ss.str();
   334          }
   335  
   336        protected:
   337          using statement<TT, ARGS...>::m_engine;
   338          CST m_cst;
   339          std::string m_prev_sql;
   340        };//end class where_statement
   341  
   342      template<typename TT>
   343        struct update_statement : public statement<TT>{
   344          public:
   345            typedef typename TT::engine_type engine_type;
   346            update_statement(engine_type *engine, const std::string &sql)
   347                : statement<TT>(engine), m_prev_sql(sql) {}
   348            virtual  row_collection<> eval(){
   349              throw std::bad_exception();
   350            }
   351          template <typename CST>
   352            where_statement<TT, CST> where(const CST & cst){
   353            static_assert(
   354                util::is_contain_types<typename TT::cols_type,
   355                                       typename CST::cols_type>::value,
   356                "Can't use rows that is not in table for *update where*");
   357            return where_statement<TT, CST>(m_engine, m_prev_sql, cst);
   358            }
   359  
   360          protected:
   361            using statement<TT>::m_engine;
   362            std::string m_prev_sql;
   363        };
   364  
   365      template<typename TT>
   366        struct delete_statement : public statement<TT>{
   367          public:
   368            typedef typename TT::engine_type engine_type;
   369            delete_statement(engine_type *engine, const std::string &sql)
   370                : statement<TT>(engine), m_prev_sql(sql) {}
   371            virtual  row_collection<> eval(){
   372              throw std::bad_exception();
   373            }
   374          template <typename CST>
   375            where_statement<TT, CST> where(const CST & cst){
   376            static_assert(
   377                util::is_contain_types<typename TT::cols_type,
   378                                       typename CST::cols_type>::value,
   379                "Can't use rows that is not in table for *delete where*");
   380            return where_statement<TT, CST>(m_engine, m_prev_sql, cst);
   381            }
   382  
   383          protected:
   384            using statement<TT>::m_engine;
   385            std::string m_prev_sql;
   386        };
   387  
   388  
   389        template <typename TT, typename... ARGS>
   390        struct select_statement : public statement<TT, ARGS...> {
   391        public:
   392          typedef typename TT::engine_type engine_type;
   393          select_statement(engine_type *engine)
   394              : statement<TT, ARGS...>(engine) {}
   395          template <typename CST>
   396          where_statement<TT, CST, ARGS...> where(const CST &cst) {
   397            static_assert(
   398                util::is_contain_types<typename TT::cols_type,
   399                                       typename CST::cols_type>::value,
   400                "Can't use rows that is not in table for *select where*");
   401            return where_statement<TT, CST, ARGS...>(m_engine,
   402                                                     get_eval_sql_string(), cst);
   403          }
   404  
   405          template <typename CT, typename ORDER>
   406          order_statement<TT, CT, ORDER, ARGS...> order_by() {
   407            static_assert(util::is_contain_types<typename TT::cols_type,
   408                                                 util::type_list<CT>>::value,
   409                          "Can't use rows that is not in table for order by");
   410            return order_statement<TT, CT, ORDER, ARGS...>(m_engine,
   411                                                           get_eval_sql_string());
   412          }
   413  
   414          limit_statement<TT, ARGS...> limit(int64_t count) {
   415            if (count <= 0) {
   416              throw std::runtime_error("limit count must be larger than 0");
   417            }
   418            return limit_statement<TT, ARGS...>(m_engine, get_eval_sql_string(),
   419                                                count);
   420          }
   421  
   422          virtual row_collection<ARGS...> eval(){
   423            std::stringstream ss;
   424            ss<<get_eval_sql_string()<<";";
   425            auto ret = m_engine->eval_sql_query_string(ss.str());
   426            return m_engine->template parse_records<ARGS...>(ret);
   427          }
   428  
   429          protected:
   430          std::string get_eval_sql_string() const{
   431            std::stringstream ss;
   432            ss<<"select ";
   433            recursive_dump_col_name<ARGS...>(ss);
   434            ss<<" from "<<TT::meta_type::table_name;
   435            return ss.str();
   436          }
   437          template<typename T, typename T1, typename... TS>
   438            void recursive_dump_col_name(std::stringstream & ss)const {
   439              ss<<T::name<<", ";
   440              recursive_dump_col_name<T1, TS...>(ss);
   441            }
   442          template<typename T>
   443            void recursive_dump_col_name(std::stringstream & ss)const{
   444              ss<<T::name;
   445            }
   446  
   447            using statement<TT, ARGS...>::m_engine;
   448        };//end class select_statement
   449  
   450    }
   451  }
   452  template <typename T1, typename T2>
   453  auto operator&&(const T1 &t1, const T2 &t2) ->
   454      typename std::enable_if<std::is_base_of<ff::sql::cond_stmt, T1>::value &&
   455                                  std::is_base_of<ff::sql::cond_stmt, T2>::value,
   456                              ff::sql::and_cond_stmt<T1, T2>>::type {
   457    return ff::sql::and_cond_stmt<T1, T2>(t1, t2);
   458           }
   459  
   460           template <typename T1, typename T2>
   461           auto operator||(const T1 &t1, const T2 &t2) -> typename std::enable_if<
   462               std::is_base_of<ff::sql::cond_stmt, T1>::value &&
   463                   std::is_base_of<ff::sql::cond_stmt, T2>::value,
   464               ff::sql::or_cond_stmt<T1, T2>>::type {
   465             return ff::sql::or_cond_stmt<T1, T2>(t1, t2);
   466           }