1 ////////////////////////////////////////////////////////////////////////// 2 // 3 // pgAdmin III - PostgreSQL Tools 4 // 5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team 6 // This software is released under the PostgreSQL Licence 7 // 8 // pgQueryThread.h - PostgreSQL threaded query class header 9 // 10 ////////////////////////////////////////////////////////////////////////// 11 12 #ifndef PGQUERYTHREAD_H 13 #define PGQUERYTHREAD_H 14 15 #include "wx/wx.h" 16 #include "wx/event.h" 17 #include "db/pgConn.h" 18 19 // Forward declaration 20 class pgSet; 21 class pgQueryThread; 22 class pgBatchQuery; 23 24 // Support for the IN & INOUT parameters type 25 class pgParam : public wxObject 26 { 27 public: 28 enum 29 { 30 PG_PARAM_IN = 1, 31 PG_PARAM_OUT = 2, 32 PG_PARAM_INOUT = 3, 33 PG_PARAM_VARIADIC = 4, 34 PG_PARAM_TABLE = 5 35 }; 36 37 // Any data 38 // 39 // This constructor won't call the functions - 'htonl' or 'htons' 40 // It will be the responsibility of the caller to take care 41 // to call 'htonl' or 'htons' depending on requirements. 42 // 43 // NOTE: 44 // This data will be owned by pgParam object and will be released. 45 pgParam(Oid _type, void *_val, int _len, short mode = PG_PARAM_IN); 46 47 // wxString data 48 pgParam(Oid _type, wxString *_val, wxMBConv *_conv = NULL, 49 short mode = PG_PARAM_IN); 50 51 ~pgParam(); 52 53 // Returns 0 for text type and 1 for otherwise 54 int GetFormat(); 55 GetType()56 Oid GetType() 57 { 58 return m_type; 59 } GetMode()60 short GetMode() 61 { 62 return m_mode; 63 } 64 65 protected: 66 Oid m_type; 67 void *m_val; 68 int m_len; 69 short m_format; 70 // Modes are required by EnterpriseDB's callable statement 71 short m_mode; 72 73 // Do not allow copy construction and shadow-copy 74 // to avoid ownership 75 // Force to use an pointer pgParam(const pgParam &)76 pgParam(const pgParam &) 77 { 78 wxASSERT(0); 79 } 80 pgParam &operator= (const pgParam &) 81 { 82 wxASSERT(0); 83 return *this; 84 } 85 86 friend class pgConn; 87 friend class pgQueryThread; 88 }; 89 90 WX_DEFINE_ARRAY_PTR(pgParam *, pgParamsArray); 91 92 class pgBatchQuery : public wxObject 93 { 94 public: 95 pgBatchQuery(const wxString &_query, pgParamsArray *_params = NULL, 96 long _eventId = -1, void *_data = NULL, bool _useCallable = false, 97 int _resultToRetrieve = 0) m_query(_query)98 : m_query(_query), m_params(_params), m_eventID(_eventId), m_data(_data), 99 m_useCallable(_useCallable), m_resToRetrieve(_resultToRetrieve), 100 m_returnCode(-1), m_resultSet(NULL), m_rowsInserted(-1), m_insertedOid(-1) 101 { 102 // Do not honour the empty query string 103 wxASSERT(!_query.IsEmpty()); 104 } 105 ~pgBatchQuery(); 106 107 bool Release(); 108 ResultSet()109 pgSet *ResultSet() 110 { 111 return m_resultSet; 112 } 113 ReturnCode()114 int ReturnCode() 115 { 116 return m_returnCode; 117 } 118 GetMessage()119 const wxString &GetMessage() 120 { 121 return m_message; 122 } 123 RowInserted()124 long RowInserted() 125 { 126 return m_rowsInserted; 127 } 128 129 const wxString &GetErrorMessage(); 130 131 protected: 132 wxString m_query; // Query 133 pgParamsArray *m_params; // parameters 134 long m_eventID; // Event ID 135 void *m_data; // Data to be send with event 136 bool m_useCallable; // Use EnterpriseDB callable statement if possible 137 int m_resToRetrieve; // Which result to be retrieved 138 int m_returnCode; // Return code 139 pgSet *m_resultSet; // Result-Set 140 long m_rowsInserted; // No of rows inserted 141 Oid m_insertedOid; // Inserted Oid 142 wxString m_message; // Message generated during query execution 143 pgError m_err; // Error 144 145 private: 146 // Do not allow copy construction and '=' operator (shadow copying) 147 // to avoid ownership of parameters and result-set 148 // 149 // This will force this class to be used as an pointer only. pgBatchQuery(const pgBatchQuery &)150 pgBatchQuery(const pgBatchQuery &) 151 { 152 wxASSERT(0); 153 } 154 pgBatchQuery &operator= (const pgBatchQuery &) 155 { 156 wxASSERT(0); 157 return *this; 158 } 159 160 friend class pgQueryThread; 161 }; 162 WX_DEFINE_ARRAY_PTR(pgBatchQuery *, pgBatchQueryArray); 163 164 class pgQueryThread : public wxThread 165 { 166 public: 167 // For running a single query (Used by few components) 168 pgQueryThread(pgConn *_conn, const wxString &qry, int resultToRetrieve = -1, 169 wxWindow *_caller = 0, long eventId = 0, void *_data = 0); 170 171 // Support for multiple queries support 172 pgQueryThread(pgConn *_conn, wxEvtHandler *_caller = NULL, 173 PQnoticeProcessor _processor = NULL, void *_noticeHandler = NULL); 174 175 ~pgQueryThread(); 176 HasMultipleQueriesSupport()177 bool HasMultipleQueriesSupport() 178 { 179 return m_multiQueries; 180 } 181 SupportCallableStatement()182 bool SupportCallableStatement() 183 { 184 return m_useCallable; 185 } 186 187 void SetEventOnCancellation(bool eventOnCancelled); 188 189 void AddQuery( 190 const wxString &_qry, pgParamsArray *_params = NULL, 191 long _eventId = 0, void *_data = NULL, bool _useCallable = false, 192 int _resultToRetrieve = -1); 193 194 virtual void *Entry(); 195 bool DataValid(int _idx = -1) const 196 { 197 if (_idx == -1) 198 _idx = m_currIndex; 199 return (_idx >= 0 && _idx > m_currIndex ? false : (m_queries[_idx]->m_resultSet != NULL)); 200 } 201 GetConn()202 pgConn *GetConn() 203 { 204 return m_conn; 205 } 206 207 pgSet *DataSet(int _idx = -1) 208 { 209 if (_idx == -1) 210 _idx = m_currIndex; 211 return (_idx >= 0 && _idx > m_currIndex ? NULL : m_queries[_idx]->m_resultSet); 212 } 213 214 int ReturnCode(int _idx = -1) const 215 { 216 if (_idx == -1) 217 _idx = m_currIndex; 218 return (_idx >= 0 && _idx > m_currIndex ? -1 : m_queries[_idx]->m_returnCode); 219 } 220 221 long RowsInserted(int _idx = -1) const 222 { 223 if (_idx == -1) 224 _idx = m_currIndex; 225 return (_idx >= 0 && _idx > m_currIndex ? -1L : m_queries[_idx]->m_rowsInserted); 226 } 227 228 Oid InsertedOid(int _idx = -1) const 229 { 230 if (_idx == -1) 231 _idx = m_currIndex; 232 return (_idx >= 0 && _idx > m_currIndex ? -1L : m_queries[_idx]->m_insertedOid); 233 } 234 CancelExecution()235 inline void CancelExecution() 236 { 237 m_cancelled = true; 238 } 239 GetNumberQueries()240 inline size_t GetNumberQueries() 241 { 242 return m_queries.GetCount(); 243 } 244 QueriesExecuted()245 size_t QueriesExecuted() 246 { 247 return m_currIndex + 1; 248 } 249 250 wxString GetMessagesAndClear(int _idx = -1); 251 void AppendMessage(const wxString &_str); 252 253 int DeleteReleasedQueries(); 254 255 pgError GetResultError(int idx = -1); 256 257 private: 258 int Execute(); 259 int RaiseEvent(int _retval = 0); 260 261 // Queries to be executed 262 pgBatchQueryArray m_queries; 263 // Current running query index 264 int m_currIndex; 265 // Connection object 266 pgConn *m_conn; 267 // Execution cancelled? 268 bool m_cancelled; 269 // Raise events even when cancelled the execution 270 bool m_eventOnCancellation; 271 // Does this thread support multiple queries 272 bool m_multiQueries; 273 // Use EDB callable statement (if available and require) 274 bool m_useCallable; 275 // Is executing a query 276 bool m_executing; 277 // Queries are being accessed at this time 278 wxMutex m_queriesLock; 279 // When one thread is accesing messages, other should not be able to access it 280 wxCriticalSection m_criticalSection; 281 // Event Handler 282 wxEvtHandler *m_caller; 283 // Database server notice-processor 284 PQnoticeProcessor m_processor; 285 // Notice Handler 286 void *m_noticeHandler; 287 288 }; 289 290 #endif 291