Examples
========


Connect to a CaosDB server
--------------------------

See also the hints on how to :doc:`get started<Install_develop>`, and set-up of libcaosdb. In order
to connect to a CaosDB server with libcaosdb you first have to configure the connection via a
configuration file as explained in the :ref:`"Client Configuration" section <Client
Configuration>`. Once the configuration is set up, connecting to the server is as easy as

.. code:: cpp

  const auto &connection =
      caosdb::connection::ConnectionManager::GetDefaultConnection();

You can print the full version of the server that you are connected to (and 
therby test the connection) via: 

.. code:: cpp

  // get version info of the server
  connection.RetrieveVersionInfo()
  const auto &v_info = connection->GetVersionInfo();
  std::cout << "Server Version: " << v_info->GetMajor() << "."
            << v_info->GetMinor() << "." << v_info->GetPatch() << "-"
            << v_info->GetPreRelease() << "-" << v_info->GetBuild()
            << std::endl;


Retrieve a Record
-----------------

With libcaosdb you can create a transaction
object, fill it with sub-requests, execute it, and retrieve the
result(s) . This
is handy when you want to have several requests in the same transaction.
However, most of the time, e.g., when retrieving one or multiple
Records, this is not necessary. libcaosdb provides helper functions so
you don’t have to worry about transactions and their executions. Assume
you want to retrieve an Entity with id=123. This is done via

.. code:: cpp

   const auto &connection =
     caosdb::connection::ConnectionManager::GetDefaultConnection();

   auto transaction(connection->CreateTransaction());

   const auto *id = "1231";
   transaction->RetrieveById(id);
   auto status = transaction->Execute();

   const auto &result_set = transaction->GetResultSet();

   const auto &entity = result_set.at(0)


You can then use the getter methods like :cpp:any:`GetId<caosdb::entity::Entity::GetId>`,
:cpp:any:`GetParents<caosdb::entity::Entity::GetParents>`, or
:cpp:any:`GetProperties`<caosdb::entity::Entity::GetProperties>` to get the name, the parents, or
the properties of the retrieved entity.

Retrieving multiple entities works in the same way. Type

.. code:: cpp

  const std::vector<std::string> ids = {"1220", "1221", "1222"};
  transaction->RetrieveById(ids.begin(), ids.end());

to retrieve the entities with ids 1220, 1221 and 1222. They can then be
accessed using ``result_set.at(1)`` etc. 

The same (and more) can be achieved by building and executing the
transaction manually. This is done by

.. code:: cpp

   const auto &connection =
     caosdb::connection::ConnectionManager::GetDefaultConnection();
   auto transaction(connection->CreateTransaction());

   transaction->RetrieveById("1231");
   transaction->RetrieveById("1233");
   auto status = transaction->Execute();

A result set can be obtained via
:cpp:any:`GetResultSet`<caosdb::transaction::Transaction::GetResultSet>` which contains the
resulting entities and can, e.g., be checked for length.

Execute queries
---------------

Executing queries works very similar to the retrieval of entities via
ids. 

FIND and SELECT queries
~~~~~~~~~~~~~~~~~~~~~~~

In general, entities can be found using CaosDB’s query language like

.. code:: cpp

  const auto &connection =
      caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("FIND ENTITY WITH id = 1222");
  query_transaction->Execute();
  auto result_set = query_transaction->GetResultSet();
  std::cout << "Found " << result_set.size() 
            << "entity with id="
            <<  result_set.at(0).GetId() << std::endl;

``result_set`` is a (possibly empty) list of entities that can be
inspected as above.

::

   SELECT queries haven't been implemented in the C++ client yet and
   thus cannot be executed from libcaosdb right now. SELECT queries
   will be added in a future release.

COUNT queries
~~~~~~~~~~~~~

COUNT queries are different from FIND or SELECT queries in two ways.
Firstly, they do not return entities but a single number which is why,
secondly, they do not have a result set that could be returned.  
The result of the count is
obtained using the :cpp:any:`GetCountResult<caosdb::transaction::Transaction::GetCountResult>` function:

.. code:: cpp

  const auto &connection =
      caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto query_transaction(connection->CreateTransaction());
  query_transaction->Query("COUNT RECORD person WITH NAME LIKE '*Baggins'");
  query_transaction->Execute();
  std::cout << "Found " << query_transaction->GetCountResult() 
            << "entities."<< std::endl;

Insert, update, and delete entities
-----------------------------------

Insert, update and delete  operations function the same way. The respective 
task is added to a transaction and the transaction is executed.

.. code:: cpp

  const auto &connection =
      caosdb::connection::ConnectionManager::GetDefaultConnection();


  // ######## INSERT ######## 
  // create the entity
  Entity entity;
  entity.SetRole(Role::RECORD_TYPE);
  entity.SetName("RT1");

  // create the transaction, add the task and execute the transaction
  auto insert_transaction(connection->CreateTransaction());
  insert_transaction->InsertEntity(&entity);
  auto insert_status = insert_transaction->Execute();

  const auto &insert_result_set = insert_transaction->GetResultSet();
  // the result is an entity with the new id
  const auto &new_entity = insert_result_set.at(0);
  std::cout << "The newly inserted entity has the id "
            << new_entity.GetId() << std::endl;


  // get the inserted entity
  // RETRIEVE
  auto retrieve_transaction(connection->CreateTransaction());
  retrieve_transaction->RetrieveById(new_entity.GetId());
  retrieve_transaction->Execute();
  // save the entity from the result set in a new variable
  auto update_entity(retrieve_transaction->GetResultSet().at(0));

  // ######## UPDATE ######## 
  // and change it
  update_entity.SetName("RT1-Update");

  // create update transaction
  auto update_transaction(connection->CreateTransaction());
  update_transaction->UpdateEntity(&update_entity);
  auto update_status = update_transaction->Execute();
  // same as with insert transaction, the update transaction returns an entity 
  // with the id
  const auto &updated_entity = update_transaction->GetResultSet().at(0);
  std::cout << "The  entity with the id "
            << update_entity.GetId() << "was updated." << std::endl;

  // ######## DELETE ######## 
  auto delete_transaction(connection->CreateTransaction());
  delete_transaction->DeleteById(updated_entity .GetId());
  auto delete_status = delete_transaction->Execute();

  // again, the delete transaction returns a result set with entities
  // with the ids that where deleted
  const auto &delete_result_set = delete_transaction->GetResultSet();


Up- and Download a file
-----------------------

.. code:: cpp

  const auto &connection =
      caosdb::connection::ConnectionManager::GetDefaultConnection();

  Entity file;
  file.SetRole(Role::FILE);
  file.SetFilePath("test.txt");
  file.SetLocalPath(test_upload_file_1);

  // in order to upload a file, the corresponding entity simply has to be 
  // inserted
  auto insert_transaction(connection->CreateTransaction());
  insert_transaction->InsertEntity(&file);
  insert_transaction->Execute();

  // entity in the result set contains the new id
  const auto &insert_results = insert_transaction->GetResultSet();
  const auto &inserted_file = insert_results.at(0);

  // for the download you need to use the RetrieveAndDownloadFileById task and
  // supply the path where the file shall be stored
  test_download_file = fs::path("test_download_file_delete_me.dat");
  auto download_transaction(connection->CreateTransaction());
  download_transaction->RetrieveAndDownloadFileById(
      inserted_file.GetId(), test_download_file.string());
  download_transaction->ExecuteAsynchronously();
  download_transaction->WaitForIt().GetCode()

  const auto &download_results = download_transaction->GetResultSet();
  const auto &downloaded_file = download_results.at(0);