C++ Native API

Dependencies

  • Java 8+
  • Maven 3.5+
  • Flex
  • Bison 2.7+
  • Boost 1.56+
  • OpenSSL 1.0+
  • GCC 5.5.0+

Installation From Source Code

Install CPP Dependencies

  • MAC

    1. Install Bison :Bison 2.3 is preinstalled on OSX, but this version is outdated, and we need a newer version.

      When building Thrift with Bison 2.3, the following error would be shown in the build output: invalid directive: '%code'

      In such a case, please update Bison:

      brew install bison
      brew link bison --force
      

      Then, you need to tell the OS where the new bison is.

      For Bash users:

      echo 'export PATH="/usr/local/opt/bison/bin:$PATH"' >> ~/.bash_profile
      

      For zsh users:

      echo 'export PATH="/usr/local/opt/bison/bin:$PATH"' >> ~/.zshrc
      
    2. Install Boost :Please make sure a relative new version of Boost is ready on your machine. If no Boost available, install the latest version of Boost:

      brew install boost
      brew link boost
      
    3. OpenSSL :Make sure the Openssl libraries has been installed on your Mac. The default Openssl include file search path is “/usr/local/opt/openssl/include”.

      If Openssl header files can not be found when building Thrift, please add option-Dopenssl.include.dir="".

  • Ubuntu 20

    To install all dependencies, run:

    sudo apt-get install gcc-9 g++-9 libstdc++-9-dev bison flex libboost-all-dev libssl-dev zlib1g-dev
    
  • CentOS 7.x

    Some packages can be installed using Yum:

    sudo yum install bison flex openssl-devel
    

    The version of gcc and boost installed by yum is too low, therefore you should compile or download these binary packages by yourself.

  • Windows

    1. Building environment

      • Install MS Visual Studio(recommend 2019 version): remember to install Visual Studio C/C++ IDE and compiler(supporting CMake, Clang, MinGW).
      • Download and install CMake .
    2. Download and install Flex & Bison

      • Download Win_Flex_Bison .
      • After downloading, please rename the executables to flex.exe and bison.exe and add the directory containing them to the PATH environment variable.
    3. Install Boost

      • Download Boost .
      • Then build Boost by executing bootstrap.bat and b2.exe.
    4. Install OpenSSL

Compile

You can download the source code from the IoTDB Website or clone the GIT repository:

git clone https://github.com/apache/iotdb.git

The default dev branch is the master branch, If you want to use a released version (e.g. 0.13.3 or 1.2.0), be sure to check out the corresponding tag:

git checkout v0.13.3

(Please note that we are using a Go compatible naming schema for our release tags, which prefixes the version by a v)

Under the root path of iotdb:

  • Mac & Linux:

    mvn package -P compile-cpp -pl example/client-cpp-example -am -DskipTest
    
  • Windows:

    mvn package -P compile-cpp -pl iotdb-client/client-cpp,iotdb-core/datanode,example/client-cpp-example -am -Dcmake.generator="your cmake generator" -Dboost.include.dir=${your boost header folder} -Dboost.library.dir=${your boost lib (stage) folder} -DskipTests
    
    • When building the client-cpp project, use the -Dcmake.generator="" option to specify a Cmake generator. E.g. -Dcmake.generator="Visual Studio 16 2019" (cmake --help shows a long list of supported Cmake generators.)
    • To help CMake find your Boost libraries on windows, you should also append -DboostIncludeDir="C:\Program Files (x86)\boost_1_78_0" -DboostLibraryDir="C:\Program Files (x86)\boost_1_78_0\stage\lib" to your mvn build command. ``

As soon as the compilation finishes successfully, the packaged zip file will be placed under client-cpp/target/client-cpp-1.3.0-SNAPSHOT-cpp-${os}.zip

Native APIs

Here we demonstrate the most commonly used interfaces and their parameters in the Native API:

Initialization

  • Open a Session:

    void open(); 
    
  • Open a session, with a parameter controlling if RPC compression should be used:

    void open(bool enableRPCCompression); 
    

    Notice: The RPC compression setting of the client is required to match that of the IoTDB server

  • Close a session:

    void close(); 
    

Data Definition Interface (DDL)

Database Management

  • Create database:
void setStorageGroup(const std::string &storageGroupId);
  • Delete one or several databases:
void deleteStorageGroup(const std::string &storageGroup);
void deleteStorageGroups(const std::vector<std::string> &storageGroups);

Timeseries Management

  • Create one or multiple timeseries:
void createTimeseries(const std::string &path, TSDataType::TSDataType dataType, TSEncoding::TSEncoding encoding,
                          CompressionType::CompressionType compressor);
                          
void createMultiTimeseries(const std::vector<std::string> &paths,
                           const std::vector<TSDataType::TSDataType> &dataTypes,
                           const std::vector<TSEncoding::TSEncoding> &encodings,
                           const std::vector<CompressionType::CompressionType> &compressors,
                           std::vector<std::map<std::string, std::string>> *propsList,
                           std::vector<std::map<std::string, std::string>> *tagsList,
                           std::vector<std::map<std::string, std::string>> *attributesList,
                           std::vector<std::string> *measurementAliasList);
  • Create aligned timeseries:
void createAlignedTimeseries(const std::string &deviceId,
                             const std::vector<std::string> &measurements,
                             const std::vector<TSDataType::TSDataType> &dataTypes,
                             const std::vector<TSEncoding::TSEncoding> &encodings,
                             const std::vector<CompressionType::CompressionType> &compressors);
  • Delete one or several timeseries:
void deleteTimeseries(const std::string &path);
void deleteTimeseries(const std::vector<std::string> &paths);
  • Check whether a specific timeseries exists:
bool checkTimeseriesExists(const std::string &path);

Schema Template

  • Create a schema template:
void createSchemaTemplate(const Template &templ);
  • Set the schema template named templateName at path prefixPath:
void setSchemaTemplate(const std::string &template_name, const std::string &prefix_path);
  • Unset the schema template:
void unsetSchemaTemplate(const std::string &prefix_path, const std::string &template_name);
  • After a schema template was created, you can edit the template with following functions:
// Add aligned measurements to a template
void addAlignedMeasurementsInTemplate(const std::string &template_name,
                                      const std::vector<std::string> &measurements,
                                      const std::vector<TSDataType::TSDataType> &dataTypes,
                                      const std::vector<TSEncoding::TSEncoding> &encodings,
                                      const std::vector<CompressionType::CompressionType> &compressors);

// Add one aligned measurement to a template
void addAlignedMeasurementsInTemplate(const std::string &template_name,
                                      const std::string &measurement,
                                      TSDataType::TSDataType dataType,
                                      TSEncoding::TSEncoding encoding,
                                      CompressionType::CompressionType compressor);

// Add unaligned measurements to a template
void addUnalignedMeasurementsInTemplate(const std::string &template_name,
                                        const std::vector<std::string> &measurements,
                                        const std::vector<TSDataType::TSDataType> &dataTypes,
                                        const std::vector<TSEncoding::TSEncoding> &encodings,
                                        const std::vector<CompressionType::CompressionType> &compressors);

// Add one unaligned measurement to a template
void addUnalignedMeasurementsInTemplate(const std::string &template_name,
                                        const std::string &measurement,
                                        TSDataType::TSDataType dataType,
                                        TSEncoding::TSEncoding encoding,
                                        CompressionType::CompressionType compressor);

// Delete a node in template and its children
void deleteNodeInTemplate(const std::string &template_name, const std::string &path);
  • You can query schema templates with these APIs:
// Return the amount of measurements inside a template
int countMeasurementsInTemplate(const std::string &template_name);

// Return true if path points to a measurement, otherwise returne false
bool isMeasurementInTemplate(const std::string &template_name, const std::string &path);

// Return true if path exists in template, otherwise return false
bool isPathExistInTemplate(const std::string &template_name, const std::string &path);

// Return all measurements paths inside template
std::vector<std::string> showMeasurementsInTemplate(const std::string &template_name);

// Return all measurements paths under the designated patter inside template
std::vector<std::string> showMeasurementsInTemplate(const std::string &template_name, const std::string &pattern);

Data Manipulation Interface (DMI)

Insert

  • Insert one record, which contains multiple measurement value of a given device and timestamp:
void insertRecord(const std::string &deviceId, 
                  int64_t time, 
                  const std::vector<std::string> &measurements,
                  const std::vector<char *> &values);
  • Insert multiple Records for multiple devices (With type info in the typesList parameter the server doesn't need to do type inference, which results in better performance):
void insertRecords(const std::vector<std::string> &deviceIds,
                   const std::vector<int64_t> &times,
                   const std::vector<std::vector<std::string>> &measurementsList,
                   const std::vector<std::vector<char *>> &valuesList);
  • Insert multiple Records for the same device:
void insertRecordsOfOneDevice(const std::string &deviceId,
                              std::vector<int64_t> &times,
                              std::vector<std::vector<std::string>> &measurementsList,
                              std::vector<std::vector<char *>> &valuesList);

All of the above versions require the server to figure out the data-types of each value, which comes with quite a performance-cost, therefore all of the above are also available in a version without type-inference:

void insertRecord(const std::string &deviceId, 
                  int64_t time, 
                  const std::vector<std::string> &measurements,
                  const std::vector<TSDataType::TSDataType> &types,
                  const std::vector<std::string> &values);


void insertRecords(const std::vector<std::string> &deviceIds,
                   const std::vector<int64_t> &times,
                   const std::vector<std::vector<std::string>> &measurementsList,
                   const std::vector<std::vector<TSDataType::TSDataType>> &typesList,
                   const std::vector<std::vector<std::string>> &valuesList);


void insertRecordsOfOneDevice(const std::string &deviceId,
                              std::vector<int64_t> &times,
                              std::vector<std::vector<std::string>> &measurementsList,
                              std::vector<std::vector<TSDataType::TSDataType>> &typesList,
                              const std::vector<std::vector<std::string>> &valuesList);

For even better performance, it is recommended to use Tablets to help improve write efficiency.

  • Insert a Tablet,which inserts multiple rows of data for a given device. Each row has the same structure:
    • Better write performance
    • Support null values: Fill the null value with any value, and then mark the null value via BitMap
void insertTablet(Tablet &tablet);
  • Insert multiple Tablets
void insertTablets(std::unordered_map<std::string, Tablet *> &tablets);

Insert data into Aligned Timeseries

The insertion of aligned timeseries is performed by functions such as insertAlignedXXX however semantically they align to the non-aligned versions of the previous chapter:

    void insertAlignedRecord(const std::string &deviceId,
                             int64_t time, 
                             const std::vector<std::string> &measurements,
                             const std::vector<std::string> &values);

    void insertAlignedRecord(const std::string &deviceId, 
                             int64_t time, 
                             const std::vector<std::string> &measurements,
                             const std::vector<TSDataType::TSDataType> &types,
                             const std::vector<char *> &values);

    void insertAlignedRecords(const std::vector<std::string> &deviceIds,
                              const std::vector<int64_t> &times,
                              const std::vector<std::vector<std::string>> &measurementsList,
                              const std::vector<std::vector<std::string>> &valuesList);

    void insertAlignedRecords(const std::vector<std::string> &deviceIds,
                              const std::vector<int64_t> &times,
                              const std::vector<std::vector<std::string>> &measurementsList,
                              const std::vector<std::vector<TSDataType::TSDataType>> &typesList,
                              const std::vector<std::vector<char *>> &valuesList);

    void insertAlignedRecordsOfOneDevice(const std::string &deviceId,
                                         std::vector<int64_t> &times,
                                         std::vector<std::vector<std::string>> &measurementsList,
                                         std::vector<std::vector<TSDataType::TSDataType>> &typesList,
                                         std::vector<std::vector<char *>> &valuesList);

    void insertAlignedRecordsOfOneDevice(const std::string &deviceId,
                                         std::vector<int64_t> &times,
                                         std::vector<std::vector<std::string>> &measurementsList,
                                         std::vector<std::vector<TSDataType::TSDataType>> &typesList,
                                         std::vector<std::vector<char *>> &valuesList,
                                         bool sorted);

    void insertAlignedTablet(Tablet &tablet);

    void insertAlignedTablet(Tablet &tablet, 
                             bool sorted);

    void insertAlignedTablets(std::unordered_map<std::string, Tablet *> &tablets, 
                              bool sorted = false);

Delete

  • Delete data in a time range of one or several timeseries
void deleteData(const std::string &path, int64_t endTime);
void deleteData(const std::vector<std::string> &paths, int64_t endTime);
void deleteData(const std::vector<std::string> &paths, int64_t startTime, int64_t endTime);

IoTDB-SQL Interface

  • Execute query statement

Query statements return data.

unique_ptr<SessionDataSet> executeQueryStatement(const std::string &sql);

Non-Query statements don't return data (Delete, Create, ... statements)

  • Execute non query statement
void executeNonQueryStatement(const std::string &sql);

Examples

The sample code for using these interfaces is located in:

  • example/client-cpp-example/src/SessionExample.cpp
  • example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp

As soon as the compilation finishes, the example project will be located at example/client-cpp-example/target

FAQ

on Mac

If errors occur when compiling thrift source code, try to downgrade your xcode-commandline from 12 to 11.5

see https://stackoverflow.com/questions/63592445/ld-unsupported-tapi-file-type-tapi-tbd-in-yaml-file/65518087#65518087

on Windows

When Building Thrift and downloading packages via “wget”, a possible annoying issue may occur with error message looks like:

Failed to delete cached file C:\Users\Administrator\.m2\repository\.cache\download-maven-plugin\index.ser

Possible fixes:

  • Try to delete the ".m2\repository.cache" directory and try again.
  • Add “<skipCache>true</skipCache>” configuration to the download-maven-plugin maven phase that complains this error.