#ifndef QDB_API_QUERY_H
#define QDB_API_QUERY_H

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

/*
 *
 * Official quasardb C API 3.3.0
 * b2792c2 2019-05-07 14:21:19 +0000
 *
 * Copyright (c) 2009-2019, 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

    //! \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_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;
        } payload;
    } qdb_point_result_t;

    //! \ingroup query
    //! \brief The list of rows and columns for the given table
    typedef struct
    {
        //! A null terminated string representing the table name
        qdb_string_t table_name;

        //! An array of null terminated strings representing the returned
        //! columns
        qdb_string_t * columns_names;
        //! The count of returned columns
        qdb_size_t columns_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 rows_count;
    } qdb_table_result_t;

    //! \ingroup query
    //! \brief Holds the result of a query
    typedef struct
    {
        //! An array of tables, may be null if the query returned nothing
        qdb_table_result_t * tables;
        //! The number of tables
        qdb_size_t tables_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
    QDB_API_LINKAGE qdb_error_t qdb_query(qdb_handle_t handle,
                                          const char * query,
                                          qdb_query_result_t ** result);

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

#endif /* QDB_API_QUERY_H */
