github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/include/ff/sql/table.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/columns.h"
    26  #include "ff/sql/common.h"
    27  #include "ff/sql/engine.h"
    28  #include "ff/sql/mod_stmt_bind.h"
    29  #include "ff/sql/rows.h"
    30  #include "ff/sql/stmt.h"
    31  #include "ff/sql/table_create.h"
    32  #include <sstream>
    33  
    34  namespace ff {
    35  namespace sql {
    36  
    37  template <typename ET, typename TM, typename... ARGS> class table {
    38  public:
    39    typedef ET engine_type;
    40    typedef TM meta_type;
    41    typedef util::type_list<ARGS...> cols_type;
    42    typedef row_type_base<ARGS...> row_type;
    43    typedef row_collection<ARGS...> row_collection_type;
    44    typedef table<ET, TM, ARGS...> self_type;
    45  
    46    template <typename... TARGS>
    47    static select_statement<self_type, TARGS...> select(engine_type *engine) {
    48      static_assert(util::is_contain_types<typename util::type_list<ARGS...>,
    49                                           util::type_list<TARGS...>>::value,
    50                    "Can't select row which is not in table");
    51      select_statement<self_type, TARGS...> ss(engine);
    52      return ss;
    53    }
    54  
    55    static void create_table(engine_type *engine) {
    56      std::stringstream ss;
    57      ss << "create table if not exists " << TM::table_name << " (";
    58      recursive_dump_col_creation<ARGS...>(ss);
    59      ss << ";";
    60      engine->eval_sql_string(ss.str());
    61      ss.str(std::string());
    62      recursive_dump_for_index<engine_type, ARGS...>(engine, ss);
    63      engine->eval_sql_string(ss.str());
    64    }
    65    static void clear_table(engine_type *engine) {
    66      std::stringstream ss;
    67      ss << "delete from " << TM::table_name << ";";
    68      engine->eval_sql_string(ss.str());
    69    }
    70    static void drop_table(engine_type *engine) {
    71      std::stringstream ss;
    72      ss << "drop table " << TM::table_name << ";";
    73      engine->eval_sql_string(ss.str());
    74    }
    75    static bool insert_or_ignore_rows(engine_type *engine,
    76                                      const row_collection_type &rows) {
    77      if (rows.size() == 0) {
    78        return true;
    79      }
    80      std::stringstream ss;
    81      ss << "insert or ignore into " << TM::table_name << " (";
    82      recursive_dump_col_name<ARGS...>(ss);
    83      ss << ") values (";
    84      for (int i = 0; i < util::type_list<ARGS...>::len; i++) {
    85        if (i != 0) {
    86          ss << ", ";
    87        }
    88        ss << "?";
    89      }
    90      ss << ");";
    91      engine->begin_transaction();
    92      for (size_t i = 0; i < rows.size(); ++i) {
    93        typename engine_type::native_statement_type stmt =
    94            engine->prepare_sql_with_string(ss.str());
    95        row_type rt = rows[i];
    96        traverse_row_for_bind<self_type, 0>::run(stmt, rt);
    97        engine->eval_native_sql_stmt(stmt);
    98      }
    99  
   100      engine->end_transaction();
   101      return true;
   102    }
   103    static bool insert_or_replace_rows(engine_type *engine,
   104                                       const row_collection_type &rows) {
   105      if (rows.size() == 0) {
   106        return true;
   107      }
   108      std::stringstream ss;
   109      ss << "replace into " << TM::table_name << " (";
   110      recursive_dump_col_name<ARGS...>(ss);
   111      ss << ") values (";
   112      for (int i = 0; i < util::type_list<ARGS...>::len; i++) {
   113        if (i != 0) {
   114          ss << ", ";
   115        }
   116        ss << "?";
   117      }
   118      ss << ");";
   119      engine->begin_transaction();
   120      for (size_t i = 0; i < rows.size(); ++i) {
   121        typename engine_type::native_statement_type stmt =
   122            engine->prepare_sql_with_string(ss.str());
   123        const row_type &rt = rows[i];
   124        traverse_row_for_bind<self_type, 0>::run(engine, stmt, rt);
   125        engine->eval_native_sql_stmt(stmt);
   126      }
   127  
   128      engine->end_transaction();
   129      return true;
   130    }
   131  
   132    template <typename... RS>
   133    static bool update_rows(engine_type *engine,
   134                            const row_collection<RS...> &rows) {
   135      static_assert(util::is_contain_types<util::type_list<ARGS...>,
   136                                           util::type_list<RS...>>::value,
   137                    "Can't update rows which are not in table");
   138      static_assert(
   139          !util::is_same_type<void, typename get_key_column_type<
   140                                        util::type_list<RS...>>::type>::value,
   141          "Have to specify a key column for update");
   142      if (rows.size() == 0) {
   143        return true;
   144      }
   145      std::stringstream ss;
   146      ss << "update " << TM::table_name << " set ";
   147      recurseive_dump_update_item_and_ignore_key<RS...>(ss);
   148      ss << " where ";
   149      recurseive_dump_update_item_for_only_where<RS...>(ss);
   150      ss << ";";
   151      std::string sql = ss.str();
   152  
   153      engine->begin_transaction();
   154  
   155      for (size_t i = 0; i < rows.size(); ++i) {
   156        typename engine_type::native_statement_type stmt =
   157            engine->prepare_sql_with_string(ss.str());
   158        const typename row_collection<RS...>::row_type &rt = rows[i];
   159        int next_index = 0;
   160        traverse_row_for_bind_and_put_key_to_last<
   161            self_type, 0, util::type_list<RS...>>::run(engine, stmt, rt,
   162                                                       next_index);
   163        engine->eval_native_sql_stmt(stmt);
   164      }
   165      engine->end_transaction();
   166      return true;
   167    }
   168  
   169    static delete_statement<self_type> delete_rows(engine_type *engine) {
   170      std::stringstream ss;
   171      ss << "delete from " << TM::table_name << ";";
   172      std::string sql = ss.str();
   173      return delete_statement<self_type>(engine, sql);
   174    }
   175  
   176  protected:
   177  #include "ff/sql/table_dump.hpp"
   178  };
   179  } // namespace sql
   180  } // namespace ff