xdevapi.h 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556
  1. /*
  2. * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License, version 2.0, as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is also distributed with certain software (including
  9. * but not limited to OpenSSL) that is licensed under separate terms,
  10. * as designated in a particular file or component or in included license
  11. * documentation. The authors of MySQL hereby grant you an
  12. * additional permission to link the program and your derivative works
  13. * with the separately licensed software that they have included with
  14. * MySQL.
  15. *
  16. * Without limiting anything contained in the foregoing, this file,
  17. * which is part of MySQL Connector/C++, is also subject to the
  18. * Universal FOSS Exception, version 1.0, a copy of which can be found at
  19. * http://oss.oracle.com/licenses/universal-foss-exception.
  20. *
  21. * This program is distributed in the hope that it will be useful, but
  22. * WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  24. * See the GNU General Public License, version 2.0, for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software Foundation, Inc.,
  28. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #ifndef MYSQL_DEVAPI_H
  31. #define MYSQL_DEVAPI_H
  32. #ifndef __cplusplus
  33. #error This header can be only used with C++ code
  34. #endif
  35. /**
  36. @defgroup devapi X DevAPI Classes
  37. X DevAPI Classes and types. See @ref devapi_ref for introduction.
  38. @defgroup devapi_op Database operations
  39. @ingroup devapi
  40. Classes representing yet-to-be-executed database operations.
  41. Such operations are created by various methods of @link mysqlx::Collection
  42. `Collection`@endlink or @link mysqlx::Table `Table`@endlink classes. Database
  43. operation classes define methods that specify additional operation
  44. characteristics before it gets executed with `execute()` method. The latter
  45. returns a @link mysqlx::Result `Result`@endlink, @link mysqlx::DocResult
  46. `DocResult`@endlink or @link mysqlx::RowResult `RowResult`@endlink object,
  47. depending on the type of the operation.
  48. @defgroup devapi_res Classes for result processing
  49. @ingroup devapi
  50. Classes used to examine results of a statement and documents or
  51. rows contained in a result.
  52. @defgroup devapi_aux Auxiliary types
  53. @ingroup devapi
  54. */
  55. /**
  56. @file
  57. The main header for MySQL Connector/C++ DevAPI.
  58. This header should be included by C++ code which uses the DevAPI implemented
  59. by MySQL Connector/C++.
  60. @sa result.h, document.h
  61. @ingroup devapi
  62. */
  63. /*
  64. X DevAPI public classes are declared in this and other headers included from
  65. devapi/ folder. The main public API classes, such as Session below, contain
  66. declarations of public interface methods. Any obscure details of the public
  67. API, which must be defined in the public header, are factored out
  68. to Session_detail class from which the main Session class inherits.
  69. Among other things, Session_detail declares the implementation class for
  70. Session. This implementation class is opaque and its details are not defined
  71. in the public headers - only in the implementation part. Definitions of
  72. XXX_detail classes can be found in devapi/detail/ sub-folder.
  73. */
  74. #include "devapi/common.h"
  75. #include "devapi/result.h"
  76. #include "devapi/collection_crud.h"
  77. #include "devapi/table_crud.h"
  78. #include "devapi/settings.h"
  79. #include "devapi/detail/session.h"
  80. namespace mysqlx {
  81. class Session;
  82. namespace internal {
  83. template <class Base> class Sch_object;
  84. } // internal
  85. /**
  86. Represents a database schema.
  87. A `Schema` instance can be obtained from `Session::getSchema()`
  88. method:
  89. ~~~~~~
  90. Session session;
  91. Schema mySchema;
  92. mySchema= session.getSchema("My Schema");
  93. ~~~~~~
  94. or it can be directly constructed as follows:
  95. ~~~~~~
  96. Session session;
  97. Schema mySchema(session, "My Schema");
  98. ~~~~~~
  99. Each `Schema` instance is tied to a particular session and all
  100. the operations on the schema and its objects are performed using
  101. that session. If the session is destroyed, an attempt to use a schema of
  102. that session yields an error.
  103. When creating a `Schema` object, by default no checks are made that
  104. it actually exists in the database. An operation that is executed
  105. on the server and involves such a non-existent schema throws
  106. an error.
  107. @ingroup devapi
  108. */
  109. class Schema
  110. : protected internal::Schema_detail
  111. {
  112. Session *m_sess;
  113. public:
  114. /**
  115. Construct an object representing the named schema.
  116. */
  117. Schema(Session &sess, const string &name);
  118. /**
  119. Construct an object representing the default schema of the session.
  120. The default schema is the one specified by session creation options.
  121. */
  122. Schema(Session&);
  123. /**
  124. Get schema name
  125. */
  126. const string& getName() const
  127. {
  128. return m_name;
  129. }
  130. /**
  131. Get Session object
  132. */
  133. Session& getSession()
  134. {
  135. return *m_sess;
  136. }
  137. const Session& getSession() const
  138. {
  139. return const_cast<Schema*>(this)->getSession();
  140. }
  141. /**
  142. Check if this schema exists in the database.
  143. @note Involves communication with the server.
  144. */
  145. bool existsInDatabase() const
  146. {
  147. try {
  148. /*
  149. Note: We get from server a list of schemata filtered by the name of
  150. this schema - if the schema exists the list should not be empty.
  151. */
  152. internal::Session_detail::Name_src list(*m_sess, m_name);
  153. list.iterator_start();
  154. return list.iterator_next();
  155. }
  156. CATCH_AND_WRAP
  157. }
  158. /**
  159. Create a new collection in the schema.
  160. Returns the created collection. Set `reuse` flag to true to return
  161. an already existing collection with the same name. Otherwise, an attempt
  162. to create a collection which already exists throws an error.
  163. */
  164. Collection createCollection(const string &name, bool reuse = false);
  165. /**
  166. Return an object representing a collection with the given name.
  167. To check if the collection actually exists in the database set
  168. `check_existence` flag to true. Otherwise the returned object can refer to
  169. a non-existing collection. An attempt to use such a non-existing collection
  170. in a database operation throws an error.
  171. @note Checking the existence of a collection involves communication with
  172. the server. If `check_exists` is false, on the other hand, no I/O is
  173. involved when creating a `Collection` object.
  174. */
  175. Collection getCollection(const string &name, bool check_exists = false);
  176. /**
  177. Return an object representing a table or a view with the given name.
  178. To check if the table actually exists in the database set
  179. `check_existence` flag to true. Otherwise the returned object can refer to
  180. a non-existing table. An attempt to use such a non-existing table
  181. in a database operation throws an error.
  182. @note The returned `Table` object can represent a plain table or
  183. a view. See `Table` class description.
  184. @note Checking the existence of a table involves communication with
  185. the server. If `check_exists` is false, on the other hand, no I/O is
  186. involved when creating a `Table` object.
  187. */
  188. Table getTable(const string &name, bool check_exists = false);
  189. /**
  190. Get a list of all collections in the schema.
  191. The returned value can be stored in a container that holds `Collection`
  192. objects, such as `std::vector<Collection>`.
  193. */
  194. CollectionList getCollections()
  195. {
  196. try {
  197. return Collection_src(*this, L"%");
  198. }
  199. CATCH_AND_WRAP
  200. }
  201. /**
  202. Get a list of names of all collections in the schema.
  203. The returned value can be stored in a container that holds strings, such as
  204. `std::vector<string>`.
  205. */
  206. StringList getCollectionNames()
  207. {
  208. try {
  209. return Name_src(*this, COLLECTION, L"%");
  210. }
  211. CATCH_AND_WRAP
  212. }
  213. /**
  214. Get a list of all tables and views in the schema.
  215. The returned value can be stored in a container that holds `Table`
  216. objects, such as `std::vector<Table>`.
  217. @note The list also contains views which are represented by `Table` objects
  218. - see `Table` class description.
  219. */
  220. TableList getTables()
  221. {
  222. try {
  223. return Table_src(*this, L"%");
  224. }
  225. CATCH_AND_WRAP
  226. }
  227. /**
  228. Get a list of names of all tables and views in the schema.
  229. The returned value can be stored in a container that holds strings, such as
  230. `std::vector<string>`.
  231. @note The list also contains names of views as views are represented
  232. by `Table` objects - see `Table` class description.
  233. */
  234. StringList getTableNames()
  235. {
  236. try {
  237. return Name_src(*this, TABLE, L"%");
  238. }
  239. CATCH_AND_WRAP
  240. }
  241. /**
  242. Return a table corresponding to the given collection.
  243. The table has two columns: `_id` and `doc`. For each document in
  244. the collection there is one row in the table with `doc` filed holding
  245. the document as a JSON value and `_id` field holding document's identifier.
  246. To check if the collection actually exists in the database set
  247. `check_existence` flag to true. Otherwise the returned table can refer to
  248. a non-existing collection. An attempt to use such a non-existing collection
  249. table throws an error.
  250. @note Checking the existence of a collection involves communication with
  251. the server. If `check_exists` is false, on the other hand, no I/O is
  252. involved when creating the `Table` object.
  253. */
  254. Table getCollectionAsTable(const string &name, bool check_exists = true);
  255. /**
  256. Drop the given collection from the schema.
  257. This method silently succeeds if a collection with the given name does
  258. not exist.
  259. @note If a table name is passed to the method, it behaves like
  260. dropTable().
  261. */
  262. void dropCollection(const mysqlx::string& name)
  263. {
  264. try {
  265. Schema_detail::drop_collection(name);
  266. }
  267. CATCH_AND_WRAP
  268. }
  269. friend Collection;
  270. friend Table;
  271. ///@cond IGNORE
  272. friend internal::Schema_detail::Name_src;
  273. template <class Base> friend class internal::Sch_object;
  274. ///@endcond
  275. };
  276. /*
  277. Database objects that belong to some schema
  278. ===========================================
  279. */
  280. namespace internal {
  281. // Common base for schema objects defining the common API methods.
  282. template <class Base = Db_obj_base>
  283. class Sch_object
  284. : public Base
  285. {
  286. protected:
  287. Schema m_schema;
  288. Sch_object(const Schema &sch, const string &name);
  289. public:
  290. using string = mysqlx::string;
  291. /**
  292. Get database object name
  293. */
  294. const string& getName() const
  295. {
  296. return Base::m_name;
  297. }
  298. /**
  299. Get Session object
  300. */
  301. Session& getSession()
  302. {
  303. return m_schema.getSession();
  304. }
  305. /**
  306. Get schema object
  307. */
  308. const Schema& getSchema() const
  309. {
  310. return m_schema;
  311. }
  312. protected:
  313. std::shared_ptr<common::Session_impl> get_session();
  314. internal::Schema_detail& get_schema()
  315. {
  316. return m_schema;
  317. }
  318. };
  319. } // internal
  320. /**
  321. Represents a collection of documents in a schema.
  322. A collection object can be obtained from `Schema::getCollection()`
  323. method:
  324. ~~~~~~
  325. Schema db;
  326. Collection myColl;
  327. myColl= db.getCollection("My Collection");
  328. ~~~~~~
  329. or directly constructed as follows:
  330. ~~~~~~
  331. Schema db;
  332. Collection myColl(db, "My Collection");
  333. ~~~~~~
  334. When creating a `Collection` object, by default no checks are made that
  335. it actually exists in the database. An operation that is executed
  336. on the server and involves such a non-existent collection throws
  337. an error. Call `existsInDatabase()` to check the existence of the collection.
  338. @ingroup devapi
  339. */
  340. class Collection
  341. : protected internal::Sch_object<internal::Collection_detail>
  342. {
  343. public:
  344. Collection(const Schema &sch, const string &name)
  345. try
  346. : Sch_object(sch, name)
  347. {}
  348. CATCH_AND_WRAP
  349. using Sch_object::getName;
  350. using Sch_object::getSession;
  351. using Sch_object::getSchema;
  352. bool existsInDatabase() const
  353. {
  354. try {
  355. Schema::StringList list(m_schema, Schema::COLLECTION, m_name);
  356. return list.begin() != list.end();
  357. }
  358. CATCH_AND_WRAP
  359. }
  360. /**
  361. Get the number of documents in the collection.
  362. */
  363. uint64_t count();
  364. /*
  365. CRUD operations on a collection
  366. -------------------------------
  367. */
  368. /**
  369. Return an operation which fetches all documents from the collection.
  370. Call `execute()` on the returned operation object to execute it and get
  371. a `DocResult` object that gives access to the documents. Specify additional
  372. query parameters, such as ordering of the documents, using chained methods
  373. of `CollectionFind` class before making the final call to `execute()`.
  374. @note Any errors related to the operation are reported when the operation
  375. is executed, not when it is created.
  376. @see `CollectionFind`
  377. */
  378. CollectionFind find()
  379. {
  380. try {
  381. return CollectionFind(*this);
  382. }
  383. CATCH_AND_WRAP;
  384. }
  385. /**
  386. Return an operation which finds documents that satisfy given criteria.
  387. The criteria are specified as a Boolean expression string.
  388. Call `execute()` on the returned operation object to execute it and get
  389. a `DocResult` object that gives access to the documents. Specify additional
  390. query parameters, such as ordering of the documents, using chained methods
  391. of `CollectionFind` class before making the final call to `execute()`.
  392. @note Any errors related to the operation are reported when the operation
  393. is executed, not when it is created.
  394. @see `CollectionFind`
  395. */
  396. CollectionFind find(const string &cond)
  397. {
  398. try {
  399. return CollectionFind(*this, cond);
  400. }
  401. CATCH_AND_WRAP;
  402. }
  403. /**
  404. Return an operation which adds documents to the collection.
  405. Specify documents to be added in the same way as when calling
  406. `CollectionAdd::add()` method. Make additional calls to `add()` method on
  407. the returned operation object to add more documents. Call `execute()`
  408. to execute the operation and add all specified documents to the collection.
  409. @note Any errors related to the operation are reported when the operation
  410. is executed, not when it is created.
  411. @see `CollectionAdd`
  412. */
  413. template <typename... Types>
  414. CollectionAdd add(Types... args)
  415. {
  416. try {
  417. CollectionAdd add(*this);
  418. return add.add(args...);
  419. }
  420. CATCH_AND_WRAP;
  421. }
  422. /**
  423. Return an operation which removes documents satisfying given criteria.
  424. The criteria are specified as a Boolean expression string.
  425. Call `execute()` on the returned operation object to execute it and remove
  426. the matching documents. Use chained methods of `CollectionRemove` class
  427. before the final call to `execute()` to further limit the set of documents
  428. that are removed.
  429. @note To remove all documents in the collection, pass "true" as selection
  430. criteria.
  431. @note Any errors related to the operation are reported when the operation
  432. is executed, not when it is created.
  433. @see `CollectionRemove`
  434. */
  435. CollectionRemove remove(const string &cond)
  436. {
  437. try {
  438. return CollectionRemove(*this, cond);
  439. }
  440. CATCH_AND_WRAP;
  441. }
  442. /**
  443. Return an operation which modifies documents that satisfy given criteria.
  444. The criteria are specified as a Boolean expression string.
  445. Specify modifications to be applied to each document using chained methods
  446. of `CollectionModify` class on the returned operation object. Call
  447. `execute()` to execute the operation and modify matching documents
  448. as specified.
  449. @note To modify all documents in the collection, pass "true" as selection
  450. criteria.
  451. @note Any errors related to the operation are reported when the operation
  452. is executed, not when it is created.
  453. @see `CollectionModify`
  454. */
  455. CollectionModify modify(const string &expr)
  456. {
  457. try {
  458. return CollectionModify(*this, expr);
  459. }
  460. CATCH_AND_WRAP;
  461. }
  462. /**
  463. Return the document with the given id.
  464. Returns null document if a document with the given id does not exist in
  465. the collection.
  466. */
  467. DbDoc getOne(const string &id)
  468. {
  469. return find("_id = :id").bind("id", id).execute().fetchOne();
  470. }
  471. /**
  472. Remove the document with the given id.
  473. Does nothing if a document with the given id does not exist in
  474. the collection.
  475. */
  476. Result removeOne(const string &id)
  477. {
  478. return remove("_id = :id").bind("id", id).execute();
  479. }
  480. /**
  481. Replace the document with the given id by a new one.
  482. Specify the new document as either a `DbDoc` object, a JSON string or
  483. an `expr(docexpr)` argument, where `docexpr` is like a JSON string but
  484. field values are given by expressions to be evaluated on the server.
  485. If a document with the given id does not exist in the collection, nothing
  486. is done and the returned `Result` object indicates that no documents were
  487. modified.
  488. @note If expressions are used, they can not use named parameters because
  489. it is not possible to bind values prior to execution of `replaceOne()`
  490. operation.
  491. */
  492. Result replaceOne(const string &id, Value &&document)
  493. {
  494. try {
  495. return
  496. Collection_detail::add_or_replace_one(id, std::move(document), true);
  497. }
  498. CATCH_AND_WRAP
  499. }
  500. /**
  501. Add a new document or replace an existing document with the given id.
  502. Specify the new document as either a `DbDoc` object, a JSON string or
  503. an `expr(docexpr)` argument, where `docexpr` is like a JSON string but
  504. field values are given by expressions to be evaluated on the server.
  505. If a document with the given id does not exist, the new document is added
  506. to the collection.
  507. @note If expressions are used, they can not use named parameters because
  508. it is not possible to bind values prior to execution of `addOrReplaceOne()`
  509. operation.
  510. */
  511. Result addOrReplaceOne(const string &id, Value &&document)
  512. {
  513. try {
  514. return
  515. Collection_detail::add_or_replace_one(id, std::move(document), false);
  516. }
  517. CATCH_AND_WRAP
  518. }
  519. /**
  520. Create index on the collection.
  521. This function creates a named index in the collection using a JSON index
  522. specification.
  523. @param name name for an index to be created
  524. @param idx_spec index specification as a JSON string
  525. @see @ref indexing for information on how to define document
  526. collection indexes.
  527. */
  528. void createIndex(const string &name, const string &idx_spec)
  529. {
  530. try {
  531. Collection_detail::index_create(name, idx_spec);
  532. }
  533. CATCH_AND_WRAP
  534. }
  535. /**
  536. Drop index on the collection.
  537. @param name name for an index to be dropped
  538. @ingroup devapi_ddl
  539. */
  540. void dropIndex(const string &name)
  541. {
  542. try {
  543. Collection_detail::index_drop(name);
  544. }
  545. CATCH_AND_WRAP
  546. }
  547. friend CollectionFind;
  548. friend CollectionAdd;
  549. friend CollectionRemove;
  550. friend CollectionModify;
  551. ///@cond IGNORE
  552. friend internal::Crud_factory;
  553. ///@endcond
  554. };
  555. inline
  556. Collection Schema::createCollection(const string &name, bool reuse)
  557. {
  558. try {
  559. Schema_detail::create_collection(name, reuse);
  560. return Collection(*this, name);
  561. }
  562. CATCH_AND_WRAP
  563. }
  564. inline
  565. Collection Schema::getCollection(const string &name, bool check_exists)
  566. {
  567. Collection coll(*this, name);
  568. if (check_exists && !coll.existsInDatabase())
  569. throw_error("Collection does not exist");
  570. return coll;
  571. }
  572. /*
  573. Table object
  574. ============
  575. */
  576. /**
  577. Represents a table in a schema.
  578. A `Table` object can be obtained from `Schema::getTable()`
  579. method:
  580. ~~~~~~
  581. Schema db;
  582. Table myTable;
  583. myTable= db.getTable("My Table");
  584. ~~~~~~
  585. or directly constructed as follows:
  586. ~~~~~~
  587. Schema db;
  588. Table myTable(db, "My Table");
  589. ~~~~~~
  590. A `Table` object can refer to a plain table or to a view. In the latter case
  591. method `isView()` called on the object returns true.
  592. When creating a `Table` object, by default no checks are made that
  593. it actually exists in the database. An operation that is executed
  594. on the server and involves such a non-existent table throws
  595. an error. Call `existsInDatabase()` to check the existence of the table.
  596. @ingroup devapi
  597. */
  598. class Table
  599. : protected internal::Sch_object<>
  600. {
  601. public:
  602. Table(const Schema &sch, const string &name)
  603. : Sch_object(sch, name)
  604. {}
  605. Table(const Schema &sch, const string &name, bool is_view)
  606. : Sch_object(sch, name)
  607. {
  608. m_type = is_view ? VIEW : TABLE;
  609. }
  610. using Sch_object::getName;
  611. using Sch_object::getSession;
  612. using Sch_object::getSchema;
  613. bool existsInDatabase() const;
  614. /**
  615. Check if this table object corresponds to a view.
  616. @note This check might involve communication with the server.
  617. */
  618. bool isView();
  619. /**
  620. Get the number of rows in the table.
  621. */
  622. uint64_t count()
  623. {
  624. try {
  625. RowResult cnt = select(L"count(*)").execute();
  626. return cnt.fetchOne()[0].get<uint64_t>();
  627. }
  628. CATCH_AND_WRAP
  629. }
  630. /*
  631. CRUD operations
  632. ---------------
  633. */
  634. /**
  635. Return an operation which inserts rows into the full table without
  636. restricting the columns.
  637. Specify rows to be inserted using methods of `TableInsert` class chained
  638. on the returned operation object. Call `execute()` to execute the operation
  639. and insert the specified rows.
  640. Each specified row must have the same number of values as the number
  641. of columns of the table. If the value count and the table column count do
  642. not match, server reports error when operation is executed.
  643. @note Any errors related to the operation are reported when the operation
  644. is executed, not when it is created.
  645. @see `TableInsert`
  646. */
  647. TableInsert insert()
  648. {
  649. try {
  650. return TableInsert(*this);
  651. }
  652. CATCH_AND_WRAP;
  653. }
  654. /**
  655. Return an operation which inserts rows into the table restricting
  656. the columns.
  657. Specify column names as method arguments. Values are inserted only into
  658. the specified columns, other columns are set to null or to column's default
  659. value (depending on the definition of the table). Specify rows to
  660. be inserted using methods of `TableInsert` class chained on the returned
  661. operation object. Call `execute()` to execute the operation and insert
  662. the specified values.
  663. Each specified row must have the same number of values as the number
  664. of columns listed here. If the value count and the column count do
  665. not match, server reports error when operation is executed.
  666. @note Any errors related to the operation are reported when the operation
  667. is executed, not when it is created.
  668. @see `TableInsert`
  669. */
  670. template <class... T>
  671. TableInsert insert(const T&... t)
  672. {
  673. try {
  674. return TableInsert(*this, t...);
  675. }
  676. CATCH_AND_WRAP;
  677. }
  678. /**
  679. Return an operation which selects rows from the table.
  680. Call `execute()` on the returned operation object to execute it and get
  681. a `RowResult` object that gives access to the rows. Specify query
  682. parameters, such as selection criteria and ordering of the rows, using
  683. chained methods of `TableSelect` class before making the final call to
  684. `execute()`. To project selected rows before returning them in the result,
  685. specify a list of expressions as arguments of this method. These expressions
  686. are evaluated to form a row in the result. An expression can be optionally
  687. followed by "AS <name>" suffix to give a name to the corresponding column
  688. in the result. If no expressions are given, rows are returned as is, without
  689. any projection.
  690. @note Any errors related to the operation are reported when the operation
  691. is executed, not when it is created.
  692. @see `TableSelect`
  693. */
  694. template<typename ...PROJ>
  695. TableSelect select(const PROJ&...proj)
  696. {
  697. try {
  698. return TableSelect(*this, proj...);
  699. }
  700. CATCH_AND_WRAP;
  701. }
  702. /**
  703. Return an operation which removes rows from the table.
  704. Use chained methods of `TableRemove` class on the returned operation object
  705. to specify the rows to be removed. Call `execute()` to execute the operation
  706. and remove the rows.
  707. @note Any errors related to the operation are reported when the operation
  708. is executed, not when it is created.
  709. @see `TableRemove`
  710. */
  711. TableRemove remove()
  712. {
  713. try {
  714. return TableRemove(*this);
  715. }
  716. CATCH_AND_WRAP;
  717. }
  718. /**
  719. Return an operation which updates rows in the table.
  720. Use chained methods of `TableUpdate` class on the returned operation object
  721. to specify which rows should be updated and what modifications to apply
  722. to each of them. Call `execute()` to execute the operation and remove
  723. the rows.
  724. @note Any errors related to the operation are reported when the operation
  725. is executed, not when it is created.
  726. @see `TableUpdate`
  727. */
  728. TableUpdate update()
  729. {
  730. try {
  731. return TableUpdate(*this);
  732. }
  733. CATCH_AND_WRAP;
  734. }
  735. private:
  736. enum { TABLE, VIEW, UNKNOWN } m_type = UNKNOWN;
  737. friend TableSelect;
  738. friend TableInsert;
  739. friend TableRemove;
  740. friend TableUpdate;
  741. ///@cond IGNORE
  742. friend internal::Crud_factory;
  743. ///@endcond
  744. };
  745. inline
  746. bool Table::existsInDatabase() const
  747. {
  748. try {
  749. /*
  750. Note: When checking existence, we also determine if this is a view or
  751. a plain table because this information is fetched from the server when
  752. querying for a list of tables.
  753. */
  754. Schema::TableList list(m_schema, m_name);
  755. auto it = list.begin();
  756. if (!(it != list.end()))
  757. return false;
  758. const_cast<Table*>(this)->m_type = (*it).isView() ? VIEW : TABLE;
  759. return true;
  760. }
  761. CATCH_AND_WRAP
  762. }
  763. inline
  764. bool Table::isView()
  765. {
  766. try {
  767. /*
  768. If view status was not determined yet, do existence check which
  769. determines it as a side effect.
  770. */
  771. if (UNKNOWN == m_type)
  772. if (!existsInDatabase())
  773. throw_error("Table does not exist");
  774. return VIEW == m_type;
  775. }
  776. CATCH_AND_WRAP
  777. }
  778. inline
  779. Table Schema::getTable(const string &name, bool check_exists)
  780. {
  781. Table tbl(*this, name);
  782. if (check_exists && !tbl.existsInDatabase())
  783. throw_error("Table does not exist");
  784. return tbl;
  785. }
  786. inline
  787. Table Schema::getCollectionAsTable(const string &name, bool check_exists)
  788. {
  789. if (check_exists && !getCollection(name).existsInDatabase())
  790. throw_error("Collection does not exist");
  791. return { *this, name };
  792. }
  793. inline
  794. uint64_t Collection::count()
  795. {
  796. return m_schema.getCollectionAsTable(m_name).count();
  797. }
  798. using SqlStatement = internal::SQL_statement;
  799. /**
  800. Represents a session which gives access to data stored in a data store.
  801. A `Session` object can be created from a connection string, from
  802. `SessionSettings` or by directly specifying a host name, TCP/IP port and user
  803. credentials. Once created, a session is ready to be used. Session destructor
  804. closes the session and cleans up after it.
  805. If it is not possible to create a valid session for some reason, errors
  806. are thrown from session constructor.
  807. Several hosts can be specified by session creation parameters. In that case
  808. a failed connection to one of the hosts triggers a fail-over attempt
  809. to connect to a different host in the list. Only if none of the hosts could
  810. be contacted, session creation fails.
  811. The fail-over logic tries hosts in the order in which they are specified in
  812. session settings unless explicit priorities are assigned to the hosts. In that
  813. case hosts are tried in the decreasing priority order and for hosts with
  814. the same priority the order in which they are tired is random.
  815. Once a valid session is created using one of the hosts, the session is bound
  816. to that host and never re-connected again. If the connection gets broken,
  817. the session fails without making any other fail-over attempts. The fail-over
  818. logic is executed only when establishing a new session.
  819. @ingroup devapi
  820. */
  821. class Session
  822. : private internal::Session_detail
  823. {
  824. public:
  825. /**
  826. Create a session specified by a `SessionSettings` object.
  827. */
  828. Session(SessionSettings settings)
  829. try
  830. : Session_detail(settings)
  831. {}
  832. CATCH_AND_WRAP
  833. /**
  834. Create a session using given session settings.
  835. This constructor forwards arguments to a `SessionSettings` constructor.
  836. Thus all forms of specifying session options are also directly available
  837. in `Session` constructor.
  838. Examples:
  839. ~~~~~~
  840. Session from_uri("mysqlx://user:pwd@host:port/db?ssl-mode=disabled");
  841. Session from_options("host", port, "user", "pwd", "db");
  842. Session from_option_list(
  843. SessionOption::USER, "user",
  844. SessionOption::PWD, "pwd",
  845. SessionOption::HOST, "host",
  846. SessionOption::PORT, port,
  847. SessionOption::DB, "db",
  848. SessionOption::SSL_MODE, SSLMode::DISABLED
  849. );
  850. ~~~~~~
  851. @see `SessionSettings`
  852. */
  853. template<typename...T>
  854. Session(T...options)
  855. try
  856. : Session(SessionSettings(options...))
  857. {}CATCH_AND_WRAP
  858. Session(Session &&other)
  859. try
  860. : internal::Session_detail(std::move(other))
  861. {}CATCH_AND_WRAP
  862. Session(Client &client);
  863. /**
  864. Create a new schema.
  865. Returns the created schema. Set `reuse` flag to true to return an already
  866. existing schema with the same name. Otherwise, an attempt to create
  867. a schema which already exists throws an error.
  868. */
  869. Schema createSchema(const string &name, bool reuse = false)
  870. {
  871. try {
  872. Session_detail::create_schema(name, reuse);
  873. return Schema(*this, name);
  874. }
  875. CATCH_AND_WRAP
  876. }
  877. /**
  878. Return an object representing a schema with the given name.
  879. To check if the schema actually exists in the database set `check_existence`
  880. flag to true. Otherwise the returned object can refer to a non-existing
  881. schema. An attempt to use such a non-existing schema in a database operation
  882. throws an error.
  883. @note Checking the existence of a schema involves communication with
  884. the server. If `check_exists` is false, on the other hand, no I/O is
  885. involved when creating a `Schema` object.
  886. */
  887. Schema getSchema(const string &name, bool check_exists = false)
  888. {
  889. Schema sch(*this, name);
  890. if (check_exists && !sch.existsInDatabase())
  891. throw_error("Schema does not exist");
  892. return sch;
  893. }
  894. /**
  895. Get the default schema specified when the session was created.
  896. */
  897. Schema getDefaultSchema()
  898. {
  899. return Schema(*this, getDefaultSchemaName());
  900. }
  901. /**
  902. Get the name of the default schema specified when the session was created.
  903. */
  904. string getDefaultSchemaName()
  905. {
  906. try {
  907. return Session_detail::get_default_schema_name();
  908. }
  909. CATCH_AND_WRAP
  910. }
  911. /**
  912. Get a list of all database schemas.
  913. The returned value can be stored in a container that holds `Schema` objects,
  914. such as `std::vector<Schema>`.
  915. */
  916. SchemaList getSchemas()
  917. {
  918. try {
  919. return Schema_src(*this, L"%");
  920. }
  921. CATCH_AND_WRAP
  922. }
  923. // TODO: Should we have getSchemaNames() too?
  924. /**
  925. Drop the named schema.
  926. Error is thrown if the schema doesn't exist,
  927. */
  928. void dropSchema(const string &name)
  929. {
  930. try {
  931. Session_detail::drop_schema(name);
  932. }
  933. CATCH_AND_WRAP
  934. }
  935. /**
  936. Return an operation which executes an arbitrary SQL statement.
  937. Call `execute()` on the returned operation object to execute the statement
  938. and get an `SqlResult` object representing its results. If the SQL statement
  939. contains `?` placeholders, call `bind()` to define their values
  940. prior to the execution.
  941. @note Errors related to SQL execution are reported when the statement
  942. is executed, not when it is created.
  943. */
  944. SqlStatement sql(const string &query)
  945. {
  946. try {
  947. return SqlStatement(this, query);
  948. }
  949. CATCH_AND_WRAP
  950. }
  951. /**
  952. Start a new transaction.
  953. Throws error if previously opened transaction is not closed.
  954. */
  955. void startTransaction()
  956. {
  957. try {
  958. Session_detail::start_transaction();
  959. }
  960. CATCH_AND_WRAP
  961. }
  962. /**
  963. Commit opened transaction, if any.
  964. Does nothing if no transaction was opened. After committing the
  965. transaction is closed.
  966. */
  967. void commit()
  968. {
  969. try {
  970. Session_detail::commit();
  971. }
  972. CATCH_AND_WRAP
  973. }
  974. /**
  975. Roll back opened transaction, if any.
  976. Does nothing if no transaction was opened. Transaction which was
  977. rolled back is closed. To start a new transaction a call to
  978. `startTransaction()` is needed.
  979. */
  980. void rollback()
  981. {
  982. try {
  983. Session_detail::rollback();
  984. }
  985. CATCH_AND_WRAP
  986. }
  987. /**
  988. Roll back opened transaction to specified savepoint.
  989. It rolls back to savepoint, but transaction remains active.
  990. Does nothing if no transaction was opened.
  991. @throws Error If savepoint doesn't exist or is empty.
  992. */
  993. void rollbackTo(const string &savepoint)
  994. {
  995. try {
  996. if (savepoint.empty())
  997. throw_error("Invalid empty save point name");
  998. Session_detail::rollback(savepoint);
  999. }
  1000. CATCH_AND_WRAP
  1001. }
  1002. /**
  1003. Sets a named transaction savepoint with a name as
  1004. identifier.
  1005. To use savepoints a transaction has to be started using startTransaction().
  1006. @returns string with savepoint name.
  1007. @note If the current transaction has a savepoint with the same name,
  1008. the old savepoint is deleted and a new one is set.
  1009. */
  1010. string setSavepoint(const string &savepoint)
  1011. {
  1012. try {
  1013. if (savepoint.empty())
  1014. throw_error("Invalid empty save point name");
  1015. return Session_detail::savepoint_set(savepoint);
  1016. }
  1017. CATCH_AND_WRAP
  1018. }
  1019. /**
  1020. Creats a transaction savepoint with a generated name as
  1021. identifier.
  1022. To use savepoints a transaction has to be started using startTransaction().
  1023. @returns string with generated savepoint name.
  1024. @note If the current transaction has a savepoint with the same name,
  1025. the old savepoint is deleted and a new one is set.
  1026. */
  1027. string setSavepoint()
  1028. {
  1029. try {
  1030. return Session_detail::savepoint_set();
  1031. }
  1032. CATCH_AND_WRAP
  1033. }
  1034. /**
  1035. Releases savepoint previously added by setSavepoint().
  1036. @note Releasing savepoint doesn't affect data.
  1037. @throws Error If savepoint doesn't exist.
  1038. */
  1039. void releaseSavepoint(const string &savepoint)
  1040. {
  1041. try {
  1042. if (savepoint.empty())
  1043. throw_error("Invalid empty save point name");
  1044. Session_detail::savepoint_remove(savepoint);
  1045. }
  1046. CATCH_AND_WRAP
  1047. }
  1048. /**
  1049. Close this session.
  1050. After the session is closed, any call to other session's methods
  1051. throws an error.
  1052. */
  1053. void close()
  1054. {
  1055. try {
  1056. Session_detail::close();
  1057. }
  1058. CATCH_AND_WRAP
  1059. }
  1060. protected:
  1061. using internal::Session_detail::m_impl;
  1062. public:
  1063. friend Schema;
  1064. friend Collection;
  1065. friend Table;
  1066. friend Result;
  1067. friend RowResult;
  1068. ///@cond IGNORE
  1069. friend internal::Session_detail;
  1070. friend internal::Crud_factory;
  1071. friend internal::Result_detail;
  1072. template <class Base> friend class internal::Sch_object;
  1073. ///@endcond
  1074. };
  1075. /**
  1076. Create a client using given client settings.
  1077. Client allows the creation of sessions from a session pool.
  1078. This constructor forwards arguments to a ClientSettings constructor.
  1079. Thus all forms of specifying client options are also directly available
  1080. in Client constructor. ClientOptions and SessionOptions can be mixed
  1081. when construction Client objects
  1082. Examples:
  1083. ~~~~~~
  1084. Client from_uri("mysqlx://user:pwd\@host:port/db?ssl-mode=disabled");
  1085. Client from_options("host", port, "user", "pwd", "db");
  1086. Client from_option_list(
  1087. SessionOption::USER, "user",
  1088. SessionOption::PWD, "pwd",
  1089. SessionOption::HOST, "host",
  1090. SessionOption::PORT, port,
  1091. SessionOption::DB, "db",
  1092. SessionOption::SSL_MODE, SSLMode::DISABLED
  1093. ClientOption::POOLING, true,
  1094. ClientOption::POOL_MAX_SIZE, 10,
  1095. ClientOption::POOL_QUEUE_TIMEOUT, 1000,
  1096. ClientOption::POOL_MAX_IDLE_TIME, 500,
  1097. );
  1098. ~~~~~~
  1099. @see ClientSettings
  1100. */
  1101. class Client : public internal::Client_detail
  1102. {
  1103. public:
  1104. Client(ClientSettings settings)
  1105. try
  1106. : Client_detail(settings)
  1107. {}
  1108. CATCH_AND_WRAP
  1109. Client(SessionSettings &settings)
  1110. try
  1111. : Client_detail(settings)
  1112. {}
  1113. CATCH_AND_WRAP
  1114. template<typename...T>
  1115. Client(T...options)
  1116. : Client(ClientSettings(options...))
  1117. {}
  1118. Session getSession()
  1119. {
  1120. return *this;
  1121. }
  1122. };
  1123. /*
  1124. Session
  1125. */
  1126. inline
  1127. Session::Session(Client &client)
  1128. try
  1129. : internal::Session_detail(client.get_session_pool())
  1130. {}CATCH_AND_WRAP
  1131. /**
  1132. @ingroup devapi
  1133. Function to get Session object.
  1134. @param p same as needed by Session constructor.
  1135. */
  1136. template<class ...P>
  1137. Session getSession(P...p)
  1138. {
  1139. return Session(p...);
  1140. }
  1141. /**
  1142. @ingroup devapi
  1143. Function to get Client object.
  1144. @param p same as needed by Client constructor.
  1145. */
  1146. template<class ...P>
  1147. Client getClient(P...p)
  1148. {
  1149. return Client(p...);
  1150. }
  1151. /*
  1152. Schema class implementation
  1153. */
  1154. inline
  1155. Schema::Schema(Session &sess, const string &name)
  1156. : Schema_detail(sess.m_impl, name)
  1157. , m_sess(&sess)
  1158. {}
  1159. template <class Base>
  1160. inline
  1161. internal::Sch_object<Base>::Sch_object(const Schema &sch, const string &name)
  1162. : Base(sch.getSession().m_impl, name)
  1163. , m_schema(sch)
  1164. {}
  1165. template <class Base>
  1166. inline
  1167. std::shared_ptr<common::Session_impl>
  1168. internal::Sch_object<Base>::get_session()
  1169. {
  1170. assert(m_schema.m_sess);
  1171. return m_schema.m_sess->m_impl;
  1172. }
  1173. } // mysqlx
  1174. #endif