00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00057
00058
00059
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
00076
00077 class CVariantSet : public CObject
00078 {
00079 public:
00080
00081
00082
00083 virtual ~CVariantSet(void) {}
00084
00085
00086
00087
00088
00089 virtual EDB_ResType GetResultType(void) = 0;
00090
00091
00092
00093
00094 virtual bool Next(void) = 0;
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 virtual const CVariant& GetVariant(const CDBParamVariant& param) = 0;
00105
00106
00107
00108
00109
00110 virtual unsigned int GetTotalColumns(void) = 0;
00111
00112
00113
00114
00115
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
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
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
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 m_StmtStr = str;
00559
00560 if (fmt.GetDriverFmt() != fmt.GetUserFmt()) {
00561
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
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
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
00823 param_len = tmp_pos - pos;
00824 } else if (str.find_first_of(num_characters, pos + 1) == pos + 1) {
00825
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
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
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
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
00883 param_len = str.size() - pos;
00884 }
00885 }
00886
00887 return pos;
00888 }
00889
00890
00891
00892 struct DataSourceDeleter
00893 {
00894
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
01001 file_name = NCBI_GetDefaultRunpath() + string("libpython_ncbi_dbapi.a");
01002
01003 #elif defined(NCBI_OS_MSWIN)
01004
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
01012
01013
01014
01015
01016
01017
01018 MEMORY_BASIC_INFORMATION mbi;
01019 VirtualQuery((const void*)RetrieveModuleFileName, &mbi, sizeof(mbi));
01020 mh = (HINSTANCE)mbi.AllocationBase;
01021
01022
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
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
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
01084 if (!pythonpp::CNone::HasSameType(extra_params)) {
01085 if (pythonpp::CDict::HasSameType(extra_params)) {
01086 const pythonpp::CDict dict = extra_params;
01087
01088
01089 pythonpp::py_ssize_t i = 0;
01090 PyObject* key;
01091 PyObject* value;
01092 while ( PyDict_Next(dict, &i, &key, &value) ) {
01093
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
01108 m_DS = m_DM.MakeDs(m_Params);
01109
01110
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
01134
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
01149 DecRefCount( m_DefTransaction );
01150
01151
01152 _ASSERT( m_TransList.empty() );
01153
01154 _ASSERT(m_DS);
01155
01156
01157
01158
01159
01160
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
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
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
01280 TConnectionList::const_iterator citer;
01281 TConnectionList::const_iterator cend = m_ConnList.end();
01282
01283
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
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
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
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
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
01441
01442
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
01497 CloseOpenCursors();
01498
01499
01500
01501
01502
01503
01504
01505
01506 RollbackInternal();
01507
01508
01509 m_SelectConnPool.Clear();
01510
01511 m_DMLConnPool.Clear();
01512 }
01513
01514 void
01515 CTransaction::CloseOpenCursors(void)
01516 {
01517 if ( !m_CursorList.empty() ) {
01518
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
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
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
01609
01610
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
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
01696 m_ParentTransaction->DestroySelectConnection( conn );
01697 } else {
01698
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
01716 m_Stmt.reset( m_ParentTransaction->CreateSelectConnection()->GetStatement() );
01717 } else {
01718
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
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;
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());
01930 col_list.Append(pythonpp::CInt(data->GetMaxSize(i)));
01931 col_list.Append(pythonpp::CNone());
01932 col_list.Append(pythonpp::CNone());
01933 col_list.Append(pythonpp::CNone());
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
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
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
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;
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
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
02264
02265
02266 break;
02267 }
02268
02269 return pythonpp::CObject();
02270 }
02271
02272
02273 pythonpp::CTuple
02274 MakeTupleFromResult(IResultSet& rs)
02275 {
02276
02277
02278
02279
02280
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
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
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;
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;
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
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
02416
02417
02418
02419
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
02434 pythonpp::CObject output_args( args[1] );
02435
02436 if (m_CallableStmtHelper.MoveToLastRS() && m_CallableStmtHelper.HasRS() ) {
02437
02438 CVariantSet& rs = m_CallableStmtHelper.GetRS();
02439
02440 if ( rs.GetResultType() == eDB_ParamResult ) {
02441
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
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
02457
02458
02459
02460
02461
02462
02463 throw CNotSupportedError("NCBI DBAPI supports pameter binding by name only");
02464 }
02465 }
02466 }
02467 }
02468 }
02469
02470
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
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
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
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
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
02555
02556
02557
02558
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
02592 pythonpp::py_ssize_t i = 0;
02593 PyObject* key;
02594 PyObject* value;
02595 while ( PyDict_Next(dict, &i, &key, &value) ) {
02596
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
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
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
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
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
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
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
03002
03003
03004
03005
03006
03007
03008
03009
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
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
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
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
03065 Py_DECREF(errno_ob);
03066
03067
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
03076 Py_DECREF(msg_ob);
03077
03078
03079 PyErr_SetObject(GetPyException(), exc_ob);
03080
03081
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
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
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468 namespace python
03469 {
03470
03471
03472 static
03473 PyObject*
03474 Connect(PyObject *self, PyObject *args)
03475 {
03476 CConnection* conn = NULL;
03477
03478 try {
03479
03480
03481
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
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
03535
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
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
03579
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
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
03623
03624
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
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
03674
03675
03676
03677
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
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
03703
03704
03705
03706
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
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
03732
03733
03734
03735
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
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
03761
03762
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
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
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
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
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
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
04086 PyDateTime_IMPORT;
04087 #endif
04088
04089
04090 python::CBinary::Declare(string(module_name + ".BINARY").c_str());
04091 python::CBinary::GetType().SetName("BINARY");
04092
04093
04094 python::CNumber::Declare(string(module_name + ".NUMBER").c_str());
04095 python::CNumber::GetType().SetName("NUMBER");
04096
04097
04098 python::CRowID::Declare(string(module_name + ".ROWID").c_str());
04099 python::CRowID::GetType().SetName("ROWID");
04100
04101
04102 python::CStringType::Declare(string(module_name + ".STRING").c_str());
04103 python::CStringType::GetType().SetName("STRING");
04104
04105
04106 python::CDateTimeType::Declare(string(module_name + ".DATETIME").c_str());
04107 python::CDateTimeType::GetType().SetName("DATETIME");
04108
04109
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
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
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
04143
04144
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
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
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
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
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
04186
04187
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
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
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
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