1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
|
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2014, 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 exectued
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
|