/*****
*
* TOra - An Oracle Toolkit for DBA's and developers
* Copyright (C) 2003-2005 Quest Software, Inc
* Portions Copyright (C) 2005 Other Contributors
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation;  only version 2 of
* the License is valid for this program.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*      As a special exception, you have permission to link this program
*      with the Oracle Client libraries and distribute executables, as long
*      as you follow the requirements of the GNU GPL in regard to all of the
*      software in the executable aside from Oracle client libraries.
*
*      Specifically you are not permitted to link this program with the
*      Qt/UNIX, Qt/Windows or Qt Non Commercial products of TrollTech.
*      And you are not permitted to distribute binaries compiled against
*      these libraries without written consent from Quest Software, Inc.
*      Observe that this does not disallow linking to the Qt Free Edition.
*
*      You may link this product with any GPL'd Qt library such as Qt/Free
*
* All trademarks belong to their respective owners.
*
*****/

#ifndef TONOBLOCKQUERY_H
#define TONOBLOCKQUERY_H

#include "config.h"
#include "toconnection.h"
#include "tothread.h"

#include <time.h>

class toResultStats;

/** This is class to be able to run a query in the background without
 * blocking until a response is available from OCI.
 */

class toNoBlockQuery
{
private:
    /** A task to implement running the query.
     */
class queryTask : public toTask
    {
        toNoBlockQuery &Parent;
    public:
        queryTask(toNoBlockQuery &parent)
                : Parent(parent)
        { }
        virtual void run(void);
    };
    friend class queryTask;

    /** This semaphore indicates wether the query is still running.
     */
    toSemaphore Running;
    /** This semaphore indicates wether the child thread should
     * continue reading values.
     */
    toSemaphore Continue;
    /** Lock for all this stuff
     */
    toLock Lock;
    /** Current location that values are being read.
     */
    toQList::iterator CurrentValue;
    /** Values read by the task. This can be changed without holding @ref Lock.
     */
    toQList ReadingValues;
    /** Values ready to be read by client.
     */
    toQList Values;
    /** Indicator if at end of query.
     */
    bool EOQ;
    /** Indicator if to quit reading from query.
     */
    bool Quit;
    /** SQL to execute.
     */
    QString SQL;
    /** Error string if error occurs.
     */
    toConnection::exception Error;
    /** Number of rows processed.
     */
    int Processed;
    /** Parameters to pass to query before execution.
     */
    toQList Param;
    /** Statistics to be used if any.
     */
    toResultStats *Statistics;
    /** Description of result
     */
    toQDescList Description;
    /** When query is executed
     */
    time_t Started;
    /** Query used to run query
     */
    toQuery *Query;
    /** Throw error if any.
     */
    void checkError();
    /** Stop reading query
     */
    void stop();
public:
    /** Create a new query.
     * @param conn Connection to run on.
     * @param sql SQL to execute.
     * @param param Parameters to pass to query.
     * @param statistics Optional statistics widget to update with values from query.
     */
    toNoBlockQuery(toConnection &conn,
                   const QString &sql,
                   const toQList &param,
                   toResultStats *statistics = NULL);
    /** Create a new query.
     * @param conn Connection to run on.
     * @param mode Query mode to execute query in.
     * @param sql SQL to execute.
     * @param param Parameters to pass to query.
     * @param statistics Optional statistics widget to update with values from query.
     */
    toNoBlockQuery(toConnection &conn,
                   toQuery::queryMode mode,
                   const QString &sql,
                   const toQList &param,
                   toResultStats *statistics = NULL);
    virtual ~toNoBlockQuery();

    /** Poll if any result is available.
     * @return True if at least one row is available.
     */
    bool poll(void);

    /** Get description of columns.
     * @return Description of columns list. Don't modify this list.
     */
    toQDescList &describe(void);

    /** Read the next value from the query.
     * @return The next available value.
     */
    toQValue readValue(void);
    /** Read the next value from the query. Don't send NULL as string.
     * @return The next available value.
     */
    toQValue readValueNull(void);

    /** Get the number of rows processed.
     * @return Number of rows processed.
     */
    int rowsProcessed(void);

    /** Check if at end of query.
     * @return True if query is done.
     */
    bool eof(void);
};

#endif
