C++DB is the database layer that was designed to work with C++CMS. This customized version is used within Ye Ol' Pi Shack.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

696 lines
15 KiB

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