MySQL Blog Archive
For the latest blogs go to blogs.oracle.com/mysql
What is new in Connector/C++ 8.0

We are proud to announce that with version 8.0.11 the new MySQL Connector/C++ 8.0 series becomes GA! Connector/C++ 8.0 is your gateway to the new exciting features of MySQL Server 8.0 such as MySQL Document Store. It also lets you perform your usual database tasks in a simpler and more powerful way using new, modern APIs that bring to you the full advantage of modern C++ programming language.

The 8.0 series is a true milestone in the development of Connector/C++. We have not only added new APIs but also completely re-implemented the connector to create good foundation for future innovation and improvements.The new implementation of Connector/C++ is based entirely on the new X Protocol of MySQL Server 8.0 and is highly modular to allow rapid development of new features. For the first time we aligned our APIs with other MySQL connectors. Also, for the first time Connector/C++ is offering a plain C API for code written in C.

New APIs of Connector/C++ 8.0

Up to now Connector/C++ implemented a single API based on JDBC4 standard. While keeping the old API for backward compatibility, the 8.0 series introduces two new APIs that can be used for accessing MySQL database.

  • X DevAPI: a C++ implementation of the new, fluent CRUD API defined for accessing MySQL Document Store and relational data. The same API is also implemented by xshell and other connectors and provides a uniform interface to the MySQL database.
  • XAPI: a new plain C API with functionality similar to that of X DevAPI. This API allows applications written in plain C to have access to the new MySQL features such as Document Store (it might feel strange to have plain C API in a C++ connector but in fact plain C can be seen as a subset of the C++ language; also, placing both APIs in the same connector allows re-using common implementation components).

To give you a feeling of the new APIs, here is a sample code which opens a session, creates a document collection, adds a document to that collection and then lists documents in the collection.

#include <iostream>
#include <mysqlx/xdevapi.h>

using ::std::cout;
using ::std::endl;

int main()
try {
  using namespace ::mysqlx;

  Session sess("user:password@host/schema");
  Collection coll = sess
                    .getDefaultSchema()
                    .createCollection("myCollection", true);

  coll.add(R"({ "name": "foo"; "age": 7 })").execute();

  CollectionFind query = coll
                         .find("age < :age")
                         .fields("name", "age");

  DocResult res = query.bind("age", 18).execute();

  for (DbDoc doc : res)
  {
    cout << "name: " << doc["name"]
         << ", age: " << doc["age"]
         << endl;
  }
}
catch (const mysqlx::Error &err)
{
  cout << "ERROR: " << err << endl;
}

The same thing implemented in plain C, using XAPI, looks as follows (for simplicity, error handling logic is omitted).

#include <stdio.h>
#include <mysqlx/xapi.h>

int main()
{
  int error;
  char err_buff[256];
  mysqlx_result_t *res;

  mysqlx_session_t *sess
    = mysqlx_get_session_from_url(
        "user:password@host/schema",
        err_buff, &error
      );

  mysqlx_schema_t *sch
    = mysqlx_get_schema(sess, "schema", 0);

  error = mysqlx_collection_create(sch, "myCollection");

  mysqlx_collection_t *coll
    = mysqlx_get_collection(sch, "myCollection", 0);

  res = mysqlx_collection_add( coll,
          "{ \"name\": \"foo\"; \"age\": 7 }",
          PARAM_END
        );

  mysqlx_stmt_t *query = mysqlx_collection_find_new(coll);
  error = mysqlx_set_find_criteria(query, "age < :age");

  mysqlx_stmt_bind(query, "age", PARAM_UINT(18), PARAM_END);

  res = mysqlx_execute(query);

  const char *doc;

  while (NULL != (doc = mysqlx_json_fetch_one(res, NULL)))
  {
    printf("%s\n", doc);
  }

  mysqlx_session_close(sess);
}

Note that the choice of the API is done by including appropriate public header: either <mysqlx/xdevapi.h> or <mysqlx/xapi.h>.

Apart from a CRUD style interface for accessing the MySQL Document Store, which is shared with other MySQL connectors, the new APIs give you full access to SQL and relational data, including transactions, parameter binding, row locking, convenient classes for representing query results and more. For example, the following code shows how to execute a plain SQL query against a relational table using X DevAPI. Similar code can be written using XAPI.

Session sess("user:password@host/schema");

SqlStatement query = sess.sql(
  "SELECT ID, Name, Info FROM city"
  "WHERE CountryCode = ? AND Info->'$.Population' > ?"
);

SqlResult res = query.bind("USA", 100000).execute();

Row city;

while ((city = res.fetchOne()))
{
  DbDoc info = city[2];

  cout << "        ID: " << city[0] << endl;
  cout << "      Name: " << city[1] << endl;
  cout << "Population: " << info["Population"] << endl;
  cout << "=================" << endl;
}

The new APIs can be used as a modern replacement for the previous, JDBC based API of Connector/C++ 1.1 and for the CAPI of the MySQL client library. The X DevAPI brings the advantage and power of modern C++ programming with support for language constructs such as iterators, range loops, method chaining, RAII, overloaded operators, custom type conversions etc. The plain C XAPI is also a major re-design of the traditional MySQL CAPI with automatic memory management, better separation of public interface from internal implementation and with functions for accessing the MySQL Document Store. Note however that these new APIs are implemented over X Protocol and for that reason they will not work with older versions of MySQL Server.

For more information check available documentation on MySQL Document Store and X DevAPI User Guide. See also reference documentation for the Connector/C++ implementation of X DevAPI and XAPI reference documentation.

Getting started with Connector/C++ 8.0

Installing Connector/C++ 8.0

To develop applications that use Connector/C++ 8.0 you need the following files

  • Public headers containing declarations for the APIs implemented by the connector.
  • Connector libraries that contain implementation of the APIs. There are actually two libraries shipped with Connector/C++ 8.0 – the main library with base name mysqlcppconn8, implementing the new APIs (X DevAPI and XAPI), and a legacy library with base name mysqlcppconn which is a drop-in replacement for the 1.1 connector library. Both static and shared variants of each library are shipped.

These files are distributed as TGZ or ZIP packages that you can unpack to the location of your choice. There are several options for how to use the connector during compile time and at run-time, all depending on the platform you are working on and whether you want to install connector locally or system-wide. Below is some basic information to get you started. For more details see usage instructions in the reference manual.

Building code which uses Connector/C++ 8.0

Building code that uses Connector/C++ requires correctly setting include path, so that connector’s public headers can be found by the compiler, and passing connector library to the linker invocation. Assuming that Connector/C++ was installed under $MYSQL_CPPCONN_DIR the include path should be set to $MYSQL_CPPCONN_DIR/include (for gcc use -I option, for MSVC the C/C++ > Additional Include Directories  project setting). After that X DevAPI or XAPI declarations can be loaded using #include <mysqlx/xdevapi.h> or #include <mysqlx/xapi.h> directive, respectively.

Note: The X DevAPI uses C++11 language features. For some compilers C++11 must be explicitly enabled. For example gcc needs option -std=c++11 to understand C++11. This is not required for MSVC nor for XAPI code (which is plain C)

Depending on the platform, the shared Connector/C++ library is named:

  • libmysqlcppconn8.so on Unix platforms (soname libmysqlcppconn8.so.1)
  • libmysqlcppconn8.dylib on the OSX platform (link name libmysqlcppconn8.1.dylib)
  • mysqlcppconn8-1-vs14.dll on Windows platforms (with import library vs14/mysqlcppconn8.lib)

You need to add this library to your compiler/linker invocation when building code that uses the connector  (for gcc add -lmysqlcppconn8 to the linker options, for MSVC add vs14/mysqlcppconn8.lib to Linker > Input > Additional Dependencies  setting of your project). You also need to specify path where the connector library can be found (for gcc use -L option, for MSVC Linker > Additional Library Directories  setting). Assuming that Connector/C++ was installed under $MYSQL_CONCPP_DIR the libraries can be found under $MYSQL_CONCPP_DIR/lib on 32-bit platforms and $MYSQL_CONCPP_DIR/lib64 on 64-bit platforms.

Example gcc invocation for building application with sources in app.cc might look as follows (assuming that environment variable MYSQL_CONCPP_DIR is set to the location where Connector/C++ was installed)

$ g++ -std=c++11 -I $MYSQL_CONCPP_DIR/include -L $MYSQL_CONCPP_DIR/lib64 app.cc -lmysqlcppconn8 -o app

Due to ABI incompatiblities between different compiler versions, the code that uses Connector/C++ libraries should be built with the same compiler version as the connector itself. The information about compiler version used to build connector libraries can be found inside BUILDINFO.txt file distributed with the connector. In principle a different version of the compiler can be used provided that it is ABI compatible, but it is difficult to determine what versions of the compiler are ABI compatible with each other.

Running code which uses Connector/C++ 8.0

Code built against Connector/C++ depends on the shared connector library which must be found at run-time by the dynamic linker. It also requires OpenSSL libraries that are used by Connector/C++.  Here are example run-time dependencies shown by ldd for an application built with Connector/C++.

$ ldd ./app
	linux-vdso.so.1 =>  (0x00007ffc5d616000)
	libmysqlcppconn8.so.1 => ./libmysqlcppconn8.so.1 (0x00007f4f642be000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f4f63f95000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f4f63c93000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4f63a7d000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f4f636be000)
	libssl.so.10 => /lib64/libssl.so.10 (0x00007f4f6344c000)
	libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f4f62feb000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4f62dce000)
	/lib64/ld-linux-x86-64.so.2 (0x000055590017d000)
        ...

To be able to run such an application the dynamic linker must be able to find the connector library in its predefined locations. The easiest way of arranging this is to copy the shared connector library to the location of the executable. This method works for any operating system. Otherwise the exact way of registering Connector/C++ libraries with the dynamic linker depends on the operating system.

Note: For platforms such as Windows, that normally do not have OpenSSL libraries available, Connector/C++ packages include these libraries. Putting these libraries next to the connector ones usually ensures that the dynamic linker can find them at run-time.

Note: On Windows the executable will depend on the MSVC 2015 runtime DLLs, that need to be installed on the target system.

Note: Connector/C++ also ships static libraries that can be used to build applications that do not require shared connector libraries to be present on the target system. However, an application linked statically with Connector/C++ will still depend on shared OpenSSL libraries and on MSVC runtime in case of Windows.

In summary

MySQL 8 brings a lot of new, exciting features which allow you to work with your data in new ways, going beyond the traditional SQL paradigm. Connector/C++ 8.0 is a part of this story and it also invites you to exploring new ways of working with MySQL from your C++ or C code. It is a result of a long effort and we are eager to hear about your impressions of the new features we brought to you. Happy coding!