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 }