1 #ifndef CPPCORE__DBAPI__SIMPLE__SDBAPI_IMPL__HPP 2 #define CPPCORE__DBAPI__SIMPLE__SDBAPI_IMPL__HPP 3 4 /* $Id: sdbapi_impl.hpp 557819 2018-02-21 18:47:17Z satskyse $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Author: Pavel Ivanov 30 * 31 * File Description: 32 * 33 */ 34 35 #include <corelib/ncbiobj.hpp> 36 #include <dbapi/dbapi.hpp> 37 38 #include <dbapi/simple/sdbapi.hpp> 39 40 BEGIN_NCBI_SCOPE 41 42 class CConnHolder; 43 44 class CSDB_UserHandler : public CDB_UserHandler_Exception 45 { 46 public: CSDB_UserHandler(CConnHolder & conn)47 CSDB_UserHandler(CConnHolder& conn) 48 : m_Conn(conn) 49 { } 50 bool HandleMessage(int severity, int msgnum, const string& message); 51 52 private: 53 CConnHolder& m_Conn; 54 }; 55 56 class CConnHolder : public CObject 57 { 58 public: 59 CConnHolder(IConnection* conn, const CSDB_ConnectionParam& params); 60 virtual ~CConnHolder(void); 61 62 IConnection* GetConn(void) const; 63 void AddOpenRef(void); 64 void CloseRef(void); 65 66 const CDB_Exception::SContext& GetContext(void) const; 67 void SetTimeout(const CTimeout& timeout); 68 void ResetTimeout(void); 69 const list<string>& GetPrintOutput(void) const; 70 void ResetPrintOutput(); 71 72 private: 73 CConnHolder(const CConnHolder&); 74 CConnHolder& operator= (const CConnHolder&); 75 76 IConnection* m_Conn; 77 size_t m_DefaultTimeout; 78 bool m_HasCustomTimeout; 79 bool m_ContinueAfterRaiserror; 80 Uint4 m_CntOpen; 81 list<string> m_PrintOutput; 82 CRef<CDB_Exception::SContext> m_Context; 83 CRef<CSDB_UserHandler> m_Handler; 84 CMutex m_Mutex; 85 86 friend class CSDB_UserHandler; 87 }; 88 89 class CDatabaseImpl : public CObject 90 { 91 public: 92 CDatabaseImpl(void); 93 CDatabaseImpl(const CDatabaseImpl& other); 94 ~CDatabaseImpl(void); 95 96 void Connect(const CSDB_ConnectionParam& params); 97 bool IsOpen() const; 98 bool EverConnected() const; 99 void Close(); 100 101 IConnection* GetConnection(void); 102 void SetTimeout(const CTimeout& timeout); 103 void ResetTimeout(void); 104 const list<string>& GetPrintOutput(void) const; 105 void ResetPrintOutput(); 106 107 const CDB_Exception::SContext& GetContext(void) const; 108 109 private: 110 CRef<CConnHolder> m_Conn; 111 bool m_IsOpen; 112 bool m_EverConnected; 113 }; 114 115 116 class CBulkInsertImpl : public CObject 117 { 118 public: 119 CBulkInsertImpl(CDatabaseImpl* db_impl, 120 const string& tableName, 121 int autoflush); 122 ~CBulkInsertImpl(void); 123 124 void SetHints(CTempString hints); 125 void AddHint(IBulkInsert::EHints hint, unsigned int value); 126 void AddOrderHint(CTempString columns); 127 128 void Bind(int col, ESDB_Type type); 129 void EndRow(void); 130 void Complete(void); 131 132 void WriteNull(void); 133 template <class T> 134 void WriteVal(const T& val); 135 136 private: 137 void x_CheckCanWrite(int col); 138 void x_CheckWriteStarted(void); 139 140 const CDB_Exception::SContext& x_GetContext(void) const; 141 142 CRef<CDatabaseImpl> m_DBImpl; 143 IBulkInsert* m_BI; 144 vector<CVariant> m_Cols; 145 int m_Autoflush; 146 int m_RowsWritten; 147 int m_ColsWritten; 148 bool m_WriteStarted; 149 150 CRef<CDB_Exception::SContext> m_Context; 151 }; 152 153 154 class IQueryFieldBasis 155 { 156 public: ~IQueryFieldBasis()157 virtual ~IQueryFieldBasis() { } 158 159 virtual const CVariant* GetValue(void) const = 0; 160 virtual const CDB_Exception::SContext& x_GetContext(void) const = 0; 161 162 virtual CNcbiOstream* GetOStream(size_t blob_size, 163 TBlobOStreamFlags flags) const; 164 virtual CBlobBookmark GetBookmark(void) const; 165 }; 166 167 class CRemoteQFB : public IQueryFieldBasis 168 { 169 public: CRemoteQFB(CQueryImpl & query,unsigned int col_num)170 CRemoteQFB(CQueryImpl& query, unsigned int col_num) 171 : m_Query(query), m_ColNum(col_num) 172 { } 173 174 const CVariant* GetValue(void) const override; 175 const CDB_Exception::SContext& x_GetContext(void) const override; 176 177 CNcbiOstream* GetOStream(size_t blob_size, 178 TBlobOStreamFlags flags) const override; 179 CBlobBookmark GetBookmark(void) const override; 180 181 private: 182 CQueryImpl& m_Query; 183 unsigned int m_ColNum; 184 }; 185 186 class CLocalQFB : public IQueryFieldBasis 187 { 188 public: CLocalQFB(CVariant * value,const CDB_Exception::SContext & context)189 CLocalQFB(CVariant* value, const CDB_Exception::SContext& context) 190 : m_Value(value), m_Context(new CDB_Exception::SContext(context)) 191 { } 192 GetValue(void) const193 const CVariant* GetValue(void) const override 194 { return m_Value.get(); } x_GetContext(void) const195 const CDB_Exception::SContext& x_GetContext(void) const override 196 { return *m_Context; } 197 198 private: 199 unique_ptr<CVariant> m_Value; 200 unique_ptr<CDB_Exception::SContext> m_Context; 201 }; 202 203 class CParamQFB : public CLocalQFB 204 { 205 public: CParamQFB(CVariant * value,const CDB_Exception::SContext & context,ESP_ParamType param_type)206 CParamQFB(CVariant* value, const CDB_Exception::SContext& context, 207 ESP_ParamType param_type) 208 : CLocalQFB(value, context), m_ParamType(param_type) 209 { } 210 GetParamType(void) const211 ESP_ParamType GetParamType(void) const { return m_ParamType; } SetParamType(ESP_ParamType type)212 void SetParamType(ESP_ParamType type) { m_ParamType = type; } 213 214 private: 215 ESP_ParamType m_ParamType; 216 }; 217 218 219 class CQueryFieldImpl : public CObject 220 { 221 public: 222 CQueryFieldImpl(CQueryImpl* q, unsigned int col_num); 223 CQueryFieldImpl(CQueryImpl* q, CVariant* v, ESP_ParamType param_type); 224 225 virtual CRef<CQueryFieldImpl> Detach(void); 226 227 const CVariant* GetValue(void) const; 228 virtual CNcbiIstream& AsIStream(void) const; 229 virtual const vector<unsigned char>& AsVector(void) const; 230 virtual CNcbiOstream& GetOStream(size_t blob_size, 231 TBlobOStreamFlags flags) const; 232 virtual CBlobBookmark GetBookmark(void) const; 233 234 protected: 235 friend class CQueryImpl; 236 237 // Takes ownership of *qf.m_Basis! 238 CQueryFieldImpl(CQueryFieldImpl& qf); 239 240 const CDB_Exception::SContext& x_GetContext(void) const; 241 242 unique_ptr<IQueryFieldBasis> m_Basis; 243 }; 244 245 class CQueryBlobImpl : public CQueryFieldImpl 246 { 247 public: 248 CQueryBlobImpl(CQueryImpl* q, unsigned int col_num); 249 CQueryBlobImpl(CQueryImpl* q, CVariant* v, ESP_ParamType param_type); 250 251 CRef<CQueryFieldImpl> Detach(void) override; 252 253 CNcbiIstream& AsIStream(void) const override; 254 const vector<unsigned char>& AsVector(void) const override; 255 CNcbiOstream& GetOStream(size_t blob_size, 256 TBlobOStreamFlags flags) const override; 257 CBlobBookmark GetBookmark(void) const override; 258 259 private: 260 // Takes ownership of *qb.m_Basis! 261 CQueryBlobImpl(CQueryBlobImpl& qb); 262 263 /// Vector to cache BLOB value 264 mutable vector<unsigned char> m_Vector; 265 /// String to cache BLOB value 266 mutable string m_ValueForStream; 267 /// Stream to cache BLOB value 268 mutable unique_ptr<CNcbiIstrstream> m_IStream; 269 /// Stream to change BLOB value 270 mutable unique_ptr<CNcbiOstream> m_OStream; 271 }; 272 273 struct SQueryRSMetaData : public CObject 274 { 275 typedef map<string, int> TColNumsMap; 276 277 TColNumsMap col_nums; 278 vector<string> col_names; 279 vector<ESDB_Type> col_types; 280 281 CConstRef<CDB_Exception::SContext> exception_context; 282 }; 283 284 class CQueryImpl: public CObject 285 { 286 public: 287 CQueryImpl(CDatabaseImpl* db_impl); 288 ~CQueryImpl(void); 289 290 template <class T> 291 void SetParameter(CTempString name, const T& value, ESDB_Type type, ESP_ParamType param_type); 292 void SetNullParameter(CTempString name, ESDB_Type type, ESP_ParamType param_type); 293 const CQuery::CField& GetParameter(CTempString name); 294 void ClearParameter(CTempString name); 295 void ClearParameters(void); 296 297 void SetSql(CTempString sql); 298 void Execute(const CTimeout& timeout); 299 void ExecuteSP(CTempString sp, const CTimeout& timeout); 300 void Cancel(void); 301 bool HasMoreResultSets(void); 302 void PurgeResults(void); 303 void BeginNewRS(void); 304 void Next(void); 305 void RequireRowCount(unsigned int min_rows, unsigned int max_rows); 306 void VerifyDone(CQuery::EHowMuch how_much = CQuery::eThisResultSet); 307 const CQuery::CRow& GetRow(void) const; 308 const CQuery::CField& GetColumn(const CDBParamVariant& col) const; 309 const CVariant& GetFieldValue(unsigned int col_num); 310 bool IsFinished(CQuery::EHowMuch how_much = CQuery::eThisResultSet) const; 311 312 void SetIgnoreBounds(bool is_ignore); 313 unsigned int GetResultSetNo(void) const; 314 unsigned int GetRowNo(CQuery::EHowMuch how_much = CQuery::eAllResultSets) const; 315 int GetRowCount(void) const; 316 int GetStatus(void) const; 317 unsigned int GetTotalColumns(void) const; 318 string GetColumnName(unsigned int col) const; 319 ESDB_Type GetColumnType(unsigned int col) const; 320 321 CDatabaseImpl* GetDatabase(void) const; 322 IConnection* GetConnection(void); 323 324 const list<string>& GetPrintOutput(void) const; 325 // Historically private, but useful for CQuery's inner classes too. 326 const CDB_Exception::SContext& x_GetContext(void) const; 327 GetMinRowCount(void) const328 unsigned int GetMinRowCount(void) const 329 { return m_MinRowCount; } GetMaxRowCount(void) const330 unsigned int GetMaxRowCount(void) const 331 { return m_MaxRowCount; } 332 333 private: 334 void x_CheckCanWork(bool need_rs = false) const; 335 void x_SetOutParameter(const string& name, const CVariant& value); 336 void x_ClearAllParams(void); 337 void x_CheckRowCount(void); 338 bool x_Fetch(void); 339 void x_InitBeforeExec(void); 340 void x_InitRSFields(void); 341 void x_DetachAllFields(void); 342 void x_Close(void); 343 344 345 typedef map<string, CQuery::CField> TParamsMap; 346 347 CRef<CDatabaseImpl> m_DBImpl; 348 IStatement* m_Stmt; 349 ICallableStatement* m_CallStmt; 350 TParamsMap m_Params; 351 string m_Sql; 352 IResultSet* m_CurRS; 353 bool m_IgnoreBounds; 354 bool m_HasExplicitMode; 355 bool m_RSBeginned; 356 bool m_RSFinished; 357 bool m_Executed; 358 bool m_ReportedWrongRowCount; 359 bool m_IsSP; 360 bool m_RowUnderConstruction; 361 unsigned int m_CurRSNo; 362 unsigned int m_CurRowNo; 363 unsigned int m_CurRelRowNo; 364 unsigned int m_MinRowCount; 365 unsigned int m_MaxRowCount; 366 int m_RowCount; 367 int m_Status; 368 CQuery::CRow m_Row; 369 mutable CRef<CDB_Exception::SContext> m_Context; 370 }; 371 372 373 class CBlobBookmarkImpl : public CObject 374 { 375 public: 376 CBlobBookmarkImpl(CDatabaseImpl* db_impl, I_BlobDescriptor* descr); 377 378 CNcbiOstream& GetOStream(size_t blob_size, TBlobOStreamFlags flags); 379 380 private: 381 const CDB_Exception::SContext& x_GetContext(void) const; 382 383 CRef<CDatabaseImpl> m_DBImpl; 384 unique_ptr<I_BlobDescriptor> m_Descr; 385 unique_ptr<CWStream> m_OStream; 386 }; 387 388 END_NCBI_SCOPE 389 390 #endif // CPPCORE__DBAPI__SIMPLE__SDBAPI_IMPL__HPP 391