#ifndef QDB_API_TS_H
#define QDB_API_TS_H

//! \file ts.h
//! \defgroup ts Time series operations
//! \warning Time series are under development. Performance and compatibility
//! are not guaranteed.

/*
 *
 * Official quasardb C API 2.5.0
 * 522fcd7 2018-04-20 17:31:05 +0200
 *
 * Copyright (c) 2009-2018, quasardb SAS
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of quasardb nor the names of its contributors may
 *      be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY QUASARDB AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "client.h"

#ifdef __cplusplus
extern "C"
{
#endif

#pragma pack(push)
#pragma pack(16)

    //! \ingroup ts
    //! \brief A timestamped data with a double-precision floating-point value.
    typedef struct
    {
        //! \brief Timestamp.
        qdb_timespec_t timestamp;
        //! \brief Numeric value.
        double value;
    } qdb_ts_double_point;

    //! \ingroup ts
    //! \brief A timestamped data with a binary content.
    typedef struct
    {
        //! \copydoc qdb_ts_double_point::timestamp
        qdb_timespec_t timestamp;
        //! Pointer to data.
        const void * content;
        //! Length, in bytes, of the data pointed to by \ref content.
        qdb_size_t content_length;
    } qdb_ts_blob_point;

    //! \ingroup ts
    //! \brief A timestamped data with a signed 64-bit integer value.
    typedef struct
    {
        //! \brief Timestamp.
        qdb_timespec_t timestamp;
        //! \brief Numeric value.
        qdb_int_t value;
    } qdb_ts_int64_point;

    //! \ingroup ts
    //! \brief A timestamped data with a signed 64-bit integer value.
    typedef struct
    {
        //! \brief Timestamp.
        qdb_timespec_t timestamp;
        //! \brief Numeric value.
        qdb_timespec_t value;
    } qdb_ts_timestamp_point;

    //! \ingroup ts
    //! \brief Time interval.
    typedef struct
    {
        //! Beginning of the interval, inclusive.
        qdb_timespec_t begin;
        //! End of the interval, exclusive.
        qdb_timespec_t end;
    } qdb_ts_range_t;

    //! \ingroup ts
    //! \brief Filter for a given time interval
    typedef enum qdb_ts_filter_type_t
    {
        //! No filtering. Return all results.
        qdb_ts_filter_none = 0,
        //! Return only unique (distinct) values.
        //! \warning Not implemented
        qdb_ts_filter_unique = 1,
        //! Return a sample of the given size.
        //! \warning Not implemented
        qdb_ts_filter_sample = 2,
        //! Return datapoints that are included in the range.
        //! \warning Not implemented
        qdb_ts_filter_double_inside_range = 3,
        //! Return datapoints that are not included in the range.
        //! \warning Not implemented
        qdb_ts_filter_double_outside_range = 4
    } qdb_ts_filter_type_t;

    //! \ingroup ts
    //! \brief A filter
    typedef struct
    {
        //! Filter the interval
        qdb_ts_filter_type_t type;

        //! Optional filter parameters
        union {

            struct
            {
                qdb_size_t size;
            } sample;

            struct
            {
                double min;
                double max;
            } double_range;

        } params;

    } qdb_ts_filter_t;

    //! \ingroup ts
    //! \brief A filtered time interval.
    typedef struct
    {
        qdb_ts_range_t range;
        qdb_ts_filter_t filter;
    } qdb_ts_filtered_range_t;

    //! \ingroup ts
    //! \brief Types of aggregations that can be computed on a time series.
    typedef enum qdb_ts_aggregation_type_t
    {
        qdb_agg_first = 0, //!< The first (earliest) data point.
        qdb_agg_last = 1,  //!< The last (latest) data point.
        qdb_agg_min = 2,   //!< The data point with the smallest value.
        qdb_agg_max = 3,   //!< The data point with the largest value.
        qdb_agg_arithmetic_mean = 4, //!< The arithmetic mean (average).
        qdb_agg_harmonic_mean = 5,   //!< The harmonic mean.
        qdb_agg_geometric_mean = 6,  //!< The geometric mean.
        qdb_agg_quadratic_mean = 7,  //!< The quadratic mean (root mean squaer).
        qdb_agg_count = 8,           //!< The number of data points.
        qdb_agg_sum = 9,             //!< The sum of values.
        qdb_agg_sum_of_squares = 10, //!< The sum of squares of values.
        qdb_agg_spread = 11,
        //!< The difference between the maximum value and the minimum value.
        qdb_agg_sample_variance = 12,     //!< The sample variance.
        qdb_agg_sample_stddev = 13,       //!< The sample standard deviation.
        qdb_agg_population_variance = 14, //!< The population variance.
        qdb_agg_population_stddev = 15, //!< The population standard deviation.
        qdb_agg_abs_min = 16,  //!< The value with the smallest absolute value.
        qdb_agg_abs_max = 17,  //!< The value with the largest absolute value.
        qdb_agg_product = 18,  //!< The product.
        qdb_agg_skewness = 19, //!< The skewness (shape parameter).
        qdb_agg_kurtosis = 20  //!< The kurtosis (shape parameter).
    } qdb_ts_aggregation_type_t;

    //! \ingroup ts
    //! \brief Aggregation input and result for columns of blobs.
    typedef struct
    {
        //! \copydoc qdb_ts_double_aggregation_t::type
        qdb_ts_aggregation_type_t type;
        //! \copydoc qdb_ts_double_aggregation_t::filtered_range
        qdb_ts_filtered_range_t filtered_range;
        //! \copydoc qdb_ts_double_aggregation_t::count
        qdb_size_t count;
        //! \copydoc qdb_ts_double_aggregation_t::result
        qdb_ts_blob_point result;
    } qdb_ts_blob_aggregation_t;

    //! \ingroup ts
    //! \brief Aggregation input and result for columns of numeric
    //! floating-point values.
    typedef struct
    {
        //! The type of the aggregation to perform.
        qdb_ts_aggregation_type_t type;
        //! The time interval on which the aggregation should be executed.
        qdb_ts_filtered_range_t filtered_range;
        //! \brief If applicable, the number of datapoints on which aggregation
        //! has been computed.
        qdb_size_t count;
        //! \brief The result of the aggregation.
        qdb_ts_double_point result;
    } qdb_ts_double_aggregation_t;

    //! \ingroup ts
    //! \brief Aggregation input and result for columns of numeric integer
    //! values.
    typedef struct
    {
        //! The type of the aggregation to perform.
        qdb_ts_aggregation_type_t type;
        //! The time interval on which the aggregation should be executed.
        qdb_ts_filtered_range_t filtered_range;
        //! \brief If applicable, the number of datapoints on which aggregation
        //! has been computed.
        qdb_size_t count;
        //! \brief The result of the aggregation.
        qdb_ts_int64_point result;
        double exact_result;
    } qdb_ts_int64_aggregation_t;

    //! \ingroup ts
    //! \brief Aggregation input and result for columns of numeric integer
    //! values.
    typedef struct
    {
        //! The type of the aggregation to perform.
        qdb_ts_aggregation_type_t type;
        //! The time interval on which the aggregation should be executed.
        qdb_ts_filtered_range_t filtered_range;
        //! \brief If applicable, the number of datapoints on which aggregation
        //! has been computed.
        qdb_size_t count;
        //! \brief The result of the aggregation.
        qdb_ts_timestamp_point result;
    } qdb_ts_timestamp_aggregation_t;

    //! \ingroup ts
    //! \brief Types of time series columns.
    typedef enum qdb_ts_column_type_t
    {
        qdb_ts_column_uninitialized = -1,
        qdb_ts_column_double = 0,   //!< Column of floating point values.
        qdb_ts_column_blob = 1,     //!< Column of binary data.
        qdb_ts_column_int64 = 2,    //!< Column of signed 64-bit integer values.
        qdb_ts_column_timestamp = 3 //!< Column of signed 64-bit integer values.
    } qdb_ts_column_type_t;

    //! \ingroup ts
    //! \brief Description of a time series column.
    typedef struct
    {
        //! \brief A pointer to a null-terminated UTF-8 string representing the
        //! name of the column.
        const char * name;
        //! The type of the column.
        qdb_ts_column_type_t type;
    } qdb_ts_column_info_t;

    typedef enum qdb_duration_t
    {
        qdb_d_millisecond = 1,
        qdb_d_second = qdb_d_millisecond * 1000,
        qdb_d_minute = qdb_d_second * 60,
        qdb_d_hour = qdb_d_minute * 60,
        qdb_d_day = qdb_d_hour * 24,
        qdb_d_week = qdb_d_day * 7,

        qdb_d_default_shard_size = qdb_d_day
    } qdb_duration_t;

#pragma pack(pop)

    //! \ingroup ts
    //! \brief Creates a time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param shard_size_ms A duration representing the time-span of a single
    //! shard (bucket) of the time series, in milliseconds.
    //!
    //! \param columns An array of column descriptions that are to be
    //! added to the time series.
    //!
    //! \param column_count The number of columns to add.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_create(qdb_handle_t handle,
                  const char * alias,
                  qdb_uint_t shard_size_ms,
                  const qdb_ts_column_info_t * columns,
                  qdb_size_t column_count);

    //! \ingroup ts
    //! \brief Appends columns to an existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param columns An array of column descriptions that are to be
    //! added to the time series.
    //!
    //! \param column_count The number of columns to append.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_insert_columns(qdb_handle_t handle,
                          const char * alias,
                          const qdb_ts_column_info_t * columns,
                          qdb_size_t column_count);

    //! \ingroup ts
    //! \brief Returns all the columns of a time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param[out] columns A pointer to an array that will contain descriptions
    //! of columns present in the time series.
    //!
    //! \param[out] column_count A pointer to an integer that will receive the
    //! number of columns.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_list_columns(qdb_handle_t handle,
                        const char * alias,
                        qdb_ts_column_info_t ** columns,
                        qdb_size_t * column_count);

    //! \ingroup ts
    //! \brief Inserts blob points in a time series column.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param values An array of data points to be inserted.
    //!
    //! \param count The number of data points to insert.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_blob_insert(qdb_handle_t handle,
                       const char * alias,
                       const char * column,
                       const qdb_ts_blob_point * values,
                       qdb_size_t count);

    //! \ingroup ts
    //! \brief Inserts double points in a time series.
    //!
    //! Time series are distributed across the cluster and support efficient
    //! insertion anywhere within the time series as well as efficient lookup
    //! based on time.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param values An array of data points to be inserted.
    //!
    //! \param count The number of data points to insert.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_double_insert(qdb_handle_t handle,
                         const char * alias,
                         const char * column,
                         const qdb_ts_double_point * values,
                         qdb_size_t count);

    //! \ingroup ts
    //! \brief Inserts int64 points in a time series.
    //!
    //! Time series are distributed across the cluster and support efficient
    //! insertion anywhere within the time series as well as efficient lookup
    //! based on time.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param values An array of data points to be inserted.
    //!
    //! \param count The number of data points to insert.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_int64_insert(qdb_handle_t handle,
                        const char * alias,
                        const char * column,
                        const qdb_ts_int64_point * values,
                        qdb_size_t count);

    //! \ingroup ts
    //! \brief Inserts timestamp points in a time series.
    //!
    //! Time series are distributed across the cluster and support efficient
    //! insertion anywhere within the time series as well as efficient lookup
    //! based on time.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param values An array of data points to be inserted.
    //!
    //! \param count The number of data points to insert.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_timestamp_insert(qdb_handle_t handle,
                            const char * alias,
                            const char * column,
                            const qdb_ts_timestamp_point * values,
                            qdb_size_t count);

    //! \ingroup ts
    //! \brief Retrieves doubles in the specified range of the time series
    //! column.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param ranges An array of ranges (intervals) for which data
    //! should be retrieved.
    //!
    //! \param range_count The number of ranges.
    //!
    //! \param[out] points A pointer to an array that will contain data points
    //! from all given ranges.
    //!
    //! \param[out] point_count A pointer to an integer that will receive the
    //! number of returned points.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_double_get_ranges(qdb_handle_t handle,
                             const char * alias,
                             const char * column,
                             const qdb_ts_filtered_range_t * ranges,
                             qdb_size_t range_count,
                             qdb_ts_double_point ** points,
                             qdb_size_t * point_count);

    //! \ingroup ts
    //! \brief Retrieves 64-bit integers in the specified range of the time
    //! series column.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param ranges An array of ranges (intervals) for which data
    //! should be retrieved.
    //!
    //! \param range_count The number of ranges.
    //!
    //! \param[out] points A pointer to an array that will contain data points
    //! from all given ranges.
    //!
    //! \param[out] point_count A pointer to an integer that will receive the
    //! number of returned points.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_int64_get_ranges(qdb_handle_t handle,
                            const char * alias,
                            const char * column,
                            const qdb_ts_filtered_range_t * ranges,
                            qdb_size_t range_count,
                            qdb_ts_int64_point ** points,
                            qdb_size_t * point_count);

    //! \ingroup ts
    //! \brief Retrieves timestamps in the specified range of the time
    //! series column.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param ranges An array of ranges (intervals) for which data
    //! should be retrieved.
    //!
    //! \param range_count The number of ranges.
    //!
    //! \param[out] points A pointer to an array that will contain data points
    //! from all given ranges.
    //!
    //! \param[out] point_count A pointer to an integer that will receive the
    //! number of returned points.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_timestamp_get_ranges(qdb_handle_t handle,
                                const char * alias,
                                const char * column,
                                const qdb_ts_filtered_range_t * ranges,
                                qdb_size_t range_count,
                                qdb_ts_timestamp_point ** points,
                                qdb_size_t * point_count);

    //! \ingroup ts
    //! \brief Aggregate a sub-part of a blob column of the time series.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param[in,out] aggregations An array of structures representing the
    //! aggregations to compute and their results.
    //!
    //! \param aggregation_count The number of elements in the aggregations
    //! array.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_ts_aggregation_type_t
    //! \see \ref qdb_release
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_blob_aggregate(qdb_handle_t handle,
                          const char * alias,
                          const char * column,
                          qdb_ts_blob_aggregation_t * aggregations,
                          qdb_size_t aggregation_count);

    //! \ingroup ts
    //! \brief Aggregate a sub-part of the double column of the time series.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param[in,out] aggregations An array of structures representing the
    //! aggregations to compute and their results.
    //!
    //! \param aggregation_count The number of elements in the aggregations
    //! array.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_ts_aggregation_type_t
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_double_aggregate(qdb_handle_t handle,
                            const char * alias,
                            const char * column,
                            qdb_ts_double_aggregation_t * aggregations,
                            qdb_size_t aggregation_count);

    //! \ingroup ts
    //! \brief Aggregate a sub-part of the int64 column of the time series.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param[in,out] aggregations An array of structures representing the
    //! aggregations to compute and their results.
    //!
    //! \param aggregation_count The number of elements in the aggregations
    //! array.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_ts_aggregation_type_t
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_int64_aggregate(qdb_handle_t handle,
                           const char * alias,
                           const char * column,
                           qdb_ts_int64_aggregation_t * aggregations,
                           qdb_size_t aggregation_count);

    //! \ingroup ts
    //! \brief Aggregate a sub-part of the timestamp column of the time series.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param[in,out] aggregations An array of structures representing the
    //! aggregations to compute and their results.
    //!
    //! \param aggregation_count The number of elements in the aggregations
    //! array.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_ts_aggregation_type_t
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_timestamp_aggregate(qdb_handle_t handle,
                               const char * alias,
                               const char * column,
                               qdb_ts_timestamp_aggregation_t * aggregations,
                               qdb_size_t aggregation_count);

    //! \ingroup ts
    //! \brief Retrieves blobs in the specified range of the time series column.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param ranges An array of ranges (intervals) for which data
    //! should be retrieved.
    //!
    //! \param range_count The number of ranges.
    //!
    //! \param[out] points A pointer to an array that will contain data points
    //! from all given ranges.
    //!
    //! \param[out] point_count A pointer to an integer that will receive the
    //! number of returned points.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_blob_get_ranges(qdb_handle_t handle,
                           const char * alias,
                           const char * column,
                           const qdb_ts_filtered_range_t * ranges,
                           qdb_size_t range_count,
                           qdb_ts_blob_point ** points,
                           qdb_size_t * point_count);

    //! \ingroup ts
    //! \brief Erase all points in the specified range (left inclusive).
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param column A pointer to a null-terminated UTF-8 string representing
    //! the name of the column to work on.
    //!
    //! \param ranges An array of ranges (intervals) for which data
    //! should be erased.
    //!
    //! \param range_count The number of ranges.
    //!
    //! \param[out] erased_count A pointer to an integer that will receive the
    //!                          number of erased points.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_erase_ranges(qdb_handle_t handle,
                        const char * alias,
                        const char * column,
                        const qdb_ts_filtered_range_t * ranges,
                        qdb_size_t range_count,
                        qdb_uint_t * erased_count);

    //! \ingroup ts
    //! \typedef qdb_local_table_t
    //! \brief An opaque local table structure used for bulk insertions
    typedef struct qdb_local_table_internal * qdb_local_table_t;

    //! \ingroup ts
    //! \brief Initialize a local table for bulk insertion in time series.
    //!
    //! It is an error to call this function on a non existing time series.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the time series.
    //!
    //! \param columns An array of column descriptions to which
    //! data will be inserted.
    //!
    //! \param column_count The number of columns.
    //!
    //! \param[out] table A pointer to a local table that will be initialized if
    //! the function returns successfully.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_local_table_init(qdb_handle_t handle,
                            const char * alias,
                            const qdb_ts_column_info_t * columns,
                            qdb_size_t column_count,
                            qdb_local_table_t * table);

    //! \ingroup ts
    //! \brief Set a value in the current row in a column of doubles indicated
    //! by the given index.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column in which the value
    //! should be set. The index is based on the order of
    //! columns in the call to \ref qdb_ts_local_table_init used to
    //! initialize table.
    //!
    //! \param value A value to be set in the chosen column in the current row.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t qdb_ts_row_set_double(qdb_local_table_t table,
                                                      qdb_size_t column_index,
                                                      double value);

    //! \ingroup ts
    //! \brief Set a value in the current row in a column of integers indicated
    //! by the given index.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column in which the value
    //! should be set. The index is based on the order of
    //! columns in the call to \ref qdb_ts_local_table_init used to
    //! initialize table.
    //!
    //! \param value A value to be set in the chosen column in the current row.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE
    qdb_error_t qdb_ts_row_set_int64(qdb_local_table_t table,
                                     qdb_size_t column_index,
                                     qdb_int_t value);

    //! \ingroup ts
    //! \brief Set a value in the current row in a column of timestamps
    //! indicated by the given index.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column in which the value
    //! should be set. The index is based on the order of
    //! columns in the call to \ref qdb_ts_local_table_init used to
    //! initialize table.
    //!
    //! \param value A pointer to the value to be set in the chosen column in
    //! the current row.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE
    qdb_error_t qdb_ts_row_set_timestamp(qdb_local_table_t table,
                                         qdb_size_t column_index,
                                         const qdb_timespec_t * value);

    //! \ingroup ts
    //! \brief Set a value in the current row in a column of blobs indicated by
    //!        the given index, copy data.
    //!
    //! The data will be copied and kept alive until the following \ref
    //! qdb_ts_push call returns.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column in which the value
    //! should be set. The index is based on the order of columns in the call to
    //! \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \param content A pointer to the data to be set in the chosen column in
    //! the current row.
    //!
    //! \param content_length Length, in bytes, of the data pointed to by \p
    //! content.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t qdb_ts_row_set_blob(qdb_local_table_t table,
                                                    qdb_size_t column_index,
                                                    const void * content,
                                                    qdb_size_t content_length);

    //! \ingroup ts
    //! \brief Set a value in the current row in a column of blobs indicated by
    //!        the given index without copying data.
    //!
    //! The data will NOT be copied and the user must ensure that the buffer
    //! pointed by \p content is kept alive until the end of the corresponding
    //! call to \ref qdb_ts_push.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column in which the value
    //! should be set. The index is based on the order of columns in the call to
    //! \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \param content A pointer to the data to be set in the chosen column in
    //! the current row. The pointed data must be kept alive until the following
    //! \ref qdb_ts_push call returns.
    //!
    //! \param content_length Length, in bytes, of the data pointed to by \p
    //! content.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \note The data pointed to by \p content must be kept alive until the
    //!       following \ref qdb_ts_push call returns.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_row_set_blob_no_copy(qdb_local_table_t table,
                                qdb_size_t column_index,
                                const void * content,
                                qdb_size_t content_length);

    //! \ingroup ts
    //! \brief Append current row to the outcoming data buffer.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param timestamp The timestamp of all data points in the row to append.
    //!
    //! \param[out] row_index A pointer to an integer that will receive the
    //! index of the currently appended row. The index is counted since the call
    //! to \ref qdb_ts_local_table_init. The pointer may be null.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_table_row_append(qdb_local_table_t table,
                            const qdb_timespec_t * timestamp,
                            qdb_size_t * row_index);

    //! \ingroup ts
    //! \brief Push all the appended rows to the database.
    //!
    //! All the rows that were appended using qdb_ts_table_row_append since the
    //! last call to \ref qdb_ts_push or \ref qdb_ts_local_table_init will be
    //! pushed.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t qdb_ts_push(qdb_local_table_t table);

    //! \ingroup ts
    //! \brief Retrieves blob data from the current row at the specified
    //! column.
    //!
    //! The retrieved data will be the copy of the internal data stored in \ref
    //! qdb_local_table_t, so the user must ensure to call \ref qdb_release when
    //! she/he no longer needs it in order to clean up the memory.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column from which the
    //! value should be retrieved. The index is based on the order of columns in
    //! the call to \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_invalid_iterator when \ref qdb_ts_table_get_ranges has not
    //! been called before calling this function.
    //!
    //! \param[out] content A non-null pointer to a variable that will hold the
    //! retrieved data.
    //!
    //! \param[out] content_length A non-null pointer to a variable that will
    //! hold the size of the retrieved data.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    //!
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_row_get_blob(qdb_local_table_t table,
                        qdb_size_t column_index,
                        const void ** content,
                        qdb_size_t * content_length);

    //! \ingroup ts
    //! \brief Retrieves blob data from the current row at the specified
    //! column without performing copy of data internal to data.
    //!
    //! The retrieved data will be valid only until the next call of \ref
    //! qdb_ts_table_get_ranges on the same \ref qdb_local_table_t or until the
    //! deallocation thereof. If you want to keep the retrieved data for a
    //! longer time, you may call \ref qdb_ts_row_get_blob instead or copy the
    //! data yourself.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column from which the
    //! value should be retrieved. The index is based on the order of columns in
    //! the call to \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_invalid_iterator when \ref qdb_ts_table_get_ranges has not
    //! been called before calling this function.
    //!
    //! \param[out] content A non-null pointer to a variable that will hold the
    //! retrieved data.
    //!
    //! \param[out] content_length A non-null pointer to a variable that will
    //! hold the size of the retrieved data.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    //!
    //! \see \ref qdb_ts_table_get_ranges
    //! \see \ref qdb_ts_row_get_blob
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_row_get_blob_no_copy(qdb_local_table_t table,
                                qdb_size_t column_index,
                                const void ** content,
                                qdb_size_t * content_length);

    //! \ingroup ts
    //! \brief Retrieves double value from the current row at the specified
    //! column.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column from which the
    //! value should be retrieved. The index is based on the order of columns in
    //! the call to \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \param[out] value A non-null pointer to a double that will hold the
    //! retrieved value.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_invalid_iterator when \ref qdb_ts_table_get_ranges has not
    //! been called before calling this function.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t qdb_ts_row_get_double(qdb_local_table_t table,
                                                      qdb_size_t column_index,
                                                      double * value);

    //! \ingroup ts
    //! \brief Retrieves signed 64-bit integer value from the current row at the
    //! specified column.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column from which the
    //! value should be retrieved. The index is based on the order of columns in
    //! the call to \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \param[out] value A non-null pointer to a signed 64-bit integer that
    //! will hold the retrieved value.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_invalid_iterator when \ref qdb_ts_table_get_ranges has not
    //! been called before calling this function.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE
    qdb_error_t qdb_ts_row_get_int64(qdb_local_table_t table,
                                     qdb_size_t column_index,
                                     qdb_int_t * value);

    //! \ingroup ts
    //! \brief Retrieves timestamp value from the current row at the specified
    //! column.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param column_index A zero-based index of the column from which the
    //! value should be retrieved. The index is based on the order of columns in
    //! the call to \ref qdb_ts_local_table_init used to initialize table.
    //!
    //! \param[out] value A non-null pointer to a timestamp that will hold the
    //! retrieved value.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_invalid_iterator when \ref qdb_ts_table_get_ranges has not
    //! been called before calling this function.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE
    qdb_error_t qdb_ts_row_get_timestamp(qdb_local_table_t table,
                                         qdb_size_t column_index,
                                         qdb_timespec_t * value);

    //! \ingroup ts
    //! \brief Fetch data and advance to the next row.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param[out] timestamp A non-null pointer to a variable that will hold a
    //! timestamp for the fetched row.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_iterator_end when there are no more rows in the specified
    //! ranges.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_table_next_row(qdb_local_table_t table, qdb_timespec_t * timestamp);

    //! \ingroup ts
    //! \brief Retrieve all the specified rows from the database.
    //!
    //! \param table A valid local table previously initialized by
    //! \ref qdb_ts_local_table_init.
    //!
    //! \param ranges An array of ranges (intervals) for which data
    //! should be retrieved.
    //!
    //! \param range_count The number of ranges.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure. Returns
    //! \ref qdb_e_iterator_end when there are no more rows in the specified
    //! ranges.
    //!
    //! \warning This function is still under development. Performance and
    //!          compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_ts_table_get_ranges(qdb_local_table_t table,
                            const qdb_ts_filtered_range_t * ranges,
                            qdb_size_t range_count);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif
