#ifndef QDB_API_QUERY_H
#define QDB_API_QUERY_H

//! \file query.h
//! \defgroup query Query related functions

/*
 *
 * Official quasardb C API 3.11.0master
 * 993f0695b 2020-10-23 11:06:50 +0200
 *
 * Copyright (c) 2009-2020, quasardb SAS. All rights reserved.
 * 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 "ts.h"

#ifdef __cplusplus
extern "C"
{
#endif

    //! \ingroup query
    //! \brief Retrieves all entries' aliases that match the specified find
    //! query.
    //!
    //! For the complete grammar, please refer to the documentation.
    //!
    //! Queries are transactional.
    //!
    //! The complexity of this function is dependent on the complexity of the
    //! query.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param query A pointer to a null-terminated UTF-8 string representing
    //! the query to perform.
    //!
    //! \param[out] aliases A pointer to an array of null-terminated UTF-8
    //! string that will list the aliases of the entries matching the query.
    //!
    //! \param[out] alias_count A pointer to an integer that will receive the
    //! number of returned aliases.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_release
    QDB_API_LINKAGE qdb_error_t qdb_query_find(qdb_handle_t handle,
                                               const char * query,
                                               const char *** aliases,
                                               size_t * alias_count);

    //! \ingroup query
    //! \brief The type of a result
    typedef enum qdb_query_result_value_type_t
    {
        qdb_query_result_none = -1,
        qdb_query_result_double = 0,
        qdb_query_result_blob = 1,
        qdb_query_result_int64 = 2,
        qdb_query_result_timestamp = 3,
        qdb_query_result_count = 4,
        qdb_query_result_string = 5,
        qdb_query_result_symbol = 6
    } qdb_query_result_value_type_t;

    /* explicit packing will prevent some incompatibility cases */
#pragma pack(push)
#pragma pack(8)
    //! \ingroup query
    //! \brief A variadic structure holding the result type as well as the
    //! result value
    typedef struct
    {
        qdb_query_result_value_type_t type;

        union
        {
            struct
            {
                double value;
            } double_;

            struct
            {
                qdb_int_t value;
            } int64_;

            struct
            {
                const void * content;
                qdb_size_t content_length;
            } blob;

            struct
            {
                qdb_timespec_t value;
            } timestamp;

            struct
            {
                qdb_size_t value;
            } count;

            struct
            {
                const char * content;
                qdb_size_t content_length;
            } string;

            struct
            {
                const char * content;
                qdb_size_t content_length;
            } symbol;
        } payload;
    } qdb_point_result_t;

    //! \ingroup query
    //! \brief Holds the result of a query
    typedef struct
    {
        //! An array of null terminated strings representing the returned
        //! columns
        qdb_string_t * column_names;

        //! The count of returned columns
        qdb_size_t column_count;

        //! A two dimensional array of rows, values are acceded as such:
        //!  rows[row_index][col_index]
        qdb_point_result_t ** rows;

        //! The number of returned rows
        qdb_size_t row_count;

        //! The number of scanned points, for information purposes
        //! The actual number of scanned points may be greater
        qdb_size_t scanned_point_count;

        //! An optional, detailed error message about the query failure
        qdb_string_t error_message;
    } qdb_query_result_t;

#pragma pack(pop)

    //! \ingroup query
    //! \brief Run the provided query and creates a table directory with the
    //! results.
    //!
    //! For the complete grammar, please refer to the documentation.
    //!
    //! Queries are transactional.
    //!
    //! The complexity of this function is dependent on the complexity of the
    //! query.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param query A pointer to a null-terminated UTF-8 string representing
    //! the query to perform.
    //!
    //! \param[out] result A pointer to a pointer of qdb_query_result_t that
    //! will receive the results. It must be released later with qdb_release.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_release, \ref qdb_option_set_client_max_parallelism
    QDB_API_LINKAGE qdb_error_t qdb_query(qdb_handle_t handle,
                                          const char * query,
                                          qdb_query_result_t ** result);

    //! \ingroup query
    //! \brief Holds a column of an experimental query
    //!
    //! \warning This structure is still under development. Compatibility is not
    //! guaranteed.
    typedef struct
    {
        //! The column name
        qdb_string_t name;

        //! The column values type
        qdb_ts_column_type_t type;

        //! The column values
        union
        {
            qdb_blob_t * blobs;
            qdb_string_t * strings;
            qdb_timespec_t * timestamps;
            qdb_int_t * ints;
            double * doubles;
        } data;
    } qdb_query_experimental_column_t;

    //! \ingroup query
    //! \brief Holds the result of an experimental query
    //!
    //! \warning This structure is still under development. Compatibility is not
    //! guaranteed.
    typedef struct
    {
        //! An array containing the table columns
        qdb_query_experimental_column_t * columns;

        //! The count of returned columns
        qdb_size_t column_count;

        //! The number of returned rows
        qdb_size_t row_count;
    } qdb_query_experimental_result_t;

    //! \ingroup query
    //! \brief Run the provided query to return a table.
    //!
    //! Currently only supports querying some columns of a timeseries.
    //!
    //! Queries are transactional.
    //!
    //! The complexity of this function is dependent on the complexity of the
    //! query.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param query A pointer to a null-terminated UTF-8 string representing
    //! the query to perform.
    //!
    //! \param[out] result A pointer to a pointer of qdb_query_result_t that
    //! will receive the results. It must be released later with qdb_release.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_release
    //!
    //! \warning This function is still under development. Performance and
    //! compatibility are not guaranteed.
    QDB_API_LINKAGE qdb_error_t
    qdb_query_experimental(qdb_handle_t handle,
                           const char * query,
                           qdb_query_experimental_result_t ** result);

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

#endif /* QDB_API_QUERY_H */
