1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2010-2011 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> 4 // 5 // Distributed under: 6 // 7 // the Boost Software License, Version 1.0. 8 // (See accompanying file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 // 11 // or (at your opinion) under: 12 // 13 // The MIT License 14 // (See accompanying file MIT.txt or a copy at 15 // http://www.opensource.org/licenses/mit-license.php) 16 // 17 /////////////////////////////////////////////////////////////////////////////// 18 #define CPPDB_SOURCE 19 #include <cppdb/frontend.h> 20 #include <cppdb/backend.h> 21 #include <cppdb/conn_manager.h> 22 #include <cppdb/pool.h> 23 24 namespace cppdb { 25 struct result::data {}; 26 27 class throw_guard { 28 public: throw_guard(ref_ptr<backend::connection> const & conn)29 throw_guard(ref_ptr<backend::connection> const &conn) : conn_(conn.get()) 30 { 31 } done()32 void done() 33 { 34 conn_ = 0; 35 } ~throw_guard()36 ~throw_guard() 37 { 38 if(conn_ && std::uncaught_exception()) { 39 conn_->recyclable(false); 40 } 41 } 42 private: 43 backend::connection *conn_; 44 }; 45 result()46 result::result() : 47 eof_(false), 48 fetched_(false), 49 current_col_(0) 50 { 51 } result(ref_ptr<backend::result> res,ref_ptr<backend::statement> stat,ref_ptr<backend::connection> conn)52 result::result( ref_ptr<backend::result> res, 53 ref_ptr<backend::statement> stat, 54 ref_ptr<backend::connection> conn) 55 : eof_(false), 56 fetched_(false), 57 current_col_(0), 58 res_(res), 59 stat_(stat), 60 conn_(conn) 61 { 62 } result(result const & other)63 result::result(result const &other) : 64 eof_(other.eof_), 65 fetched_(other.fetched_), 66 current_col_(other.current_col_), 67 res_(other.res_), 68 stat_(other.stat_), 69 conn_(other.conn_) 70 { 71 } 72 operator =(result const & other)73 result const &result::operator=(result const &other) 74 { 75 eof_ = other.eof_; 76 fetched_ = other.fetched_; 77 current_col_ = other.current_col_; 78 res_ = other.res_; 79 stat_ = other.stat_; 80 conn_ = other.conn_; 81 return *this; 82 } 83 ~result()84 result::~result() 85 { 86 clear(); 87 } 88 cols()89 int result::cols() 90 { 91 return res_->cols(); 92 } 93 next()94 bool result::next() 95 { 96 throw_guard g(conn_); 97 98 if(eof_) 99 return false; 100 fetched_=true; 101 eof_ = res_->next()==false; 102 current_col_ = 0; 103 return !eof_; 104 } 105 index(std::string const & n)106 int result::index(std::string const &n) 107 { 108 int c = res_->name_to_column(n); 109 if(c<0) 110 throw invalid_column(); 111 return c; 112 } 113 name(int col)114 std::string result::name(int col) 115 { 116 if(col < 0 || col>= cols()) 117 throw invalid_column(); 118 return res_->column_to_name(col); 119 } 120 find_column(std::string const & name)121 int result::find_column(std::string const &name) 122 { 123 int c = res_->name_to_column(name); 124 if(c < 0) 125 return -1; 126 return c; 127 } 128 rewind_column()129 void result::rewind_column() 130 { 131 current_col_ = 0; 132 } 133 empty()134 bool result::empty() 135 { 136 if(!res_) 137 return true; 138 return eof_ || !fetched_; 139 } 140 clear()141 void result::clear() 142 { 143 eof_ = true; 144 fetched_ = true; 145 res_.reset(); 146 stat_.reset(); 147 conn_.reset(); 148 } 149 check()150 void result::check() 151 { 152 if(empty()) 153 throw empty_row_access(); 154 } 155 is_null(int col)156 bool result::is_null(int col) 157 { 158 return res_->is_null(col); 159 } is_null(std::string const & n)160 bool result::is_null(std::string const &n) 161 { 162 return is_null(index(n)); 163 } 164 165 fetch(int col,short & v)166 bool result::fetch(int col,short &v) { return res_->fetch(col,v); } fetch(int col,unsigned short & v)167 bool result::fetch(int col,unsigned short &v) { return res_->fetch(col,v); } fetch(int col,int & v)168 bool result::fetch(int col,int &v) { return res_->fetch(col,v); } fetch(int col,unsigned & v)169 bool result::fetch(int col,unsigned &v) { return res_->fetch(col,v); } fetch(int col,long & v)170 bool result::fetch(int col,long &v) { return res_->fetch(col,v); } fetch(int col,unsigned long & v)171 bool result::fetch(int col,unsigned long &v) { return res_->fetch(col,v); } fetch(int col,long long & v)172 bool result::fetch(int col,long long &v) { return res_->fetch(col,v); } fetch(int col,unsigned long long & v)173 bool result::fetch(int col,unsigned long long &v) { return res_->fetch(col,v); } fetch(int col,float & v)174 bool result::fetch(int col,float &v) { return res_->fetch(col,v); } fetch(int col,double & v)175 bool result::fetch(int col,double &v) { return res_->fetch(col,v); } fetch(int col,long double & v)176 bool result::fetch(int col,long double &v) { return res_->fetch(col,v); } fetch(int col,std::string & v)177 bool result::fetch(int col,std::string &v) { return res_->fetch(col,v); } fetch(int col,std::tm & v)178 bool result::fetch(int col,std::tm &v) { return res_->fetch(col,v); } fetch(int col,std::ostream & v)179 bool result::fetch(int col,std::ostream &v) { return res_->fetch(col,v); } 180 fetch(std::string const & n,short & v)181 bool result::fetch(std::string const &n,short &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,unsigned short & v)182 bool result::fetch(std::string const &n,unsigned short &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,int & v)183 bool result::fetch(std::string const &n,int &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,unsigned & v)184 bool result::fetch(std::string const &n,unsigned &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,long & v)185 bool result::fetch(std::string const &n,long &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,unsigned long & v)186 bool result::fetch(std::string const &n,unsigned long &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,long long & v)187 bool result::fetch(std::string const &n,long long &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,unsigned long long & v)188 bool result::fetch(std::string const &n,unsigned long long &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,float & v)189 bool result::fetch(std::string const &n,float &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,double & v)190 bool result::fetch(std::string const &n,double &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,long double & v)191 bool result::fetch(std::string const &n,long double &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,std::string & v)192 bool result::fetch(std::string const &n,std::string &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,std::tm & v)193 bool result::fetch(std::string const &n,std::tm &v) { return res_->fetch(index(n),v); } fetch(std::string const & n,std::ostream & v)194 bool result::fetch(std::string const &n,std::ostream &v) { return res_->fetch(index(n),v); } 195 fetch(short & v)196 bool result::fetch(short &v) { return res_->fetch(current_col_++,v); } fetch(unsigned short & v)197 bool result::fetch(unsigned short &v) { return res_->fetch(current_col_++,v); } fetch(int & v)198 bool result::fetch(int &v) { return res_->fetch(current_col_++,v); } fetch(unsigned & v)199 bool result::fetch(unsigned &v) { return res_->fetch(current_col_++,v); } fetch(long & v)200 bool result::fetch(long &v) { return res_->fetch(current_col_++,v); } fetch(unsigned long & v)201 bool result::fetch(unsigned long &v) { return res_->fetch(current_col_++,v); } fetch(long long & v)202 bool result::fetch(long long &v) { return res_->fetch(current_col_++,v); } fetch(unsigned long long & v)203 bool result::fetch(unsigned long long &v) { return res_->fetch(current_col_++,v); } fetch(float & v)204 bool result::fetch(float &v) { return res_->fetch(current_col_++,v); } fetch(double & v)205 bool result::fetch(double &v) { return res_->fetch(current_col_++,v); } fetch(long double & v)206 bool result::fetch(long double &v) { return res_->fetch(current_col_++,v); } fetch(std::string & v)207 bool result::fetch(std::string &v) { return res_->fetch(current_col_++,v); } fetch(std::tm & v)208 bool result::fetch(std::tm &v) { return res_->fetch(current_col_++,v); } fetch(std::ostream & v)209 bool result::fetch(std::ostream &v) { return res_->fetch(current_col_++,v); } 210 211 212 213 struct statement::data {}; 214 statement()215 statement::statement() : placeholder_(1) {} ~statement()216 statement::~statement() 217 { 218 stat_.reset(); 219 conn_.reset(); 220 } 221 statement(statement const & other)222 statement::statement(statement const &other) : 223 placeholder_(other.placeholder_), 224 stat_(other.stat_), 225 conn_(other.conn_) 226 { 227 } operator =(statement const & other)228 statement const &statement::operator=(statement const &other) 229 { 230 placeholder_ = other.placeholder_; 231 stat_=other.stat_; 232 conn_=other.conn_; 233 return *this; 234 } 235 statement(ref_ptr<backend::statement> stat,ref_ptr<backend::connection> conn)236 statement::statement(ref_ptr<backend::statement> stat,ref_ptr<backend::connection> conn) : 237 placeholder_(1), 238 stat_(stat), 239 conn_(conn) 240 { 241 } 242 empty() const243 bool statement::empty() const 244 { 245 return !stat_; 246 } 247 clear()248 void statement::clear() 249 { 250 stat_.reset(); 251 conn_.reset(); 252 } 253 reset()254 void statement::reset() 255 { 256 throw_guard g(conn_); 257 placeholder_ = 1; 258 stat_->reset(); 259 } 260 operator <<(std::string const & v)261 statement &statement::operator<<(std::string const &v) 262 { 263 return bind(v); 264 } operator <<(char const * s)265 statement &statement::operator<<(char const *s) 266 { 267 return bind(s); 268 } 269 operator <<(std::tm const & v)270 statement &statement::operator<<(std::tm const &v) 271 { 272 return bind(v); 273 } 274 operator <<(std::istream & v)275 statement &statement::operator<<(std::istream &v) 276 { 277 return bind(v); 278 } 279 operator <<(void (* manipulator)(statement & st))280 statement &statement::operator<<(void (*manipulator)(statement &st)) 281 { 282 manipulator(*this); 283 return *this; 284 } operator <<(result (* manipulator)(statement & st))285 result statement::operator<<(result (*manipulator)(statement &st)) 286 { 287 return manipulator(*this); 288 } 289 bind(int v)290 statement &statement::bind(int v) 291 { 292 stat_->bind(placeholder_++,v); 293 return *this; 294 } bind(unsigned v)295 statement &statement::bind(unsigned v) 296 { 297 stat_->bind(placeholder_++,v); 298 return *this; 299 } bind(long v)300 statement &statement::bind(long v) 301 { 302 stat_->bind(placeholder_++,v); 303 return *this; 304 } bind(unsigned long v)305 statement &statement::bind(unsigned long v) 306 { 307 stat_->bind(placeholder_++,v); 308 return *this; 309 } bind(long long v)310 statement &statement::bind(long long v) 311 { 312 stat_->bind(placeholder_++,v); 313 return *this; 314 } bind(unsigned long long v)315 statement &statement::bind(unsigned long long v) 316 { 317 stat_->bind(placeholder_++,v); 318 return *this; 319 } bind(double v)320 statement &statement::bind(double v) 321 { 322 stat_->bind(placeholder_++,v); 323 return *this; 324 } bind(long double v)325 statement &statement::bind(long double v) 326 { 327 stat_->bind(placeholder_++,v); 328 return *this; 329 } 330 bind(std::string const & v)331 statement &statement::bind(std::string const &v) 332 { 333 stat_->bind(placeholder_++,v); 334 return *this; 335 } bind(char const * s)336 statement &statement::bind(char const *s) 337 { 338 stat_->bind(placeholder_++,s); 339 return *this; 340 } bind(char const * b,char const * e)341 statement &statement::bind(char const *b,char const *e) 342 { 343 stat_->bind(placeholder_++,b,e); 344 return *this; 345 } bind(std::tm const & v)346 statement &statement::bind(std::tm const &v) 347 { 348 stat_->bind(placeholder_++,v); 349 return *this; 350 } bind(std::istream & v)351 statement &statement::bind(std::istream &v) 352 { 353 stat_->bind(placeholder_++,v); 354 return *this; 355 } bind_null()356 statement &statement::bind_null() 357 { 358 stat_->bind_null(placeholder_++); 359 return *this; 360 } 361 362 bind(int col,std::string const & v)363 void statement::bind(int col,std::string const &v) 364 { 365 stat_->bind(col,v); 366 } bind(int col,char const * s)367 void statement::bind(int col,char const *s) 368 { 369 stat_->bind(col,s); 370 } bind(int col,char const * b,char const * e)371 void statement::bind(int col,char const *b,char const *e) 372 { 373 stat_->bind(col,b,e); 374 } bind(int col,std::tm const & v)375 void statement::bind(int col,std::tm const &v) 376 { 377 stat_->bind(col,v); 378 } bind(int col,std::istream & v)379 void statement::bind(int col,std::istream &v) 380 { 381 stat_->bind(col,v); 382 } bind(int col,int v)383 void statement::bind(int col,int v) 384 { 385 stat_->bind(col,v); 386 } bind(int col,unsigned v)387 void statement::bind(int col,unsigned v) 388 { 389 stat_->bind(col,v); 390 } bind(int col,long v)391 void statement::bind(int col,long v) 392 { 393 stat_->bind(col,v); 394 } bind(int col,unsigned long v)395 void statement::bind(int col,unsigned long v) 396 { 397 stat_->bind(col,v); 398 } bind(int col,long long v)399 void statement::bind(int col,long long v) 400 { 401 stat_->bind(col,v); 402 } bind(int col,unsigned long long v)403 void statement::bind(int col,unsigned long long v) 404 { 405 stat_->bind(col,v); 406 } bind(int col,double v)407 void statement::bind(int col,double v) 408 { 409 stat_->bind(col,v); 410 } bind(int col,long double v)411 void statement::bind(int col,long double v) 412 { 413 stat_->bind(col,v); 414 } bind_null(int col)415 void statement::bind_null(int col) 416 { 417 stat_->bind_null(col); 418 } 419 last_insert_id()420 long long statement::last_insert_id() 421 { 422 throw_guard g(conn_); 423 return stat_->sequence_last(std::string()); 424 } 425 sequence_last(std::string const & seq)426 long long statement::sequence_last(std::string const &seq) 427 { 428 throw_guard g(conn_); 429 return stat_->sequence_last(seq); 430 } affected()431 unsigned long long statement::affected() 432 { 433 throw_guard g(conn_); 434 return stat_->affected(); 435 } 436 row()437 result statement::row() 438 { 439 throw_guard g(conn_); 440 ref_ptr<backend::result> backend_res = stat_->query(); 441 result res(backend_res,stat_,conn_); 442 if(res.next()) { 443 if(res.res_->has_next() == backend::result::next_row_exists) { 444 g.done(); 445 throw multiple_rows_query(); 446 } 447 } 448 return res; 449 } 450 query()451 result statement::query() 452 { 453 throw_guard g(conn_); 454 ref_ptr<backend::result> res(stat_->query()); 455 return result(res,stat_,conn_); 456 } operator result()457 statement::operator result() 458 { 459 return query(); 460 } exec()461 void statement::exec() 462 { 463 throw_guard g(conn_); 464 stat_->exec(); 465 } 466 467 struct session::data {}; 468 session()469 session::session() 470 { 471 } session(session const & other)472 session::session(session const &other) : 473 conn_(other.conn_) 474 { 475 } operator =(session const & other)476 session const &session::operator=(session const &other) 477 { 478 conn_ = other.conn_; 479 return *this; 480 } session(ref_ptr<backend::connection> conn)481 session::session(ref_ptr<backend::connection> conn) : conn_(conn) 482 { 483 } session(ref_ptr<backend::connection> conn,once_functor const & f)484 session::session(ref_ptr<backend::connection> conn,once_functor const &f) : conn_(conn) 485 { 486 once(f); 487 } ~session()488 session::~session() 489 { 490 } session(connection_info const & ci)491 session::session(connection_info const &ci) 492 { 493 open(ci); 494 } session(std::string const & cs)495 session::session(std::string const &cs) 496 { 497 open(cs); 498 } session(connection_info const & ci,once_functor const & f)499 session::session(connection_info const &ci,once_functor const &f) 500 { 501 open(ci); 502 once(f); 503 } session(std::string const & cs,once_functor const & f)504 session::session(std::string const &cs,once_functor const &f) 505 { 506 open(cs); 507 once(f); 508 } 509 open(connection_info const & ci)510 void session::open(connection_info const &ci) 511 { 512 conn_ = connections_manager::instance().open(ci); 513 } open(std::string const & cs)514 void session::open(std::string const &cs) 515 { 516 conn_ = connections_manager::instance().open(cs); 517 } close()518 void session::close() 519 { 520 conn_.reset(); 521 } 522 is_open()523 bool session::is_open() 524 { 525 return conn_; 526 } 527 prepare(std::string const & query)528 statement session::prepare(std::string const &query) 529 { 530 throw_guard g(conn_); 531 ref_ptr<backend::statement> stat_ptr(conn_->prepare(query)); 532 statement stat(stat_ptr,conn_); 533 return stat; 534 } 535 create_statement(std::string const & query)536 statement session::create_statement(std::string const &query) 537 { 538 throw_guard g(conn_); 539 ref_ptr<backend::statement> stat_ptr(conn_->get_statement(query)); 540 statement stat(stat_ptr,conn_); 541 return stat; 542 } 543 create_prepared_statement(std::string const & query)544 statement session::create_prepared_statement(std::string const &query) 545 { 546 throw_guard g(conn_); 547 ref_ptr<backend::statement> stat_ptr(conn_->get_prepared_statement(query)); 548 statement stat(stat_ptr,conn_); 549 return stat; 550 } 551 create_prepared_uncached_statement(std::string const & query)552 statement session::create_prepared_uncached_statement(std::string const &query) 553 { 554 throw_guard g(conn_); 555 ref_ptr<backend::statement> stat_ptr(conn_->get_prepared_uncached_statement(query)); 556 statement stat(stat_ptr,conn_); 557 return stat; 558 } 559 560 operator <<(std::string const & q)561 statement session::operator<<(std::string const &q) 562 { 563 return prepare(q); 564 } operator <<(char const * s)565 statement session::operator<<(char const *s) 566 { 567 return prepare(s); 568 } begin()569 void session::begin() 570 { 571 throw_guard g(conn_); 572 conn_->begin(); 573 } commit()574 void session::commit() 575 { 576 throw_guard g(conn_); 577 conn_->commit(); 578 } rollback()579 void session::rollback() 580 { 581 throw_guard g(conn_); 582 conn_->rollback(); 583 } escape(char const * b,char const * e)584 std::string session::escape(char const *b,char const *e) 585 { 586 return conn_->escape(b,e); 587 } escape(char const * s)588 std::string session::escape(char const *s) 589 { 590 return conn_->escape(s); 591 } escape(std::string const & s)592 std::string session::escape(std::string const &s) 593 { 594 return conn_->escape(s); 595 } driver()596 std::string session::driver() 597 { 598 return conn_->driver(); 599 } engine()600 std::string session::engine() 601 { 602 return conn_->engine(); 603 } 604 once_called(bool v)605 void session::once_called(bool v) 606 { 607 conn_->once_called(v); 608 } once_called()609 bool session::once_called() 610 { 611 return conn_->once_called(); 612 } 613 once(once_functor const & f)614 void session::once(once_functor const &f) 615 { 616 if(!once_called()) { 617 f(*this); 618 once_called(true); 619 } 620 } 621 622 struct transaction::data {}; 623 transaction(session & s)624 transaction::transaction(session &s) : 625 s_(&s), 626 commited_(false) 627 { 628 s_->begin(); 629 } 630 commit()631 void transaction::commit() 632 { 633 s_->commit(); 634 commited_ =true; 635 } rollback()636 void transaction::rollback() 637 { 638 if(!commited_) 639 s_->rollback(); 640 commited_=true; 641 } ~transaction()642 transaction::~transaction() 643 { 644 try { 645 rollback(); 646 } 647 catch(...) 648 { 649 } 650 } 651 clear_cache()652 void session::clear_cache() 653 { 654 conn_->clear_cache(); 655 } 656 clear_pool()657 void session::clear_pool() 658 { 659 conn_->clear_cache(); 660 conn_->recyclable(false); 661 conn_->get_pool()->clear(); 662 } 663 recyclable()664 bool session::recyclable() 665 { 666 return conn_->recyclable(); 667 } recyclable(bool v)668 void session::recyclable(bool v) 669 { 670 conn_->recyclable(v); 671 } 672 get_specific(std::type_info const & t)673 connection_specific_data *session::get_specific(std::type_info const &t) 674 { 675 return conn_->connection_specific_get(t); 676 } release_specific(std::type_info const & t)677 connection_specific_data *session::release_specific(std::type_info const &t) 678 { 679 return conn_->connection_specific_release(t); 680 } reset_specific(std::type_info const & t,connection_specific_data * p)681 void session::reset_specific(std::type_info const &t,connection_specific_data *p) 682 { 683 conn_->connection_specific_reset(t,p); 684 } 685 version_string()686 char const *version_string() 687 { 688 return CPPDB_VERSION; 689 } version_number()690 int version_number() 691 { 692 return CPPDB_MAJOR * 10000 + CPPDB_MINOR * 100 + CPPDB_PATCH; 693 } 694 695 } // cppdb 696