1 #ifndef DBAPI_DRIVER___PUBLIC__HPP
2 #define DBAPI_DRIVER___PUBLIC__HPP
3 
4 /* $Id: public.hpp 626337 2021-02-25 18:42:32Z ivanov $
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:  Vladimir Soussov
30  *
31  * File Description:  Data Server public interfaces
32  *
33  */
34 
35 #include <corelib/plugin_manager.hpp>
36 #include <dbapi/driver/interfaces.hpp>
37 
38 
39 // Visual Studio 2013 and 2015 overreact on deprecated methods
40 #if defined(_MSC_VER) && _MSC_VER < 1920
41     #pragma warning(push)
42     #pragma warning(disable : 4996)
43 #endif
44 
45 
46 /** @addtogroup DbPubInterfaces
47  *
48  * @{
49  */
50 
51 
52 BEGIN_NCBI_SCOPE
53 
54 NCBI_DECLARE_INTERFACE_VERSION(I_DriverContext,  "xdbapi", 14, 0, 0);
55 
56 
57 namespace impl
58 {
59     class CDriverContext;
60     class CConnection;
61     class CCommand;
62 }
63 
64 
65 class CAutoTrans;
66 template <class I> class CInterfaceHook;
67 
68 
69 class NCBI_DBAPIDRIVER_EXPORT CDB_Connection
70     : public I_Connection, public IBalanceable
71 {
72 public:
73     /// @brief
74     /// Check out if connection is alive.
75     ///
76     /// This function doesn't ping the server,
77     /// it just checks the status of connection which was set by the last
78     /// i/o operation.
79     ///
80     /// @return
81     ///   - true if connection is alive
82     ///   - false in other case.
83     virtual bool IsAlive();
84 
85     // These methods:  LangCmd(), RPC(), BCPIn(), Cursor() and SendDataCmd()
86     // create and return a "command" object, register it for later use with
87     // this (and only this!) connection.
88     // On error, an exception will be thrown (they never return NULL!).
89     // It is the user's responsibility to delete the returned "command" object.
90 
91     /// Make language command
92     virtual CDB_LangCmd*     LangCmd(const string& lang_query);
93     /// Make remote procedure call command
94     virtual CDB_RPCCmd*      RPC(const string& rpc_name);
95     /// Make "bulk copy in" command
96     virtual CDB_BCPInCmd*    BCPIn(const string& table_name);
97     /// Make cursor command
98     virtual CDB_CursorCmd*   Cursor(const string& cursor_name,
99                                     const string& query,
100                                     unsigned int  batch_size);
Cursor(const string & cursor_name,const string & query)101     CDB_CursorCmd* Cursor(const string& cursor_name,
102                           const string& query)
103     {
104         return Cursor(cursor_name, query, 1);
105     }
106 
107     /// Make "send-data" command
108     /// @brief
109     ///   Create send-data command.
110     ///
111     /// @param desc
112     ///   Lob descriptor.
113     /// @param data_size
114     ///   Maximal data size.
115     /// @param log_it
116     ///   Log LOB operation if this value is set to true.
117     /// @param discard_results
118     ///   Discard all resultsets that might be returned from server
119     ///   if this value is set to true.
120     ///
121     /// @return
122     ///   Newly created send-data object.
123     ///
124     /// @sa SendData
125     virtual CDB_SendDataCmd* SendDataCmd(I_BlobDescriptor& desc,
126                                          size_t            data_size,
127                                          bool              log_it = true,
128                                          bool              discard_results = true);
129 
130     /// @brief
131     ///   Shortcut to send text and image to the server without using the
132     ///   "Send-data" command (SendDataCmd)
133     ///
134     /// @param desc
135     ///   Lob descriptor.
136     /// @param lob
137     ///   Large object -- [N]TEXT, IMAGE, [N]VARCHAR(MAX), or VARBINARY(MAX).
138     /// @param log_it
139     ///   Log LOB operation if this value is set to true.
140     ///
141     /// @return
142     ///   - true on success.
143     ///
144     /// @sa
145     ///   SendDataCmd
146     virtual bool SendData(I_BlobDescriptor& desc, CDB_Stream& lob,
147                           bool log_it = true);
148 
149     /// @brief
150     ///   Set database name
151     ///
152     /// @param name
153     ///   Database name
154     void SetDatabaseName(const string& name);
155 
156     /// @brief
157     /// Reset the connection to the "ready" state (cancel all active commands)
158     ///
159     /// @return
160     ///   - true on success.
161     virtual bool Refresh();
162 
163     /// @brief
164     ///   Get the server name.
165     ///
166     /// @return
167     ///   Server/Service name.
168     virtual const string& ServerName() const;
169 
170     /// @brief
171     ///   Get the host.
172     ///
173     /// @return
174     ///   host ip.
175     virtual Uint4 Host() const;
176 
177     /// @brief
178     ///   Get the port.
179     ///
180     /// @return
181     ///   port.
182     virtual Uint2 Port() const;
183 
184     /// @brief
185     ///   Get the user user.
186     ///
187     /// @return
188     ///   User name.
189     virtual const string& UserName() const;
190 
191     /// @brief
192     ///   Get the  password.
193     ///
194     /// @return
195     ///   Password value.
196     virtual const string& Password() const;
197 
198     /// @brief
199     ///   Get the database name.
200     ///
201     /// @return
202     ///   Database name.
203     virtual const string& DatabaseName(void) const;
204 
205     /// @brief
206     /// Get the bitmask for the connection mode (BCP, secure login, ...)
207     ///
208     /// @return
209     ///  bitmask for the connection mode (BCP, secure login, ...)
210     virtual I_DriverContext::TConnectionMode ConnectMode() const;
211 
212     /// @brief
213     ///   Check if this connection is a reusable one
214     ///
215     /// @return
216     ///   - true if this connection is a reusable one.
217     virtual bool IsReusable() const;
218 
219     /// Indicate how many times (if at all) this connection has been
220     /// previously used.
221     unsigned int GetReuseCount() const;
222 
223     /// @brief
224     ///   Find out which connection pool this connection belongs to
225     ///
226     /// @return
227     ///   connection pool
228     virtual const string& PoolName() const;
229 
230     /// @brief
231     ///   Get pointer to the driver context
232     ///
233     /// @return
234     ///   pointer to the driver context
235     virtual I_DriverContext* Context() const;
236 
237     /// @brief
238     ///   Put the message handler into message handler stack
239     ///
240     /// @param h
241     ///   Error message handler.
242     /// @param ownership
243     ///   If set to eNoOwnership, it is user's responsibility to unregister
244     ///   and delete the error message handler.
245     ///   If set to eTakeOwnership, then DBAPI will take ownership of the
246     ///   error message handler and delete it itself.
247     ///
248     /// @sa
249     ///   PopMsgHandler
250     virtual void PushMsgHandler(CDB_UserHandler* h,
251                                 EOwnership ownership = eNoOwnership);
252 
253     /// @brief
254     ///   Remove the message handler (and all above it) from the stack
255     ///
256     /// @param h
257     ///   Error message handler.
258     /// @sa
259     ///   PushMsgHandler
260     virtual void PopMsgHandler(CDB_UserHandler* h);
261 
262     /// @brief
263     ///   Set new result-processor.
264     ///
265     /// @param rp
266     ///   New result-processor.
267     ///
268     /// @return
269     ///   Old result-processor
270     virtual CDB_ResultProcessor* SetResultProcessor(CDB_ResultProcessor* rp);
271 
272     /// Destructor
273     virtual ~CDB_Connection();
274 
275     /// Abort the connection
276     ///
277     /// @return
278     ///  TRUE - if succeeded, FALSE if not
279     ///
280     /// @note
281     ///   Attention: it is not recommended to use this method unless you
282     ///   absolutely have to.  The expected implementation is - close
283     ///   underlying file descriptor[s] without destroing any objects
284     ///   associated with a connection.
285     ///
286     /// @sa
287     ///   Close
288     virtual bool Abort();
289 
290     ///  Close an open connection.
291     ///  This method will return connection (if it is created as reusable) to
292     ///  its connection pool
293     ///
294     /// @return
295     ///  TRUE - if succeeded, FALSE if not
296     ///
297     /// @sa
298     ///   Abort, I_DriverContext::Connect
299     virtual bool Close(void);
300 
301     /// @brief
302     ///   Set connection timeout.
303     ///
304     /// This timeout limits how long each query or the like can take.
305     /// @param nof_secs
306     ///   Number of seconds.  If "nof_secs" is zero or is "too big"
307     ///   (depends on the underlying DB API), then set the timeout to infinite.
308     /// @sa GetTimeout, SetCancelTimeout, I_DriverContext::SetTimeout, I_DriverContext::SetLoginTimeout
309     virtual void SetTimeout(size_t nof_secs);
310 
311     /// Set timeout for command cancellation and connection closing
312     ///
313     /// This timeout limits how long to wait for the server to acknowledge
314     /// requests to cancel a query gracefully or close a connection gracefully
315     /// before pulling the plug.
316     /// @sa GetCancelTimeout, SetTimeout, I_DriverContext::SetTimeout, I_DriverContext::SetLoginTimeout
317     virtual void SetCancelTimeout(size_t nof_secs);
318 
319     /// Get connection timeout.
320     ///
321     /// This timeout limits how long each query or the like can take.
322     /// @sa SetTimeout, GetCancelTimeout, I_DriverContext::GetTimeout, I_DriverContext::GetLoginTimeout
323     size_t GetTimeout(void) const;
324 
325     /// Get timeout for command cancellation and connection closing
326     ///
327     /// This timeout limits how long to wait for the server to acknowledge
328     /// requests to cancel a query gracefully or close a connection gracefully
329     /// before pulling the plug.
330     /// @sa SetCancelTimeout, GetTimeout, I_DriverContext::GetTimeout, I_DriverContext::GetLoginTimeout
331     size_t GetCancelTimeout(void) const;
332 
333     /// Get interface for extra features that could be implemented in the driver.
334     virtual I_ConnectionExtra& GetExtraFeatures(void);
335 
336     virtual string GetDriverName(void) const;
337 
HasTransaction(void) const338     bool HasTransaction(void) const
339     {
340         return m_HasTransaction;
341     }
342 
343 public:
344     // Deprecated legacy methods.
345     // CXX-601
346 
347     /// @deprecated
348 #ifndef NCBI_UNDEPRECATE__DBAPI_OLD_CONNECTION
349     NCBI_DEPRECATED
350 #endif
LangCmd(const string & lang_query,unsigned int)351     CDB_LangCmd* LangCmd(const string& lang_query, unsigned int /*unused*/)
352     {
353         return LangCmd(lang_query);
354     }
355     /// @deprecated
356 #ifndef NCBI_UNDEPRECATE__DBAPI_OLD_CONNECTION
357     NCBI_DEPRECATED
358 #endif
RPC(const string & rpc_name,unsigned int)359     CDB_RPCCmd* RPC(const string& rpc_name, unsigned int /*unused*/)
360     {
361         return RPC(rpc_name);
362     }
363     /// @deprecated
364 #ifndef NCBI_UNDEPRECATE__DBAPI_OLD_CONNECTION
365     NCBI_DEPRECATED
366 #endif
BCPIn(const string & table_name,unsigned int)367     CDB_BCPInCmd* BCPIn(const string& table_name, unsigned int /*unused*/)
368     {
369         return BCPIn(table_name);
370     }
371     /// @deprecated
372 #ifndef NCBI_UNDEPRECATE__DBAPI_OLD_CONNECTION
373     NCBI_DEPRECATED
374 #endif
Cursor(const string & cursor_name,const string & query,unsigned int,unsigned int batch_size)375     CDB_CursorCmd* Cursor(const string& cursor_name,
376                           const string& query,
377                           unsigned int /*unused*/,
378                           unsigned int  batch_size)
379     {
380         return Cursor(cursor_name, query, batch_size);
381     }
382 
383     void FinishOpening(void);
384 
385 private:
386     impl::CConnection* m_ConnImpl;
387     bool               m_HasTransaction;
388 
389     CDB_Connection(impl::CConnection* c);
390 
391     // Prohibit default- and copy- constructors, and assignment
392     CDB_Connection();
393     CDB_Connection& operator= (const CDB_Connection&);
394     CDB_Connection(const CDB_Connection&);
395 
ReleaseImpl(void)396     void ReleaseImpl(void)
397     {
398         m_ConnImpl = NULL;;
399     }
400 
401     bool x_IsAlive(void);
402 
403     // The constructor should be called by "I_DriverContext" only!
404     friend class impl::CDriverContext;
405     friend class CAutoTrans;
406     friend class CInterfaceHook<CDB_Connection>;
407 };
408 
409 
410 class NCBI_DBAPIDRIVER_EXPORT CDB_Result : public I_Result
411 {
412 public:
413     /// @brief
414     ///   Get type of the result
415     ///
416     /// @return
417     ///   Result type
418     virtual EDB_ResType ResultType() const;
419 
420     /// Get meta-information about rows in resultset.
421     virtual const CDBParams& GetDefineParams(void) const;
422 
423     /// Get # of items (columns) in the result
424     /// @brief
425     ///   Get # of items (columns) in the result.
426     ///
427     /// @return
428     ///   Number of items (columns) in the result.
429     virtual unsigned int NofItems() const;
430 
431     /// @brief
432     ///   Get name of a result item.
433     ///
434     /// @param item_num
435     ///   Number of item, starting from 0.
436     ///
437     /// @return
438     ///   NULL if "item_num" >= NofItems(), otherwise item name.
439     virtual const char* ItemName(unsigned int item_num) const;
440 
441     /// @brief
442     ///   Get size (in bytes) of a result item.
443     ///
444     /// @param item_num
445     ///   Number of item, starting from 0.
446     ///
447     /// @return
448     ///   Return zero if "item_num" >= NofItems().
449     virtual size_t ItemMaxSize(unsigned int item_num) const;
450 
451     /// @brief
452     ///   Get datatype of a result item.
453     ///
454     /// @param item_num
455     ///   Number of item, starting from 0.
456     ///
457     /// @return
458     ///   Return 'eDB_UnsupportedType' if "item_num" >= NofItems().
459     virtual EDB_Type ItemDataType(unsigned int item_num) const;
460 
461     /// @brief
462     ///   Fetch next row
463     ///
464     /// @return
465     ///   - true if a record was fetched.
466     ///   - false if no more record can be fetched.
467     virtual bool Fetch();
468 
469     /// @brief
470     ///   Return current item number we can retrieve (0,1,...)
471     ///
472     /// @return
473     ///   Return current item number we can retrieve (0,1,...)
474     ///   Return "-1" if no more items left (or available) to read.
475     virtual int CurrentItemNo() const;
476 
477     /// @brief
478     ///   Return number of columns in the recordset.
479     ///
480     /// @return
481     ///   number of columns in the recordset.
482     virtual int GetColumnNum(void) const;
483 
484     /// @brief
485     ///   Get a result item (you can use either GetItem or ReadItem).
486     ///
487     /// @param item_buf
488     ///   If "item_buf" is not NULL, then use "*item_buf" (its type should be
489     ///   compatible with the type of retrieved item!) to retrieve the item to;
490     ///   otherwise allocate new "CDB_Object".
491     ///   If the existing "item_buf" has a BLOB type (CDB_Image, CDB_Text,
492     ///   CDB_VarBinaryMax, or CDB_VarCharMax), the value will be *appended*
493     ///   to the "item_buf" by default (policy == eAppendLOB).
494     ///
495     /// @param policy
496     ///   Data retrieval policy. If policy == eAppendLOB *and* "item_buf" has a
497     ///   BLOB type (CDB_Image, CDB_Text, CDB_VarBinaryMax, or CDB_VarCharMax),
498     ///   data will be *appended* to the end of previously assigned data.
499     ///   Otherwise (policy == eAssignLOB or "item_buf" has some other type),
500     ///   the new value will be *assigned* to the "item_buf" object.
501     ///
502     /// @return
503     ///   a result item
504     ///
505     /// @sa
506     ///   ReadItem, SkipItem
507     virtual CDB_Object* GetItem(CDB_Object* item_buf = 0, EGetItem policy = eAppendLOB);
508 
509     /// @brief
510     ///   Read a result item body (for BLOB columns, mostly).
511     ///   Throw an exception on any error.
512     ///
513     /// @param buffer
514     ///   Buffer to fill with data.
515     /// @param buffer_size
516     ///   Buffere size.
517     /// @param is_null
518     ///   Set "*is_null" to TRUE if the item is <NULL>.
519     ///
520     /// @return
521     ///   number of successfully read bytes.
522     ///
523     /// @sa
524     ///   GetItem, SkipItem
525     virtual size_t ReadItem(void* buffer, size_t buffer_size,
526                             bool* is_null = 0);
527 
528     /// @brief
529     ///   Get a descriptor for a BLOB column (for SendData).
530     ///
531     /// @return
532     ///   Return NULL if this result doesn't (or can't) have a BLOB descriptor.
533     ///
534     /// @note
535     ///   You need to call ReadItem (maybe even with buffer_size == 0)
536     ///   before calling this method!
537     /// @deprecated
538     ///   Please use CDB_BlobDescriptor instead.
539     /// @sa
540     ///   CDB_BlobDescriptor
541     NCBI_DEPRECATED
542     virtual I_BlobDescriptor* GetBlobDescriptor();
543 
544     /// @brief
545     /// Skip result item
546     ///
547     /// @return
548     ///   TRUE on success.
549     ///
550     /// @sa
551     ///   GetItem, ReadItem
552     virtual bool SkipItem();
553 
554     /// Destructor
555     virtual ~CDB_Result();
556 
557 private:
GetIResultPtr(void) const558     impl::CResult* GetIResultPtr(void) const
559     {
560         return m_ResImpl;
561     }
GetIResult(void) const562     impl::CResult& GetIResult(void) const
563     {
564         _ASSERT(m_ResImpl);
565         return *m_ResImpl;
566     }
567 
ReleaseImpl(void)568     void ReleaseImpl(void)
569     {
570         m_ResImpl = NULL;;
571     }
572 
573 private:
574     impl::CResult* m_ResImpl;
575 
576     CDB_Result(impl::CResult* r);
577 
578     // Prohibit default- and copy- constructors, and assignment
579     CDB_Result& operator= (const CDB_Result&);
580     CDB_Result(const CDB_Result&);
581     CDB_Result(void);
582 
583     // The constructor should be called by "I_***Cmd" only!
584     friend class impl::CConnection;
585     friend class impl::CCommand;
586     friend class CInterfaceHook<CDB_Result>;
587 };
588 
589 
590 
591 class NCBI_DBAPIDRIVER_EXPORT CDB_LangCmd : public I_LangCmd
592 {
593 public:
594     /// Add more text to the language command
595     /// @deprecated
596     // CXX-601
597 #ifndef NCBI_UNDEPRECATE__DBAPI_OLD_LANGCMD
598     NCBI_DEPRECATED
599 #endif
600     virtual bool More(const string& query_text);
601 
602     /// Get meta-information about parameters.
603     virtual CDBParams& GetBindParams(void);
604     virtual CDBParams& GetDefineParams(void);
605 
606     // Bind cmd parameter with name "name" to the object pointed by "value"
BindParam(const string & name,CDB_Object * value)607     bool BindParam(const string& name, CDB_Object* value)
608     {
609         GetBindParams().Bind(name, value);
610         return true;
611     }
612 
613     // Set cmd parameter with name "name" to the object pointed by "value"
SetParam(const string & name,CDB_Object * value)614     bool SetParam(const string& name, CDB_Object* value)
615     {
616         GetBindParams().Set(name, value);
617         return true;
618     }
619 
620     /// Send command to the server
621     virtual bool Send();
622     /// Implementation-specific.
623     /// @deprecated
624     NCBI_DEPRECATED virtual bool WasSent() const;
625 
626     /// Cancel the command execution
627     virtual bool Cancel();
628     /// Implementation-specific.
629     /// @deprecated
630     NCBI_DEPRECATED virtual bool WasCanceled() const;
631 
632     /// Get result set
633     virtual CDB_Result* Result();
634     virtual bool HasMoreResults() const;
635 
636     /// Check if command has failed
637     virtual bool HasFailed() const;
638 
639     /// Get the number of rows affected by the command.
640     /// Special case:  negative on error or if there is no way that this
641     ///                command could ever affect any rows (like PRINT).
642     virtual int RowCount() const;
643 
644     /// Dump the results of the command
645     /// If result processor is installed for this connection, then it will be
646     /// called for each result set
647     virtual void DumpResults();
648 
649     // Destructor
650     virtual ~CDB_LangCmd();
651 
652 private:
653     impl::CBaseCmd* m_CmdImpl;
654 
655     CDB_LangCmd(impl::CBaseCmd* cmd);
656 
657     // Prohibit default- and copy- constructors, and assignment
658     CDB_LangCmd& operator= (const CDB_LangCmd&);
659     CDB_LangCmd(const CDB_LangCmd&);
660     CDB_LangCmd();
661 
ReleaseImpl(void)662     void ReleaseImpl(void)
663     {
664         m_CmdImpl = NULL;;
665     }
666 
667     // The constructor should be called by "I_Connection" only!
668     friend class impl::CConnection;
669     friend class CInterfaceHook<CDB_LangCmd>;
670 };
671 
672 
673 
674 class NCBI_DBAPIDRIVER_EXPORT CDB_RPCCmd : public I_RPCCmd
675 {
676 public:
677     /// Get meta-information about parameters.
678     virtual CDBParams& GetBindParams(void);
679     virtual CDBParams& GetDefineParams(void);
680 
681     // Binding
BindParam(const string & name,CDB_Object * value,bool out_param=false)682     bool BindParam(
683             const string& name,
684             CDB_Object* value,
685             bool out_param = false
686             )
687     {
688         GetBindParams().Bind(name, value, out_param);
689         return true;
690     }
691 
692     // Setting
SetParam(const string & name,CDB_Object * value,bool out_param=false)693     bool SetParam(
694             const string& name,
695             CDB_Object* value,
696             bool out_param = false
697             )
698     {
699         GetBindParams().Set(name, value, out_param);
700         return true;
701     }
702 
703     /// Send command to the server
704     virtual bool Send();
705     /// Implementation-specific.
706     /// @deprecated
707     NCBI_DEPRECATED virtual bool WasSent() const;
708 
709     /// Cancel the command execution
710     virtual bool Cancel();
711     /// Implementation-specific.
712     /// @deprecated
713     NCBI_DEPRECATED virtual bool WasCanceled() const;
714 
715     /// Get result set.
716     /// Return NULL if no more results left to read.
717     /// Throw exception on error or if attempted to read after NULL was returned
718     virtual CDB_Result* Result();
719 
720     /// Return TRUE if it makes sense (at all) to call Result()
721     virtual bool HasMoreResults() const;
722 
723     /// Check if command has failed
724     virtual bool HasFailed() const;
725 
726     /// Get the number of rows affected by the command
727     /// Special case:  negative on error or if there is no way that this
728     ///                command could ever affect any rows (like PRINT).
729     virtual int RowCount() const;
730 
731     /// Dump the results of the command
732     /// If result processor is installed for this connection, then it will be
733     /// called for each result set
734     virtual void DumpResults();
735 
736     /// Set the "recompile before execute" flag for the stored proc
737     /// Implementation-specific.
738     /// @deprecated
739     NCBI_DEPRECATED virtual void SetRecompile(bool recompile = true);
740 
741     /// Get a name of the procedure.
742     virtual const string& GetProcName(void) const;
743 
744     // Destructor
745     virtual ~CDB_RPCCmd();
746 
747 private:
748     impl::CBaseCmd* m_CmdImpl;
749 
750     CDB_RPCCmd(impl::CBaseCmd* rpc);
751 
752     // Prohibit default- and copy- constructors, and assignment
753     CDB_RPCCmd& operator= (const CDB_RPCCmd&);
754     CDB_RPCCmd(const CDB_RPCCmd&);
755     CDB_RPCCmd();
756 
ReleaseImpl(void)757     void ReleaseImpl(void)
758     {
759         m_CmdImpl = NULL;;
760     }
761 
762     // Constructor should be called by "I_Connection" only!
763     friend class impl::CConnection;
764     friend class CInterfaceHook<CDB_RPCCmd>;
765 };
766 
767 
768 
769 class NCBI_DBAPIDRIVER_EXPORT CDB_BCPInCmd : public I_BCPInCmd
770 {
771 public:
772     /// Set hints by one call. Resets everything that was set by Add*Hint().
773     void SetHints(CTempString hints);
774 
775     /// Type of hint that can be set.
776     enum EBCP_Hints {
777         eOrder,
778         eRowsPerBatch,
779         eKilobytesPerBatch,
780         eTabLock,
781         eCheckConstraints,
782         eFireTriggers
783     };
784 
785     /// Add hint with value.
786     /// Can be used with any hint type except eOrder and with e..PerBatch
787     /// value should be non-zero.
788     /// Resets everything that was set by SetHints().
789     void AddHint(EBCP_Hints hint, unsigned int value = 0);
790 
791     /// Add "ORDER" hint.
792     /// Resets everything that was set by SetHints().
793     void AddOrderHint(CTempString columns);
794 
795     /// Get meta-information about parameters.
796     virtual CDBParams& GetBindParams(void);
797 
798     // Binding
799     bool Bind(unsigned int column_num, CDB_Object* value);
800 
801     /// Send row to the server
802     virtual bool SendRow();
803 
804     /// Complete batch -- to store all rows transferred by far in this batch
805     /// into the table
806     virtual bool CompleteBatch();
807 
808     /// Cancel the BCP command
809     virtual bool Cancel();
810 
811     /// Complete the BCP and store all rows transferred in last batch into
812     /// the table
813     virtual bool CompleteBCP();
814 
815     // Destructor
816     virtual ~CDB_BCPInCmd();
817 
818 private:
819     impl::CBaseCmd* m_CmdImpl;
820 
821     CDB_BCPInCmd(impl::CBaseCmd* bcp);
822 
823     // Prohibit default- and copy- constructors, and assignment
824     CDB_BCPInCmd& operator= (const CDB_BCPInCmd&);
825     CDB_BCPInCmd(const CDB_BCPInCmd&);
826     CDB_BCPInCmd();
827 
ReleaseImpl(void)828     void ReleaseImpl(void)
829     {
830         m_CmdImpl = NULL;;
831     }
832 
833     // The constructor should be called by "I_Connection" only!
834     friend class impl::CConnection;
835     friend class CInterfaceHook<CDB_BCPInCmd>;
836 };
837 
838 
839 
840 class NCBI_DBAPIDRIVER_EXPORT CDB_CursorCmd : public I_CursorCmd
841 {
842 public:
843     /// Get meta-information about parameters.
844     virtual CDBParams& GetBindParams(void);
845     virtual CDBParams& GetDefineParams(void);
846 
847     // Binding
BindParam(const string & name,CDB_Object * value)848     bool BindParam(const string& name, CDB_Object* value)
849     {
850         GetBindParams().Bind(name, value);
851         return true;
852     }
853 
854     /// Open the cursor.
855     /// Return NULL if cursor resulted in no data.
856     /// Throw exception on error.
857     virtual CDB_Result* Open();
858 
859     /// Update the last fetched row.
860     /// NOTE: the cursor must be declared for update in CDB_Connection::Cursor()
861     virtual bool Update(const string& table_name, const string& upd_query);
862 
863     /// @deprecated
864     ///   Please use CDB_Connection::SendData instead.
865     /// @sa
866     ///   CDB_Connection::SendData
867     NCBI_DEPRECATED
868     virtual bool UpdateBlob(unsigned int item_num, CDB_Stream& data,
869                             bool log_it = true);
870     /// Make "send-data" command
871     /// @brief
872     ///   Create send-data command.
873     ///
874     /// @param item_num
875     ///   Column number to rewrite.
876     /// @param size
877     ///   Maximal data size.
878     /// @param log_it
879     ///   Log LOB operation if this value is set to true.
880     /// @param discard_results
881     ///   Discard all resultsets that might be returned from server
882     ///   if this value is set to true.
883     ///
884     /// @return
885     ///   Newly created send-data object.
886     /// @deprecated
887     ///   Please use CDB_Connection::SendDataCmd instead.
888     /// @sa
889     ///   CDB_Connection::SendDataCmd
890     NCBI_DEPRECATED
891     virtual CDB_SendDataCmd* SendDataCmd(unsigned int item_num, size_t size,
892                                          bool log_it = true,
893                                          bool discard_results = true);
894 
895     /// Delete the last fetched row.
896     /// NOTE: the cursor must be declared for delete in CDB_Connection::Cursor()
897     virtual bool Delete(const string& table_name);
898 
899     /// Get the number of fetched rows
900     /// Special case:  negative on error or if there is no way that this
901     ///                command could ever affect any rows (like PRINT).
902     virtual int RowCount() const;
903 
904     /// Close the cursor.
905     /// Return FALSE if the cursor is closed already (or not opened yet)
906     virtual bool Close();
907 
908     // Destructor
909     virtual ~CDB_CursorCmd();
910 
911 private:
912     impl::CBaseCmd* m_CmdImpl;
913 
914     CDB_CursorCmd(impl::CBaseCmd* cur);
915 
916     // Prohibit default- and copy- constructors, and assignment
917     CDB_CursorCmd& operator= (const CDB_CursorCmd&);
918     CDB_CursorCmd(const CDB_CursorCmd&);
919     CDB_CursorCmd();
920 
ReleaseImpl(void)921     void ReleaseImpl(void)
922     {
923         m_CmdImpl = NULL;;
924     }
925 
926     // The constructor should be called by "I_Connection" only!
927     friend class impl::CConnection;
928     friend class CInterfaceHook<CDB_CursorCmd>;
929 };
930 
931 
932 
933 class NCBI_DBAPIDRIVER_EXPORT CDB_SendDataCmd : public I_SendDataCmd
934 {
935 public:
936     /// Send chunk of data to the server.
937     /// Return number of bytes actually transferred to server.
938     virtual size_t SendChunk(const void* data, size_t size);
939     virtual bool Cancel(void);
940 
941     /// Get result set
942     virtual CDB_Result* Result();
943     virtual bool HasMoreResults() const;
944 
945     /// Dump the results of the command
946     /// If result processor is installed for this connection, then it will be
947     /// called for each result set
948     virtual void DumpResults();
949 
950     // Destructor
951     virtual ~CDB_SendDataCmd();
952 
953 private:
954     impl::CSendDataCmd* m_CmdImpl;
955 
956     CDB_SendDataCmd(impl::CSendDataCmd* c);
957 
958     // Prohibit default- and copy- constructors, and assignment
959     CDB_SendDataCmd& operator= (const CDB_SendDataCmd&);
960     CDB_SendDataCmd(const CDB_CursorCmd&);
961     CDB_SendDataCmd();
962 
ReleaseImpl(void)963     void ReleaseImpl(void)
964     {
965         m_CmdImpl = NULL;;
966     }
967 
968     // The constructor should be called by "I_Connection" only!
969     friend class impl::CConnection;
970     friend class CInterfaceHook<CDB_SendDataCmd>;
971 };
972 
973 
974 
975 class NCBI_DBAPIDRIVER_EXPORT CDB_BlobDescriptor : public I_BlobDescriptor
976 {
977 public:
978     enum ETDescriptorType {eUnknown, eText, eBinary};
979 
980     CDB_BlobDescriptor(const string& table_name,
981                        const string& column_name,
982                        const string& search_conditions,
983                        ETDescriptorType column_type = eUnknown,
984                        ETriState     has_legacy_type = eTriState_Unknown);
985     virtual ~CDB_BlobDescriptor(void);
986 
987     virtual int DescriptorType(void) const;
988 
TableName() const989     const string& TableName()        const { return m_TableName;        }
SetTableName(const string & name)990     void SetTableName(const string& name)  { m_TableName = name;        }
ColumnName() const991     const string& ColumnName()       const { return m_ColumnName;       }
SetColumnName(const string & name)992     void SetColumnName(const string& name) { m_ColumnName = name;       }
SearchConditions() const993     const string& SearchConditions() const { return m_SearchConditions; }
SetSearchConditions(const string & cond)994     void SetSearchConditions(const string& cond) { m_SearchConditions = cond; }
995 
GetColumnType(void) const996     ETDescriptorType GetColumnType(void) const
997     {
998         return m_ColumnType;
999     }
SetColumnType(ETDescriptorType type)1000     void SetColumnType(ETDescriptorType type)
1001     {
1002         m_ColumnType = type;
1003     }
1004 
GetHasLegacyType(void) const1005     ETriState GetHasLegacyType(void) const {
1006         return m_HasLegacyType;
1007     }
SetHasLegacyType(ETriState state)1008     void SetHasLegacyType(ETriState state) {
1009         m_HasLegacyType = state;
1010     }
1011 
1012 protected:
1013     string              m_TableName;
1014     string              m_ColumnName;
1015     string              m_SearchConditions;
1016     ETDescriptorType    m_ColumnType;
1017     ETriState           m_HasLegacyType;
1018 };
1019 
1020 // historical name
1021 typedef CDB_BlobDescriptor CDB_ITDescriptor;
1022 
1023 
1024 class NCBI_DBAPIDRIVER_EXPORT CDB_ResultProcessor
1025 {
1026 public:
1027     CDB_ResultProcessor(CDB_Connection* c);
1028     virtual ~CDB_ResultProcessor();
1029 
1030     /// The default implementation just dumps all rows.
1031     /// To get the data you will need to override this method.
1032     virtual void ProcessResult(CDB_Result& res);
1033 
1034 private:
1035     // Prohibit default- and copy- constructors, and assignment
1036     CDB_ResultProcessor();
1037     CDB_ResultProcessor& operator= (const CDB_ResultProcessor&);
1038     CDB_ResultProcessor(const CDB_ResultProcessor&);
1039 
1040     void ReleaseConn(void);
1041     void SetConn(CDB_Connection* c);
1042 
1043     CDB_Connection*      m_Con;
1044     CDB_ResultProcessor* m_Prev;
1045     CDB_ResultProcessor* m_Next;
1046 
1047     friend class impl::CConnection;
1048 };
1049 
1050 
1051 ////////////////////////////////////////////////////////////////////////////////
1052 class NCBI_DBAPIDRIVER_EXPORT CAutoTrans
1053 {
1054 public:
1055     /// Helper class to allow safe initialization from higher-layer objects.
1056     class CSubject {
1057     public:
CSubject(CDB_Connection & connection)1058         CSubject(CDB_Connection& connection) : m_Connection(connection) { }
1059 
1060     private:
1061         CDB_Connection& m_Connection;
1062         friend class CAutoTrans;
1063     };
1064 
1065     CAutoTrans(const CSubject& subject);
1066     ~CAutoTrans(void);
1067 
1068 public:
Continue(void) const1069     bool Continue(void) const
1070     {
1071         return m_Abort;
1072     }
Finish(void)1073     void Finish(void)
1074     {
1075         m_Abort = false;
1076     }
1077 
1078 private:
1079     CAutoTrans(const CAutoTrans&);
1080     CAutoTrans& operator =(const CAutoTrans&);
1081 
1082     void BeginTransaction(void);
1083     void Commit(void);
1084     void Rollback(void);
1085     int GetTranCount(void);
1086 
1087 private:
1088     bool m_Abort;
1089     CDB_Connection& m_Conn;
1090     int m_TranCount;
1091     string m_SavepointName;
1092 };
1093 
1094 
1095 ////////////////////////////////////////////////////////////////////////////////
1096 inline
DBAPI_MakeTrans(CDB_Connection & connection)1097 CAutoTrans::CSubject DBAPI_MakeTrans(CDB_Connection& connection)
1098 {
1099     return CAutoTrans::CSubject(connection);
1100 }
1101 
1102 
1103 ////////////////////////////////////////////////////////////////////////////////
1104 /// Establish an automatically managed SQL transaction on the
1105 /// specified connection for the duration of the immediately following
1106 /// code block: DBAPI_TRANSACTION(connection) { ... }
1107 ///
1108 /// Automatically COMMIT upon reaching the end of the block normally.
1109 /// Automatically ROLLBACK upon leaving the block early, via a break
1110 /// or return statement or uncaught exception.  A client crash or
1111 /// severed connection will trigger an implicit server-side ROLLBACK.
1112 ///
1113 /// Nested transactions are possible, and will use savepoints for
1114 /// inner transactions so they can fail cleanly (without also
1115 /// canceling outer transactions).
1116 #define DBAPI_TRANSACTION(connection) \
1117 for(ncbi::CAutoTrans auto_trans(ncbi::DBAPI_MakeTrans(connection)); \
1118     auto_trans.Continue(); \
1119     auto_trans.Finish())
1120 
1121 
1122 END_NCBI_SCOPE
1123 
1124 
1125 /* @} */
1126 
1127 #if defined(_MSC_VER) && _MSC_VER < 1920
1128     #pragma warning(pop)
1129 #endif
1130 
1131 
1132 #endif  /* DBAPI_DRIVER___PUBLIC__HPP */
1133