PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/mysql++/query.cpp

https://code.google.com/p/bitfighter/
C++ | 696 lines | 494 code | 93 blank | 109 comment | 131 complexity | a24ac05f96c91025712734aa3b899624 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-3.0, LGPL-2.0, GPL-3.0
  1. /***********************************************************************
  2. query.cpp - Implements the Query class.
  3. Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
  4. (c) 2004-2009 by Educational Technology Resources, Inc. Others may
  5. also hold copyrights on code in this file. See the CREDITS.txt file
  6. in the top directory of the distribution for details.
  7. This file is part of MySQL++.
  8. MySQL++ is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU Lesser General Public License as published
  10. by the Free Software Foundation; either version 2.1 of the License, or
  11. (at your option) any later version.
  12. MySQL++ is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  15. License for more details.
  16. You should have received a copy of the GNU Lesser General Public
  17. License along with MySQL++; if not, write to the Free Software
  18. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19. USA
  20. ***********************************************************************/
  21. #include "query.h"
  22. #include "autoflag.h"
  23. #include "dbdriver.h"
  24. #include "connection.h"
  25. namespace mysqlpp {
  26. // Force insertfrom() policy template instantiation. Required to make
  27. // VC++ happy.
  28. Query::RowCountInsertPolicy<Transaction> RowCountInsertPolicyI(0);
  29. Query::SizeThresholdInsertPolicy<Transaction> SizeThresholdInsertPolicyI(0);
  30. Query::MaxPacketInsertPolicy<Transaction> MaxPacketInsertPolicyI(0);
  31. Query::Query(Connection* c, bool te, const char* qstr) :
  32. #if defined(MYSQLPP_HAVE_STD__NOINIT)
  33. // prevents a double-init memory leak in native VC++ RTL (not STLport!)
  34. std::ostream(std::_Noinit),
  35. #else
  36. std::ostream(0),
  37. #endif
  38. OptionalExceptions(te),
  39. template_defaults(this),
  40. conn_(c),
  41. copacetic_(true)
  42. {
  43. // Set up our internal IOStreams string buffer
  44. init(&sbuffer_);
  45. // Insert passed query string into our string buffer, if given
  46. if (qstr) {
  47. sbuffer_.str(qstr);
  48. seekp(0, std::ios::end); // allow more insertions at end
  49. }
  50. // Override any global locale setting; we want to use the classic C
  51. // locale so we don't get weird things like thousands separators in
  52. // integers inserted into the query stream.
  53. imbue(std::locale::classic());
  54. }
  55. Query::Query(const Query& q) :
  56. #if defined(MYSQLPP_HAVE_STD__NOINIT)
  57. // ditto above
  58. std::ostream(std::_Noinit),
  59. #else
  60. std::ostream(0),
  61. #endif
  62. OptionalExceptions(q.throw_exceptions())
  63. {
  64. // Set up our internal IOStreams string buffer
  65. init(&sbuffer_);
  66. // See above for reason we override locale for Query streams.
  67. imbue(std::locale::classic());
  68. // Copy the other query as best we can
  69. operator =(q);
  70. }
  71. ulonglong
  72. Query::affected_rows()
  73. {
  74. return conn_->driver()->affected_rows();
  75. }
  76. int
  77. Query::errnum() const
  78. {
  79. return conn_->errnum();
  80. }
  81. const char*
  82. Query::error() const
  83. {
  84. return conn_->error();
  85. }
  86. size_t
  87. Query::escape_string(std::string* ps, const char* original,
  88. size_t length) const
  89. {
  90. if (conn_ && *conn_) {
  91. // Normal case
  92. return conn_->driver()->escape_string(ps, original, length);
  93. }
  94. else {
  95. // Should only happen in test/test_manip.cpp, since it doesn't
  96. // want to open a DB connection just to test the manipulators.
  97. return DBDriver::escape_string_no_conn(ps, original, length);
  98. }
  99. }
  100. size_t
  101. Query::escape_string(char* escaped, const char* original,
  102. size_t length) const
  103. {
  104. if (conn_ && *conn_) {
  105. // Normal case
  106. return conn_->driver()->escape_string(escaped, original, length);
  107. }
  108. else {
  109. // Should only happen in test/test_manip.cpp, since it doesn't
  110. // want to open a DB connection just to test the manipulators.
  111. return DBDriver::escape_string_no_conn(escaped, original, length);
  112. }
  113. }
  114. bool
  115. Query::exec(const std::string& str)
  116. {
  117. if ((copacetic_ = conn_->driver()->execute(str.data(),
  118. static_cast<unsigned long>(str.length()))) == true) {
  119. if (parse_elems_.size() == 0) {
  120. // Not a template query, so auto-reset
  121. reset();
  122. }
  123. return true;
  124. }
  125. else if (throw_exceptions()) {
  126. throw BadQuery(error(), errnum());
  127. }
  128. else {
  129. return false;
  130. }
  131. }
  132. SimpleResult
  133. Query::execute()
  134. {
  135. AutoFlag<> af(template_defaults.processing_);
  136. return execute(str(template_defaults));
  137. }
  138. SimpleResult
  139. Query::execute(SQLQueryParms& p)
  140. {
  141. AutoFlag<> af(template_defaults.processing_);
  142. return execute(str(p));
  143. }
  144. SimpleResult
  145. Query::execute(const SQLTypeAdapter& s)
  146. {
  147. if (!parse_elems_.empty() && !template_defaults.processing_) {
  148. // We're a template query and this isn't a recursive call, so
  149. // take s to be a lone parameter for the query. We will come
  150. // back in here with a completed query, but the processing_
  151. // flag will be set, allowing us to avoid an infinite loop.
  152. AutoFlag<> af(template_defaults.processing_);
  153. return execute(SQLQueryParms() << s);
  154. }
  155. else {
  156. // Take s to be the entire query string
  157. return execute(s.data(), s.length());
  158. }
  159. }
  160. SimpleResult
  161. Query::execute(const char* str, size_t len)
  162. {
  163. if (!parse_elems_.empty() && !template_defaults.processing_) {
  164. // We're a template query and this isn't a recursive call, so
  165. // take s to be a lone parameter for the query. We will come
  166. // back in here with a completed query, but the processing_
  167. // flag will be set, allowing us to avoid an infinite loop.
  168. AutoFlag<> af(template_defaults.processing_);
  169. return execute(SQLQueryParms() << str << len );
  170. }
  171. if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
  172. if (parse_elems_.size() == 0) {
  173. // Not a template query, so auto-reset
  174. reset();
  175. }
  176. return SimpleResult(conn_, insert_id(), affected_rows(), info());
  177. }
  178. else if (throw_exceptions()) {
  179. throw BadQuery(error(), errnum());
  180. }
  181. else {
  182. return SimpleResult();
  183. }
  184. }
  185. std::string
  186. Query::info()
  187. {
  188. return conn_->driver()->query_info();
  189. }
  190. ulonglong
  191. Query::insert_id()
  192. {
  193. return conn_->driver()->insert_id();
  194. }
  195. bool
  196. Query::more_results()
  197. {
  198. return conn_->driver()->more_results();
  199. }
  200. Query&
  201. Query::operator=(const Query& rhs)
  202. {
  203. set_exceptions(rhs.throw_exceptions());
  204. template_defaults = rhs.template_defaults;
  205. conn_ = rhs.conn_;
  206. copacetic_ = rhs.copacetic_;
  207. *this << rhs.sbuffer_.str();
  208. parse_elems_ = rhs.parse_elems_;
  209. parsed_names_ = rhs.parsed_names_;
  210. parsed_nums_ = rhs.parsed_nums_;
  211. return *this;
  212. }
  213. Query::operator void*() const
  214. {
  215. return *conn_ && copacetic_ ? const_cast<Query*>(this) : 0;
  216. }
  217. void
  218. Query::parse()
  219. {
  220. std::string str = "";
  221. char num[4];
  222. std::string name;
  223. char* s = new char[sbuffer_.str().size() + 1];
  224. memcpy(s, sbuffer_.str().data(), sbuffer_.str().size());
  225. s[sbuffer_.str().size()] = '\0';
  226. const char* s0 = s;
  227. while (*s) {
  228. if (*s == '%') {
  229. // Following might be a template parameter declaration...
  230. s++;
  231. if (*s == '%') {
  232. // Doubled percent sign, so insert literal percent sign.
  233. str += *s++;
  234. }
  235. else if (isdigit(*s)) {
  236. // Number following percent sign, so it signifies a
  237. // positional parameter. First step: find position
  238. // value, up to 3 digits long.
  239. num[0] = *s;
  240. s++;
  241. if (isdigit(*s)) {
  242. num[1] = *s;
  243. num[2] = 0;
  244. s++;
  245. if (isdigit(*s)) {
  246. num[2] = *s;
  247. num[3] = 0;
  248. s++;
  249. }
  250. else {
  251. num[2] = 0;
  252. }
  253. }
  254. else {
  255. num[1] = 0;
  256. }
  257. signed char n = atoi(num);
  258. // Look for option character following position value.
  259. char option = ' ';
  260. if (*s == 'q' || *s == 'Q') {
  261. option = *s++;
  262. }
  263. // Is it a named parameter?
  264. if (*s == ':') {
  265. // Save all alphanumeric and underscore characters
  266. // following colon as parameter name.
  267. s++;
  268. for (/* */; isalnum(*s) || *s == '_'; ++s) {
  269. name += *s;
  270. }
  271. // Eat trailing colon, if it's present.
  272. if (*s == ':') {
  273. s++;
  274. }
  275. // Update maps that translate parameter name to
  276. // number and vice versa.
  277. if (n >= static_cast<short>(parsed_names_.size())) {
  278. parsed_names_.insert(parsed_names_.end(),
  279. static_cast<std::vector<std::string>::size_type>(
  280. n + 1) - parsed_names_.size(),
  281. std::string());
  282. }
  283. parsed_names_[n] = name;
  284. parsed_nums_[name] = n;
  285. }
  286. // Finished parsing parameter; save it.
  287. parse_elems_.push_back(SQLParseElement(str, option, n));
  288. str = "";
  289. name = "";
  290. }
  291. else {
  292. // Insert literal percent sign, because sign didn't
  293. // precede a valid parameter string; this allows users
  294. // to play a little fast and loose with the rules,
  295. // avoiding a double percent sign here.
  296. str += '%';
  297. }
  298. }
  299. else {
  300. // Regular character, so just copy it.
  301. str += *s++;
  302. }
  303. }
  304. parse_elems_.push_back(SQLParseElement(str, ' ', -1));
  305. delete[] s0;
  306. }
  307. SQLTypeAdapter*
  308. Query::pprepare(char option, SQLTypeAdapter& S, bool replace)
  309. {
  310. if (S.is_processed()) {
  311. return &S;
  312. }
  313. if (option == 'q') {
  314. std::string temp(S.quote_q() ? "'" : "", S.quote_q() ? 1 : 0);
  315. if (S.escape_q()) {
  316. char *escaped = new char[S.size() * 2 + 1];
  317. size_t len = conn_->driver()->escape_string(escaped,
  318. S.data(), static_cast<unsigned long>(S.size()));
  319. temp.append(escaped, len);
  320. delete[] escaped;
  321. }
  322. else {
  323. temp.append(S.data(), S.length());
  324. }
  325. if (S.quote_q()) temp.append("'", 1);
  326. SQLTypeAdapter* ss = new SQLTypeAdapter(temp);
  327. if (replace) {
  328. S = *ss;
  329. S.set_processed();
  330. delete ss;
  331. return &S;
  332. }
  333. else {
  334. return ss;
  335. }
  336. }
  337. else if (option == 'Q' && S.quote_q()) {
  338. std::string temp("'", 1);
  339. temp.append(S.data(), S.length());
  340. temp.append("'", 1);
  341. SQLTypeAdapter *ss = new SQLTypeAdapter(temp);
  342. if (replace) {
  343. S = *ss;
  344. S.set_processed();
  345. delete ss;
  346. return &S;
  347. }
  348. else {
  349. return ss;
  350. }
  351. }
  352. else {
  353. if (replace) {
  354. S.set_processed();
  355. }
  356. return &S;
  357. }
  358. }
  359. void
  360. Query::proc(SQLQueryParms& p)
  361. {
  362. sbuffer_.str("");
  363. for (std::vector<SQLParseElement>::iterator i = parse_elems_.begin();
  364. i != parse_elems_.end(); ++i) {
  365. MYSQLPP_QUERY_THISPTR << i->before;
  366. int num = i->num;
  367. if (num >= 0) {
  368. SQLQueryParms* c;
  369. if (size_t(num) < p.size()) {
  370. c = &p;
  371. }
  372. else if (size_t(num) < template_defaults.size()) {
  373. c = &template_defaults;
  374. }
  375. else {
  376. *this << " ERROR";
  377. throw BadParamCount(
  378. "Not enough parameters to fill the template.");
  379. }
  380. SQLTypeAdapter& param = (*c)[num];
  381. if (param.is_null()) {
  382. MYSQLPP_QUERY_THISPTR << "NULL";
  383. }
  384. else {
  385. SQLTypeAdapter* ss = pprepare(i->option, param, c->bound());
  386. MYSQLPP_QUERY_THISPTR << *ss;
  387. if (ss != &param) {
  388. // pprepare() returned a new string object instead of
  389. // updating param in place, so we need to delete it.
  390. delete ss;
  391. }
  392. }
  393. }
  394. }
  395. }
  396. void
  397. Query::reset()
  398. {
  399. seekp(0);
  400. clear();
  401. sbuffer_.str("");
  402. parse_elems_.clear();
  403. template_defaults.clear();
  404. }
  405. StoreQueryResult
  406. Query::store()
  407. {
  408. AutoFlag<> af(template_defaults.processing_);
  409. return store(str(template_defaults));
  410. }
  411. StoreQueryResult
  412. Query::store(SQLQueryParms& p)
  413. {
  414. AutoFlag<> af(template_defaults.processing_);
  415. return store(str(p));
  416. }
  417. StoreQueryResult
  418. Query::store(const SQLTypeAdapter& s)
  419. {
  420. if (!parse_elems_.empty() && !template_defaults.processing_) {
  421. // We're a template query and this isn't a recursive call, so
  422. // take s to be a lone parameter for the query. We will come
  423. // back in here with a completed query, but the processing_
  424. // flag will be set, allowing us to avoid an infinite loop.
  425. AutoFlag<> af(template_defaults.processing_);
  426. return store(SQLQueryParms() << s);
  427. }
  428. else {
  429. // Take s to be the entire query string
  430. return store(s.data(), s.length());
  431. }
  432. }
  433. StoreQueryResult
  434. Query::store(const char* str, size_t len)
  435. {
  436. if (!parse_elems_.empty() && !template_defaults.processing_) {
  437. // We're a template query and this isn't a recursive call, so
  438. // take s to be a lone parameter for the query. We will come
  439. // back in here with a completed query, but the processing_
  440. // flag will be set, allowing us to avoid an infinite loop.
  441. AutoFlag<> af(template_defaults.processing_);
  442. return store(SQLQueryParms() << str << len );
  443. }
  444. MYSQL_RES* res = 0;
  445. if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
  446. res = conn_->driver()->store_result();
  447. }
  448. if (res) {
  449. if (parse_elems_.size() == 0) {
  450. // Not a template query, so auto-reset
  451. reset();
  452. }
  453. return StoreQueryResult(res, conn_->driver(), throw_exceptions());
  454. }
  455. else {
  456. // Either result set is empty, or there was a problem executing
  457. // the query or storing its results. Since it's not an error to
  458. // use store() with queries that never return results (INSERT,
  459. // DELETE, CREATE, ALTER...) we need to figure out which case
  460. // this is. (You might use store() instead of execute() for
  461. // such queries when the query strings come from "outside".)
  462. copacetic_ = (conn_->errnum() == 0);
  463. if (copacetic_) {
  464. if (parse_elems_.size() == 0) {
  465. // Not a template query, so auto-reset
  466. reset();
  467. }
  468. return StoreQueryResult();
  469. }
  470. else if (throw_exceptions()) {
  471. throw BadQuery(error(), errnum());
  472. }
  473. else {
  474. return StoreQueryResult();
  475. }
  476. }
  477. }
  478. StoreQueryResult
  479. Query::store_next()
  480. {
  481. #if MYSQL_VERSION_ID > 41000 // only in MySQL v4.1 +
  482. DBDriver::nr_code rc = conn_->driver()->next_result();
  483. if (rc == DBDriver::nr_more_results) {
  484. // There are more results, so return next result set.
  485. MYSQL_RES* res = conn_->driver()->store_result();
  486. if (res) {
  487. return StoreQueryResult(res, conn_->driver(),
  488. throw_exceptions());
  489. }
  490. else {
  491. // Result set is null, but throw an exception only i it is
  492. // null because of some error. If not, it's just an empty
  493. // result set, which is harmless. We return an empty result
  494. // set if exceptions are disabled, as well.
  495. if (conn_->errnum() && throw_exceptions()) {
  496. throw BadQuery(error(), errnum());
  497. }
  498. else {
  499. return StoreQueryResult();
  500. }
  501. }
  502. }
  503. else if (throw_exceptions()) {
  504. if (rc == DBDriver::nr_error) {
  505. throw BadQuery(error(), errnum());
  506. }
  507. else if (conn_->errnum()) {
  508. throw BadQuery(error(), errnum());
  509. }
  510. else {
  511. return StoreQueryResult(); // normal end-of-result-sets case
  512. }
  513. }
  514. else {
  515. return StoreQueryResult();
  516. }
  517. #else
  518. return store();
  519. #endif // MySQL v4.1+
  520. }
  521. std::string
  522. Query::str(SQLQueryParms& p)
  523. {
  524. if (!parse_elems_.empty()) {
  525. proc(p);
  526. }
  527. return sbuffer_.str();
  528. }
  529. UseQueryResult
  530. Query::use()
  531. {
  532. AutoFlag<> af(template_defaults.processing_);
  533. return use(str(template_defaults));
  534. }
  535. UseQueryResult
  536. Query::use(SQLQueryParms& p)
  537. {
  538. AutoFlag<> af(template_defaults.processing_);
  539. return use(str(p));
  540. }
  541. UseQueryResult
  542. Query::use(const SQLTypeAdapter& s)
  543. {
  544. if (!parse_elems_.empty() && !template_defaults.processing_) {
  545. // We're a template query and this isn't a recursive call, so
  546. // take s to be a lone parameter for the query. We will come
  547. // back in here with a completed query, but the processing_
  548. // flag will be set, allowing us to avoid an infinite loop.
  549. AutoFlag<> af(template_defaults.processing_);
  550. return use(SQLQueryParms() << s);
  551. }
  552. else {
  553. // Take s to be the entire query string
  554. return use(s.data(), s.length());
  555. }
  556. }
  557. UseQueryResult
  558. Query::use(const char* str, size_t len)
  559. {
  560. if (!parse_elems_.empty() && !template_defaults.processing_) {
  561. // We're a template query and this isn't a recursive call, so
  562. // take s to be a lone parameter for the query. We will come
  563. // back in here with a completed query, but the processing_
  564. // flag will be set, allowing us to avoid an infinite loop.
  565. AutoFlag<> af(template_defaults.processing_);
  566. return use(SQLQueryParms() << str << len );
  567. }
  568. MYSQL_RES* res = 0;
  569. if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
  570. res = conn_->driver()->use_result();
  571. }
  572. if (res) {
  573. if (parse_elems_.size() == 0) {
  574. // Not a template query, so auto-reset
  575. reset();
  576. }
  577. return UseQueryResult(res, conn_->driver(), throw_exceptions());
  578. }
  579. else {
  580. // See comments in store() above for why we distinguish between
  581. // empty result sets and actual error returns here.
  582. copacetic_ = (conn_->errnum() == 0);
  583. if (copacetic_) {
  584. if (parse_elems_.size() == 0) {
  585. // Not a template query, so auto-reset
  586. reset();
  587. }
  588. return UseQueryResult();
  589. }
  590. else if (throw_exceptions()) {
  591. throw BadQuery(error(), errnum());
  592. }
  593. else {
  594. return UseQueryResult();
  595. }
  596. }
  597. }
  598. } // end namespace mysqlpp