src/dbapi/lang_bind/python/python_ncbi_dbapi.cpp

Go to the documentation of this file.
00001 /*  $Id: python_ncbi_dbapi.cpp 173033 2009-10-14 13:16:54Z ivanovp $
00002 * ===========================================================================
00003 *
00004 *                            PUBLIC DOMAIN NOTICE
00005 *               National Center for Biotechnology Information
00006 *
00007 *  This software/database is a "United States Government Work" under the
00008 *  terms of the United States Copyright Act.  It was written as part of
00009 *  the author's official duties as a United States Government employee and
00010 *  thus cannot be copyrighted.  This software/database is freely available
00011 *  to the public for use. The National Library of Medicine and the U.S.
00012 *  Government have not placed any restriction on its use or reproduction.
00013 *
00014 *  Although all reasonable efforts have been taken to ensure the accuracy
00015 *  and reliability of the software and data, the NLM and the U.S.
00016 *  Government do not and cannot warrant the performance or results that
00017 *  may be obtained by using this software or data. The NLM and the U.S.
00018 *  Government disclaim all warranties, express or implied, including
00019 *  warranties of performance, merchantability or fitness for any particular
00020 *  purpose.
00021 *
00022 *  Please cite the author in any work or product based on this material.
00023 *
00024 * ===========================================================================
00025 *
00026 * Author: Sergey Sikorskiy
00027 *
00028 * File Description:
00029 * Status: *Initial*
00030 *
00031 * ===========================================================================
00032 */
00033 
00034 #include <ncbi_pch.hpp>
00035 
00036 #include <common/ncbi_package_ver.h>
00037 #include <corelib/ncbi_safe_static.hpp>
00038 #include <corelib/plugin_manager_store.hpp>
00039 #include <dbapi/error_codes.hpp>
00040 #include <dbapi/driver/dbapi_svc_mapper.hpp>
00041 
00042 #include "python_ncbi_dbapi.hpp"
00043 #include "pythonpp/pythonpp_pdt.hpp"
00044 #if PY_VERSION_HEX >= 0x02040000
00045 #  include "pythonpp/pythonpp_date.hpp"
00046 #endif
00047 #include "../../ds_impl.hpp"
00048 
00049 #if defined(NCBI_OS_CYGWIN)
00050 #include <corelib/ncbicfg.h>
00051 #elif !defined(NCBI_OS_MSWIN)
00052 #include <dlfcn.h>
00053 #endif
00054 
00055 //////////////////////////////////////////////////////////////////////////////
00056 // Compatibility macros
00057 //
00058 // From Python 2.2 to 2.3, the way to export the module init function
00059 // has changed. These macros keep the code compatible to both ways.
00060 //
00061 #if PY_VERSION_HEX >= 0x02030000
00062 #  define PYDBAPI_MODINIT_FUNC(name)         PyMODINIT_FUNC name(void)
00063 #else
00064 #  define PYDBAPI_MODINIT_FUNC(name)         DL_EXPORT(void) name(void)
00065 #endif
00066 
00067 
00068 #define NCBI_USE_ERRCODE_X   Dbapi_Python
00069 
00070 BEGIN_NCBI_SCOPE
00071 
00072 namespace python
00073 {
00074 
00075 // A striped version of IResultSet because it is hard to implement all member
00076 // functions from IResultSet in case of cached data.
00077 class CVariantSet : public CObject
00078 {
00079 public:
00080     /// Destructor.
00081     ///
00082     /// Clean up the resultset.
00083     virtual ~CVariantSet(void) {}
00084 
00085     /// Get result type.
00086     ///
00087     /// @sa
00088     ///   See in <dbapi/driver/interfaces.hpp> for the list of result types.
00089     virtual EDB_ResType GetResultType(void) = 0;
00090 
00091     /// Get next row.
00092     ///
00093     /// NOTE: no results are fetched before first call to this function.
00094     virtual bool Next(void) = 0;
00095 
00096     /// Retrieve a CVariant class describing the data stored in a given column.
00097     /// Note that the index supplied is one-based, not zero-based; the first
00098     /// column is column 1.
00099     ///
00100     /// @param param
00101     ///   Column number (one-based) or name
00102     /// @return
00103     ///   All data (for BLOB data see below) is returned as CVariant.
00104     virtual const CVariant& GetVariant(const CDBParamVariant& param) = 0;
00105 
00106     /// Get total columns.
00107     ///
00108     /// @return
00109     ///   Returns total number of columns in the resultset
00110     virtual unsigned int GetTotalColumns(void) = 0;
00111 
00112     /// Get Metadata.
00113     ///
00114     /// @return
00115     ///   Pointer to result metadata.
00116     virtual const IResultSetMetaData& GetMetaData(void) const = 0;
00117 };
00118 
00119 //////////////////////////////////////////////////////////////////////////////
00120 class CCachedResultSet : public CVariantSet
00121 {
00122 public:
00123     CCachedResultSet(IResultSet& other);
00124     virtual ~CCachedResultSet(void);
00125 
00126     virtual EDB_ResType GetResultType(void);
00127     virtual bool Next(void);
00128     virtual const CVariant& GetVariant(const CDBParamVariant& param);
00129     virtual unsigned int GetTotalColumns(void);
00130     virtual const IResultSetMetaData& GetMetaData(void) const;
00131 
00132 private:
00133     typedef deque<CVariant> TRecord;
00134     typedef deque<TRecord>  TRecordSet;
00135 
00136     const EDB_ResType   m_ResType;
00137     const unsigned int  m_ColumsNum;
00138    
00139     TRecordSet  m_RecordSet;
00140     auto_ptr<const IResultSetMetaData> m_MetaData;
00141     size_t      m_CurRowNum;
00142     size_t      m_CurColNum;
00143 };
00144 
00145 CCachedResultSet::CCachedResultSet(IResultSet& other)
00146 : m_ResType(other.GetResultType())
00147 , m_ColumsNum(other.GetTotalColumns())
00148 , m_MetaData(other.GetMetaData(eTakeOwnership))
00149 , m_CurRowNum(0)
00150 , m_CurColNum(0)
00151 {
00152     while (other.Next()) {
00153         m_RecordSet.push_back(TRecord());
00154         TRecordSet::reference record = m_RecordSet.back();
00155 
00156         for (unsigned int col = 1; col <= m_ColumsNum; ++col) {
00157             record.push_back(other.GetVariant(col));
00158         }
00159     }
00160 }
00161 
00162 CCachedResultSet::~CCachedResultSet(void)
00163 {
00164 }
00165 
00166 EDB_ResType 
00167 CCachedResultSet::GetResultType(void)
00168 {
00169     return m_ResType;
00170 }
00171 
00172 bool 
00173 CCachedResultSet::Next(void)
00174 {
00175     if (m_CurRowNum < m_RecordSet.size()) {
00176         ++m_CurRowNum;
00177         return true;
00178     }
00179 
00180     return false;
00181 }
00182 
00183 const CVariant& 
00184 CCachedResultSet::GetVariant(const CDBParamVariant& param)
00185 {
00186     if (param.IsPositional()) {
00187         unsigned int col_num = param.GetPosition();
00188 
00189         if (col_num > 0 
00190             && col_num <= GetTotalColumns() 
00191             && m_CurRowNum <= m_RecordSet.size()
00192             ) {
00193             return m_RecordSet[m_CurRowNum - 1][col_num - 1];
00194         }
00195     }
00196 
00197     static CVariant value(eDB_UnsupportedType);
00198     return value;
00199 }
00200 
00201 unsigned int 
00202 CCachedResultSet::GetTotalColumns(void)
00203 {
00204     return m_ColumsNum;
00205 }
00206 
00207 const IResultSetMetaData& 
00208 CCachedResultSet::GetMetaData(void) const
00209 {
00210     return *m_MetaData;
00211 }
00212 
00213 
00214 //////////////////////////////////////////////////////////////////////////////
00215 class CRealResultSet : public CVariantSet
00216 {
00217 public:
00218     CRealResultSet(IResultSet* other);
00219     virtual ~CRealResultSet(void);
00220 
00221     virtual EDB_ResType GetResultType(void);
00222     virtual bool Next(void);
00223     virtual const CVariant& GetVariant(const CDBParamVariant& param);
00224     virtual unsigned int GetTotalColumns(void);
00225     virtual const IResultSetMetaData& GetMetaData(void) const;
00226 
00227 private:
00228     // Lifetime of m_RS shouldn't be managed by auto_ptr
00229     IResultSet* m_RS;
00230 };
00231 
00232 CRealResultSet::CRealResultSet(IResultSet* other)
00233 : m_RS(other)
00234 {
00235     _ASSERT(other);
00236 }
00237 
00238 CRealResultSet::~CRealResultSet(void)
00239 {
00240 }
00241 
00242 EDB_ResType 
00243 CRealResultSet::GetResultType(void)
00244 {
00245     return m_RS->GetResultType();
00246 }
00247 
00248 bool 
00249 CRealResultSet::Next(void)
00250 {
00251     return m_RS->Next();
00252 }
00253 
00254 const CVariant& 
00255 CRealResultSet::GetVariant(const CDBParamVariant& param)
00256 {
00257     return m_RS->GetVariant(param);
00258 }
00259 
00260 unsigned int 
00261 CRealResultSet::GetTotalColumns(void)
00262 {
00263     return m_RS->GetTotalColumns();
00264 }
00265 
00266 const IResultSetMetaData& 
00267 CRealResultSet::GetMetaData(void) const
00268 {
00269     return *m_RS->GetMetaData();
00270 }
00271 
00272 //////////////////////////////////////////////////////////////////////////////
00273 class CRealSetProxy : public CResultSetProxy
00274 {
00275 public:
00276     CRealSetProxy(ICallableStatement& stmt);
00277     virtual ~CRealSetProxy(void);
00278 
00279     virtual bool MoveToNextRS(void);
00280     virtual bool MoveToLastRS(void);
00281     virtual CVariantSet& GetRS(void);
00282     virtual const CVariantSet& GetRS(void) const;
00283     virtual bool HasRS(void) const;
00284     virtual void DumpResult(void);
00285 
00286 private:
00287     ICallableStatement* m_Stmt;
00288     auto_ptr<CVariantSet> m_VariantSet;
00289     bool m_HasRS;
00290 };
00291 
00292 CRealSetProxy::CRealSetProxy(ICallableStatement& stmt)
00293 : m_Stmt(&stmt)
00294 , m_HasRS(false)
00295 {
00296 }
00297 
00298 CRealSetProxy::~CRealSetProxy(void)
00299 {
00300 }
00301 
00302 
00303 bool CRealSetProxy::MoveToNextRS(void)
00304 {
00305     m_HasRS = false;
00306 
00307     while (m_Stmt->HasMoreResults()) {
00308         if ( m_Stmt->HasRows() ) {
00309             m_VariantSet.reset(new CRealResultSet(m_Stmt->GetResultSet()));
00310             m_HasRS = true;
00311             break;
00312         }
00313     }
00314 
00315     return m_HasRS;
00316 }
00317 
00318 bool 
00319 CRealSetProxy::MoveToLastRS(void)
00320 {
00321     return false;
00322 }
00323 
00324 CVariantSet& 
00325 CRealSetProxy::GetRS(void)
00326 {
00327     return *m_VariantSet;
00328 }
00329 
00330 const CVariantSet& CRealSetProxy::GetRS(void) const
00331 {
00332     return *m_VariantSet;
00333 }
00334 
00335 bool CRealSetProxy::HasRS(void) const
00336 {
00337     return m_HasRS;
00338 }
00339 
00340 void 
00341 CRealSetProxy::DumpResult(void)
00342 {
00343     while ( m_Stmt->HasMoreResults() ) {
00344         if ( m_Stmt->HasRows() ) {
00345             // Keep very last ResultSet in case somebody calls GetRS().
00346             m_VariantSet.reset(new CRealResultSet(m_Stmt->GetResultSet()));
00347         }
00348     }
00349 }
00350 
00351 
00352 //////////////////////////////////////////////////////////////////////////////
00353 class CVariantSetProxy : public CResultSetProxy
00354 {
00355 public:
00356     CVariantSetProxy(ICallableStatement& stmt);
00357     virtual ~CVariantSetProxy(void);
00358 
00359     virtual bool MoveToNextRS(void);
00360     virtual bool MoveToLastRS(void);
00361     virtual CVariantSet& GetRS(void);
00362     virtual const CVariantSet& GetRS(void) const;
00363     virtual bool HasRS(void) const;
00364     virtual void DumpResult(void);
00365 
00366 private:
00367     typedef deque<CRef<CVariantSet> > TCachedSet;
00368 
00369     TCachedSet m_CachedSet;
00370     CRef<CVariantSet> m_CurResultSet;
00371     bool m_HasRS;
00372 };
00373 
00374 CVariantSetProxy::CVariantSetProxy(ICallableStatement& stmt)
00375 : m_HasRS(false)
00376 {
00377     while (stmt.HasMoreResults()) {
00378         if (stmt.HasRows()) {
00379             auto_ptr<IResultSet> rs(stmt.GetResultSet());
00380             m_CachedSet.push_back(CRef<CVariantSet>(new CCachedResultSet(*rs)));
00381         }
00382     }
00383 }
00384 
00385 CVariantSetProxy::~CVariantSetProxy(void)
00386 {
00387 }
00388 
00389 
00390 bool CVariantSetProxy::MoveToNextRS(void)
00391 {
00392     m_HasRS = false;
00393     
00394     if (!m_CachedSet.empty()) {
00395         m_CurResultSet.Reset(m_CachedSet.front());
00396         m_CachedSet.pop_front();
00397         m_HasRS = true;
00398     }
00399 
00400     return m_HasRS;
00401 }
00402 
00403 bool 
00404 CVariantSetProxy::MoveToLastRS(void)
00405 {
00406     m_HasRS = false;
00407 
00408     if (!m_CachedSet.empty()) {
00409         m_CurResultSet.Reset(m_CachedSet.back());
00410         m_CachedSet.pop_back();
00411         m_HasRS = true;
00412     }
00413 
00414     return m_HasRS;
00415 }
00416 
00417 CVariantSet& CVariantSetProxy::GetRS(void)
00418 {
00419     return *m_CurResultSet;
00420 }
00421 
00422 const CVariantSet& CVariantSetProxy::GetRS(void) const
00423 {
00424     return *m_CurResultSet;
00425 }
00426 
00427 bool CVariantSetProxy::HasRS(void) const
00428 {
00429     return m_HasRS;
00430 }
00431 
00432 void CVariantSetProxy::DumpResult(void)
00433 {
00434     while (MoveToNextRS()) {;}
00435 }
00436 
00437 
00438 //////////////////////////////////////////////////////////////////////////////
00439 CBinary::CBinary(void)
00440 {
00441     PrepareForPython(this);
00442 }
00443 
00444 CBinary::CBinary(const string& value)
00445 : m_Value(value)
00446 {
00447     PrepareForPython(this);
00448 }
00449 
00450 CBinary::~CBinary(void)
00451 {
00452 }
00453 
00454 //////////////////////////////////////////////////////////////////////////////
00455 CNumber::CNumber(void)
00456 {
00457     PrepareForPython(this);
00458 }
00459 
00460 CNumber::~CNumber(void)
00461 {
00462 }
00463 
00464 //////////////////////////////////////////////////////////////////////////////
00465 CRowID::CRowID(void)
00466 {
00467     PrepareForPython(this);
00468 }
00469 
00470 CRowID::~CRowID(void)
00471 {
00472 }
00473 
00474 //////////////////////////////////////////////////////////////////////////////
00475 CStringType::CStringType(void)
00476 {
00477     PrepareForPython(this);
00478 }
00479 
00480 CStringType::~CStringType(void)
00481 {
00482 }
00483 
00484 //////////////////////////////////////////////////////////////////////////////
00485 CDateTimeType::CDateTimeType(void)
00486 {
00487     PrepareForPython(this);
00488 }
00489 
00490 CDateTimeType::~CDateTimeType(void)
00491 {
00492 }
00493 
00494 //////////////////////////////////////////////////////////////////////////////
00495 CParamFmt::CParamFmt(TFormat user_fmt, TFormat drv_fmt)
00496 : m_UserFmt(user_fmt)
00497 , m_DrvFmt(drv_fmt)
00498 {
00499 }
00500 
00501 const char*
00502 CParamFmt::GetName(TFormat fmt)
00503 {
00504     switch (fmt) {
00505     case eTSQL:
00506         return "TSQL";
00507     case eQmark:
00508         return "qmark";
00509     case eNumeric:
00510         return "numeric";
00511     case eNamed:
00512         return "named";
00513     case eFormat:
00514         return "format";
00515     case ePyFormat:
00516         return "pyformat";
00517     }
00518 
00519     return "unknown";
00520 }
00521 
00522 //////////////////////////////////////////////////////////////////////////////
00523 void
00524 CStmtStr::SetStr(const string& str,
00525                  EStatementType default_type,
00526                  const CParamFmt& fmt
00527                  )
00528 {
00529     m_StmType = RetrieveStatementType(str, default_type);
00530 
00531     /* Do not delete this code ...
00532     static char const* space_characters = " \t\n";
00533 
00534     if ( GetType() == estFunction ) {
00535         // Cut off the "EXECUTE" prefix if any ...
00536 
00537         string::size_type pos;
00538         string str_uc = str;
00539 
00540         NStr::ToUpper(str_uc);
00541         pos = str_uc.find_first_not_of(space_characters);
00542         if (pos != string::npos) {
00543             if (str_uc.compare(pos, sizeof("EXEC") - 1, "EXEC") == 0) {
00544                 // We have the "EXECUTE" prefix ...
00545                 pos = str_uc.find_first_of(space_characters, pos);
00546                 if (pos != string::npos) {
00547                     pos = str_uc.find_first_not_of(space_characters, pos);
00548                     if (pos != string::npos) {
00549                         m_StmtStr = str.substr(pos);
00550                         return;
00551                     }
00552                 }
00553             }
00554         }
00555     }
00556     */
00557 
00558     m_StmtStr = str;
00559 
00560     if (fmt.GetDriverFmt() != fmt.GetUserFmt()) {
00561         // Replace parameters ...
00562         if (fmt.GetUserFmt() == CParamFmt::eQmark) {
00563             if (fmt.GetDriverFmt() == CParamFmt::eNumeric) {
00564                 string::size_type pos = 0;
00565                 string::size_type prev_pos = pos;
00566 
00567                 if ((pos = m_StmtStr.find('?', pos)) != string::npos) {
00568                     string tmp_stmt;
00569                     int pos_num = 1;
00570 
00571                     while (pos != string::npos) {
00572                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00573                         tmp_stmt += ":" + NStr::IntToString(pos_num++);
00574                         prev_pos = pos + 1;
00575 
00576                         pos = m_StmtStr.find('?', prev_pos);
00577                     }
00578 
00579                     tmp_stmt += m_StmtStr.substr(prev_pos);
00580                     m_StmtStr = tmp_stmt;
00581                 }
00582 
00583                 return;
00584             } else if (fmt.GetDriverFmt() == CParamFmt::eTSQL) {
00585                 string::size_type pos = 0;
00586                 string::size_type prev_pos = pos;
00587 
00588                 if ((pos = m_StmtStr.find('?', pos)) != string::npos) {
00589                     string tmp_stmt;
00590                     int pos_num = 1;
00591 
00592                     while (pos != string::npos) {
00593                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00594                         tmp_stmt += "@" + NStr::IntToString(pos_num++);
00595                         prev_pos = pos + 1;
00596 
00597                         pos = m_StmtStr.find('?', prev_pos);
00598                     }
00599 
00600                     tmp_stmt += m_StmtStr.substr(prev_pos);
00601                     m_StmtStr = tmp_stmt;
00602                 }
00603 
00604                 return;
00605             }
00606         } else if (fmt.GetUserFmt() == CParamFmt::eNumeric) {
00607             if (fmt.GetDriverFmt() == CParamFmt::eQmark) {
00608                 string::size_type pos = 0;
00609                 string::size_type prev_pos = pos;
00610                 int param_len = 0;
00611 
00612                 if ((pos = find_numeric(m_StmtStr, pos, param_len)) != string::npos) {
00613                     string tmp_stmt;
00614 
00615                     while (pos != string::npos) {
00616                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00617                         tmp_stmt += "?";
00618                         prev_pos = pos + param_len;
00619 
00620                         pos = find_numeric(m_StmtStr, prev_pos, param_len);
00621                     }
00622 
00623                     tmp_stmt += m_StmtStr.substr(prev_pos);
00624                     m_StmtStr = tmp_stmt;
00625                 }
00626 
00627                 return;
00628             }
00629         } else if (fmt.GetUserFmt() == CParamFmt::eNamed) {
00630             if (fmt.GetDriverFmt() == CParamFmt::eQmark) {
00631                 string::size_type pos = 0;
00632                 string::size_type prev_pos = pos;
00633                 int param_len = 0;
00634 
00635                 if ((pos = find_named(m_StmtStr, pos, param_len)) != string::npos) {
00636                     string tmp_stmt;
00637 
00638                     while (pos != string::npos) {
00639                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00640                         tmp_stmt += "?";
00641                         prev_pos = pos + param_len;
00642 
00643                         pos = find_named(m_StmtStr, prev_pos, param_len);
00644                     }
00645 
00646                     tmp_stmt += m_StmtStr.substr(prev_pos);
00647                     m_StmtStr = tmp_stmt;
00648                 }
00649 
00650                 return;
00651             } else if (fmt.GetDriverFmt() == CParamFmt::eNumeric) {
00652                 string::size_type pos = 0;
00653                 string::size_type prev_pos = pos;
00654                 int param_len = 0;
00655 
00656                 if ((pos = find_named(m_StmtStr, pos, param_len)) != string::npos) {
00657                     string tmp_stmt;
00658                     int pos_num = 1;
00659                     typedef map<string, string> name_map_t;
00660                     name_map_t name2num;
00661 
00662                     while (pos != string::npos) {
00663                         string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
00664                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00665                         tmp_stmt += ":";
00666 
00667                         // Get number ...
00668                         name_map_t::iterator it = name2num.find(param_name);
00669                         if (it == name2num.end()) {
00670                             it = name2num.insert(
00671                                 name_map_t::value_type(
00672                                     param_name,
00673                                     NStr::IntToString(pos_num++)
00674                                     )
00675                                 ).first;
00676                         }
00677                         tmp_stmt += it->second;
00678 
00679                         prev_pos = pos + param_len;
00680 
00681                         pos = find_named(m_StmtStr, prev_pos, param_len);
00682                     }
00683 
00684                     tmp_stmt += m_StmtStr.substr(prev_pos);
00685                     m_StmtStr = tmp_stmt;
00686                 }
00687 
00688                 return;
00689             } else if (fmt.GetDriverFmt() == CParamFmt::eTSQL) {
00690                 string::size_type pos = 0;
00691                 string::size_type prev_pos = pos;
00692                 int param_len = 0;
00693 
00694                 if ((pos = find_named(m_StmtStr, pos, param_len)) != string::npos) {
00695                     string tmp_stmt;
00696 
00697                     while (pos != string::npos) {
00698                         string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
00699                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00700                         tmp_stmt += "@" + param_name;
00701                         prev_pos = pos + param_len;
00702 
00703                         pos = find_named(m_StmtStr, prev_pos, param_len);
00704                     }
00705 
00706                     tmp_stmt += m_StmtStr.substr(prev_pos);
00707                     m_StmtStr = tmp_stmt;
00708                 }
00709 
00710                 return;
00711             }
00712         } else if (fmt.GetUserFmt() == CParamFmt::eTSQL) {
00713             if (fmt.GetDriverFmt() == CParamFmt::eQmark) {
00714                 string::size_type pos = 0;
00715                 string::size_type prev_pos = pos;
00716                 int param_len = 0;
00717 
00718                 if ((pos = find_TSQL(m_StmtStr, pos, param_len)) != string::npos) {
00719                     string tmp_stmt;
00720 
00721                     while (pos != string::npos) {
00722                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00723                         tmp_stmt += "?";
00724                         prev_pos = pos + param_len;
00725 
00726                         pos = find_TSQL(m_StmtStr, prev_pos, param_len);
00727                     }
00728 
00729                     tmp_stmt += m_StmtStr.substr(prev_pos);
00730                     m_StmtStr = tmp_stmt;
00731                 }
00732 
00733                 return;
00734             } else if (fmt.GetDriverFmt() == CParamFmt::eNumeric) {
00735                 string::size_type pos = 0;
00736                 string::size_type prev_pos = pos;
00737                 int param_len = 0;
00738 
00739                 if ((pos = find_TSQL(m_StmtStr, pos, param_len)) != string::npos) {
00740                     string tmp_stmt;
00741                     int pos_num = 1;
00742                     typedef map<string, string> name_map_t;
00743                     name_map_t name2num;
00744 
00745                     while (pos != string::npos) {
00746                         string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
00747                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00748                         tmp_stmt += ":";
00749 
00750                         // Get number ...
00751                         name_map_t::iterator it = name2num.find(param_name);
00752                         if (it == name2num.end()) {
00753                             it = name2num.insert(
00754                                 name_map_t::value_type(
00755                                     param_name,
00756                                     NStr::IntToString(pos_num++)
00757                                     )
00758                                 ).first;
00759                         }
00760                         tmp_stmt += it->second;
00761 
00762                         prev_pos = pos + param_len;
00763 
00764                         pos = find_TSQL(m_StmtStr, prev_pos, param_len);
00765                     }
00766 
00767                     tmp_stmt += m_StmtStr.substr(prev_pos);
00768                     m_StmtStr = tmp_stmt;
00769                 }
00770 
00771                 return;
00772             } else if (fmt.GetDriverFmt() == CParamFmt::eNamed) {
00773                 string::size_type pos = 0;
00774                 string::size_type prev_pos = pos;
00775                 int param_len = 0;
00776 
00777                 if ((pos = find_TSQL(m_StmtStr, pos, param_len)) != string::npos) {
00778                     string tmp_stmt;
00779 
00780                     while (pos != string::npos) {
00781                         string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
00782                         tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
00783                         tmp_stmt += ":" + param_name;
00784                         prev_pos = pos + param_len;
00785 
00786                         pos = find_TSQL(m_StmtStr, prev_pos, param_len);
00787                     }
00788 
00789                     tmp_stmt += m_StmtStr.substr(prev_pos);
00790                     m_StmtStr = tmp_stmt;
00791                 }
00792 
00793                 return;
00794             }
00795         }
00796 
00797         string err = "Cannot convert '";
00798         err += CParamFmt::GetName(fmt.GetUserFmt());
00799         err += "' parameter format to '";
00800         err += CParamFmt::GetName(fmt.GetDriverFmt());
00801         err += "'";
00802         throw CInterfaceError(err);
00803     }
00804 }
00805 
00806 
00807 string::size_type
00808 CStmtStr::find_numeric(const string& str,
00809                        string::size_type offset,
00810                        int& param_len
00811                        )
00812 {
00813     string::size_type pos = 0;
00814     static const char* num_characters = "0123456789";
00815 
00816     pos = str.find(':', offset);
00817     if ((pos != string::npos) && (pos + 1 != string::npos)) {
00818         string::size_type tmp_pos = 0;
00819 
00820         tmp_pos = str.find_first_not_of(num_characters, pos + 1);
00821         if (tmp_pos != string::npos) {
00822             // We've got the end of the number ...
00823             param_len = tmp_pos - pos;
00824         } else if (str.find_first_of(num_characters, pos + 1) == pos + 1) {
00825             // Number till the end of the string ...
00826             param_len = str.size() - pos;
00827         }
00828     }
00829 
00830     return pos;
00831 }
00832 
00833 
00834 string::size_type
00835 CStmtStr::find_named(const string& str,
00836                      string::size_type offset,
00837                      int& param_len
00838                      )
00839 {
00840     string::size_type pos = 0;
00841     static char const* sep_characters = " \t\n,.()-+<>=";
00842 
00843     pos = str.find(':', offset);
00844     if ((pos != string::npos) && (pos + 1 != string::npos)) {
00845         string::size_type tmp_pos = 0;
00846 
00847         tmp_pos = str.find_first_of(sep_characters, pos + 1);
00848         if (tmp_pos != string::npos) {
00849             // We've got the end of the number ...
00850             param_len = tmp_pos - pos;
00851         } else if ((str[pos + 1] >= 'A' && str[pos + 1] <= 'Z') ||
00852                    (str[pos + 1] >= 'a' && str[pos + 1] <= 'z')
00853                    ) {
00854             // Number till the end of the string ...
00855             param_len = str.size() - pos;
00856         }
00857     }
00858 
00859     return pos;
00860 }
00861 
00862 string::size_type
00863 CStmtStr::find_TSQL(const string& str,
00864                     string::size_type offset,
00865                     int& param_len
00866                     )
00867 {
00868     string::size_type pos = 0;
00869     static char const* sep_characters = " \t\n,.()-+<>=";
00870 
00871     pos = str.find('@', offset);
00872     if ((pos != string::npos) && (pos + 1 != string::npos)) {
00873         string::size_type tmp_pos = 0;
00874 
00875         tmp_pos = str.find_first_of(sep_characters, pos + 1);
00876         if (tmp_pos != string::npos) {
00877             // We've got the end of the number ...
00878             param_len = tmp_pos - pos;
00879         } else if ((str[pos + 1] >= 'A' && str[pos + 1] <= 'Z') ||
00880                    (str[pos + 1] >= 'a' && str[pos + 1] <= 'z')
00881                    ) {
00882             // Number till the end of the string ...
00883             param_len = str.size() - pos;
00884         }
00885     }
00886 
00887     return pos;
00888 }
00889 
00890 /* Future development
00891 //////////////////////////////////////////////////////////////////////////////
00892 struct DataSourceDeleter
00893 {
00894     /// Default delete function.
00895     static void Delete(ncbi::IDataSource* const object)
00896     {
00897         CDriverManager::DeleteDs( object );
00898     }
00899 };
00900 
00901 //////////////////////////////////////////////////////////////////////////////
00902 class CDataSourcePool
00903 {
00904 public:
00905     CDataSourcePool(void);
00906     ~CDataSourcePool(void);
00907 
00908 public:
00909     static CDataSourcePool& GetInstance(void);
00910 
00911 public:
00912     IDataSource& GetDataSource(
00913         const string& driver_name,
00914         const TPluginManagerParamTree* const params = NULL);
00915 
00916 private:
00917     typedef CPluginManager<I_DriverContext> TContextManager;
00918     typedef CPluginManagerGetter<I_DriverContext> TContextManagerStore;
00919     typedef map<string, AutoPtr<IDataSource, DataSourceDeleter> > TDSMap;
00920 
00921     CRef<TContextManager>   m_ContextManager;
00922     TDSMap                  m_DataSourceMap;
00923 };
00924 
00925 CDataSourcePool::CDataSourcePool(void)
00926 {
00927     m_ContextManager.Reset( TContextManagerStore::Get() );
00928     _ASSERT( m_ContextManager );
00929 
00930 #if defined(NCBI_OS_MSWIN)
00931     // Add an additional search path ...
00932 #endif
00933 }
00934 
00935 CDataSourcePool::~CDataSourcePool(void)
00936 {
00937 }
00938 
00939 void
00940 DataSourceCleanup(void* ptr)
00941 {
00942     CDriverManager::DeleteDs( static_cast<ncbi::IDataSource *const>(ptr) );
00943 }
00944 
00945 CDataSourcePool&
00946 CDataSourcePool::GetInstance(void)
00947 {
00948     static CSafeStaticPtr<CDataSourcePool> ds_pool;
00949 
00950     return *ds_pool;
00951 }
00952 
00953 IDataSource&
00954 CDataSourcePool::GetDataSource(
00955     const string& driver_name,
00956     const TPluginManagerParamTree* const params)
00957 {
00958     TDSMap::const_iterator citer = m_DataSourceMap.find( driver_name );
00959 
00960     if ( citer != m_DataSourceMap.end() ) {
00961         return *citer->second;
00962     }
00963 
00964     // Build a new context ...
00965     I_DriverContext* drv = NULL;
00966 
00967     try {
00968         drv = m_ContextManager->CreateInstance(
00969             driver_name,
00970             NCBI_INTERFACE_VERSION(I_DriverContext),
00971             params
00972             );
00973         _ASSERT( drv );
00974     }
00975     catch( const CPluginManagerException& e ) {
00976         throw CDatabaseError( e.what() );
00977     }
00978     catch ( const exception& e ) {
00979         throw CDatabaseError( driver_name + " is not available :: " + e.what() );
00980     }
00981     catch( ... ) {
00982         throw CDatabaseError( driver_name + " was unable to load due an unknown error" );
00983     }
00984 
00985     // Store new value
00986     IDataSource* ds = CDriverManager::CreateDs( drv );
00987     m_DataSourceMap[driver_name] = ds;
00988 
00989     return *ds;
00990 }
00991     */
00992 
00993 //////////////////////////////////////////////////////////////////////////////
00994 static
00995 string RetrieveModuleFileName(void)
00996 {
00997     string file_name;
00998 
00999 #if defined(NCBI_OS_CYGWIN)
01000     // no dladdr; just return the standard location
01001     file_name = NCBI_GetDefaultRunpath() + string("libpython_ncbi_dbapi.a");
01002 
01003 #elif defined(NCBI_OS_MSWIN)
01004     // Add an additional search path ...
01005     const DWORD buff_size = 1024;
01006     DWORD cur_size = 0;
01007     char buff[buff_size];
01008     HMODULE mh = NULL;
01009     const char* module_name = NULL;
01010 
01011 // #ifdef NDEBUG
01012 //     module_name = "python_ncbi_dbapi.pyd";
01013 // #else
01014 //     module_name = "python_ncbi_dbapi_d.pyd";
01015 // #endif
01016 
01017     // Get module handle ...
01018     MEMORY_BASIC_INFORMATION mbi;
01019     VirtualQuery((const void*)RetrieveModuleFileName, &mbi, sizeof(mbi));
01020     mh = (HINSTANCE)mbi.AllocationBase;
01021 
01022 //     if ( mh = GetModuleHandle( module_name ) ) {
01023     if (mh) {
01024         if ( cur_size = GetModuleFileName( mh, buff, buff_size ) ) {
01025             if ( cur_size < buff_size ) {
01026                 file_name = buff;
01027             }
01028         }
01029     }
01030 
01031 #else
01032 
01033     ::Dl_info dli;
01034 
01035     // if (::dladdr(&ncbi::python::CConnection::CConnection, &dli) != 0) {
01036     void* method_ptr = (void*)RetrieveModuleFileName;
01037     if (::dladdr(method_ptr, &dli) != 0) {
01038         file_name = dli.dli_fname;
01039     }
01040 
01041 #endif
01042 
01043     return file_name;
01044 }
01045 
01046 //////////////////////////////////////////////////////////////////////////////
01047 CConnection::CConnection(
01048     const string& driver_name,
01049     const string& db_type,
01050     const string& server_name,
01051     const string& db_name,
01052     const string& user_name,
01053     const string& user_pswd,
01054     const pythonpp::CObject& extra_params
01055     )
01056 : m_DefParams(server_name, user_name, user_pswd)
01057 , m_Params(m_DefParams)
01058 , m_DM(CDriverManager::GetInstance())
01059 , m_DS(NULL)
01060 , m_DefTransaction( NULL )
01061 , m_ConnectionMode(eSimpleMode)
01062 {
01063     try {
01064         m_DefParams.SetDriverName(driver_name);
01065         m_DefParams.SetDatabaseName(db_name);
01066 
01067         // Set up a server type ...
01068         string db_type_uc = db_type;
01069         NStr::ToUpper(db_type_uc);
01070 
01071         if ( db_type_uc == "SYBASE"  ||  db_type_uc == "SYB" ) {
01072             m_DefParams.SetServerType(CDBConnParams::eSybaseSQLServer);
01073         } else if ( db_type_uc == "MYSQL" ) {
01074             m_DefParams.SetServerType(CDBConnParams::eMySQL);
01075         } else if ( db_type_uc == "MSSQL" ||
01076                 db_type_uc == "MS_SQL" ||
01077                 db_type_uc == "MS SQL") 
01078         {
01079             m_DefParams.SetServerType(CDBConnParams::eMSSqlServer);
01080         }
01081 
01082 
01083         // Handle extra-parameters ...
01084         if (!pythonpp::CNone::HasSameType(extra_params)) {
01085             if (pythonpp::CDict::HasSameType(extra_params)) {
01086                 const pythonpp::CDict dict = extra_params;
01087 
01088                 // Iterate over a dict.
01089                 pythonpp::py_ssize_t i = 0;
01090                 PyObject* key;
01091                 PyObject* value;
01092                 while ( PyDict_Next(dict, &i, &key, &value) ) {
01093                     // Refer to borrowed references in key and value.
01094                     const string param_name = pythonpp::CString(key);
01095                     const string param_value = pythonpp::CString(value);
01096 
01097                     m_DefParams.SetParam(param_name, param_value);
01098                 }
01099             } else if (pythonpp::CBool::HasSameType(extra_params)) {
01100                 bool support_standard_interface = pythonpp::CBool(extra_params);
01101                 m_ConnectionMode = (support_standard_interface ? eStandardMode : eSimpleMode);
01102             } else {
01103                 throw CNotSupportedError("Expected dictionary as an argument.");
01104             }
01105         }
01106 
01107         // Make a datasource ...
01108         m_DS = m_DM.MakeDs(m_Params);
01109 
01110         // Set up message handlers ...
01111         I_DriverContext* drv_context = m_DS->GetDriverContext();
01112 
01113         drv_context->PushCntxMsgHandler(
01114                 new CDB_UserHandler_Exception,
01115                 eTakeOwnership
01116                 );
01117 
01118         drv_context->PushDefConnMsgHandler(
01119                 new CDB_UserHandler_Exception,
01120                 eTakeOwnership
01121                 );
01122     }
01123     catch(const CDB_Exception& e) {
01124         throw CDatabaseError(e);
01125     }
01126     catch(const CException& e) {
01127         throw CDatabaseError(e.what());
01128     }
01129 
01130     PrepareForPython(this);
01131 
01132     try {
01133         // Create a default transaction ...
01134         // m_DefTransaction = new CTransaction(this, pythonpp::eBorrowed, m_ConnectionMode);
01135         m_DefTransaction = new CTransaction(this, pythonpp::eAcquired, m_ConnectionMode);
01136     }
01137     catch(const CDB_Exception& e) {
01138         throw CDatabaseError(e);
01139     }
01140     catch(const CException& e) {
01141         throw CDatabaseError(e.what());
01142     }
01143 }
01144 
01145 CConnection::~CConnection(void)
01146 {
01147     try {
01148         // This DecRefCount caused a lot of problems for some reason ...
01149         DecRefCount( m_DefTransaction );
01150         // delete m_DefTransaction;
01151 
01152         _ASSERT( m_TransList.empty() );
01153 
01154         _ASSERT(m_DS);
01155 
01156         // DO NOT destroy data source because there is only one data source per
01157         // driver in Kholodov's API.
01158         // Destroying data source will cause closed and reopened connection to
01159         // crash ...
01160         // m_DM.DestroyDs(m_DS);
01161         m_DS = NULL;                        // ;-)
01162     }
01163     NCBI_CATCH_ALL_X( 1, NCBI_CURRENT_FUNCTION )
01164 }
01165 
01166 IConnection*
01167 CConnection::MakeDBConnection(void) const
01168 {
01169     _ASSERT(m_DS);
01170     // !!! eTakeOwnership !!!
01171     IConnection* connection = m_DS->CreateConnection( eTakeOwnership );
01172     connection->Connect(m_Params);
01173     return connection;
01174 }
01175 
01176 CTransaction*
01177 CConnection::CreateTransaction(void)
01178 {
01179     CTransaction* trans = NULL;
01180 
01181     trans = new CTransaction(this, pythonpp::eOwned, m_ConnectionMode);
01182 
01183     m_TransList.insert(trans);
01184     return trans;
01185 }
01186 
01187 void
01188 CConnection::DestroyTransaction(CTransaction* trans)
01189 {
01190     if (m_DefTransaction == trans) {
01191         m_DefTransaction = NULL;
01192     }
01193 
01194     // Python will take care of the object deallocation ...
01195     m_TransList.erase(trans);
01196 }
01197 
01198 pythonpp::CObject
01199 CConnection::close(const pythonpp::CTuple& args)
01200 {
01201     TTransList::const_iterator citer;
01202     TTransList::const_iterator cend = m_TransList.end();
01203 
01204     for ( citer = m_TransList.begin(); citer != cend; ++citer) {
01205         (*citer)->close(args);
01206     }
01207     return GetDefaultTransaction().close(args);
01208 }
01209 
01210 pythonpp::CObject
01211 CConnection::cursor(const pythonpp::CTuple& args)
01212 {
01213     return GetDefaultTransaction().cursor(args);
01214 }
01215 
01216 pythonpp::CObject
01217 CConnection::commit(const pythonpp::CTuple& args)
01218 {
01219     return GetDefaultTransaction().commit(args);
01220 }
01221 
01222 pythonpp::CObject
01223 CConnection::rollback(const pythonpp::CTuple& args)
01224 {
01225     return GetDefaultTransaction().rollback(args);
01226 }
01227 
01228 pythonpp::CObject
01229 CConnection::transaction(const pythonpp::CTuple& args)
01230 {
01231     return pythonpp::CObject(CreateTransaction(), pythonpp::eTakeOwnership);
01232 }
01233 
01234 //////////////////////////////////////////////////////////////////////////////
01235 CSelectConnPool::CSelectConnPool(CTransaction* trans, size_t size)
01236 : m_Transaction(trans)
01237 , m_PoolSize(size)
01238 {
01239 }
01240 
01241 IConnection*
01242 CSelectConnPool::Create(void)
01243 {
01244     IConnection* db_conn = NULL;
01245 
01246     if ( m_ConnPool.empty() ) {
01247         db_conn = GetConnection().MakeDBConnection();
01248         m_ConnList.insert(db_conn);
01249     } else {
01250         db_conn = *m_ConnPool.begin();
01251         m_ConnPool.erase(m_ConnPool.begin());
01252     }
01253 
01254     return db_conn;
01255 }
01256 
01257 void
01258 CSelectConnPool::Destroy(IConnection* db_conn)
01259 {
01260     if ( m_ConnPool.size() < m_PoolSize ) {
01261         m_ConnPool.insert(db_conn);
01262     } else {
01263         if ( m_ConnList.erase(db_conn) == 0) {
01264             _ASSERT(false);
01265         }
01266         delete db_conn;
01267     }
01268 }
01269 
01270 void
01271 CSelectConnPool::Clear(void)
01272 {
01273     if ( !Empty() ) {
01274         throw CInternalError("Unable to close a transaction. There are open cursors in use.");
01275     }
01276 
01277     if ( !m_ConnList.empty() )
01278     {
01279         // Close all open connections ...
01280         TConnectionList::const_iterator citer;
01281         TConnectionList::const_iterator cend = m_ConnList.end();
01282 
01283         // Delete all allocated "SELECT" database connections ...
01284         for ( citer = m_ConnList.begin(); citer != cend; ++citer) {
01285             delete *citer;
01286         }
01287         m_ConnList.clear();
01288         m_ConnPool.clear();
01289     }
01290 }
01291 
01292 //////////////////////////////////////////////////////////////////////////////
01293 CDMLConnPool::CDMLConnPool(
01294     CTransaction* trans,
01295     ETransType trans_type
01296     )
01297 : m_Transaction( trans )
01298 , m_NumOfActive( 0 )
01299 , m_Started( false )
01300 , m_TransType( trans_type )
01301 {
01302 }
01303 
01304 IConnection*
01305 CDMLConnPool::Create(void)
01306 {
01307     // Delayed connection creation ...
01308     if ( m_DMLConnection.get() == NULL ) {
01309         m_DMLConnection.reset( GetConnection().MakeDBConnection() );
01310         _ASSERT( m_LocalStmt.get() == NULL );
01311 
01312         if ( m_TransType == eImplicitTrans ) {
01313             m_LocalStmt.reset( m_DMLConnection->GetStatement() );
01314             // Begin transaction ...
01315             GetLocalStmt().ExecuteUpdate( "BEGIN TRANSACTION" );
01316             m_Started = true;
01317         }
01318     }
01319 
01320     ++m_NumOfActive;
01321     return m_DMLConnection.get();
01322 }
01323 
01324 void
01325 CDMLConnPool::Destroy(IConnection* db_conn)
01326 {
01327     --m_NumOfActive;
01328 }
01329 
01330 void
01331 CDMLConnPool::Clear(void)
01332 {
01333     if ( !Empty() ) {
01334         throw CInternalError("Unable to close a transaction. There are open cursors in use.");
01335     }
01336 
01337     // Close the DML connection ...
01338     m_LocalStmt.reset();
01339     m_DMLConnection.reset();
01340     m_Started = false;
01341 }
01342 
01343 IStatement&
01344 CDMLConnPool::GetLocalStmt(void) const
01345 {
01346     _ASSERT(m_LocalStmt.get() != NULL);
01347     return *m_LocalStmt;
01348 }
01349 
01350 void
01351 CDMLConnPool::commit(void) const
01352 {
01353     if (
01354         m_TransType == eImplicitTrans &&
01355         m_Started &&
01356         m_DMLConnection.get() != NULL &&
01357         m_DMLConnection->IsAlive()
01358     ) {
01359         try {
01360             GetLocalStmt().ExecuteUpdate( "COMMIT TRANSACTION" );
01361             GetLocalStmt().ExecuteUpdate( "BEGIN TRANSACTION" );
01362         }
01363         catch(const CDB_Exception& e) {
01364             throw CDatabaseError(e);
01365         }
01366         catch(const CException& e) {
01367             throw CDatabaseError(e.what());
01368         }
01369     }
01370 }
01371 
01372 void
01373 CDMLConnPool::rollback(void) const
01374 {
01375     if (
01376         m_TransType == eImplicitTrans &&
01377         m_Started &&
01378         m_DMLConnection.get() != NULL &&
01379         m_DMLConnection->IsAlive()
01380     ) {
01381         try {
01382             GetLocalStmt().ExecuteUpdate( "ROLLBACK TRANSACTION" );
01383             GetLocalStmt().ExecuteUpdate( "BEGIN TRANSACTION" );
01384         }
01385         catch(const CDB_Exception& e) {
01386             throw CDatabaseError(e);
01387         }
01388         catch(const CException& e) {
01389             throw CDatabaseError(e.what());
01390         }
01391     }
01392 }
01393 
01394 //////////////////////////////////////////////////////////////////////////////
01395 CTransaction::CTransaction(
01396     CConnection* conn,
01397     pythonpp::EOwnershipFuture ownnership,
01398     EConnectionMode conn_mode
01399     )
01400 : m_ParentConnection( conn )
01401 , m_DMLConnPool( this, (conn_mode == eSimpleMode ? eExplicitTrans : eImplicitTrans) )
01402 , m_SelectConnPool( this )
01403 , m_ConnectionMode( conn_mode )
01404 {
01405     if ( conn == NULL ) {
01406         throw CInternalError("Invalid CConnection object");
01407     }
01408 
01409     if ( ownnership != pythonpp::eBorrowed ) {
01410         m_PythonConnection = conn;
01411     }
01412 
01413     PrepareForPython(this);
01414 }
01415 
01416 CTransaction::~CTransaction(void)
01417 {
01418     try {
01419         CloseInternal();
01420 
01421         // Unregister this transaction with the parent connection ...
01422         GetParentConnection().DestroyTransaction(this);
01423     }
01424     NCBI_CATCH_ALL_X( 2, NCBI_CURRENT_FUNCTION )
01425 }
01426 
01427 pythonpp::CObject
01428 CTransaction::close(const pythonpp::CTuple& args)
01429 {
01430     try {
01431         CloseInternal();
01432     }
01433     catch(const CDB_Exception& e) {
01434         throw CDatabaseError(e);
01435     }
01436     catch(const CException& e) {
01437         throw CDatabaseError(e.what());
01438     }
01439 
01440     // Unregister this transaction with the parent connection ...
01441     // I'm not absolutely shure about this ... 1/24/2005 5:31PM
01442     // GetConnection().DestroyTransaction(this);
01443 
01444     return pythonpp::CNone();
01445 }
01446 
01447 pythonpp::CObject
01448 CTransaction::cursor(const pythonpp::CTuple& args)
01449 {
01450     try {
01451         return pythonpp::CObject(CreateCursor(), pythonpp::eTakeOwnership);
01452     }
01453     catch(const CDB_Exception& e) {
01454         throw CDatabaseError(e);
01455     }
01456     catch(const CException& e) {
01457         throw CDatabaseError(e.what());
01458     }
01459 }
01460 
01461 pythonpp::CObject
01462 CTransaction::commit(const pythonpp::CTuple& args)
01463 {
01464     try {
01465         CommitInternal();
01466     }
01467     catch(const CDB_Exception& e) {
01468         throw CDatabaseError(e);
01469     }
01470     catch(const CException& e) {
01471         throw CDatabaseError(e.what());
01472     }
01473 
01474     return pythonpp::CNone();
01475 }
01476 
01477 pythonpp::CObject
01478 CTransaction::rollback(const pythonpp::CTuple& args)
01479 {
01480     try {
01481         RollbackInternal();
01482     }
01483     catch(const CDB_Exception& e) {
01484         throw CDatabaseError(e);
01485     }
01486     catch(const CException& e) {
01487         throw CDatabaseError(e.what());
01488     }
01489 
01490     return pythonpp::CNone();
01491 }
01492 
01493 void
01494 CTransaction::CloseInternal(void)
01495 {
01496     // Close all cursors ...
01497     CloseOpenCursors();
01498 
01499     // Double check ...
01500     // Check for the DML connection also ...
01501     // if ( !m_SelectConnPool.Empty() || !m_DMLConnPool.Empty() ) {
01502     //     throw CInternalError("Unable to close a transaction. There are open cursors in use.");
01503     // }
01504 
01505     // Rollback transaction ...
01506     RollbackInternal();
01507 
01508     // Close all open connections ...
01509     m_SelectConnPool.Clear();
01510     // Close the DML connection ...
01511     m_DMLConnPool.Clear();
01512 }
01513 
01514 void
01515 CTransaction::CloseOpenCursors(void)
01516 {
01517     if ( !m_CursorList.empty() ) {
01518         // Make a copy of m_CursorList because it will be modified ...
01519         TCursorList tmp_CursorList = m_CursorList;
01520         TCursorList::const_iterator citer;
01521         TCursorList::const_iterator cend = tmp_CursorList.end();
01522 
01523         for ( citer = tmp_CursorList.begin(); citer != cend; ++citer ) {
01524             (*citer)->CloseInternal();
01525         }
01526     }
01527 }
01528 
01529 CCursor*
01530 CTransaction::CreateCursor(void)
01531 {
01532     CCursor* cursor = new CCursor(this);
01533 
01534     m_CursorList.insert(cursor);
01535     return cursor;
01536 }
01537 
01538 void
01539 CTransaction::DestroyCursor(CCursor* cursor)
01540 {
01541     // Python will take care of the object deallocation ...
01542     m_CursorList.erase(cursor);
01543 }
01544 
01545 IConnection*
01546 CTransaction::CreateSelectConnection(void)
01547 {
01548     IConnection* conn = NULL;
01549 
01550     if ( m_ConnectionMode == eSimpleMode ) {
01551         conn = m_DMLConnPool.Create();
01552     } else {
01553         conn = m_SelectConnPool.Create();
01554     }
01555     return conn;
01556 }
01557 
01558 void
01559 CTransaction::DestroySelectConnection(IConnection* db_conn)
01560 {
01561     if ( m_ConnectionMode == eSimpleMode ) {
01562         m_DMLConnPool.Destroy(db_conn);
01563     } else {
01564         m_SelectConnPool.Destroy(db_conn);
01565     }
01566 }
01567 
01568 //////////////////////////////////////////////////////////////////////////////
01569 EStatementType
01570 RetrieveStatementType(const string& stmt, EStatementType default_type)
01571 {
01572     EStatementType stmtType = default_type;
01573 
01574     string::size_type pos = stmt.find_first_not_of(" \t\n");
01575     if (pos != string::npos)
01576     {
01577         // "CREATE" should be before DML ...
01578         if (NStr::EqualNocase(stmt, pos, sizeof("CREATE") - 1, "CREATE"))
01579         {
01580             stmtType = estCreate;
01581         } else if (NStr::EqualNocase(stmt, pos, sizeof("SELECT") - 1, "SELECT"))
01582         {
01583             stmtType = estSelect;
01584         } else if (NStr::EqualNocase(stmt, pos, sizeof("UPDATE") - 1, "UPDATE"))
01585         {
01586             stmtType = estUpdate;
01587         } else if (NStr::EqualNocase(stmt, pos, sizeof("DELETE") - 1, "DELETE"))
01588         {
01589             stmtType = estDelete;
01590         } else if (NStr::EqualNocase(stmt, pos, sizeof("INSERT") - 1, "INSERT"))
01591         {
01592             stmtType = estInsert;
01593         } else if (NStr::EqualNocase(stmt, pos, sizeof("DROP") - 1, "DROP"))
01594         {
01595             stmtType = estDrop;
01596         } else if (NStr::EqualNocase(stmt, pos, sizeof("ALTER") - 1, "ALTER"))
01597         {
01598             stmtType = estAlter;
01599         } else if (NStr::EqualNocase(stmt, pos, sizeof("BEGIN") - 1, "BEGIN"))
01600         {
01601             stmtType = estTransaction;
01602         } else if (NStr::EqualNocase(stmt, pos, sizeof("COMMIT") - 1, "COMMIT"))
01603         {
01604             stmtType = estTransaction;
01605         } else if (NStr::EqualNocase(stmt, pos, sizeof("ROLLBACK") - 1, "ROLLBACK"))
01606         {
01607             stmtType = estTransaction;
01608         // } else if (NStr::EqualNocase(stmt, pos, sizeof("EXEC") - 1, "EXEC"))
01609         // {
01610         //    stmtType = estFunction;
01611         }
01612     }
01613 
01614     return stmtType;
01615 }
01616 
01617 //////////////////////////////////////////////////////////////////////////////
01618 CStmtHelper::CStmtHelper(CTransaction* trans)
01619 : m_ParentTransaction( trans )
01620 , m_RS(NULL)
01621 , m_Executed( false )
01622 , m_ResultStatus( 0 )
01623 , m_ResultStatusAvailable( false )
01624 , m_UserHandler(NULL)
01625 {
01626     if ( m_ParentTransaction == NULL ) {
01627         throw CInternalError("Invalid CTransaction object");
01628     }
01629 }
01630 
01631 CStmtHelper::CStmtHelper(CTransaction* trans, const CStmtStr& stmt)
01632 : m_ParentTransaction( trans )
01633 , m_StmtStr( stmt )
01634 , m_Executed(false)
01635 , m_ResultStatus( 0 )
01636 , m_ResultStatusAvailable( false )
01637 , m_UserHandler(NULL)
01638 {
01639     if ( m_ParentTransaction == NULL ) {
01640         throw CInternalError("Invalid CTransaction object");
01641     }
01642 
01643     CreateStmt(NULL);
01644 }
01645 
01646 CStmtHelper::~CStmtHelper(void)
01647 {
01648     try {
01649         Close();
01650     }
01651     NCBI_CATCH_ALL_X( 3, NCBI_CURRENT_FUNCTION )
01652 }
01653 
01654 void
01655 CStmtHelper::Close(void)
01656 {
01657     DumpResult();
01658     ReleaseStmt();
01659     m_Executed = false;
01660     m_ResultStatus = 0;
01661     m_ResultStatusAvailable = false;
01662 }
01663 
01664 void
01665 CStmtHelper::DumpResult(void)
01666 {
01667     if ( m_Stmt.get() && m_Executed ) {
01668         while ( m_Stmt->HasMoreResults() ) {
01669             if ( m_Stmt->HasRows() ) {
01670                 m_RS.reset(m_Stmt->GetResultSet());
01671             }
01672         }
01673     }
01674     m_RS.reset();
01675 }
01676 
01677 void
01678 CStmtHelper::ReleaseStmt(void)
01679 {
01680     if ( m_Stmt.get() ) {
01681         IConnection* conn = m_Stmt->GetParentConn();
01682 
01683         // Release the statement before a connection release because it is a child object for a connection.
01684         m_RS.reset();
01685         m_Stmt.reset();
01686 
01687         _ASSERT( m_StmtStr.GetType() != estNone );
01688 
01689         if (m_UserHandler) {
01690             conn->GetCDB_Connection()->PopMsgHandler(m_UserHandler);
01691             m_UserHandler = NULL;
01692         }
01693 
01694         if ( m_StmtStr.GetType() == estSelect ) {
01695             // Release SELECT Connection ...
01696             m_ParentTransaction->DestroySelectConnection( conn );
01697         } else {
01698             // Release DML Connection ...
01699             m_ParentTransaction->DestroyDMLConnection( conn );
01700         }
01701         m_Executed = false;
01702         m_ResultStatus = 0;
01703         m_ResultStatusAvailable = false;
01704     }
01705 }
01706 
01707 void
01708 CStmtHelper::CreateStmt(CDB_UserHandler* handler)
01709 {
01710     m_Executed = false;
01711     m_ResultStatus = 0;
01712     m_ResultStatusAvailable = false;
01713 
01714     if ( m_StmtStr.GetType() == estSelect ) {
01715         // Get a SELECT connection ...
01716         m_Stmt.reset( m_ParentTransaction->CreateSelectConnection()->GetStatement() );
01717     } else {
01718         // Get a DML connection ...
01719         m_Stmt.reset( m_ParentTransaction->CreateDMLConnection()->GetStatement() );
01720     }
01721 
01722     if (handler) {
01723         m_Stmt->GetParentConn()->GetCDB_Connection()->PushMsgHandler(handler);
01724         m_UserHandler = handler;
01725     }
01726 }
01727 
01728 void
01729 CStmtHelper::SetStr(const CStmtStr& stmt, CDB_UserHandler* handler)
01730 {
01731     EStatementType oldStmtType = m_StmtStr.GetType();
01732     EStatementType currStmtType = stmt.GetType();
01733     m_StmtStr = stmt;
01734 
01735     if ( m_Stmt.get() ) {
01736         // If a new statement type needs a different connection type then release an old one.
01737         if (
01738             (oldStmtType == estSelect && currStmtType != estSelect) ||
01739             (oldStmtType != estSelect && currStmtType == estSelect)
01740         ) {
01741             DumpResult();
01742             ReleaseStmt();
01743             CreateStmt(handler);
01744         } else {
01745             DumpResult();
01746             m_Stmt->ClearParamList();
01747         }
01748     } else {
01749         CreateStmt(handler);
01750     }
01751 
01752     m_Executed = false;
01753     m_ResultStatus = 0;
01754     m_ResultStatusAvailable = false;
01755 }
01756 
01757 void
01758 CStmtHelper::SetParam(const string& name, const CVariant& value)
01759 {
01760     _ASSERT( m_Stmt.get() );
01761 
01762     string param_name = name;
01763 
01764     if ( param_name.size() > 0) {
01765         if ( param_name[0] != '@') {
01766             param_name = "@" + param_name;
01767         }
01768     } else {
01769         throw CProgrammingError("Invalid SQL parameter name");
01770     }
01771 
01772     try {
01773         m_Stmt->SetParam( value, param_name );
01774     }
01775     catch(const CDB_Exception& e) {
01776         throw CDatabaseError(e);
01777     }
01778     catch(const CException& e) {
01779         throw CDatabaseError( e.what() );
01780     }
01781 }
01782 
01783 void
01784 CStmtHelper::Execute(void)
01785 {
01786     _ASSERT( m_Stmt.get() );
01787 
01788     try {
01789         m_RS.reset();
01790         switch ( m_StmtStr.GetType() ) {
01791         case estSelect :
01792             m_Stmt->Execute ( m_StmtStr.GetStr() );
01793             break;
01794         default:
01795             m_Stmt->ExecuteUpdate ( m_StmtStr.GetStr() );
01796         }
01797         m_Executed = true;
01798     }
01799     catch(const bad_cast&) {
01800         throw CInternalError("std::bad_cast exception within 'CStmtHelper::Execute'");
01801     }
01802     catch(const CDB_Exception& e) {
01803         throw CDatabaseError(e);
01804     }
01805     catch(const CException& e) {
01806         throw CDatabaseError(e.what());
01807     }
01808     catch(const exception&) {
01809         throw CInternalError("std::exception exception within 'CStmtHelper::Execute'");
01810     }
01811 }
01812 
01813 long
01814 CStmtHelper::GetRowCount(void) const
01815 {
01816     if ( m_Executed ) {
01817         return m_Stmt->GetRowCount();
01818     }
01819     return -1;                          // As required by the specification ...
01820 }
01821 
01822 IResultSet&
01823 CStmtHelper::GetRS(void)
01824 {
01825     if ( m_RS.get() == NULL ) {
01826         throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
01827     }
01828 
01829     return *m_RS;
01830 }
01831 
01832 const IResultSet&
01833 CStmtHelper::GetRS(void) const
01834 {
01835     if ( m_RS.get() == NULL ) {
01836         throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
01837     }
01838 
01839     return *m_RS;
01840 }
01841 
01842 bool
01843 CStmtHelper::HasRS(void) const
01844 {
01845     return m_RS.get() != NULL;
01846 }
01847 
01848 int
01849 CStmtHelper::GetReturnStatus(void)
01850 {
01851     if ( !m_ResultStatusAvailable ) {
01852         throw CDatabaseError("Procedure return code is not defined within this context.");
01853     }
01854     return m_ResultStatus;
01855 }
01856 
01857 bool
01858 CStmtHelper::MoveToNextRS(void)
01859 {
01860     _ASSERT( m_Stmt.get() );
01861 
01862     try {
01863         while ( m_Stmt->HasMoreResults() ) {
01864             if ( m_Stmt->HasRows() ) {
01865                 m_RS.reset(m_Stmt->GetResultSet());
01866                 if ( m_RS->GetResultType() == eDB_StatusResult ) {
01867                     m_RS->Next();
01868                     m_ResultStatus = m_RS->GetVariant(1).GetInt4();
01869                     m_ResultStatusAvailable = true;
01870                     m_RS.reset();
01871                 }
01872                 else {
01873                     return true;
01874                 }
01875             }
01876         }
01877     }
01878     catch(const CDB_Exception& e) {
01879         throw CDatabaseError(e);
01880     }
01881     catch(const CException& e) {
01882         throw CDatabaseError(e.what());
01883     }
01884 
01885     return false;
01886 }
01887 
01888 static void
01889 s_FillDescription(pythonpp::CList& descr, const IResultSetMetaData* data)
01890 {
01891     descr.Clear();
01892 
01893     unsigned int cnt = data->GetTotalColumns();
01894     for (unsigned int i = 1; i <= cnt; ++i) {
01895         pythonpp::CList col_list;
01896         IncRefCount(col_list);
01897         col_list.Append(pythonpp::CString(data->GetName(i)));
01898         switch (data->GetType(i)) {
01899         case eDB_Int:
01900         case eDB_SmallInt:
01901         case eDB_TinyInt:
01902         case eDB_BigInt:
01903         case eDB_Float:
01904         case eDB_Double:
01905         case eDB_Bit:
01906         case eDB_Numeric:
01907             col_list.Append((PyObject*) &python::CNumber::GetType());
01908             break;
01909         case eDB_VarChar:
01910         case eDB_Char:
01911         case eDB_LongChar:
01912         case eDB_Text:
01913             col_list.Append((PyObject*) &python::CStringType::GetType());
01914             break;
01915         case eDB_VarBinary:
01916         case eDB_Binary:
01917         case eDB_LongBinary:
01918         case eDB_Image:
01919             col_list.Append((PyObject*) &python::CBinary::GetType());
01920             break;
01921         case eDB_DateTime:
01922         case eDB_SmallDateTime:
01923             col_list.Append((PyObject*) &python::CDateTimeType::GetType());
01924             break;
01925         default:
01926             throw CInternalError("Invalid type of the column: "
01927                                  + NStr::IntToString(int(data->GetType(i))));
01928         };
01929         col_list.Append(pythonpp::CNone());  // display_size
01930         col_list.Append(pythonpp::CInt(data->GetMaxSize(i)));  // internal_size
01931         col_list.Append(pythonpp::CNone());  // precision
01932         col_list.Append(pythonpp::CNone());  // scale
01933         col_list.Append(pythonpp::CNone());  // null_ok
01934 
01935         descr.Append(col_list);
01936     }
01937 }
01938 
01939 void
01940 CStmtHelper::FillDescription(pythonpp::CList& descr)
01941 {
01942     s_FillDescription(descr, m_RS->GetMetaData());
01943 }
01944 
01945 //////////////////////////////////////////////////////////////////////////////
01946 CCallableStmtHelper::CCallableStmtHelper(CTransaction* trans)
01947 : m_ParentTransaction( trans )
01948 , m_Executed( false )
01949 , m_ResultStatus( 0 )
01950 , m_ResultStatusAvailable( false )
01951 , m_UserHandler(NULL)
01952 {
01953     if ( m_ParentTransaction == NULL ) {
01954         throw CInternalError("Invalid CTransaction object");
01955     }
01956 }
01957 
01958 CCallableStmtHelper::CCallableStmtHelper(CTransaction* trans, const CStmtStr& stmt)
01959 : m_ParentTransaction( trans )
01960 , m_StmtStr( stmt )
01961 , m_Executed( false )
01962 , m_ResultStatus( 0 )
01963 , m_ResultStatusAvailable( false )
01964 , m_UserHandler(NULL)
01965 {
01966     if ( m_ParentTransaction == NULL ) {
01967         throw CInternalError("Invalid CTransaction object");
01968     }
01969 
01970     CreateStmt(NULL);
01971 }
01972 
01973 CCallableStmtHelper::~CCallableStmtHelper(void)
01974 {
01975     try {
01976         Close();
01977     }
01978     NCBI_CATCH_ALL_X( 4, NCBI_CURRENT_FUNCTION )
01979 }
01980 
01981 void
01982 CCallableStmtHelper::Close(void)
01983 {
01984     DumpResult();
01985     ReleaseStmt();
01986     m_Executed = false;
01987     m_ResultStatus = 0;
01988     m_ResultStatusAvailable = false;
01989 }
01990 
01991 void
01992 CCallableStmtHelper::DumpResult(void)
01993 {
01994     if ( m_Stmt.get() ) {
01995         if (m_RSProxy.get()) {
01996             m_RSProxy->DumpResult();
01997         }
01998     }
01999 }
02000 
02001 void
02002 CCallableStmtHelper::ReleaseStmt(void)
02003 {
02004     if ( m_Stmt.get() ) {
02005         IConnection* conn = m_Stmt->GetParentConn();
02006 
02007         // Release the statement before a connection release because it is a child object for a connection.
02008         m_Stmt.reset();
02009 
02010         _ASSERT( m_StmtStr.GetType() != estNone );
02011 
02012         if (m_UserHandler) {
02013             conn->GetCDB_Connection()->PopMsgHandler(m_UserHandler);
02014             m_UserHandler = NULL;
02015         }
02016 
02017         // Release DML Connection ...
02018         m_ParentTransaction->DestroyDMLConnection( conn );
02019         m_Executed = false;
02020         m_ResultStatus = 0;
02021         m_ResultStatusAvailable = false;
02022     }
02023 }
02024 
02025 void
02026 CCallableStmtHelper::CreateStmt(CDB_UserHandler* handler)
02027 {
02028     _ASSERT( m_StmtStr.GetType() == estFunction );
02029 
02030     ReleaseStmt();
02031     m_Stmt.reset( m_ParentTransaction->CreateDMLConnection()->GetCallableStatement(m_StmtStr.GetStr()) );
02032 
02033     if (handler) {
02034         m_Stmt->GetParentConn()->GetCDB_Connection()->PushMsgHandler(handler);
02035         m_UserHandler = handler;
02036     }
02037 }
02038 
02039 void
02040 CCallableStmtHelper::SetStr(const CStmtStr& stmt, CDB_UserHandler* handler)
02041 {
02042     m_StmtStr = stmt;
02043 
02044     DumpResult();
02045     CreateStmt(handler);
02046 
02047     m_Executed = false;
02048     m_ResultStatus = 0;
02049     m_ResultStatusAvailable = false;
02050 }
02051 
02052 void
02053 CCallableStmtHelper::SetParam(const string& name, const CVariant& value, bool& output_param)
02054 {
02055     _ASSERT( m_Stmt.get() );
02056 
02057     string param_name = name;
02058 
02059     if ( param_name.size() > 0) {
02060         if ( param_name[0] != '@') {
02061             param_name = "@" + param_name;
02062         }
02063     } else {
02064         throw CProgrammingError("Invalid SQL parameter name");
02065     }
02066 
02067     try {
02068         if (m_Stmt->GetParamsMetaData().GetDirection(name) == CDBParams::eIn) {
02069             m_Stmt->SetParam( value, param_name );
02070             output_param = false;
02071         } else {
02072             m_Stmt->SetOutputParam( value, param_name );
02073             output_param = true;
02074         }
02075     }
02076     catch(const CDB_Exception& e) {
02077         throw CDatabaseError(e);
02078     }
02079     catch(const CException& e) {
02080         throw CDatabaseError( e.what() );
02081     }
02082 }
02083 
02084 void
02085 CCallableStmtHelper::Execute(bool cache_results)
02086 {
02087     _ASSERT( m_Stmt.get() );
02088 
02089     try {
02090         m_ResultStatus = 0;
02091         m_ResultStatusAvailable = false;
02092 
02093         m_Stmt->Execute();
02094 
02095         // Retrieve a resut if there is any ...
02096         if (cache_results) {
02097             m_RSProxy.reset(new CVariantSetProxy(*m_Stmt));
02098         } else {
02099             m_RSProxy.reset(new CRealSetProxy(*m_Stmt));
02100         }
02101         m_Executed = true;
02102     }
02103     catch(const bad_cast&) {
02104         throw CInternalError("std::bad_cast exception within 'CCallableStmtHelper::Execute'");
02105     }
02106     catch(const CDB_Exception& e) {
02107         throw CDatabaseError(e);
02108     }
02109     catch(const CException& e) {
02110         throw CDatabaseError(e.what());
02111     }
02112     catch(const exception&) {
02113         throw CInternalError("std::exception exception within 'CCallableStmtHelper::Execute'");
02114     }
02115 }
02116 
02117 long
02118 CCallableStmtHelper::GetRowCount(void) const
02119 {
02120     if ( m_Executed ) {
02121         return m_Stmt->GetRowCount();
02122     }
02123     return -1;                          // As required by the specification ...
02124 }
02125 
02126 CVariantSet&
02127 CCallableStmtHelper::GetRS(void)
02128 {
02129     if ( m_RSProxy.get() == NULL ) {
02130         throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
02131     }
02132 
02133     return m_RSProxy->GetRS();
02134 }
02135 
02136 const CVariantSet&
02137 CCallableStmtHelper::GetRS(void) const
02138 {
02139     if ( m_RSProxy.get() == NULL ) {
02140         throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
02141     }
02142 
02143     return m_RSProxy->GetRS();
02144 }
02145 
02146 bool
02147 CCallableStmtHelper::HasRS(void) const
02148 {
02149     if (m_RSProxy.get()) {
02150         return m_RSProxy->HasRS();
02151     }
02152 
02153     return false;
02154 }
02155 
02156 int
02157 CCallableStmtHelper::GetReturnStatus(void)
02158 {
02159     if ( !m_ResultStatusAvailable ) {
02160         throw CDatabaseError("Procedure return code is not defined within this context.");
02161     }
02162     return m_Stmt->GetReturnStatus();
02163 }
02164 
02165 bool
02166 CCallableStmtHelper::MoveToNextRS(void)
02167 {
02168     if ( m_RSProxy.get() == NULL ) {
02169         throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
02170     }
02171 
02172     bool result = m_RSProxy->MoveToNextRS();
02173 
02174     if (!result) {
02175         m_ResultStatusAvailable = true;
02176     }
02177 
02178     return result;
02179 }
02180 
02181 bool 
02182 CCallableStmtHelper::MoveToLastRS(void)
02183 {
02184     if ( m_RSProxy.get() == NULL ) {
02185         throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
02186     }
02187 
02188     return m_RSProxy->MoveToLastRS();
02189 }
02190 
02191 void
02192 CCallableStmtHelper::FillDescription(pythonpp::CList& descr)
02193 {
02194     s_FillDescription(descr, &m_RSProxy->GetRS().GetMetaData());
02195 }
02196 
02197 
02198 //////////////////////////////////////////////////////////////////////////////
02199 pythonpp::CObject
02200 ConvertCVariant2PCObject(const CVariant& value)
02201 {
02202     if ( value.IsNull() ) {
02203     return pythonpp::CObject();
02204     }
02205 
02206     switch ( value.GetType() ) {
02207     case eDB_Int :
02208         return pythonpp::CInt( value.GetInt4() );
02209     case eDB_SmallInt :
02210         return pythonpp::CInt( value.GetInt2() );
02211     case eDB_TinyInt :
02212         return pythonpp::CInt( value.GetByte() );
02213     case eDB_BigInt :
02214         return pythonpp::CLong( value.GetInt8() );
02215     case eDB_Float :
02216         return pythonpp::CFloat( value.GetFloat() );
02217     case eDB_Double :
02218         return pythonpp::CFloat( value.GetDouble() );
02219     case eDB_Bit :
02220         // BIT --> BOOL ...
02221         return pythonpp::CBool( value.GetBit() );
02222 #if PY_VERSION_HEX >= 0x02040000
02223     case eDB_DateTime :
02224     case eDB_SmallDateTime :
02225         {
02226         const CTime& cur_time = value.GetCTime();
02227         return pythonpp::CDateTime(
02228             cur_time.Year(),
02229             cur_time.Month(),
02230             cur_time.Day(),
02231             cur_time.Hour(),
02232             cur_time.Minute(),
02233             cur_time.Second(),
02234             cur_time.NanoSecond() / 1000
02235             );
02236         }
02237 #endif
02238     case eDB_VarChar :
02239     case eDB_Char :
02240     case eDB_LongChar :
02241         {
02242         string str = value.GetString();
02243         return pythonpp::CString( str );
02244         }
02245     case eDB_LongBinary :
02246     case eDB_VarBinary :
02247     case eDB_Binary :
02248     case eDB_Numeric :
02249         return pythonpp::CString( value.GetString() );
02250     case eDB_Text :
02251     case eDB_Image :
02252         {
02253         size_t lob_size = value.GetBlobSize();
02254         string tmp_str;
02255 
02256         tmp_str.resize(lob_size);
02257         value.Read( (void*)tmp_str.c_str(), lob_size );
02258         return pythonpp::CString(tmp_str);
02259         }
02260     case eDB_UnsupportedType :
02261         break;
02262     default:
02263         // All cases are supposed to be handled.
02264         // In case of PY_VERSION_HEX < 0x02040000 eDB_DateTime and
02265         // eDB_SmallDateTime will be missed.
02266         break;
02267     }
02268 
02269     return pythonpp::CObject();
02270 }
02271 
02272 //////////////////////////////////////////////////////////////////////////////
02273 pythonpp::CTuple
02274 MakeTupleFromResult(IResultSet& rs)
02275 {
02276     // Previous implementation of GetColumnNo/GetTotalColumns used to return
02277     // invalid value ...
02278     // col_num = (col_num > 0 ? col_num - 1 : col_num);
02279 
02280     // Set data. Make a sequence (tuple) ...
02281     int col_num = rs.GetTotalColumns();
02282 
02283     pythonpp::CTuple tuple(col_num);
02284 
02285     for ( int i = 0; i < col_num; ++i) {
02286         const CVariant& value = rs.GetVariant (i + 1);
02287 
02288         tuple[i] = ConvertCVariant2PCObject(value);
02289     }
02290 
02291     return tuple;
02292 }
02293 
02294 //////////////////////////////////////////////////////////////////////////////
02295 pythonpp::CTuple
02296 MakeTupleFromResult(CVariantSet& rs)
02297 {
02298     // Set data. Make a sequence (tuple) ...
02299     int col_num = rs.GetTotalColumns();
02300 
02301     pythonpp::CTuple tuple(col_num);
02302 
02303     for ( int i = 0; i < col_num; ++i) {
02304         const CVariant& value = rs.GetVariant (i + 1);
02305 
02306         tuple[i] = ConvertCVariant2PCObject(value);
02307     }
02308 
02309     return tuple;
02310 }
02311 
02312 
02313 bool CInfoHandler_CursorCollect::HandleIt(CDB_Exception* ex)
02314 {
02315     if (ex->GetSybaseSeverity() <= 10) {
02316         m_Cursor->AddInfoMessage(ex->GetMsg());
02317         return true;
02318     }
02319 
02320     return false;
02321 }
02322 
02323 
02324 //////////////////////////////////////////////////////////////////////////////
02325 CCursor::CCursor(CTransaction* trans)
02326 : m_PythonConnection( &trans->GetParentConnection() )
02327 , m_PythonTransaction( trans )
02328 , m_ParentTransaction( trans )
02329 , m_NumOfArgs( 0 )
02330 , m_RowsNum( -1 )
02331 , m_InfoHandler( this )
02332 , m_ArraySize( 1 )
02333 , m_StmtHelper( trans )
02334 , m_CallableStmtHelper( trans )
02335 , m_AllDataFetched( false )
02336 , m_AllSetsFetched( false )
02337 {
02338     if ( trans == NULL ) {
02339         throw CInternalError("Invalid CTransaction object");
02340     }
02341 
02342     ROAttr( "rowcount", m_RowsNum );
02343     ROAttr( "messages", m_InfoMessages );
02344     ROAttr( "description", m_Description );
02345 
02346     IncRefCount(m_InfoMessages);
02347     IncRefCount(m_DescrList);
02348 
02349     m_Description = pythonpp::CNone();
02350 
02351     PrepareForPython(this);
02352 }
02353 
02354 CCursor::~CCursor(void)
02355 {
02356     try {
02357         CloseInternal();
02358 
02359         // Unregister this cursor with the parent transaction ...
02360         GetTransaction().DestroyCursor(this);
02361     }
02362     NCBI_CATCH_ALL_X( 5, NCBI_CURRENT_FUNCTION )
02363 }
02364 
02365 void
02366 CCursor::CloseInternal(void)
02367 {
02368     m_StmtHelper.Close();
02369     m_CallableStmtHelper.Close();
02370     m_RowsNum = -1;                     // As required by the specification ...
02371     m_AllDataFetched = false;
02372     m_AllSetsFetched = false;
02373 }
02374 
02375 void
02376 CCursor::AddInfoMessage(const string& message)
02377 {
02378     m_InfoMessages.Append(pythonpp::CString(message));
02379 }
02380 
02381 pythonpp::CObject
02382 CCursor::callproc(const pythonpp::CTuple& args)
02383 {
02384     try {
02385         const size_t args_size = args.size();
02386 
02387         m_RowsNum = -1;                     // As required by the specification ...
02388         m_AllDataFetched = false;
02389         m_AllSetsFetched = false;
02390         bool has_out_params = false;
02391 
02392         if ( args_size == 0 ) {
02393             throw CProgrammingError("A stored procedure name is expected as a parameter");
02394         } else if ( args_size > 0 ) {
02395             pythonpp::CObject obj(args[0]);
02396 
02397             if ( pythonpp::CString::HasSameType(obj) ) {
02398                 m_StmtStr.SetStr(pythonpp::CString(args[0]), estFunction);
02399             } else {
02400                 throw CProgrammingError("A stored procedure name is expected as a parameter");
02401             }
02402 
02403             m_StmtHelper.Close();
02404 
02405             // Setup parameters ...
02406             if ( args_size > 1 ) {
02407                 pythonpp::CObject obj( args[1] );
02408 
02409                 if ( pythonpp::CDict::HasSameType(obj) ) {
02410                     const pythonpp::CDict dict = obj;
02411 
02412                     m_CallableStmtHelper.SetStr(m_StmtStr, &m_InfoHandler);
02413                     has_out_params = SetupParameters(dict, m_CallableStmtHelper);
02414                 } else  {
02415                     // Currently, NCBI DBAPI supports parameter binding by name only ...
02416                     //            pythonpp::CSequence sequence;
02417                     //            if ( pythonpp::CList::HasSameType(obj) ) {
02418                     //            } else if ( pythonpp::CTuple::HasSameType(obj) ) {
02419                     //            } else if ( pythonpp::CSet::HasSameType(obj) ) {
02420                     //            }
02421                     throw CNotSupportedError("NCBI DBAPI supports parameter binding by name only");
02422                 }
02423             } else {
02424                 m_CallableStmtHelper.SetStr(m_StmtStr, &m_InfoHandler);
02425             }
02426         }
02427 
02428         m_InfoMessages.Clear();
02429         m_CallableStmtHelper.Execute(has_out_params);
02430         m_RowsNum = m_CallableStmtHelper.GetRowCount();
02431 
02432         if ( args_size > 1 && has_out_params) {
02433             // If we have input parameters ...
02434             pythonpp::CObject output_args( args[1] );
02435 
02436             if (m_CallableStmtHelper.MoveToLastRS() && m_CallableStmtHelper.HasRS() ) {
02437                 // We can have out/inout arguments ...
02438                 CVariantSet& rs = m_CallableStmtHelper.GetRS();
02439 
02440                 if ( rs.GetResultType() == eDB_ParamResult ) {
02441                     // We've got ParamResult with output arguments ...
02442                     if ( rs.Next() ) {
02443                         int col_num = rs.GetTotalColumns();
02444                         const IResultSetMetaData& md = rs.GetMetaData();
02445 
02446                         for ( int i = 0; i < col_num; ++i) {
02447                             const CVariant& value = rs.GetVariant (i + 1);
02448 
02449                             if ( pythonpp::CDict::HasSameType(output_args) ) {
02450                                 // Dictionary ...
02451                                 pythonpp::CDict dict = output_args;
02452                                 const string param_name = md.GetName(i + 1);
02453 
02454                                 dict.SetItem(param_name, ConvertCVariant2PCObject(value));
02455                             } else  {
02456                                 // tuple[i] = ConvertCVariant2PCObject(value);
02457                                 // Curently, NCBI DBAPI supports pameter binding by name only ...
02458                                 //            pythonpp::CSequence sequence;
02459                                 //            if ( pythonpp::CList::HasSameType(obj) ) {
02460                                 //            } else if ( pythonpp::CTuple::HasSameType(obj) ) {
02461                                 //            } else if ( pythonpp::CSet::HasSameType(obj) ) {
02462                                 //            }
02463                                 throw CNotSupportedError("NCBI DBAPI supports pameter binding by name only");
02464                             }
02465                         }
02466                     }
02467                 }
02468             }
02469 
02470             // Get RowResultSet ...
02471             if (m_CallableStmtHelper.MoveToNextRS()) {
02472                 m_CallableStmtHelper.FillDescription(m_DescrList);
02473                 m_Description = m_DescrList;
02474             }
02475             else {
02476                 m_AllDataFetched = m_AllSetsFetched = true;
02477                 m_Description = pythonpp::CNone();
02478             }
02479 
02480             return output_args;
02481         }
02482     }
02483     catch(const CDB_Exception& e) {
02484         throw CDatabaseError(e);
02485     }
02486     catch(const CException& e) {
02487         throw CDatabaseError(e.what());
02488     }
02489 
02490     // Get RowResultSet ...
02491     if (m_CallableStmtHelper.MoveToNextRS()) {
02492         m_CallableStmtHelper.FillDescription(m_DescrList);
02493         m_Description = m_DescrList;
02494     }
02495     else {
02496         m_AllDataFetched = m_AllSetsFetched = true;
02497         m_Description = pythonpp::CNone();
02498     }
02499 
02500     return pythonpp::CNone();
02501 
02502 }
02503 
02504 pythonpp::CObject
02505 CCursor::close(const pythonpp::CTuple& args)
02506 {
02507     try {
02508         CloseInternal();
02509 
02510         // Unregister this cursor with the parent transaction ...
02511         GetTransaction().DestroyCursor(this);
02512     }
02513     catch(const CDB_Exception& e) {
02514         throw CDatabaseError(e);
02515     }
02516     catch(const CException& e) {
02517         throw CDatabaseError(e.what());
02518     }
02519 
02520     return pythonpp::CNone();
02521 }
02522 
02523 pythonpp::CObject
02524 CCursor::execute(const pythonpp::CTuple& args)
02525 {
02526     try {
02527         const size_t args_size = args.size();
02528 
02529         m_AllDataFetched = false;
02530         m_AllSetsFetched = false;
02531 
02532         // Process function's arguments ...
02533         if ( args_size == 0 ) {
02534             throw CProgrammingError("An SQL statement string is expected as a parameter");
02535         } else if ( args_size > 0 ) {
02536             pythonpp::CObject obj(args[0]);
02537 
02538             if ( pythonpp::CString::HasSameType(obj) ) {
02539                 m_StmtStr.SetStr(pythonpp::CString(args[0]), estSelect);
02540             } else {
02541                 throw CProgrammingError("An SQL statement string is expected as a parameter");
02542             }
02543 
02544             m_CallableStmtHelper.Close();
02545             m_StmtHelper.SetStr(m_StmtStr, &m_InfoHandler);
02546 
02547             // Setup parameters ...
02548             if ( args_size > 1 ) {
02549                 pythonpp::CObject obj(args[1]);
02550 
02551                 if ( pythonpp::CDict::HasSameType(obj) ) {
02552                     SetupParameters(obj, m_StmtHelper);
02553                 } else  {
02554                     // Curently, NCBI DBAPI supports parameter binding by name only ...
02555                     //            pythonpp::CSequence sequence;
02556                     //            if ( pythonpp::CList::HasSameType(obj) ) {
02557                     //            } else if ( pythonpp::CTuple::HasSameType(obj) ) {
02558                     //            } else if ( pythonpp::CSet::HasSameType(obj) ) {
02559                     //            }
02560                     throw CNotSupportedError("NCBI DBAPI supports pameter binding by name only");
02561                 }
02562             }
02563         }
02564 
02565         m_InfoMessages.Clear();
02566         m_StmtHelper.Execute();
02567         m_RowsNum = m_StmtHelper.GetRowCount();
02568 
02569         if (m_StmtHelper.MoveToNextRS()) {
02570             m_StmtHelper.FillDescription(m_DescrList);
02571             m_Description = m_DescrList;
02572         }
02573         else {
02574             m_AllDataFetched = m_AllSetsFetched = true;
02575             m_Description = pythonpp::CNone();
02576         }
02577     }
02578     catch(const CDB_Exception& e) {
02579         throw CDatabaseError(e);
02580     }
02581     catch(const CException& e) {
02582         throw CDatabaseError(e.what());
02583     }
02584 
02585     return pythonpp::CNone();
02586 }
02587 
02588 void
02589 CCursor::SetupParameters(const pythonpp::CDict& dict, CStmtHelper& stmt)
02590 {
02591     // Iterate over a dict.
02592     pythonpp::py_ssize_t i = 0;
02593     PyObject* key;
02594     PyObject* value;
02595     while ( PyDict_Next(dict, &i, &key, &value) ) {
02596         // Refer to borrowed references in key and value.
02597         const pythonpp::CObject key_obj(key);
02598         const pythonpp::CObject value_obj(value);
02599         string param_name = pythonpp::CString(key_obj);
02600 
02601         stmt.SetParam(param_name, GetCVariant(value_obj));
02602     }
02603 }
02604 
02605 bool
02606 CCursor::SetupParameters(const pythonpp::CDict& dict, CCallableStmtHelper& stmt)
02607 {
02608     // Iterate over a dict.
02609     pythonpp::py_ssize_t i = 0;
02610     PyObject* key;
02611     PyObject* value;
02612     bool result = false;
02613     bool output_param = false;
02614 
02615     while ( PyDict_Next(dict, &i, &key, &value) ) {
02616         // Refer to borrowed references in key and value.
02617         const pythonpp::CObject key_obj(key);
02618         const pythonpp::CObject value_obj(value);
02619         string param_name = pythonpp::CString(key_obj);
02620 
02621         stmt.SetParam(param_name, GetCVariant(value_obj), output_param);
02622         result |= output_param;
02623     }
02624 
02625     return result;
02626 }
02627 
02628 CVariant
02629 CCursor::GetCVariant(const pythonpp::CObject& obj) const
02630 {
02631     if ( pythonpp::CNone::HasSameType(obj) ) {
02632         return CVariant(eDB_VarChar);
02633     } else if ( pythonpp::CBool::HasSameType(obj) ) {
02634         return CVariant( pythonpp::CBool(obj) );
02635     } else if ( pythonpp::CInt::HasSameType(obj) ) {
02636         return CVariant( static_cast<int>(pythonpp::CInt(obj)) );
02637     } else if ( pythonpp::CLong::HasSameType(obj) ) {
02638         return CVariant( static_cast<Int8>(pythonpp::CLong(obj)) );
02639     } else if ( pythonpp::CFloat::HasSameType(obj) ) {
02640         return CVariant( pythonpp::CFloat(obj) );
02641     } else if ( pythonpp::CString::HasSameType(obj) ) {
02642         const pythonpp::CString python_str(obj);
02643         const string std_str(python_str);
02644         return CVariant( std_str );
02645     } else if (obj == CBinary::GetType()) {
02646         const string value = static_cast<CBinary*>(obj.Get())->GetValue();
02647         return CVariant::VarBinary(value.c_str(), value.size());
02648     }
02649 
02650     return CVariant(eDB_UnsupportedType);
02651 }
02652 
02653 pythonpp::CObject
02654 CCursor::executemany(const pythonpp::CTuple& args)
02655 {
02656     try {
02657         const size_t args_size = args.size();
02658 
02659         m_AllDataFetched = false;
02660         m_AllSetsFetched = false;
02661 
02662         // Process function's arguments ...
02663         if ( args_size == 0 ) {
02664             throw CProgrammingError("A SQL statement string is expected as a parameter");
02665         } else if ( args_size > 0 ) {
02666             pythonpp::CObject obj(args[0]);
02667 
02668             if ( pythonpp::CString::HasSameType(obj) ) {
02669                 m_StmtStr.SetStr(pythonpp::CString(args[0]), estSelect);
02670             } else {
02671                 throw CProgrammingError("A SQL statement string is expected as a parameter");
02672             }
02673 
02674             // Setup parameters ...
02675             if ( args_size > 1 ) {
02676                 pythonpp::CObject obj(args[1]);
02677 
02678                 if ( pythonpp::CList::HasSameType(obj) || pythonpp::CTuple::HasSameType(obj) ) {
02679                     const pythonpp::CSequence params(obj);
02680                     pythonpp::CList::const_iterator citer;
02681                     pythonpp::CList::const_iterator cend = params.end();
02682 
02683                     //
02684                     m_CallableStmtHelper.Close();
02685                     m_StmtHelper.SetStr( m_StmtStr, &m_InfoHandler );
02686                     m_RowsNum = 0;
02687                     m_InfoMessages.Clear();
02688 
02689                     for ( citer = params.begin(); citer != cend; ++citer ) {
02690                         SetupParameters(*citer, m_StmtHelper);
02691                         m_StmtHelper.Execute();
02692                         m_RowsNum += m_StmtHelper.GetRowCount();
02693                     }
02694 
02695                     if (m_StmtHelper.MoveToNextRS()) {
02696                         m_StmtHelper.FillDescription(m_DescrList);
02697                         m_Description = m_DescrList;
02698                     }
02699                     else {
02700                         m_AllDataFetched = m_AllSetsFetched = true;
02701                         m_Description = pythonpp::CNone();
02702                     }
02703                 } else {
02704                     throw CProgrammingError("Sequence of parameters should be provided either as a list or as a tuple data type");
02705                 }
02706             } else {
02707                 throw CProgrammingError("A sequence of parameters is expected with the 'executemany' function");
02708             }
02709         }
02710     }
02711     catch(const CDB_Exception& e) {
02712         throw CDatabaseError(e);
02713     }
02714     catch(const CException& e) {
02715         throw CDatabaseError(e.what());
02716     }
02717 
02718     return pythonpp::CNone();
02719 }
02720 
02721 pythonpp::CObject
02722 CCursor::fetchone(const pythonpp::CTuple& args)
02723 {
02724     try {
02725         if ( m_AllDataFetched ) {
02726             return pythonpp::CNone();
02727         }
02728         if ( m_StmtStr.GetType() == estFunction ) {
02729             CVariantSet& rs = m_CallableStmtHelper.GetRS();
02730 
02731             if ( rs.Next() ) {
02732                 m_RowsNum = m_CallableStmtHelper.GetRowCount();
02733                 return MakeTupleFromResult( rs );
02734             }
02735         } else {
02736             IResultSet& rs = m_StmtHelper.GetRS();
02737 
02738             if ( rs.Next() ) {
02739                 m_RowsNum = m_StmtHelper.GetRowCount();
02740                 return MakeTupleFromResult( rs );
02741             }
02742         }
02743     }
02744     catch (const CDB_Exception& e) {
02745         throw CDatabaseError(e);
02746     }
02747     catch (const CException& e) {
02748         throw CDatabaseError(e.what());
02749     }
02750 
02751     m_AllDataFetched = true;
02752     return pythonpp::CNone();
02753 }
02754 
02755 pythonpp::CObject
02756 CCursor::fetchmany(const pythonpp::CTuple& args)
02757 {
02758     size_t array_size = m_ArraySize;
02759 
02760     try {
02761         if ( args.size() > 0 ) {
02762             array_size = static_cast<unsigned long>(pythonpp::CLong(args[0]));
02763         }
02764     } catch (const pythonpp::CError&) {
02765         throw CProgrammingError("Invalid parameters within 'CCursor::fetchmany' function");
02766     }
02767 
02768     pythonpp::CList py_list;
02769     try {
02770         if ( m_AllDataFetched ) {
02771             return py_list;
02772         }
02773         if ( m_StmtStr.GetType() == estFunction ) {
02774             CVariantSet& rs = m_CallableStmtHelper.GetRS();
02775 
02776             size_t i = 0;
02777             for ( ; i < array_size && rs.Next(); ++i ) {
02778                 py_list.Append(MakeTupleFromResult(rs));
02779             }
02780 
02781             // We fetched less than expected ...
02782             if ( i < array_size ) {
02783                 m_AllDataFetched = true;
02784             }
02785 
02786             m_RowsNum = m_CallableStmtHelper.GetRowCount();
02787         } else {
02788             IResultSet& rs = m_StmtHelper.GetRS();
02789 
02790             size_t i = 0;
02791             for ( ; i < array_size && rs.Next(); ++i ) {
02792                 py_list.Append(MakeTupleFromResult(rs));
02793             }
02794 
02795             // We fetched less than expected ...
02796             if ( i < array_size ) {
02797                 m_AllDataFetched = true;
02798             }
02799 
02800             m_RowsNum = m_StmtHelper.GetRowCount();
02801         }
02802     }
02803     catch (const CDB_Exception& e) {
02804         throw CDatabaseError(e);
02805     }
02806     catch(const CException& e) {
02807         throw CDatabaseError(e.what());
02808     }
02809 
02810     return py_list;
02811 }
02812 
02813 pythonpp::CObject
02814 CCursor::fetchall(const pythonpp::CTuple& args)
02815 {
02816     pythonpp::CList py_list;
02817 
02818     try {
02819         if ( m_AllDataFetched ) {
02820             return py_list;
02821         }
02822 
02823         if ( m_StmtStr.GetType() == estFunction ) {
02824             if (m_CallableStmtHelper.HasRS()) {
02825                 CVariantSet& rs = m_CallableStmtHelper.GetRS();
02826 
02827                 while ( rs.Next() ) {
02828                     py_list.Append(MakeTupleFromResult(rs));
02829                 }
02830 
02831                 m_RowsNum = m_CallableStmtHelper.GetRowCount();
02832             }
02833         } else {
02834             if (m_StmtHelper.HasRS()) {
02835                 IResultSet& rs = m_StmtHelper.GetRS();
02836 
02837                 while ( rs.Next() ) {
02838                     py_list.Append(MakeTupleFromResult(rs));
02839                 }
02840 
02841                 m_RowsNum = m_StmtHelper.GetRowCount();
02842             }
02843         }
02844     }
02845     catch (const CDB_Exception& e) {
02846         throw CDatabaseError(e);
02847     }
02848     catch(const CException& e) {
02849         throw CDatabaseError(e.what());
02850     }
02851 
02852     m_AllDataFetched = true;
02853     return py_list;
02854 }
02855 
02856 bool
02857 CCursor::NextSetInternal(void)
02858 {
02859     try {
02860         m_RowsNum = 0;
02861 
02862         if ( !m_AllSetsFetched ) {
02863             if ( m_StmtStr.GetType() == estFunction ) {
02864                 if (m_CallableStmtHelper.HasRS()) {
02865                     if ( m_CallableStmtHelper.MoveToNextRS() ) {
02866                         m_AllDataFetched = false;
02867                         return true;
02868                     }
02869                 } else {
02870                     return false;
02871                 }
02872             } else {
02873                 if (m_StmtHelper.HasRS()) {
02874                     if ( m_StmtHelper.MoveToNextRS() ) {
02875                         m_AllDataFetched = false;
02876                         return true;
02877                     }
02878                 } else {
02879                     return false;
02880                 }
02881             }
02882         }
02883     }
02884     catch (const CDB_Exception& e) {
02885         throw CDatabaseError(e);
02886     }
02887     catch(const CException& e) {
02888         throw CDatabaseError(e.what());
02889     }
02890 
02891     m_AllDataFetched = true;
02892     m_AllSetsFetched = true;
02893 
02894     return false;
02895 }
02896 
02897 pythonpp::CObject
02898 CCursor::nextset(const pythonpp::CTuple& args)
02899 {
02900     try {
02901         if ( NextSetInternal() ) {
02902             if (m_StmtStr.GetType() == estFunction) {
02903                 m_CallableStmtHelper.FillDescription(m_DescrList);
02904             }
02905             else {
02906                 m_StmtHelper.FillDescription(m_DescrList);
02907             }
02908             m_Description = m_DescrList;
02909             return pythonpp::CBool(true);
02910         }
02911         m_Description = pythonpp::CNone();
02912     }
02913     catch (const CDB_Exception& e) {
02914         throw CDatabaseError(e);
02915     }
02916     catch(const CException& e) {
02917         throw CDatabaseError(e.what());
02918     }
02919 
02920     return pythonpp::CNone();
02921 }
02922 
02923 pythonpp::CObject
02924 CCursor::setinputsizes(const pythonpp::CTuple& args)
02925 {
02926     return pythonpp::CNone();
02927 }
02928 
02929 pythonpp::CObject
02930 CCursor::setoutputsize(const pythonpp::CTuple& args)
02931 {
02932     return pythonpp::CNone();
02933 }
02934 
02935 pythonpp::CObject
02936 CCursor::get_proc_return_status(const pythonpp::CTuple& args)
02937 {
02938     try {
02939         if ( !m_AllDataFetched ) {
02940             throw CDatabaseError("Call get_proc_return_status after you retrieve all data.");
02941         }
02942 
02943         NextSetInternal();
02944 
02945         if ( !m_AllSetsFetched ) {
02946             throw CDatabaseError("Call get_proc_return_status after you retrieve all data.");
02947         }
02948 
02949         if ( m_StmtStr.GetType() == estFunction ) {
02950             return pythonpp::CInt( m_CallableStmtHelper.GetReturnStatus() );
02951         } else {
02952             return pythonpp::CInt( m_StmtHelper.GetReturnStatus() );
02953         }
02954     }
02955     catch (const CDB_Exception& e) {
02956         throw CDatabaseError(e);
02957     }
02958     catch(const CException& e) {
02959         throw CDatabaseError(e.what());
02960     }
02961 
02962     return pythonpp::CNone();
02963 }
02964 
02965 
02966 ///////////////////////////////////////////////////////////////////////////////
02967 CWarning::CWarning(const string& msg)
02968 : pythonpp::CUserError<CWarning>( msg )
02969 {
02970 }
02971 
02972 ///////////////////////////////////////////////////////////////////////////////
02973 CError::CError(void)
02974 {
02975 }
02976 
02977 CError::CError(const string& msg)
02978 : pythonpp::CUserError<CError>( msg )
02979 {
02980 }
02981 
02982 CError::CError(const string& msg, PyObject* err_type)
02983 : pythonpp::CUserError<CError>(msg, err_type)
02984 {
02985 }
02986 
02987 ///////////////////////////////////////////////////////////////////////////////
02988 CInterfaceError::CInterfaceError(const string& msg)
02989 : pythonpp::CUserError<CInterfaceError, CError>( msg )
02990 {
02991 }
02992 
02993 ///////////////////////////////////////////////////////////////////////////////
02994 CDatabaseError::CDatabaseError(const CDB_Exception& e)
02995 : pythonpp::CUserError<CDatabaseError, CError>()
02996 {
02997     const CException* cur_exception = &e;
02998     string srv_msg;
02999 
03000     for (; cur_exception; cur_exception = cur_exception->GetPredecessor()) {
03001         /* Collect all messages ...
03002         if (!srv_msg.empty() && !cur_exception->GetMsg().empty()) {
03003             srv_msg += " ";
03004         }
03005 
03006         srv_msg += cur_exception->GetMsg();
03007         */
03008 
03009         // Get the last message only ...
03010         srv_msg = cur_exception->GetMsg();
03011     }
03012 
03013     SetPythonExeption(e.what(), e.GetDBErrCode(), srv_msg);
03014 }
03015 
03016 CDatabaseError::CDatabaseError(const string& msg, long db_errno, const string& db_msg)
03017 : pythonpp::CUserError<CDatabaseError, CError>()
03018 {
03019     SetPythonExeption(msg, db_errno, db_msg);
03020 }
03021 
03022 CDatabaseError::CDatabaseError(const string& msg, PyObject* err_type)
03023 : pythonpp::CUserError<CDatabaseError, CError>(msg, err_type)
03024 {
03025 }
03026 
03027 void 
03028 CDatabaseError::SetPythonExeption(const string& msg, long db_errno, const string& db_msg)
03029 {        
03030     PyObject *exc_ob = NULL;
03031     PyObject *errno_ob = NULL;
03032     PyObject *msg_ob = NULL;
03033 
03034     // Make an integer for the error code. 
03035     errno_ob = PyInt_FromLong(db_errno);
03036     if (errno_ob == NULL) {
03037         return;
03038     }
03039 
03040     msg_ob = PyString_FromString((char*)db_msg.c_str());
03041     if (errno_ob == NULL) {
03042         Py_DECREF(errno_ob);
03043         return;
03044     }
03045 
03046     // Instantiate a SubversionException object.
03047     exc_ob = PyObject_CallFunction(GetPyException(), (char *)"s", (char*)msg.c_str());
03048     if (exc_ob == NULL)
03049     {
03050         Py_DECREF(errno_ob);
03051         Py_DECREF(msg_ob);
03052         return;
03053     }
03054 
03055     //  Set the "db_errno" attribute of the exception to our error code.
03056     if (PyObject_SetAttrString(exc_ob, (char *)"srv_errno", errno_ob) == -1)
03057     {
03058         Py_DECREF(errno_ob);
03059         Py_DECREF(msg_ob);
03060         Py_DECREF(exc_ob);
03061         return;
03062     }
03063 
03064     //  Finished with the errno_ob object.
03065     Py_DECREF(errno_ob);
03066 
03067     //  Set the "db_msg" attribute of the exception to our message.
03068     if (PyObject_SetAttrString(exc_ob, (char *)"srv_msg", msg_ob) == -1)
03069     {
03070         Py_DECREF(msg_ob);
03071         Py_DECREF(exc_ob);
03072         return;
03073     }
03074 
03075     //  Finished with the msg_ob object.
03076     Py_DECREF(msg_ob);
03077     
03078     //  Set the error state to our exception object.
03079     PyErr_SetObject(GetPyException(), exc_ob);
03080 
03081     //  Finished with the exc_ob object.
03082     Py_DECREF(exc_ob);
03083 }
03084 
03085 ///////////////////////////////////////////////////////////////////////////////
03086 CInternalError::CInternalError(const string& msg)
03087 : pythonpp::CUserError<CInternalError, CDatabaseError>( msg )
03088 {
03089 }
03090 
03091 ///////////////////////////////////////////////////////////////////////////////
03092 COperationalError::COperationalError(const string& msg)
03093 : pythonpp::CUserError<COperationalError, CDatabaseError>( msg )
03094 {
03095 }
03096 
03097 ///////////////////////////////////////////////////////////////////////////////
03098 CProgrammingError::CProgrammingError(const string& msg)
03099 : pythonpp::CUserError<CProgrammingError, CDatabaseError>( msg )
03100 {
03101 }
03102 
03103 ///////////////////////////////////////////////////////////////////////////////
03104 CIntegrityError::CIntegrityError(const string& msg)
03105 : pythonpp::CUserError<CIntegrityError, CDatabaseError>( msg )
03106 {
03107 }
03108 
03109 ///////////////////////////////////////////////////////////////////////////////
03110 CDataError::CDataError(const string& msg)
03111 : pythonpp::CUserError<CDataError, CDatabaseError>( msg )
03112 {
03113 }
03114 
03115 ///////////////////////////////////////////////////////////////////////////////
03116 CNotSupportedError::CNotSupportedError(const string& msg)
03117 : pythonpp::CUserError<CNotSupportedError, CDatabaseError>( msg )
03118 {
03119 }
03120 
03121 ///////////////////////////////////////////////////////////////////////////////
03122 /* Future development ... 2/4/2005 12:05PM
03123 //////////////////////////////////////////////////////////////////////////////
03124 // Future development ...
03125 class CModuleDBAPI : public pythonpp::CExtModule<CModuleDBAPI>
03126 {
03127 public:
03128     CModuleDBAPI(const char* name, const char* descr = 0)
03129     : pythonpp::CExtModule<CModuleDBAPI>(name, descr)
03130     {
03131         PrepareForPython(this);
03132     }
03133 
03134 public:
03135     // connect(driver_name, db_type, db_name, user_name, user_pswd)
03136     pythonpp::CObject connect(const pythonpp::CTuple& args);
03137     pythonpp::CObject Binary(const pythonpp::CTuple& args);
03138     pythonpp::CObject TimestampFromTicks(const pythonpp::CTuple& args);
03139     pythonpp::CObject TimeFromTicks(const pythonpp::CTuple& args);
03140     pythonpp::CObject DateFromTicks(const pythonpp::CTuple& args);
03141     pythonpp::CObject Timestamp(const pythonpp::CTuple& args);
03142     pythonpp::CObject Time(const pythonpp::CTuple& args);
03143     pythonpp::CObject Date(const pythonpp::CTuple& args);
03144 };
03145 
03146 pythonpp::CObject
03147 CModuleDBAPI::connect(const pythonpp::CTuple& args)
03148 {
03149     string driver_name;
03150     string db_type;
03151     string server_name;
03152     string db_name;
03153     string user_name;
03154     string user_pswd;
03155 
03156     try {
03157         try {
03158             const pythonpp::CTuple func_args(args);
03159 
03160             driver_name = pythonpp::CString(func_args[0]);
03161             db_type = pythonpp::CString(func_args[1]);
03162             server_name = pythonpp::CString(func_args[2]);
03163             db_name = pythonpp::CString(func_args[3]);
03164             user_name = pythonpp::CString(func_args[4]);
03165             user_pswd = pythonpp::CString(func_args[5]);
03166         } catch (const pythonpp::CError&) {
03167             throw CProgrammingError("Invalid parameters within 'connect' function");
03168         }
03169 
03170         CConnection* conn = new CConnection( CConnParam(
03171             driver_name,
03172             db_type,
03173             server_name,
03174             db_name,
03175             user_name,
03176             user_pswd
03177             ));
03178 
03179         // Feef the object to the Python interpreter ...
03180         return pythonpp::CObject(conn, pythonpp::eTakeOwnership);
03181     }
03182     catch (const CDB_Exception& e) {
03183         throw CDatabaseError(e);
03184     }
03185     catch (const CException& e) {
03186         pythonpp::CError::SetString(e.what());
03187     }
03188 
03189     // Return a dummy object ...
03190     return pythonpp::CNone();
03191 }
03192 
03193 // This function constructs an object holding a date value.
03194 // Date(year,month,day)
03195 pythonpp::CObject
03196 CModuleDBAPI::Date(const pythonpp::CTuple& args)
03197 {
03198     try {
03199         int year;
03200         int month;
03201         int day;
03202 
03203         try {
03204             const pythonpp::CTuple func_args(args);
03205 
03206             year = pythonpp::CInt(func_args[0]);
03207             month = pythonpp::CInt(func_args[1]);
03208             day = pythonpp::CInt(func_args[2]);
03209         } catch (const pythonpp::CError&) {
03210             throw CProgrammingError("Invalid parameters within 'Date' function");
03211         }
03212 
03213         // Feef the object to the Python interpreter ...
03214         return pythonpp::CDate(year, month, day);
03215     }
03216     catch (const CDB_Exception& e) {
03217         throw CDatabaseError(e);
03218     }
03219     catch (const CException& e) {
03220         pythonpp::CError::SetString(e.what());
03221     }
03222 
03223     // Return a dummy object ...
03224     return pythonpp::CNone();
03225 }
03226 
03227 // This function constructs an object holding a time value.
03228 // Time(hour,minute,second)
03229 pythonpp::CObject
03230 CModuleDBAPI::Time(const pythonpp::CTuple& args)
03231 {
03232     try {
03233         int hour;
03234         int minute;
03235         int second;
03236 
03237         try {
03238             const pythonpp::CTuple func_args(args);
03239 
03240             hour = pythonpp::CInt(func_args[0]);
03241             minute = pythonpp::CInt(func_args[1]);
03242             second = pythonpp::CInt(func_args[2]);
03243         } catch (const pythonpp::CError&) {
03244             throw CProgrammingError("Invalid parameters within 'Time' function");
03245         }
03246 
03247         // Feef the object to the Python interpreter ...
03248         return pythonpp::CTime(hour, minute, second, 0);
03249     }
03250     catch (const CDB_Exception& e) {
03251         throw CDatabaseError(e);
03252     }
03253     catch (const CException& e) {
03254         pythonpp::CError::SetString(e.what());
03255     }
03256 
03257     // Return a dummy object ...
03258     return pythonpp::CNone();
03259 }
03260 
03261 // This function constructs an object holding a time stamp
03262 // value.
03263 // Timestamp(year,month,day,hour,minute,second)
03264 pythonpp::CObject
03265 CModuleDBAPI::Timestamp(const pythonpp::CTuple& args)
03266 {
03267     try {
03268         int year;
03269         int month;
03270         int day;
03271         int hour;
03272         int minute;
03273         int second;
03274 
03275         try {
03276             const pythonpp::CTuple func_args(args);
03277 
03278             year = pythonpp::CInt(func_args[0]);
03279             month = pythonpp::CInt(func_args[1]);
03280             day = pythonpp::CInt(func_args[2]);
03281             hour = pythonpp::CInt(func_args[3]);
03282             minute = pythonpp::CInt(func_args[4]);
03283             second = pythonpp::CInt(func_args[5]);
03284         } catch (const pythonpp::CError&) {
03285             throw CProgrammingError("Invalid parameters within 'Timestamp' function");
03286         }
03287 
03288         // Feef the object to the Python interpreter ...
03289         return pythonpp::CDateTime(year, month, day, hour, minute, second, 0);
03290     }
03291     catch (const CDB_Exception& e) {
03292         throw CDatabaseError(e);
03293     }
03294     catch (const CException& e) {
03295         pythonpp::CError::SetString(e.what());
03296     }
03297 
03298     // Return a dummy object ...
03299     return pythonpp::CNone();
03300 }
03301 
03302 // This function constructs an object holding a date value
03303 // from the given ticks value (number of seconds since the
03304 // epoch; see the documentation of the standard Python time
03305 // module for details).
03306 // DateFromTicks(ticks)
03307 pythonpp::CObject
03308 CModuleDBAPI::DateFromTicks(const pythonpp::CTuple& args)
03309 {
03310     try {
03311     }
03312     catch (const CDB_Exception& e) {
03313         throw CDatabaseError(e);
03314     }
03315     catch (const CException& e) {
03316         pythonpp::CError::SetString(e.what());
03317     }
03318 
03319     // Return a dummy object ...
03320     return pythonpp::CNone();
03321 }
03322 
03323 // This function constructs an object holding a time value
03324 // from the given ticks value (number of seconds since the
03325 // epoch; see the documentation of the standard Python time
03326 // module for details).
03327 // TimeFromTicks(ticks)
03328 pythonpp::CObject
03329 CModuleDBAPI::TimeFromTicks(const pythonpp::CTuple& args)
03330 {
03331     try {
03332     }
03333     catch (const CDB_Exception& e) {
03334         throw CDatabaseError(e);
03335     }
03336     catch (const CException& e) {
03337         pythonpp::CError::SetString(e.what());
03338     }
03339 
03340     // Return a dummy object ...
03341     return pythonpp::CNone();
03342 }
03343 
03344 // This function constructs an object holding a time stamp
03345 // value from the given ticks value (number of seconds since
03346 // the epoch; see the documentation of the standard Python
03347 // time module for details).
03348 // TimestampFromTicks(ticks)
03349 pythonpp::CObject
03350 CModuleDBAPI::TimestampFromTicks(const pythonpp::CTuple& args)
03351 {
03352     try {
03353     }
03354     catch (const CDB_Exception& e) {
03355         throw CDatabaseError(e);
03356     }
03357     catch (const CException& e) {
03358         pythonpp::CError::SetString(e.what());
03359     }
03360 
03361     // Return a dummy object ...
03362     return pythonpp::CNone();
03363 }
03364 
03365 // This function constructs an object capable of holding a
03366 // binary (long) string value.
03367 // Binary(string)
03368 pythonpp::CObject
03369 CModuleDBAPI::Binary(const pythonpp::CTuple& args)
03370 {
03371 
03372     try {
03373         string value;
03374 
03375         try {
03376             const pythonpp::CTuple func_args(args);
03377 
03378             value = pythonpp::CString(func_args[0]);
03379         } catch (const pythonpp::CError&) {
03380             throw CProgrammingError("Invalid parameters within 'Binary' function");
03381         }
03382 
03383         CBinary* obj = new CBinary(
03384             );
03385 
03386         // Feef the object to the Python interpreter ...
03387         return pythonpp::CObject(obj, pythonpp::eTakeOwnership);
03388     }
03389     catch (const CDB_Exception& e) {
03390         throw CDatabaseError(e);
03391     }
03392     catch (const CException& e) {
03393         pythonpp::CError::SetString(e.what());
03394     }
03395 
03396     return pythonpp::CNone();
03397 }
03398 
03399 */
03400 
03401 }
03402 
03403 /* Future development ... 2/4/2005 12:05PM
03404 // Module initialization
03405 PYDBAPI_MODINIT_FUNC(initpython_ncbi_dbapi)
03406 {
03407     // Initialize DateTime module ...
03408     PyDateTime_IMPORT;
03409 
03410     // Declare CBinary
03411     python::CBinary::Declare("python_ncbi_dbapi.BINARY");
03412 
03413     // Declare CNumber
03414     python::CNumber::Declare("python_ncbi_dbapi.NUMBER");
03415 
03416     // Declare CRowID
03417     python::CRowID::Declare("python_ncbi_dbapi.ROWID");
03418 
03419     // Declare CConnection
03420     python::CConnection::
03421         Def("close",        &python::CConnection::close,        "close").
03422         Def("commit",       &python::CConnection::commit,       "commit").
03423         Def("rollback",     &python::CConnection::rollback,     "rollback").
03424         Def("cursor",       &python::CConnection::cursor,       "cursor").
03425         Def("transaction",  &python::CConnection::transaction,  "transaction");
03426     python::CConnection::Declare("python_ncbi_dbapi.Connection");
03427 
03428     // Declare CTransaction
03429     python::CTransaction::
03430         Def("close",        &python::CTransaction::close,        "close").
03431         Def("cursor",       &python::CTransaction::cursor,       "cursor").
03432         Def("commit",       &python::CTransaction::commit,       "commit").
03433         Def("rollback",     &python::CTransaction::rollback,     "rollback");
03434     python::CTransaction::Declare("python_ncbi_dbapi.Transaction");
03435 
03436     // Declare CCursor
03437     python::CCursor::
03438         Def("callproc",     &python::CCursor::callproc,     "callproc").
03439         Def("close",        &python::CCursor::close,        "close").
03440         Def("execute",      &python::CCursor::execute,      "execute").
03441         Def("executemany",  &python::CCursor::executemany,  "executemany").
03442         Def("fetchone",     &python::CCursor::fetchone,     "fetchone").
03443         Def("fetchmany",    &python::CCursor::fetchmany,    "fetchmany").
03444         Def("fetchall",     &python::CCursor::fetchall,     "fetchall").
03445         Def("nextset",      &python::CCursor::nextset,      "nextset").
03446         Def("setinputsizes", &python::CCursor::setinputsizes, "setinputsizes").
03447         Def("setoutputsize", &python::CCursor::setoutputsize, "setoutputsize");
03448     python::CCursor::Declare("python_ncbi_dbapi.Cursor");
03449 
03450 
03451     // Declare CModuleDBAPI
03452     python::CModuleDBAPI::
03453         Def("connect",    &python::CModuleDBAPI::connect, "connect").
03454         Def("Date", &python::CModuleDBAPI::Date, "Date").
03455         Def("Time", &python::CModuleDBAPI::Time, "Time").
03456         Def("Timestamp", &python::CModuleDBAPI::Timestamp, "Timestamp").
03457         Def("DateFromTicks", &python::CModuleDBAPI::DateFromTicks, "DateFromTicks").
03458         Def("TimeFromTicks", &python::CModuleDBAPI::TimeFromTicks, "TimeFromTicks").
03459         Def("TimestampFromTicks", &python::CModuleDBAPI::TimestampFromTicks, "TimestampFromTicks").
03460         Def("Binary", &python::CModuleDBAPI::Binary, "Binary");
03461 //    python::CModuleDBAPI module_("python_ncbi_dbapi");
03462     // Python interpreter will tale care of deleting module object ...
03463     python::CModuleDBAPI* module2 = new python::CModuleDBAPI("python_ncbi_dbapi");
03464 }
03465 */
03466 
03467 // Genetal declarations ...
03468 namespace python
03469 {
03470 //////////////////////////////////////////////////////////////////////////////
03471 // connect(driver_name, db_type, db_name, user_name, user_pswd)
03472 static
03473 PyObject*
03474 Connect(PyObject *self, PyObject *args)
03475 {
03476     CConnection* conn = NULL;
03477 
03478     try {
03479         // Debugging ...
03480         // throw  python::CDatabaseError("oops ..."); 
03481         // throw  python::CDatabaseError("oops ...", 200, "Blah-blah-blah"); 
03482 
03483         string driver_name;
03484         string db_type;
03485         string server_name;
03486         string db_name;
03487         string user_name;
03488         string user_pswd;
03489         pythonpp::CObject extra_params = pythonpp::CNone();
03490 
03491         try {
03492             const pythonpp::CTuple func_args(args);
03493 
03494             driver_name = pythonpp::CString(func_args[0]);
03495             db_type = pythonpp::CString(func_args[1]);
03496             server_name = pythonpp::CString(func_args[2]);
03497             db_name = pythonpp::CString(func_args[3]);
03498             user_name = pythonpp::CString(func_args[4]);
03499             user_pswd = pythonpp::CString(func_args[5]);
03500             if ( func_args.size() > 6 ) {
03501                 extra_params = func_args[6];
03502             }
03503         } catch (const pythonpp::CError&) {
03504             throw CProgrammingError("Invalid parameters within 'connect' function");
03505         }
03506 
03507         conn = new CConnection(
03508             driver_name,
03509             db_type,
03510             server_name,
03511             db_name,
03512             user_name,
03513             user_pswd,
03514             extra_params
03515             );
03516     }
03517     catch (const CDB_Exception& e) {
03518         throw CDatabaseError(e);
03519     }
03520     catch (const CException& e) {
03521         pythonpp::CError::SetString(e.what());
03522     }
03523     catch (const pythonpp::CError&) {
03524         // An error message is already set by an exception ...
03525         return NULL;
03526     }
03527     catch (...) {
03528         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Connect");
03529     }
03530 
03531     return conn;
03532 }
03533 
03534 // This function constructs an object holding a date value.
03535 // Date(year,month,day)
03536 static
03537 PyObject*
03538 Date(PyObject *self, PyObject *args)
03539 {
03540 #if PY_VERSION_HEX < 0x02040000
03541     pythonpp::CError::SetString("python_ncbi_dbapi::Date requires Python 2.4 or newer.");
03542 #else
03543     try {
03544         int year;
03545         int month;
03546         int day;
03547 
03548         try {
03549             const pythonpp::CTuple func_args(args);
03550 
03551             year = pythonpp::CInt(func_args[0]);
03552             month = pythonpp::CInt(func_args[1]);
03553             day = pythonpp::CInt(func_args[2]);
03554         } catch (const pythonpp::CError&) {
03555             throw CProgrammingError("Invalid parameters within 'Date' function");
03556         }
03557 
03558         return IncRefCount(pythonpp::CDate(year, month, day));
03559     }
03560     catch (const CDB_Exception& e) {
03561         throw CDatabaseError(e);
03562     }
03563     catch (const CException& e) {
03564         pythonpp::CError::SetString(e.what());
03565     }
03566     catch(const pythonpp::CError&) {
03567         // An error message is already set by an exception ...
03568         return NULL;
03569     }
03570     catch(...) {
03571         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Date");
03572     }
03573 #endif
03574 
03575     return NULL;
03576 }
03577 
03578 // This function constructs an object holding a time value.
03579 // Time(hour,minute,second)
03580 static
03581 PyObject*
03582 Time(PyObject *self, PyObject *args)
03583 {
03584 #if PY_VERSION_HEX < 0x02040000
03585     pythonpp::CError::SetString("python_ncbi_dbapi::Time requires Python 2.4 or newer.");
03586 #else
03587     try {
03588         int hour;
03589         int minute;
03590         int second;
03591 
03592         try {
03593             const pythonpp::CTuple func_args(args);
03594 
03595             hour = pythonpp::CInt(func_args[0]);
03596             minute = pythonpp::CInt(func_args[1]);
03597             second = pythonpp::CInt(func_args[2]);
03598         } catch (const pythonpp::CError&) {
03599             throw CProgrammingError("Invalid parameters within 'Time' function");
03600         }
03601 
03602         return IncRefCount(pythonpp::CTime(hour, minute, second, 0));
03603     }
03604     catch (const CDB_Exception& e) {
03605         throw CDatabaseError(e);
03606     }
03607     catch (const CException& e) {
03608         pythonpp::CError::SetString(e.what());
03609     }
03610     catch(const pythonpp::CError&) {
03611         // An error message is already set by an exception ...
03612         return NULL;
03613     }
03614     catch(...) {
03615         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Time");
03616     }
03617 #endif
03618 
03619     return NULL;
03620 }
03621 
03622 // This function constructs an object holding a time stamp
03623 // value.
03624 // Timestamp(year,month,day,hour,minute,second)
03625 static
03626 PyObject*
03627 Timestamp(PyObject *self, PyObject *args)
03628 {
03629 #if PY_VERSION_HEX < 0x02040000
03630     pythonpp::CError::SetString("python_ncbi_dbapi::Timestamp requires Python 2.4 or newer.");
03631 #else
03632     try {
03633         int year;
03634         int month;
03635         int day;
03636         int hour;
03637         int minute;
03638         int second;
03639 
03640         try {
03641             const pythonpp::CTuple func_args(args);
03642 
03643             year = pythonpp::CInt(func_args[0]);
03644             month = pythonpp::CInt(func_args[1]);
03645             day = pythonpp::CInt(func_args[2]);
03646             hour = pythonpp::CInt(func_args[3]);
03647             minute = pythonpp::CInt(func_args[4]);
03648             second = pythonpp::CInt(func_args[5]);
03649         } catch (const pythonpp::CError&) {
03650             throw CProgrammingError("Invalid parameters within 'Timestamp' function");
03651         }
03652 
03653         return IncRefCount(pythonpp::CDateTime(year, month, day, hour, minute, second, 0));
03654     }
03655     catch (const CDB_Exception& e) {
03656         throw CDatabaseError(e);
03657     }
03658     catch (const CException& e) {
03659         pythonpp::CError::SetString(e.what());
03660     }
03661     catch(const pythonpp::CError&) {
03662         // An error message is already set by an exception ...
03663         return NULL;
03664     }
03665     catch(...) {
03666         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Timestamp");
03667     }
03668 #endif
03669 
03670     return NULL;
03671 }
03672 
03673 // This function constructs an object holding a date value
03674 // from the given ticks value (number of seconds since the
03675 // epoch; see the documentation of the standard Python time
03676 // module for details).
03677 // DateFromTicks(ticks)
03678 static
03679 PyObject*
03680 DateFromTicks(PyObject *self, PyObject *args)
03681 {
03682     try {
03683         throw CNotSupportedError("Function DateFromTicks");
03684     }
03685     catch (const CDB_Exception& e) {
03686         throw CDatabaseError(e);
03687     }
03688     catch (const CException& e) {
03689         pythonpp::CError::SetString(e.what());
03690     }
03691     catch(const pythonpp::CError&) {
03692         // An error message is already set by an exception ...
03693         return NULL;
03694     }
03695     catch(...) {
03696         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::DateFromTicks");
03697     }
03698 
03699     return NULL;
03700 }
03701 
03702 // This function constructs an object holding a time value
03703 // from the given ticks value (number of seconds since the
03704 // epoch; see the documentation of the standard Python time
03705 // module for details).
03706 // TimeFromTicks(ticks)
03707 static
03708 PyObject*
03709 TimeFromTicks(PyObject *self, PyObject *args)
03710 {
03711     try {
03712         throw CNotSupportedError("Function TimeFromTicks");
03713     }
03714     catch (const CDB_Exception& e) {
03715         throw CDatabaseError(e);
03716     }
03717     catch (const CException& e) {
03718         pythonpp::CError::SetString(e.what());
03719     }
03720     catch(const pythonpp::CError&) {
03721         // An error message is already set by an exception ...
03722         return NULL;
03723     }
03724     catch(...) {
03725         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::TimeFromTicks");
03726     }
03727 
03728     return NULL;
03729 }
03730 
03731 // This function constructs an object holding a time stamp
03732 // value from the given ticks value (number of seconds since
03733 // the epoch; see the documentation of the standard Python
03734 // time module for details).
03735 // TimestampFromTicks(ticks)
03736 static
03737 PyObject*
03738 TimestampFromTicks(PyObject *self, PyObject *args)
03739 {
03740     try {
03741         throw CNotSupportedError("Function TimestampFromTicks");
03742     }
03743     catch (const CDB_Exception& e) {
03744         throw CDatabaseError(e);
03745     }
03746     catch (const CException& e) {
03747         pythonpp::CError::SetString(e.what());
03748     }
03749     catch(const pythonpp::CError&) {
03750         // An error message is already set by an exception ...
03751         return NULL;
03752     }
03753     catch(...) {
03754         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::TimestampFromTicks");
03755     }
03756 
03757     return NULL;
03758 }
03759 
03760 // This function constructs an object capable of holding a
03761 // binary (long) string value.
03762 // Binary(string)
03763 static
03764 PyObject*
03765 Binary(PyObject *self, PyObject *args)
03766 {
03767     CBinary* obj = NULL;
03768 
03769     try {
03770         string value;
03771 
03772         try {
03773             const pythonpp::CTuple func_args(args);
03774 
03775             value = pythonpp::CString(func_args[0]);
03776         } catch (const pythonpp::CError&) {
03777             throw CProgrammingError("Invalid parameters within 'Binary' function");
03778         }
03779 
03780         obj = new CBinary(value);
03781     }
03782     catch (const CDB_Exception& e) {
03783         throw CDatabaseError(e);
03784     }
03785     catch (const CException& e) {
03786         pythonpp::CError::SetString(e.what());
03787     }
03788     catch(const pythonpp::CError&) {
03789         // An error message is already set by an exception ...
03790         return NULL;
03791     }
03792     catch(...) {
03793         pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Binary");
03794     }
03795 
03796     return obj;
03797 }
03798 
03799 class CDBAPIModule
03800 {
03801 public:
03802     static void Declare(const char* name, PyMethodDef* methods);
03803 
03804 private:
03805     static PyObject* m_Module;
03806 };
03807 PyObject* CDBAPIModule::m_Module = NULL;
03808 
03809 void
03810 CDBAPIModule::Declare(const char* name, PyMethodDef* methods)
03811 {
03812     m_Module = Py_InitModule(const_cast<char*>(name), methods);
03813 }
03814 
03815 }
03816 
03817 static struct PyMethodDef python_ncbi_dbapi_methods[] = {
03818     {(char*)"connect", (PyCFunction) python::Connect, METH_VARARGS, (char*)
03819         "connect(driver_name, db_type, server_name, database_name, userid, password) "
03820         "-- connect to the "
03821         "driver_name; db_type; server_name; database_name; userid; password;"
03822     },
03823     {(char*)"Date", (PyCFunction) python::Date, METH_VARARGS, (char*)"Date"},
03824     {(char*)"Time", (PyCFunction) python::Time, METH_VARARGS, (char*)"Time"},
03825     {(char*)"Timestamp", (PyCFunction) python::Timestamp, METH_VARARGS, (char*)"Timestamp"},
03826     {(char*)"DateFromTicks", (PyCFunction) python::DateFromTicks, METH_VARARGS, (char*)"DateFromTicks"},
03827     {(char*)"TimeFromTicks", (PyCFunction) python::TimeFromTicks, METH_VARARGS, (char*)"TimeFromTicks"},
03828     {(char*)"TimestampFromTicks", (PyCFunction) python::TimestampFromTicks, METH_VARARGS, (char*)"TimestampFromTicks"},
03829     {(char*)"Binary", (PyCFunction) python::Binary, METH_VARARGS, (char*)"Binary"},
03830     { NULL, NULL }
03831 };
03832 
03833 ///////////////////////////////////////////////////////////////////////////////
03834 // DatabaseErrorExt extends PyBaseExceptionObject
03835 /* DO NOT delete this code ...
03836 struct PyDatabaseErrorExtObject : public PyBaseExceptionObject
03837 {
03838     PyObject *db_message;
03839     PyObject *db_code;
03840 };
03841  
03842 
03843 static int
03844 DatabaseErrorExt_init(PyDatabaseErrorExtObject *self, PyObject *args, PyObject *kwds)
03845 {
03846     if (PyExc_BaseException->ob_type->tp_init((PyObject *)self, args, kwds) < 0) {
03847         return -1;
03848     }
03849 
03850     PyObject* message = NULL;
03851     PyObject *db_message = NULL, *db_code = NULL, *tmp;
03852 
03853     static char *kwlist[] = {"message", "db_message", "db_code", NULL};
03854 
03855     if (! PyArg_ParseTupleAndKeywords(
03856             args, 
03857             kwds, 
03858             "S|SO", 
03859             kwlist, 
03860             &message,
03861             &db_message, 
03862             &db_code
03863             )
03864         ) 
03865     {
03866         return -1; 
03867     }
03868 
03869     if (db_message) {
03870         tmp = self->db_message;
03871         Py_INCREF(db_message);
03872         self->db_message = db_message;
03873         Py_DECREF(tmp);
03874     }
03875 
03876     if (db_code) {
03877         // We are reading an object. Let us check the type.
03878         if (! PyInt_CheckExact(db_code)) {
03879             PyErr_SetString(PyExc_TypeError, 
03880                     "The second attribute value must be an int or a long");
03881             return -1;
03882         }
03883 
03884         tmp = self->db_code;
03885         Py_INCREF(db_code);
03886         self->db_code = db_code;
03887         Py_DECREF(tmp);
03888     }
03889 
03890     return 0;
03891 }
03892 
03893 static PyObject *
03894 DatabaseErrorExt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
03895 {
03896     PyDatabaseErrorExtObject *self;
03897 
03898     self = (PyDatabaseErrorExtObject *)type->tp_alloc(type, 0);
03899     // self = (PyDatabaseErrorExtObject *)type->tp_new(type, args, kwds);
03900     if (self != NULL) {
03901         self->db_message = PyString_FromString("");
03902         if (self->db_message == NULL)
03903         {
03904             Py_DECREF(self);
03905             return NULL;
03906         }
03907 
03908         self->db_code = PyLong_FromLong(0);
03909         if (self->db_code == NULL)
03910         {
03911             Py_DECREF(self);
03912             return NULL;
03913         }
03914     }
03915 
03916     return (PyObject *)self;
03917 }
03918 
03919 static PyObject *
03920 DatabaseErrorExt_get_db_message(PyDatabaseErrorExtObject *self, void* )
03921 {
03922     Py_INCREF(self->db_message);
03923     return self->db_message;
03924 }
03925 
03926 static int
03927 DatabaseErrorExt_set_db_message(PyDatabaseErrorExtObject *self, PyObject *value, void* )
03928 {
03929     if (value == NULL) {
03930         PyErr_SetString(PyExc_TypeError, "Cannot delete the db_message attribute");
03931         return -1;
03932     }
03933 
03934     if (! PyString_Check(value)) {
03935         PyErr_SetString(PyExc_TypeError, 
03936                 "The first attribute value must be a string");
03937         return -1;
03938     }
03939 
03940     Py_DECREF(self->db_message);
03941     Py_INCREF(value);
03942     self->db_message = value;    
03943 
03944     return 0;
03945 }
03946 
03947 static PyObject *
03948 DatabaseErrorExt_get_db_code(PyDatabaseErrorExtObject *self, void *closure)
03949 {
03950     Py_INCREF(self->db_code);
03951     return self->db_code;
03952 }
03953 
03954 static int
03955 DatabaseErrorExt_set_db_code(PyDatabaseErrorExtObject *self, PyObject *value, void *closure)
03956 {
03957     if (value == NULL) {
03958         PyErr_SetString(PyExc_TypeError, "Cannot delete the db_code attribute");
03959         return -1;
03960     }
03961 
03962     if (! PyLong_Check(value)) {
03963         PyErr_SetString(PyExc_TypeError, 
03964                 "The second attribute value must be a long");
03965         return -1;
03966     }
03967 
03968     Py_DECREF(self->db_code);
03969     Py_INCREF(value);
03970     self->db_code = value;    
03971 
03972     return 0;
03973 }
03974 
03975 static PyGetSetDef DatabaseErrorExt_getseters[] = {
03976     {"db_message", (getter)DatabaseErrorExt_get_db_message, (setter)DatabaseErrorExt_set_db_message, "Database message", NULL},
03977     {"db_code", (getter)DatabaseErrorExt_get_db_code, (setter)DatabaseErrorExt_set_db_code, "Database error code", NULL},
03978     {NULL}  
03979 };
03980 
03981 static int
03982 DatabaseErrorExt_traverse(PyDatabaseErrorExtObject *self, visitproc visit, void *arg)
03983 {
03984     Py_VISIT(self->db_message);
03985     Py_VISIT(self->db_code);
03986 
03987     return 0;
03988 }
03989 
03990 static int 
03991 DatabaseErrorExt_clear(PyDatabaseErrorExtObject *self)
03992 {
03993     Py_CLEAR(self->db_message);
03994     Py_CLEAR(self->db_code);
03995 
03996     return 0;
03997 }
03998 
03999 static void
04000 DatabaseErrorExt_dealloc(PyDatabaseErrorExtObject *self)
04001 {
04002     // ???
04003     // PyExc_BaseException->ob_type->tp_dealloc((PyObject *)self);
04004 
04005     DatabaseErrorExt_clear(self);
04006 
04007     self->ob_type->tp_free((PyObject *)self);
04008 }
04009 */
04010 
04011 
04012 // static PyTypeObject DatabaseErrorExtType = {
04013 //     PyObject_HEAD_INIT(NULL)
04014 //     0,                       /* ob_size */
04015 //     "python_ncbi_dbapi.DatabaseErrorExt", /* tp_name */
04016 //     sizeof(PyDatabaseErrorExtObject), /* tp_basicsize */
04017 //     0,                       /* tp_itemsize */
04018 //     (destructor)DatabaseErrorExt_dealloc,  /* tp_dealloc */
04019 //     0,                       /* tp_print */
04020 //     0,                       /* tp_getattr */
04021 //     0,                       /* tp_setattr */
04022 //     0,                       /* tp_compare */
04023 //     0,                       /* tp_repr */
04024 //     0,                       /* tp_as_number */
04025 //     0,                       /* tp_as_sequence */
04026 //     0,                       /* tp_as_mapping */
04027 //     0,                       /* tp_hash */
04028 //     0,                       /* tp_call */
04029 //     0,                       /* tp_str */
04030 //     0,                       /* tp_getattro */
04031 //     0,                       /* tp_setattro */
04032 //     0,                       /* tp_as_buffer */
04033 //     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
04034 //     "Database error",        /* tp_doc */
04035 //     (traverseproc)DatabaseErrorExt_traverse, /* tp_traverse */
04036 //     (inquiry)DatabaseErrorExt_clear, /* tp_clear */
04037 //     0,                       /* tp_richcompare */
04038 //     0,                       /* tp_weaklistoffset */
04039 //     0,                       /* tp_iter */
04040 //     0,                       /* tp_iternext */
04041 //     0,                       /* tp_methods */
04042 //     0,                       /* tp_members */
04043 //     DatabaseErrorExt_getseters, /* tp_getset */
04044 //     0,                       /* tp_base */
04045 //     0,                       /* tp_dict */
04046 //     0,                       /* tp_descr_get */
04047 //     0,                       /* tp_descr_set */
04048 //     0,                       /* tp_dictoffset */
04049 //     (initproc)DatabaseErrorExt_init, /* tp_init */
04050 //     0,                       /* tp_alloc */
04051 //     0, // DatabaseErrorExt_new,    /* tp_new */
04052 // };
04053 // static PyObject *PyExc_DatabaseErrorExtType = (PyObject *)&DatabaseErrorExtType; 
04054 // static PyObject* PyExc_DatabaseErrorExt = NULL;
04055 
04056 ///////////////////////////////////////////////////////////////////////////////
04057 static
04058 void init_common(const string& module_name)
04059 {
04060     DBLB_INSTALL_DEFAULT();
04061 
04062     const char* rev_str = "$Revision: 173033 $";
04063     PyObject *module;
04064 
04065     // Fix plugin manager ...
04066     CFile file(python::RetrieveModuleFileName());
04067     string module_dir = file.GetDir()
04068                         + "python_ncbi_dbapi/" NCBI_PACKAGE_VERSION;
04069     CDriverManager::GetInstance().AddDllSearchPath(module_dir.c_str());
04070 
04071 
04072     pythonpp::CModuleExt::Declare(module_name, python_ncbi_dbapi_methods);
04073 
04074     // Define module attributes ...
04075     pythonpp::CModuleExt::AddConst("apilevel", "2.0");
04076     pythonpp::CModuleExt::AddConst("__version__", string( rev_str + 11, strlen( rev_str + 11 ) - 2 ));
04077     pythonpp::CModuleExt::AddConst("threadsafety", 1);
04078     pythonpp::CModuleExt::AddConst("paramstyle", "named");
04079 
04080     module = pythonpp::CModuleExt::GetPyModule();
04081 
04082     ///////////////////////////////////
04083 
04084 #if PY_VERSION_HEX >= 0x02040000
04085     // Initialize DateTime module ...
04086     PyDateTime_IMPORT;
04087 #endif
04088 
04089     // Declare CBinary
04090     python::CBinary::Declare(string(module_name + ".BINARY").c_str());
04091     python::CBinary::GetType().SetName("BINARY");
04092 
04093     // Declare CNumber
04094     python::CNumber::Declare(string(module_name + ".NUMBER").c_str());
04095     python::CNumber::GetType().SetName("NUMBER");
04096 
04097     // Declare CRowID
04098     python::CRowID::Declare(string(module_name + ".ROWID").c_str());
04099     python::CRowID::GetType().SetName("ROWID");
04100 
04101     // Declare CString
04102     python::CStringType::Declare(string(module_name + ".STRING").c_str());
04103     python::CStringType::GetType().SetName("STRING");
04104 
04105     // Declare CString
04106     python::CDateTimeType::Declare(string(module_name + ".DATETIME").c_str());
04107     python::CDateTimeType::GetType().SetName("DATETIME");
04108 
04109     // Declare CConnection
04110     python::CConnection::
04111         Def("close",        &python::CConnection::close,        "close").
04112         Def("commit",       &python::CConnection::commit,       "commit").
04113         Def("rollback",     &python::CConnection::rollback,     "rollback").
04114         Def("cursor",       &python::CConnection::cursor,       "cursor").
04115         Def("transaction",  &python::CConnection::transaction,  "transaction");
04116     python::CConnection::Declare(string(module_name + ".Connection").c_str());
04117 
04118     // Declare CTransaction
04119     python::CTransaction::
04120         Def("close",        &python::CTransaction::close,        "close").
04121         Def("cursor",       &python::CTransaction::cursor,       "cursor").
04122         Def("commit",       &python::CTransaction::commit,       "commit").
04123         Def("rollback",     &python::CTransaction::rollback,     "rollback");
04124     python::CTransaction::Declare(string(module_name + ".Transaction").c_str());
04125 
04126     // Declare CCursor
04127     python::CCursor::
04128         Def("callproc",     &python::CCursor::callproc,     "callproc").
04129         Def("close",        &python::CCursor::close,        "close").
04130         Def("execute",      &python::CCursor::execute,      "execute").
04131         Def("executemany",  &python::CCursor::executemany,  "executemany").
04132         Def("fetchone",     &python::CCursor::fetchone,     "fetchone").
04133         Def("fetchmany",    &python::CCursor::fetchmany,    "fetchmany").
04134         Def("fetchall",     &python::CCursor::fetchall,     "fetchall").
04135         Def("nextset",      &python::CCursor::nextset,      "nextset").
04136         Def("setinputsizes", &python::CCursor::setinputsizes, "setinputsizes").
04137         Def("setoutputsize", &python::CCursor::setoutputsize, "setoutputsize").
04138         Def("get_proc_return_status", &python::CCursor::get_proc_return_status, "get_proc_return_status");
04139     python::CCursor::Declare(string(module_name + ".Cursor").c_str());
04140 
04141     ///////////////////////////////////
04142     // Declare types ...
04143 
04144     // Declare BINARY
04145     if ( PyType_Ready(&python::CBinary::GetType()) == -1 ) {
04146         return;
04147     }
04148     if ( PyModule_AddObject(module, const_cast<char*>("BINARY"), (PyObject*)&python::CBinary::GetType() ) == -1 ) {
04149         return;
04150     }
04151 
04152     // Declare NUMBER
04153     if ( PyType_Ready(&python::CNumber::GetType()) == -1 ) {
04154         return;
04155     }
04156     if ( PyModule_AddObject(module, const_cast<char*>("NUMBER"), (PyObject*)&python::CNumber::GetType() ) == -1 ) {
04157         return;
04158     }
04159 
04160     // Declare ROWID
04161     if ( PyType_Ready(&python::CRowID::GetType()) == -1 ) {
04162         return;
04163     }
04164     if ( PyModule_AddObject(module, const_cast<char*>("ROWID"), (PyObject*)&python::CRowID::GetType() ) == -1 ) {
04165         return;
04166     }
04167 
04168     // Declare STRING
04169     if ( PyType_Ready(&python::CStringType::GetType()) == -1 ) {
04170         return;
04171     }
04172     if ( PyModule_AddObject(module, const_cast<char*>("STRING"), (PyObject*)&python::CStringType::GetType() ) == -1 ) {
04173         return;
04174     }
04175 
04176     // Declare DATETIME
04177     if ( PyType_Ready(&python::CDateTimeType::GetType()) == -1 ) {
04178         return;
04179     }
04180     if ( PyModule_AddObject(module, const_cast<char*>("DATETIME"), (PyObject*)&python::CDateTimeType::GetType() ) == -1 ) {
04181         return;
04182     }
04183 
04184     ///////////////////////////////////
04185     // Add exceptions ...
04186 
04187     /* DO NOT delete this code ...
04188     {
04189         DatabaseErrorExtType.tp_new = DatabaseErrorExt_new;
04190         DatabaseErrorExtType.tp_base = python::CError::GetPyException()->ob_type;
04191 
04192         if (PyType_Ready(&DatabaseErrorExtType) < 0) {
04193             Py_FatalError("exceptions bootstrapping error.");
04194             return;
04195         }
04196 
04197         PyObject* dict = PyModule_GetDict(module);
04198         if (dict == NULL) {
04199             Py_FatalError("exceptions bootstrapping error."); 
04200         }
04201 
04202         Py_INCREF(PyExc_DatabaseErrorExtType);
04203         PyModule_AddObject(module, "DatabaseErrorExt", PyExc_DatabaseErrorExtType);
04204         if (PyDict_SetItemString(dict, "DatabaseErrorExt", PyExc_DatabaseErrorExtType)) {
04205             Py_FatalError("Module dictionary insertion problem.");
04206         }
04207 
04208         PyExc_DatabaseErrorExt = (PyObject*) PyErr_NewException("python_ncbi_dbapi.DatabaseErrorExt2", PyExc_DatabaseErrorExtType, NULL);
04209         python::CError::Check( PyExc_DatabaseErrorExt );
04210         if ( PyModule_AddObject( module, "DatabaseErrorExt2", PyExc_DatabaseErrorExt ) == -1 ) {
04211             throw pythonpp::CSystemError( "Unable to add an object to a module" );
04212         }
04213         if (PyDict_SetItemString(dict, "DatabaseErrorExt2", PyExc_DatabaseErrorExt)) {
04214             Py_FatalError("Module dictionary insertion problem.");
04215         }
04216     }
04217     */
04218 
04219     /* DO NOT delete this code ...
04220 
04221     python::CDatabaseError::Declare(
04222         string(module_name + ".DatabaseErrorExt").c_str(), 
04223         NULL, 
04224         python::CError::GetPyException()->ob_type
04225         );
04226     */
04227 
04228     python::CWarning::Declare("Warning");
04229     python::CError::Declare("Error");
04230     python::CInterfaceError::Declare("InterfaceError");
04231     python::CDatabaseError::Declare("DatabaseError");
04232     python::CInternalError::Declare("InternalError");
04233     python::COperationalError::Declare("OperationalError");
04234     python::CProgrammingError::Declare("ProgrammingError");
04235     python::CIntegrityError::Declare("IntegrityError");
04236     python::CDataError::Declare("DataError");
04237     python::CNotSupportedError::Declare("NotSupportedError");
04238 }
04239 
04240 // Module initialization
04241 PYDBAPI_MODINIT_FUNC(initpython_ncbi_dbapi)
04242 {
04243     init_common("python_ncbi_dbapi");
04244 }
04245 
04246 PYDBAPI_MODINIT_FUNC(initncbi_dbapi)
04247 {
04248     init_common("ncbi_dbapi");
04249 }
04250 
04251 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_current)
04252 {
04253     init_common("ncbi_dbapi_current");
04254 }
04255 
04256 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_frozen)
04257 {
04258     init_common("ncbi_dbapi_frozen");
04259 }
04260 
04261 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_metastable)
04262 {
04263     init_common("ncbi_dbapi_metastable");
04264 }
04265 
04266 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_potluck)
04267 {
04268     init_common("ncbi_dbapi_potluck");
04269 }
04270 
04271 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_production)
04272 {
04273     init_common("ncbi_dbapi_production");
04274 }
04275 
04276 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_stable)
04277 {
04278     init_common("ncbi_dbapi_stable");
04279 }
04280 
04281 
04282 #ifdef NCBI_OS_DARWIN
04283 // force more of corelib to make it in
04284 PYDBAPI_MODINIT_FUNC(initncbi_dbapi_darwin_kludge)
04285 {
04286     CFastMutexGuard GUARD(CPluginManagerGetterImpl::GetMutex());
04287     CConfig config(NULL, eNoOwnership);
04288 }
04289 #endif
04290 
04291 END_NCBI_SCOPE
04292 
04293 
04294 
04295 

Generated on Sun Dec 6 22:23:30 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:20:59 2009 by modify_doxy.py rev. 173732