12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556 |
- /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2.0, as
- * published by the Free Software Foundation.
- *
- * This program is also distributed with certain software (including
- * but not limited to OpenSSL) that is licensed under separate terms,
- * as designated in a particular file or component or in included license
- * documentation. The authors of MySQL hereby grant you an
- * additional permission to link the program and your derivative works
- * with the separately licensed software that they have included with
- * MySQL.
- *
- * Without limiting anything contained in the foregoing, this file,
- * which is part of MySQL Connector/C++, is also subject to the
- * Universal FOSS Exception, version 1.0, a copy of which can be found at
- * http://oss.oracle.com/licenses/universal-foss-exception.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License, version 2.0, for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #ifndef MYSQL_DEVAPI_H
- #define MYSQL_DEVAPI_H
- #ifndef __cplusplus
- #error This header can be only used with C++ code
- #endif
- /**
- @defgroup devapi X DevAPI Classes
- X DevAPI Classes and types. See @ref devapi_ref for introduction.
- @defgroup devapi_op Database operations
- @ingroup devapi
- Classes representing yet-to-be-executed database operations.
- Such operations are created by various methods of @link mysqlx::Collection
- `Collection`@endlink or @link mysqlx::Table `Table`@endlink classes. Database
- operation classes define methods that specify additional operation
- characteristics before it gets executed with `execute()` method. The latter
- returns a @link mysqlx::Result `Result`@endlink, @link mysqlx::DocResult
- `DocResult`@endlink or @link mysqlx::RowResult `RowResult`@endlink object,
- depending on the type of the operation.
- @defgroup devapi_res Classes for result processing
- @ingroup devapi
- Classes used to examine results of a statement and documents or
- rows contained in a result.
- @defgroup devapi_aux Auxiliary types
- @ingroup devapi
- */
- /**
- @file
- The main header for MySQL Connector/C++ DevAPI.
- This header should be included by C++ code which uses the DevAPI implemented
- by MySQL Connector/C++.
- @sa result.h, document.h
- @ingroup devapi
- */
- /*
- X DevAPI public classes are declared in this and other headers included from
- devapi/ folder. The main public API classes, such as Session below, contain
- declarations of public interface methods. Any obscure details of the public
- API, which must be defined in the public header, are factored out
- to Session_detail class from which the main Session class inherits.
- Among other things, Session_detail declares the implementation class for
- Session. This implementation class is opaque and its details are not defined
- in the public headers - only in the implementation part. Definitions of
- XXX_detail classes can be found in devapi/detail/ sub-folder.
- */
- #include "devapi/common.h"
- #include "devapi/result.h"
- #include "devapi/collection_crud.h"
- #include "devapi/table_crud.h"
- #include "devapi/settings.h"
- #include "devapi/detail/session.h"
- namespace mysqlx {
- class Session;
- namespace internal {
- template <class Base> class Sch_object;
- } // internal
- /**
- Represents a database schema.
- A `Schema` instance can be obtained from `Session::getSchema()`
- method:
- ~~~~~~
- Session session;
- Schema mySchema;
- mySchema= session.getSchema("My Schema");
- ~~~~~~
- or it can be directly constructed as follows:
- ~~~~~~
- Session session;
- Schema mySchema(session, "My Schema");
- ~~~~~~
- Each `Schema` instance is tied to a particular session and all
- the operations on the schema and its objects are performed using
- that session. If the session is destroyed, an attempt to use a schema of
- that session yields an error.
- When creating a `Schema` object, by default no checks are made that
- it actually exists in the database. An operation that is executed
- on the server and involves such a non-existent schema throws
- an error.
- @ingroup devapi
- */
- class Schema
- : protected internal::Schema_detail
- {
- Session *m_sess;
- public:
- /**
- Construct an object representing the named schema.
- */
- Schema(Session &sess, const string &name);
- /**
- Construct an object representing the default schema of the session.
- The default schema is the one specified by session creation options.
- */
- Schema(Session&);
- /**
- Get schema name
- */
- const string& getName() const
- {
- return m_name;
- }
- /**
- Get Session object
- */
- Session& getSession()
- {
- return *m_sess;
- }
- const Session& getSession() const
- {
- return const_cast<Schema*>(this)->getSession();
- }
- /**
- Check if this schema exists in the database.
- @note Involves communication with the server.
- */
- bool existsInDatabase() const
- {
- try {
- /*
- Note: We get from server a list of schemata filtered by the name of
- this schema - if the schema exists the list should not be empty.
- */
- internal::Session_detail::Name_src list(*m_sess, m_name);
- list.iterator_start();
- return list.iterator_next();
- }
- CATCH_AND_WRAP
- }
- /**
- Create a new collection in the schema.
- Returns the created collection. Set `reuse` flag to true to return
- an already existing collection with the same name. Otherwise, an attempt
- to create a collection which already exists throws an error.
- */
- Collection createCollection(const string &name, bool reuse = false);
- /**
- Return an object representing a collection with the given name.
- To check if the collection actually exists in the database set
- `check_existence` flag to true. Otherwise the returned object can refer to
- a non-existing collection. An attempt to use such a non-existing collection
- in a database operation throws an error.
- @note Checking the existence of a collection involves communication with
- the server. If `check_exists` is false, on the other hand, no I/O is
- involved when creating a `Collection` object.
- */
- Collection getCollection(const string &name, bool check_exists = false);
- /**
- Return an object representing a table or a view with the given name.
- To check if the table actually exists in the database set
- `check_existence` flag to true. Otherwise the returned object can refer to
- a non-existing table. An attempt to use such a non-existing table
- in a database operation throws an error.
- @note The returned `Table` object can represent a plain table or
- a view. See `Table` class description.
- @note Checking the existence of a table involves communication with
- the server. If `check_exists` is false, on the other hand, no I/O is
- involved when creating a `Table` object.
- */
- Table getTable(const string &name, bool check_exists = false);
- /**
- Get a list of all collections in the schema.
- The returned value can be stored in a container that holds `Collection`
- objects, such as `std::vector<Collection>`.
- */
- CollectionList getCollections()
- {
- try {
- return Collection_src(*this, L"%");
- }
- CATCH_AND_WRAP
- }
- /**
- Get a list of names of all collections in the schema.
- The returned value can be stored in a container that holds strings, such as
- `std::vector<string>`.
- */
- StringList getCollectionNames()
- {
- try {
- return Name_src(*this, COLLECTION, L"%");
- }
- CATCH_AND_WRAP
- }
- /**
- Get a list of all tables and views in the schema.
- The returned value can be stored in a container that holds `Table`
- objects, such as `std::vector<Table>`.
- @note The list also contains views which are represented by `Table` objects
- - see `Table` class description.
- */
- TableList getTables()
- {
- try {
- return Table_src(*this, L"%");
- }
- CATCH_AND_WRAP
- }
- /**
- Get a list of names of all tables and views in the schema.
- The returned value can be stored in a container that holds strings, such as
- `std::vector<string>`.
- @note The list also contains names of views as views are represented
- by `Table` objects - see `Table` class description.
- */
- StringList getTableNames()
- {
- try {
- return Name_src(*this, TABLE, L"%");
- }
- CATCH_AND_WRAP
- }
- /**
- Return a table corresponding to the given collection.
- The table has two columns: `_id` and `doc`. For each document in
- the collection there is one row in the table with `doc` filed holding
- the document as a JSON value and `_id` field holding document's identifier.
- To check if the collection actually exists in the database set
- `check_existence` flag to true. Otherwise the returned table can refer to
- a non-existing collection. An attempt to use such a non-existing collection
- table throws an error.
- @note Checking the existence of a collection involves communication with
- the server. If `check_exists` is false, on the other hand, no I/O is
- involved when creating the `Table` object.
- */
- Table getCollectionAsTable(const string &name, bool check_exists = true);
- /**
- Drop the given collection from the schema.
- This method silently succeeds if a collection with the given name does
- not exist.
- @note If a table name is passed to the method, it behaves like
- dropTable().
- */
- void dropCollection(const mysqlx::string& name)
- {
- try {
- Schema_detail::drop_collection(name);
- }
- CATCH_AND_WRAP
- }
- friend Collection;
- friend Table;
- ///@cond IGNORE
- friend internal::Schema_detail::Name_src;
- template <class Base> friend class internal::Sch_object;
- ///@endcond
- };
- /*
- Database objects that belong to some schema
- ===========================================
- */
- namespace internal {
- // Common base for schema objects defining the common API methods.
- template <class Base = Db_obj_base>
- class Sch_object
- : public Base
- {
- protected:
- Schema m_schema;
- Sch_object(const Schema &sch, const string &name);
- public:
- using string = mysqlx::string;
- /**
- Get database object name
- */
- const string& getName() const
- {
- return Base::m_name;
- }
- /**
- Get Session object
- */
- Session& getSession()
- {
- return m_schema.getSession();
- }
- /**
- Get schema object
- */
- const Schema& getSchema() const
- {
- return m_schema;
- }
- protected:
- std::shared_ptr<common::Session_impl> get_session();
- internal::Schema_detail& get_schema()
- {
- return m_schema;
- }
- };
- } // internal
- /**
- Represents a collection of documents in a schema.
- A collection object can be obtained from `Schema::getCollection()`
- method:
- ~~~~~~
- Schema db;
- Collection myColl;
- myColl= db.getCollection("My Collection");
- ~~~~~~
- or directly constructed as follows:
- ~~~~~~
- Schema db;
- Collection myColl(db, "My Collection");
- ~~~~~~
- When creating a `Collection` object, by default no checks are made that
- it actually exists in the database. An operation that is executed
- on the server and involves such a non-existent collection throws
- an error. Call `existsInDatabase()` to check the existence of the collection.
- @ingroup devapi
- */
- class Collection
- : protected internal::Sch_object<internal::Collection_detail>
- {
- public:
- Collection(const Schema &sch, const string &name)
- try
- : Sch_object(sch, name)
- {}
- CATCH_AND_WRAP
- using Sch_object::getName;
- using Sch_object::getSession;
- using Sch_object::getSchema;
- bool existsInDatabase() const
- {
- try {
- Schema::StringList list(m_schema, Schema::COLLECTION, m_name);
- return list.begin() != list.end();
- }
- CATCH_AND_WRAP
- }
- /**
- Get the number of documents in the collection.
- */
- uint64_t count();
- /*
- CRUD operations on a collection
- -------------------------------
- */
- /**
- Return an operation which fetches all documents from the collection.
- Call `execute()` on the returned operation object to execute it and get
- a `DocResult` object that gives access to the documents. Specify additional
- query parameters, such as ordering of the documents, using chained methods
- of `CollectionFind` class before making the final call to `execute()`.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `CollectionFind`
- */
- CollectionFind find()
- {
- try {
- return CollectionFind(*this);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which finds documents that satisfy given criteria.
- The criteria are specified as a Boolean expression string.
- Call `execute()` on the returned operation object to execute it and get
- a `DocResult` object that gives access to the documents. Specify additional
- query parameters, such as ordering of the documents, using chained methods
- of `CollectionFind` class before making the final call to `execute()`.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `CollectionFind`
- */
- CollectionFind find(const string &cond)
- {
- try {
- return CollectionFind(*this, cond);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which adds documents to the collection.
- Specify documents to be added in the same way as when calling
- `CollectionAdd::add()` method. Make additional calls to `add()` method on
- the returned operation object to add more documents. Call `execute()`
- to execute the operation and add all specified documents to the collection.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `CollectionAdd`
- */
- template <typename... Types>
- CollectionAdd add(Types... args)
- {
- try {
- CollectionAdd add(*this);
- return add.add(args...);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which removes documents satisfying given criteria.
- The criteria are specified as a Boolean expression string.
- Call `execute()` on the returned operation object to execute it and remove
- the matching documents. Use chained methods of `CollectionRemove` class
- before the final call to `execute()` to further limit the set of documents
- that are removed.
- @note To remove all documents in the collection, pass "true" as selection
- criteria.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `CollectionRemove`
- */
- CollectionRemove remove(const string &cond)
- {
- try {
- return CollectionRemove(*this, cond);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which modifies documents that satisfy given criteria.
- The criteria are specified as a Boolean expression string.
- Specify modifications to be applied to each document using chained methods
- of `CollectionModify` class on the returned operation object. Call
- `execute()` to execute the operation and modify matching documents
- as specified.
- @note To modify all documents in the collection, pass "true" as selection
- criteria.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `CollectionModify`
- */
- CollectionModify modify(const string &expr)
- {
- try {
- return CollectionModify(*this, expr);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return the document with the given id.
- Returns null document if a document with the given id does not exist in
- the collection.
- */
- DbDoc getOne(const string &id)
- {
- return find("_id = :id").bind("id", id).execute().fetchOne();
- }
- /**
- Remove the document with the given id.
- Does nothing if a document with the given id does not exist in
- the collection.
- */
- Result removeOne(const string &id)
- {
- return remove("_id = :id").bind("id", id).execute();
- }
- /**
- Replace the document with the given id by a new one.
- Specify the new document as either a `DbDoc` object, a JSON string or
- an `expr(docexpr)` argument, where `docexpr` is like a JSON string but
- field values are given by expressions to be evaluated on the server.
- If a document with the given id does not exist in the collection, nothing
- is done and the returned `Result` object indicates that no documents were
- modified.
- @note If expressions are used, they can not use named parameters because
- it is not possible to bind values prior to execution of `replaceOne()`
- operation.
- */
- Result replaceOne(const string &id, Value &&document)
- {
- try {
- return
- Collection_detail::add_or_replace_one(id, std::move(document), true);
- }
- CATCH_AND_WRAP
- }
- /**
- Add a new document or replace an existing document with the given id.
- Specify the new document as either a `DbDoc` object, a JSON string or
- an `expr(docexpr)` argument, where `docexpr` is like a JSON string but
- field values are given by expressions to be evaluated on the server.
- If a document with the given id does not exist, the new document is added
- to the collection.
- @note If expressions are used, they can not use named parameters because
- it is not possible to bind values prior to execution of `addOrReplaceOne()`
- operation.
- */
- Result addOrReplaceOne(const string &id, Value &&document)
- {
- try {
- return
- Collection_detail::add_or_replace_one(id, std::move(document), false);
- }
- CATCH_AND_WRAP
- }
- /**
- Create index on the collection.
- This function creates a named index in the collection using a JSON index
- specification.
- @param name name for an index to be created
- @param idx_spec index specification as a JSON string
- @see @ref indexing for information on how to define document
- collection indexes.
- */
- void createIndex(const string &name, const string &idx_spec)
- {
- try {
- Collection_detail::index_create(name, idx_spec);
- }
- CATCH_AND_WRAP
- }
- /**
- Drop index on the collection.
- @param name name for an index to be dropped
- @ingroup devapi_ddl
- */
- void dropIndex(const string &name)
- {
- try {
- Collection_detail::index_drop(name);
- }
- CATCH_AND_WRAP
- }
- friend CollectionFind;
- friend CollectionAdd;
- friend CollectionRemove;
- friend CollectionModify;
- ///@cond IGNORE
- friend internal::Crud_factory;
- ///@endcond
- };
- inline
- Collection Schema::createCollection(const string &name, bool reuse)
- {
- try {
- Schema_detail::create_collection(name, reuse);
- return Collection(*this, name);
- }
- CATCH_AND_WRAP
- }
- inline
- Collection Schema::getCollection(const string &name, bool check_exists)
- {
- Collection coll(*this, name);
- if (check_exists && !coll.existsInDatabase())
- throw_error("Collection does not exist");
- return coll;
- }
- /*
- Table object
- ============
- */
- /**
- Represents a table in a schema.
- A `Table` object can be obtained from `Schema::getTable()`
- method:
- ~~~~~~
- Schema db;
- Table myTable;
- myTable= db.getTable("My Table");
- ~~~~~~
- or directly constructed as follows:
- ~~~~~~
- Schema db;
- Table myTable(db, "My Table");
- ~~~~~~
- A `Table` object can refer to a plain table or to a view. In the latter case
- method `isView()` called on the object returns true.
- When creating a `Table` object, by default no checks are made that
- it actually exists in the database. An operation that is executed
- on the server and involves such a non-existent table throws
- an error. Call `existsInDatabase()` to check the existence of the table.
- @ingroup devapi
- */
- class Table
- : protected internal::Sch_object<>
- {
- public:
- Table(const Schema &sch, const string &name)
- : Sch_object(sch, name)
- {}
- Table(const Schema &sch, const string &name, bool is_view)
- : Sch_object(sch, name)
- {
- m_type = is_view ? VIEW : TABLE;
- }
- using Sch_object::getName;
- using Sch_object::getSession;
- using Sch_object::getSchema;
- bool existsInDatabase() const;
- /**
- Check if this table object corresponds to a view.
- @note This check might involve communication with the server.
- */
- bool isView();
- /**
- Get the number of rows in the table.
- */
- uint64_t count()
- {
- try {
- RowResult cnt = select(L"count(*)").execute();
- return cnt.fetchOne()[0].get<uint64_t>();
- }
- CATCH_AND_WRAP
- }
- /*
- CRUD operations
- ---------------
- */
- /**
- Return an operation which inserts rows into the full table without
- restricting the columns.
- Specify rows to be inserted using methods of `TableInsert` class chained
- on the returned operation object. Call `execute()` to execute the operation
- and insert the specified rows.
- Each specified row must have the same number of values as the number
- of columns of the table. If the value count and the table column count do
- not match, server reports error when operation is executed.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `TableInsert`
- */
- TableInsert insert()
- {
- try {
- return TableInsert(*this);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which inserts rows into the table restricting
- the columns.
- Specify column names as method arguments. Values are inserted only into
- the specified columns, other columns are set to null or to column's default
- value (depending on the definition of the table). Specify rows to
- be inserted using methods of `TableInsert` class chained on the returned
- operation object. Call `execute()` to execute the operation and insert
- the specified values.
- Each specified row must have the same number of values as the number
- of columns listed here. If the value count and the column count do
- not match, server reports error when operation is executed.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `TableInsert`
- */
- template <class... T>
- TableInsert insert(const T&... t)
- {
- try {
- return TableInsert(*this, t...);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which selects rows from the table.
- Call `execute()` on the returned operation object to execute it and get
- a `RowResult` object that gives access to the rows. Specify query
- parameters, such as selection criteria and ordering of the rows, using
- chained methods of `TableSelect` class before making the final call to
- `execute()`. To project selected rows before returning them in the result,
- specify a list of expressions as arguments of this method. These expressions
- are evaluated to form a row in the result. An expression can be optionally
- followed by "AS <name>" suffix to give a name to the corresponding column
- in the result. If no expressions are given, rows are returned as is, without
- any projection.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `TableSelect`
- */
- template<typename ...PROJ>
- TableSelect select(const PROJ&...proj)
- {
- try {
- return TableSelect(*this, proj...);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which removes rows from the table.
- Use chained methods of `TableRemove` class on the returned operation object
- to specify the rows to be removed. Call `execute()` to execute the operation
- and remove the rows.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `TableRemove`
- */
- TableRemove remove()
- {
- try {
- return TableRemove(*this);
- }
- CATCH_AND_WRAP;
- }
- /**
- Return an operation which updates rows in the table.
- Use chained methods of `TableUpdate` class on the returned operation object
- to specify which rows should be updated and what modifications to apply
- to each of them. Call `execute()` to execute the operation and remove
- the rows.
- @note Any errors related to the operation are reported when the operation
- is executed, not when it is created.
- @see `TableUpdate`
- */
- TableUpdate update()
- {
- try {
- return TableUpdate(*this);
- }
- CATCH_AND_WRAP;
- }
- private:
- enum { TABLE, VIEW, UNKNOWN } m_type = UNKNOWN;
- friend TableSelect;
- friend TableInsert;
- friend TableRemove;
- friend TableUpdate;
- ///@cond IGNORE
- friend internal::Crud_factory;
- ///@endcond
- };
- inline
- bool Table::existsInDatabase() const
- {
- try {
- /*
- Note: When checking existence, we also determine if this is a view or
- a plain table because this information is fetched from the server when
- querying for a list of tables.
- */
- Schema::TableList list(m_schema, m_name);
- auto it = list.begin();
- if (!(it != list.end()))
- return false;
- const_cast<Table*>(this)->m_type = (*it).isView() ? VIEW : TABLE;
- return true;
- }
- CATCH_AND_WRAP
- }
- inline
- bool Table::isView()
- {
- try {
- /*
- If view status was not determined yet, do existence check which
- determines it as a side effect.
- */
- if (UNKNOWN == m_type)
- if (!existsInDatabase())
- throw_error("Table does not exist");
- return VIEW == m_type;
- }
- CATCH_AND_WRAP
- }
- inline
- Table Schema::getTable(const string &name, bool check_exists)
- {
- Table tbl(*this, name);
- if (check_exists && !tbl.existsInDatabase())
- throw_error("Table does not exist");
- return tbl;
- }
- inline
- Table Schema::getCollectionAsTable(const string &name, bool check_exists)
- {
- if (check_exists && !getCollection(name).existsInDatabase())
- throw_error("Collection does not exist");
- return { *this, name };
- }
- inline
- uint64_t Collection::count()
- {
- return m_schema.getCollectionAsTable(m_name).count();
- }
- using SqlStatement = internal::SQL_statement;
- /**
- Represents a session which gives access to data stored in a data store.
- A `Session` object can be created from a connection string, from
- `SessionSettings` or by directly specifying a host name, TCP/IP port and user
- credentials. Once created, a session is ready to be used. Session destructor
- closes the session and cleans up after it.
- If it is not possible to create a valid session for some reason, errors
- are thrown from session constructor.
- Several hosts can be specified by session creation parameters. In that case
- a failed connection to one of the hosts triggers a fail-over attempt
- to connect to a different host in the list. Only if none of the hosts could
- be contacted, session creation fails.
- The fail-over logic tries hosts in the order in which they are specified in
- session settings unless explicit priorities are assigned to the hosts. In that
- case hosts are tried in the decreasing priority order and for hosts with
- the same priority the order in which they are tired is random.
- Once a valid session is created using one of the hosts, the session is bound
- to that host and never re-connected again. If the connection gets broken,
- the session fails without making any other fail-over attempts. The fail-over
- logic is executed only when establishing a new session.
- @ingroup devapi
- */
- class Session
- : private internal::Session_detail
- {
- public:
- /**
- Create a session specified by a `SessionSettings` object.
- */
- Session(SessionSettings settings)
- try
- : Session_detail(settings)
- {}
- CATCH_AND_WRAP
- /**
- Create a session using given session settings.
- This constructor forwards arguments to a `SessionSettings` constructor.
- Thus all forms of specifying session options are also directly available
- in `Session` constructor.
- Examples:
- ~~~~~~
- Session from_uri("mysqlx://user:pwd@host:port/db?ssl-mode=disabled");
- Session from_options("host", port, "user", "pwd", "db");
- Session from_option_list(
- SessionOption::USER, "user",
- SessionOption::PWD, "pwd",
- SessionOption::HOST, "host",
- SessionOption::PORT, port,
- SessionOption::DB, "db",
- SessionOption::SSL_MODE, SSLMode::DISABLED
- );
- ~~~~~~
- @see `SessionSettings`
- */
- template<typename...T>
- Session(T...options)
- try
- : Session(SessionSettings(options...))
- {}CATCH_AND_WRAP
- Session(Session &&other)
- try
- : internal::Session_detail(std::move(other))
- {}CATCH_AND_WRAP
- Session(Client &client);
- /**
- Create a new schema.
- Returns the created schema. Set `reuse` flag to true to return an already
- existing schema with the same name. Otherwise, an attempt to create
- a schema which already exists throws an error.
- */
- Schema createSchema(const string &name, bool reuse = false)
- {
- try {
- Session_detail::create_schema(name, reuse);
- return Schema(*this, name);
- }
- CATCH_AND_WRAP
- }
- /**
- Return an object representing a schema with the given name.
- To check if the schema actually exists in the database set `check_existence`
- flag to true. Otherwise the returned object can refer to a non-existing
- schema. An attempt to use such a non-existing schema in a database operation
- throws an error.
- @note Checking the existence of a schema involves communication with
- the server. If `check_exists` is false, on the other hand, no I/O is
- involved when creating a `Schema` object.
- */
- Schema getSchema(const string &name, bool check_exists = false)
- {
- Schema sch(*this, name);
- if (check_exists && !sch.existsInDatabase())
- throw_error("Schema does not exist");
- return sch;
- }
- /**
- Get the default schema specified when the session was created.
- */
- Schema getDefaultSchema()
- {
- return Schema(*this, getDefaultSchemaName());
- }
- /**
- Get the name of the default schema specified when the session was created.
- */
- string getDefaultSchemaName()
- {
- try {
- return Session_detail::get_default_schema_name();
- }
- CATCH_AND_WRAP
- }
- /**
- Get a list of all database schemas.
- The returned value can be stored in a container that holds `Schema` objects,
- such as `std::vector<Schema>`.
- */
- SchemaList getSchemas()
- {
- try {
- return Schema_src(*this, L"%");
- }
- CATCH_AND_WRAP
- }
- // TODO: Should we have getSchemaNames() too?
- /**
- Drop the named schema.
- Error is thrown if the schema doesn't exist,
- */
- void dropSchema(const string &name)
- {
- try {
- Session_detail::drop_schema(name);
- }
- CATCH_AND_WRAP
- }
- /**
- Return an operation which executes an arbitrary SQL statement.
- Call `execute()` on the returned operation object to execute the statement
- and get an `SqlResult` object representing its results. If the SQL statement
- contains `?` placeholders, call `bind()` to define their values
- prior to the execution.
- @note Errors related to SQL execution are reported when the statement
- is executed, not when it is created.
- */
- SqlStatement sql(const string &query)
- {
- try {
- return SqlStatement(this, query);
- }
- CATCH_AND_WRAP
- }
- /**
- Start a new transaction.
- Throws error if previously opened transaction is not closed.
- */
- void startTransaction()
- {
- try {
- Session_detail::start_transaction();
- }
- CATCH_AND_WRAP
- }
- /**
- Commit opened transaction, if any.
- Does nothing if no transaction was opened. After committing the
- transaction is closed.
- */
- void commit()
- {
- try {
- Session_detail::commit();
- }
- CATCH_AND_WRAP
- }
- /**
- Roll back opened transaction, if any.
- Does nothing if no transaction was opened. Transaction which was
- rolled back is closed. To start a new transaction a call to
- `startTransaction()` is needed.
- */
- void rollback()
- {
- try {
- Session_detail::rollback();
- }
- CATCH_AND_WRAP
- }
- /**
- Roll back opened transaction to specified savepoint.
- It rolls back to savepoint, but transaction remains active.
- Does nothing if no transaction was opened.
- @throws Error If savepoint doesn't exist or is empty.
- */
- void rollbackTo(const string &savepoint)
- {
- try {
- if (savepoint.empty())
- throw_error("Invalid empty save point name");
- Session_detail::rollback(savepoint);
- }
- CATCH_AND_WRAP
- }
- /**
- Sets a named transaction savepoint with a name as
- identifier.
- To use savepoints a transaction has to be started using startTransaction().
- @returns string with savepoint name.
- @note If the current transaction has a savepoint with the same name,
- the old savepoint is deleted and a new one is set.
- */
- string setSavepoint(const string &savepoint)
- {
- try {
- if (savepoint.empty())
- throw_error("Invalid empty save point name");
- return Session_detail::savepoint_set(savepoint);
- }
- CATCH_AND_WRAP
- }
- /**
- Creats a transaction savepoint with a generated name as
- identifier.
- To use savepoints a transaction has to be started using startTransaction().
- @returns string with generated savepoint name.
- @note If the current transaction has a savepoint with the same name,
- the old savepoint is deleted and a new one is set.
- */
- string setSavepoint()
- {
- try {
- return Session_detail::savepoint_set();
- }
- CATCH_AND_WRAP
- }
- /**
- Releases savepoint previously added by setSavepoint().
- @note Releasing savepoint doesn't affect data.
- @throws Error If savepoint doesn't exist.
- */
- void releaseSavepoint(const string &savepoint)
- {
- try {
- if (savepoint.empty())
- throw_error("Invalid empty save point name");
- Session_detail::savepoint_remove(savepoint);
- }
- CATCH_AND_WRAP
- }
- /**
- Close this session.
- After the session is closed, any call to other session's methods
- throws an error.
- */
- void close()
- {
- try {
- Session_detail::close();
- }
- CATCH_AND_WRAP
- }
- protected:
- using internal::Session_detail::m_impl;
- public:
- friend Schema;
- friend Collection;
- friend Table;
- friend Result;
- friend RowResult;
- ///@cond IGNORE
- friend internal::Session_detail;
- friend internal::Crud_factory;
- friend internal::Result_detail;
- template <class Base> friend class internal::Sch_object;
- ///@endcond
- };
- /**
- Create a client using given client settings.
- Client allows the creation of sessions from a session pool.
- This constructor forwards arguments to a ClientSettings constructor.
- Thus all forms of specifying client options are also directly available
- in Client constructor. ClientOptions and SessionOptions can be mixed
- when construction Client objects
- Examples:
- ~~~~~~
- Client from_uri("mysqlx://user:pwd\@host:port/db?ssl-mode=disabled");
- Client from_options("host", port, "user", "pwd", "db");
- Client from_option_list(
- SessionOption::USER, "user",
- SessionOption::PWD, "pwd",
- SessionOption::HOST, "host",
- SessionOption::PORT, port,
- SessionOption::DB, "db",
- SessionOption::SSL_MODE, SSLMode::DISABLED
- ClientOption::POOLING, true,
- ClientOption::POOL_MAX_SIZE, 10,
- ClientOption::POOL_QUEUE_TIMEOUT, 1000,
- ClientOption::POOL_MAX_IDLE_TIME, 500,
- );
- ~~~~~~
- @see ClientSettings
- */
- class Client : public internal::Client_detail
- {
- public:
- Client(ClientSettings settings)
- try
- : Client_detail(settings)
- {}
- CATCH_AND_WRAP
- Client(SessionSettings &settings)
- try
- : Client_detail(settings)
- {}
- CATCH_AND_WRAP
- template<typename...T>
- Client(T...options)
- : Client(ClientSettings(options...))
- {}
- Session getSession()
- {
- return *this;
- }
- };
- /*
- Session
- */
- inline
- Session::Session(Client &client)
- try
- : internal::Session_detail(client.get_session_pool())
- {}CATCH_AND_WRAP
- /**
- @ingroup devapi
- Function to get Session object.
- @param p same as needed by Session constructor.
- */
- template<class ...P>
- Session getSession(P...p)
- {
- return Session(p...);
- }
- /**
- @ingroup devapi
- Function to get Client object.
- @param p same as needed by Client constructor.
- */
- template<class ...P>
- Client getClient(P...p)
- {
- return Client(p...);
- }
- /*
- Schema class implementation
- */
- inline
- Schema::Schema(Session &sess, const string &name)
- : Schema_detail(sess.m_impl, name)
- , m_sess(&sess)
- {}
- template <class Base>
- inline
- internal::Sch_object<Base>::Sch_object(const Schema &sch, const string &name)
- : Base(sch.getSession().m_impl, name)
- , m_schema(sch)
- {}
- template <class Base>
- inline
- std::shared_ptr<common::Session_impl>
- internal::Sch_object<Base>::get_session()
- {
- assert(m_schema.m_sess);
- return m_schema.m_sess->m_impl;
- }
- } // mysqlx
- #endif
|