pgadmin3/include/db/pgQueryThread.h
2020-07-07 22:19:12 +05:00

290 lines
6.9 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// pgQueryThread.h - PostgreSQL threaded query class header
//
//////////////////////////////////////////////////////////////////////////
#ifndef PGQUERYTHREAD_H
#define PGQUERYTHREAD_H
#include "wx/wx.h"
#include "wx/event.h"
#include "db/pgConn.h"
// Forward declaration
class pgSet;
class pgQueryThread;
class pgBatchQuery;
// Support for the IN & INOUT parameters type
class pgParam : public wxObject
{
public:
enum
{
PG_PARAM_IN = 1,
PG_PARAM_OUT = 2,
PG_PARAM_INOUT = 3,
PG_PARAM_VARIADIC = 4,
PG_PARAM_TABLE = 5
};
// Any data
//
// This constructor won't call the functions - 'htonl' or 'htons'
// It will be the responsibility of the caller to take care
// to call 'htonl' or 'htons' depending on requirements.
//
// NOTE:
// This data will be owned by pgParam object and will be released.
pgParam(Oid _type, void *_val, int _len, short mode = PG_PARAM_IN);
// wxString data
pgParam(Oid _type, wxString *_val, wxMBConv *_conv = NULL,
short mode = PG_PARAM_IN);
~pgParam();
// Returns 0 for text type and 1 for otherwise
int GetFormat();
Oid GetType()
{
return m_type;
}
short GetMode()
{
return m_mode;
}
protected:
Oid m_type;
void *m_val;
int m_len;
short m_format;
// Modes are required by EnterpriseDB's callable statement
short m_mode;
// Do not allow copy construction and shadow-copy
// to avoid ownership
// Force to use an pointer
pgParam(const pgParam &)
{
wxASSERT(0);
}
pgParam &operator= (const pgParam &)
{
wxASSERT(0);
return *this;
}
friend class pgConn;
friend class pgQueryThread;
};
WX_DEFINE_ARRAY_PTR(pgParam *, pgParamsArray);
class pgBatchQuery : public wxObject
{
public:
pgBatchQuery(const wxString &_query, pgParamsArray *_params = NULL,
long _eventId = -1, void *_data = NULL, bool _useCallable = false,
int _resultToRetrieve = 0)
: m_query(_query), m_params(_params), m_eventID(_eventId), m_data(_data),
m_useCallable(_useCallable), m_resToRetrieve(_resultToRetrieve),
m_returnCode(-1), m_resultSet(NULL), m_rowsInserted(-1), m_insertedOid(-1)
{
// Do not honour the empty query string
wxASSERT(!_query.IsEmpty());
}
~pgBatchQuery();
bool Release();
pgSet *ResultSet()
{
return m_resultSet;
}
int ReturnCode()
{
return m_returnCode;
}
const wxString &GetMessage()
{
return m_message;
}
long RowInserted()
{
return m_rowsInserted;
}
const wxString &GetErrorMessage();
protected:
wxString m_query; // Query
pgParamsArray *m_params; // parameters
long m_eventID; // Event ID
void *m_data; // Data to be send with event
bool m_useCallable; // Use EnterpriseDB callable statement if possible
int m_resToRetrieve; // Which result to be retrieved
int m_returnCode; // Return code
pgSet *m_resultSet; // Result-Set
long m_rowsInserted; // No of rows inserted
Oid m_insertedOid; // Inserted Oid
wxString m_message; // Message generated during query execution
pgError m_err; // Error
private:
// Do not allow copy construction and '=' operator (shadow copying)
// to avoid ownership of parameters and result-set
//
// This will force this class to be used as an pointer only.
pgBatchQuery(const pgBatchQuery &)
{
wxASSERT(0);
}
pgBatchQuery &operator= (const pgBatchQuery &)
{
wxASSERT(0);
return *this;
}
friend class pgQueryThread;
};
WX_DEFINE_ARRAY_PTR(pgBatchQuery *, pgBatchQueryArray);
class pgQueryThread : public wxThread
{
public:
// For running a single query (Used by few components)
pgQueryThread(pgConn *_conn, const wxString &qry, int resultToRetrieve = -1,
wxWindow *_caller = 0, long eventId = 0, void *_data = 0);
// Support for multiple queries support
pgQueryThread(pgConn *_conn, wxEvtHandler *_caller = NULL,
PQnoticeProcessor _processor = NULL, void *_noticeHandler = NULL);
~pgQueryThread();
bool HasMultipleQueriesSupport()
{
return m_multiQueries;
}
bool SupportCallableStatement()
{
return m_useCallable;
}
void SetEventOnCancellation(bool eventOnCancelled);
void AddQuery(
const wxString &_qry, pgParamsArray *_params = NULL,
long _eventId = 0, void *_data = NULL, bool _useCallable = false,
int _resultToRetrieve = -1);
virtual void *Entry();
bool DataValid(int _idx = -1) const
{
if (_idx == -1)
_idx = m_currIndex;
return (_idx >= 0 && _idx > m_currIndex ? false : (m_queries[_idx]->m_resultSet != NULL));
}
pgConn *GetConn()
{
return m_conn;
}
pgSet *DataSet(int _idx = -1)
{
if (_idx == -1)
_idx = m_currIndex;
return (_idx >= 0 && _idx > m_currIndex ? NULL : m_queries[_idx]->m_resultSet);
}
int ReturnCode(int _idx = -1) const
{
if (_idx == -1)
_idx = m_currIndex;
return (_idx >= 0 && _idx > m_currIndex ? -1 : m_queries[_idx]->m_returnCode);
}
long RowsInserted(int _idx = -1) const
{
if (_idx == -1)
_idx = m_currIndex;
return (_idx >= 0 && _idx > m_currIndex ? -1L : m_queries[_idx]->m_rowsInserted);
}
Oid InsertedOid(int _idx = -1) const
{
if (_idx == -1)
_idx = m_currIndex;
return (_idx >= 0 && _idx > m_currIndex ? -1L : m_queries[_idx]->m_insertedOid);
}
inline void CancelExecution()
{
m_cancelled = true;
}
inline size_t GetNumberQueries()
{
return m_queries.GetCount();
}
size_t QueriesExecuted()
{
return m_currIndex + 1;
}
wxString GetMessagesAndClear(int _idx = -1);
void AppendMessage(const wxString &_str);
int DeleteReleasedQueries();
pgError GetResultError(int idx = -1);
private:
int Execute();
int RaiseEvent(int _retval = 0);
// Queries to be executed
pgBatchQueryArray m_queries;
// Current running query index
int m_currIndex;
// Connection object
pgConn *m_conn;
// Execution cancelled?
bool m_cancelled;
// Raise events even when cancelled the execution
bool m_eventOnCancellation;
// Does this thread support multiple queries
bool m_multiQueries;
// Use EDB callable statement (if available and require)
bool m_useCallable;
// Is executing a query
bool m_executing;
// Queries are being accessed at this time
wxMutex m_queriesLock;
// When one thread is accesing messages, other should not be able to access it
wxCriticalSection m_criticalSection;
// Event Handler
wxEvtHandler *m_caller;
// Database server notice-processor
PQnoticeProcessor m_processor;
// Notice Handler
void *m_noticeHandler;
};
#endif