NCBI C++ ToolKit
python_ncbi_dbapi.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: python_ncbi_dbapi.cpp 72088 2016-04-14 19:07:55Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Sikorskiy
27 *
28 * File Description:
29 * Status: *Initial*
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 
36 #define PYTHONPP_DEFINE_GLOBALS 1
37 #include "python_ncbi_dbapi.hpp"
39 #if PY_VERSION_HEX >= 0x02040000
41 #endif
42 #include <structmember.h>
43 
47 #include <util/static_map.hpp>
49 #include <dbapi/error_codes.hpp>
51 #include "../../ds_impl.hpp"
52 
53 #if defined(NCBI_OS_CYGWIN)
54 #include <corelib/ncbicfg.h>
55 #elif !defined(NCBI_OS_MSWIN)
56 #include <dlfcn.h>
57 #endif
58 
59 //////////////////////////////////////////////////////////////////////////////
60 // Compatibility macros
61 //
62 // From Python 2.x to 3.x, the way to export the module init function
63 // has changed. These macros keep the code compatible to both ways.
64 //
65 #if PY_MAJOR_VERSION >= 3
66 # define PYDBAPI_MOD_RETURN return
67 # define PYDBAPI_MODINIT_FUNC(name) \
68  PyMODINIT_FUNC NCBI_NAME2(PyInit_,name)(void)
69 #else
70 # define PYDBAPI_MOD_RETURN
71 # define PYDBAPI_MODINIT_FUNC(name) PyMODINIT_FUNC NCBI_NAME2(init,name)(void)
72 #endif
73 
74 #ifndef PYDBAPI_SUPPORT_DIR
75 # define PYDBAPI_SUPPORT_DIR "python_ncbi_dbapi/" NCBI_PACKAGE_VERSION
76 #endif
77 
78 #define NCBI_USE_ERRCODE_X Dbapi_Python
79 
81 
82 
83 /// Flag showing whether all pythonpp::CString objects should be created as
84 /// Python unicode strings (TRUE value) or regular strings (FALSE value)
86 
87 
88 namespace python
89 {
90 
91 // A striped version of IResultSet because it is hard to implement all member
92 // functions from IResultSet in case of cached data.
93 class CVariantSet : public CObject
94 {
95 public:
96  /// Destructor.
97  ///
98  /// Clean up the resultset.
99  virtual ~CVariantSet(void) {}
100 
101  /// Get result type.
102  ///
103  /// @sa
104  /// See in <dbapi/driver/interfaces.hpp> for the list of result types.
105  virtual EDB_ResType GetResultType(void) = 0;
106 
107  /// Get next row.
108  ///
109  /// NOTE: no results are fetched before first call to this function.
110  virtual bool Next(void) = 0;
111 
112  /// Retrieve a CVariant class describing the data stored in a given column.
113  /// Note that the index supplied is one-based, not zero-based; the first
114  /// column is column 1.
115  ///
116  /// @param param
117  /// Column number (one-based) or name
118  /// @return
119  /// All data (for BLOB data see below) is returned as CVariant.
120  virtual const CVariant& GetVariant(const CDBParamVariant& param) = 0;
121 
122  /// Get total columns.
123  ///
124  /// @return
125  /// Returns total number of columns in the resultset
126  virtual unsigned int GetTotalColumns(void) = 0;
127 
128  /// Get Metadata.
129  ///
130  /// @return
131  /// Pointer to result metadata.
132  virtual const IResultSetMetaData& GetMetaData(void) const = 0;
133 };
134 
135 //////////////////////////////////////////////////////////////////////////////
137 {
138 public:
140  virtual ~CCachedResultSet(void);
141 
142  virtual EDB_ResType GetResultType(void);
143  virtual bool Next(void);
144  virtual const CVariant& GetVariant(const CDBParamVariant& param);
145  virtual unsigned int GetTotalColumns(void);
146  virtual const IResultSetMetaData& GetMetaData(void) const;
147 
148 private:
149  typedef deque<CVariant> TRecord;
150  typedef deque<TRecord> TRecordSet;
151 
153  const unsigned int m_ColumsNum;
154 
155  TRecordSet m_RecordSet;
157  size_t m_CurRowNum;
158 };
159 
161 : m_ResType(other.GetResultType())
162 , m_ColumsNum(other.GetTotalColumns())
163 , m_MetaData(other.GetMetaData(eTakeOwnership))
164 , m_CurRowNum(0)
165 {
166  while (other.Next()) {
167  m_RecordSet.push_back(TRecord());
168  TRecordSet::reference record = m_RecordSet.back();
169 
170  for (unsigned int col = 1; col <= m_ColumsNum; ++col) {
171  record.push_back(other.GetVariant(col));
172  }
173  }
174 }
175 
177 {
178 }
179 
182 {
183  return m_ResType;
184 }
185 
186 bool
188 {
189  if (m_CurRowNum < m_RecordSet.size()) {
190  ++m_CurRowNum;
191  return true;
192  }
193 
194  return false;
195 }
196 
197 
199 {
200 public:
201  CVariant* Create(void) {
202  return new CVariant(eDB_UnsupportedType);
203  }
205 };
206 
207 
208 const CVariant&
210 {
211  if (param.IsPositional()) {
212  unsigned int col_num = param.GetPosition();
213 
214  if (col_num > 0
215  && col_num <= GetTotalColumns()
216  && m_CurRowNum <= m_RecordSet.size()
217  ) {
218  return m_RecordSet[m_CurRowNum - 1][col_num - 1];
219  }
220  }
221 
223  return value.Get();
224 }
225 
226 unsigned int
228 {
229  return m_ColumsNum;
230 }
231 
232 const IResultSetMetaData&
234 {
235  return *m_MetaData;
236 }
237 
238 
239 //////////////////////////////////////////////////////////////////////////////
241 {
242 public:
243  CRealResultSet(IResultSet* other);
244  virtual ~CRealResultSet(void);
245 
246  virtual EDB_ResType GetResultType(void);
247  virtual bool Next(void);
248  virtual const CVariant& GetVariant(const CDBParamVariant& param);
249  virtual unsigned int GetTotalColumns(void);
250  virtual const IResultSetMetaData& GetMetaData(void) const;
251 
252 private:
253  // Lifetime of m_RS shouldn't be managed by auto_ptr
255 };
256 
258 : m_RS(other)
259 {
260  _ASSERT(other);
261 }
262 
264 {
265 }
266 
269 {
270  return m_RS->GetResultType();
271 }
272 
273 bool
275 {
276  return m_RS->Next();
277 }
278 
279 const CVariant&
281 {
282  return m_RS->GetVariant(param);
283 }
284 
285 unsigned int
287 {
288  return m_RS->GetTotalColumns();
289 }
290 
291 const IResultSetMetaData&
293 {
294  return *m_RS->GetMetaData();
295 }
296 
297 //////////////////////////////////////////////////////////////////////////////
299 {
300 public:
302  virtual ~CRealSetProxy(void);
303 
304  virtual bool MoveToNextRS(void);
305  virtual bool MoveToLastRS(void);
306  virtual CVariantSet& GetRS(void);
307  virtual const CVariantSet& GetRS(void) const;
308  virtual bool HasRS(void) const;
309  virtual void DumpResult(void);
310 
311 private:
314  bool m_HasRS;
315 };
316 
318 : m_Stmt(&stmt)
319 , m_HasRS(false)
320 {
321 }
322 
324 {
325 }
326 
327 
329 {
330  m_HasRS = false;
331 
332  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
333 
334  while (m_Stmt->HasMoreResults()) {
335  if ( m_Stmt->HasRows() ) {
337  m_HasRS = true;
338  break;
339  }
340  }
341 
342  return m_HasRS;
343 }
344 
345 bool
347 {
348  return false;
349 }
350 
353 {
354  return *m_VariantSet;
355 }
356 
358 {
359  return *m_VariantSet;
360 }
361 
362 bool CRealSetProxy::HasRS(void) const
363 {
364  return m_HasRS;
365 }
366 
367 void
369 {
370  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
371  while ( m_Stmt->HasMoreResults() ) {
372  if ( m_Stmt->HasRows() ) {
373  // Keep very last ResultSet in case somebody calls GetRS().
375  }
376  }
377 }
378 
379 
380 //////////////////////////////////////////////////////////////////////////////
382 {
383 public:
385  virtual ~CVariantSetProxy(void);
386 
387  virtual bool MoveToNextRS(void);
388  virtual bool MoveToLastRS(void);
389  virtual CVariantSet& GetRS(void);
390  virtual const CVariantSet& GetRS(void) const;
391  virtual bool HasRS(void) const;
392  virtual void DumpResult(void);
393 
394 private:
395  typedef deque<CRef<CVariantSet> > TCachedSet;
396 
397  TCachedSet m_CachedSet;
399  bool m_HasRS;
400 };
401 
403 : m_HasRS(false)
404 {
405  while (stmt.HasMoreResults()) {
406  if (stmt.HasRows()) {
408  m_CachedSet.push_back(CRef<CVariantSet>(new CCachedResultSet(*rs)));
409  }
410  }
411 }
412 
414 {
415 }
416 
417 
419 {
420  m_HasRS = false;
421 
422  if (!m_CachedSet.empty()) {
423  m_CurResultSet.Reset(m_CachedSet.front());
424  m_CachedSet.pop_front();
425  m_HasRS = true;
426  }
427 
428  return m_HasRS;
429 }
430 
431 bool
433 {
434  m_HasRS = false;
435 
436  if (!m_CachedSet.empty()) {
437  m_CurResultSet.Reset(m_CachedSet.back());
438  m_CachedSet.pop_back();
439  m_HasRS = true;
440  }
441 
442  return m_HasRS;
443 }
444 
446 {
447  return *m_CurResultSet;
448 }
449 
451 {
452  return *m_CurResultSet;
453 }
454 
455 bool CVariantSetProxy::HasRS(void) const
456 {
457  return m_HasRS;
458 }
459 
461 {
462  while (MoveToNextRS()) {;}
463 }
464 
465 
466 //////////////////////////////////////////////////////////////////////////////
468 {
469  PrepareForPython(this);
470 }
471 
472 CBinary::CBinary(const string& value)
473 : m_Value(value)
474 {
475  PrepareForPython(this);
476 }
477 
479 {
480 }
481 
482 //////////////////////////////////////////////////////////////////////////////
484 {
485  PrepareForPython(this);
486 }
487 
489 {
490 }
491 
492 //////////////////////////////////////////////////////////////////////////////
494 {
495  PrepareForPython(this);
496 }
497 
499 {
500 }
501 
502 //////////////////////////////////////////////////////////////////////////////
504 {
505  PrepareForPython(this);
506 }
507 
509 {
510 }
511 
512 //////////////////////////////////////////////////////////////////////////////
514 {
515  PrepareForPython(this);
516 }
517 
519 {
520 }
521 
522 //////////////////////////////////////////////////////////////////////////////
524 : m_UserFmt(user_fmt)
525 , m_DrvFmt(drv_fmt)
526 {
527 }
528 
529 const char*
531 {
532  switch (fmt) {
533  case eTSQL:
534  return "TSQL";
535  case eQmark:
536  return "qmark";
537  case eNumeric:
538  return "numeric";
539  case eNamed:
540  return "named";
541  case eFormat:
542  return "format";
543  case ePyFormat:
544  return "pyformat";
545  }
546 
547  return "unknown";
548 }
549 
550 //////////////////////////////////////////////////////////////////////////////
551 void
552 CStmtStr::SetStr(const string& str,
553  EStatementType default_type,
554  const CParamFmt& fmt
555  )
556 {
557  m_StmType = RetrieveStatementType(str, default_type);
558 
559  /* Do not delete this code ...
560  static char const* space_characters = " \t\n";
561 
562  if ( GetType() == estFunction ) {
563  // Cut off the "EXECUTE" prefix if any ...
564 
565  string::size_type pos;
566  string str_uc = str;
567 
568  NStr::ToUpper(str_uc);
569  pos = str_uc.find_first_not_of(space_characters);
570  if (pos != string::npos) {
571  if (str_uc.compare(pos, sizeof("EXEC") - 1, "EXEC") == 0) {
572  // We have the "EXECUTE" prefix ...
573  pos = str_uc.find_first_of(space_characters, pos);
574  if (pos != string::npos) {
575  pos = str_uc.find_first_not_of(space_characters, pos);
576  if (pos != string::npos) {
577  m_StmtStr = str.substr(pos);
578  return;
579  }
580  }
581  }
582  }
583  }
584  */
585 
586  m_StmtStr = str;
587 
588  if (fmt.GetDriverFmt() != fmt.GetUserFmt()) {
589  // Replace parameters ...
590  if (fmt.GetUserFmt() == CParamFmt::eQmark) {
591  if (fmt.GetDriverFmt() == CParamFmt::eNumeric) {
592  string::size_type pos = 0;
593  string::size_type prev_pos = pos;
594 
595  if ((pos = m_StmtStr.find('?', pos)) != string::npos) {
596  string tmp_stmt;
597  int pos_num = 1;
598 
599  while (pos != string::npos) {
600  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
601  tmp_stmt += ":" + NStr::IntToString(pos_num++);
602  prev_pos = pos + 1;
603 
604  pos = m_StmtStr.find('?', prev_pos);
605  }
606 
607  tmp_stmt += m_StmtStr.substr(prev_pos);
608  m_StmtStr = tmp_stmt;
609  }
610 
611  return;
612  } else if (fmt.GetDriverFmt() == CParamFmt::eTSQL) {
613  string::size_type pos = 0;
614  string::size_type prev_pos = pos;
615 
616  if ((pos = m_StmtStr.find('?', pos)) != string::npos) {
617  string tmp_stmt;
618  int pos_num = 1;
619 
620  while (pos != string::npos) {
621  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
622  tmp_stmt += "@" + NStr::IntToString(pos_num++);
623  prev_pos = pos + 1;
624 
625  pos = m_StmtStr.find('?', prev_pos);
626  }
627 
628  tmp_stmt += m_StmtStr.substr(prev_pos);
629  m_StmtStr = tmp_stmt;
630  }
631 
632  return;
633  }
634  } else if (fmt.GetUserFmt() == CParamFmt::eNumeric) {
635  if (fmt.GetDriverFmt() == CParamFmt::eQmark) {
636  string::size_type pos = 0;
637  string::size_type prev_pos = pos;
638  int param_len = 0;
639 
640  if ((pos = find_numeric(m_StmtStr, pos, param_len)) != string::npos) {
641  string tmp_stmt;
642 
643  while (pos != string::npos) {
644  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
645  tmp_stmt += "?";
646  prev_pos = pos + param_len;
647 
648  pos = find_numeric(m_StmtStr, prev_pos, param_len);
649  }
650 
651  tmp_stmt += m_StmtStr.substr(prev_pos);
652  m_StmtStr = tmp_stmt;
653  }
654 
655  return;
656  }
657  } else if (fmt.GetUserFmt() == CParamFmt::eNamed) {
658  if (fmt.GetDriverFmt() == CParamFmt::eQmark) {
659  string::size_type pos = 0;
660  string::size_type prev_pos = pos;
661  int param_len = 0;
662 
663  if ((pos = find_named(m_StmtStr, pos, param_len)) != string::npos) {
664  string tmp_stmt;
665 
666  while (pos != string::npos) {
667  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
668  tmp_stmt += "?";
669  prev_pos = pos + param_len;
670 
671  pos = find_named(m_StmtStr, prev_pos, param_len);
672  }
673 
674  tmp_stmt += m_StmtStr.substr(prev_pos);
675  m_StmtStr = tmp_stmt;
676  }
677 
678  return;
679  } else if (fmt.GetDriverFmt() == CParamFmt::eNumeric) {
680  string::size_type pos = 0;
681  string::size_type prev_pos = pos;
682  int param_len = 0;
683 
684  if ((pos = find_named(m_StmtStr, pos, param_len)) != string::npos) {
685  string tmp_stmt;
686  int pos_num = 1;
687  typedef map<string, string> name_map_t;
688  name_map_t name2num;
689 
690  while (pos != string::npos) {
691  string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
692  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
693  tmp_stmt += ":";
694 
695  // Get number ...
696  name_map_t::iterator it = name2num.find(param_name);
697  if (it == name2num.end()) {
698  it = name2num.insert(
700  param_name,
701  NStr::IntToString(pos_num++)
702  )
703  ).first;
704  }
705  tmp_stmt += it->second;
706 
707  prev_pos = pos + param_len;
708 
709  pos = find_named(m_StmtStr, prev_pos, param_len);
710  }
711 
712  tmp_stmt += m_StmtStr.substr(prev_pos);
713  m_StmtStr = tmp_stmt;
714  }
715 
716  return;
717  } else if (fmt.GetDriverFmt() == CParamFmt::eTSQL) {
718  string::size_type pos = 0;
719  string::size_type prev_pos = pos;
720  int param_len = 0;
721 
722  if ((pos = find_named(m_StmtStr, pos, param_len)) != string::npos) {
723  string tmp_stmt;
724 
725  while (pos != string::npos) {
726  string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
727  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
728  tmp_stmt += "@" + param_name;
729  prev_pos = pos + param_len;
730 
731  pos = find_named(m_StmtStr, prev_pos, param_len);
732  }
733 
734  tmp_stmt += m_StmtStr.substr(prev_pos);
735  m_StmtStr = tmp_stmt;
736  }
737 
738  return;
739  }
740  } else if (fmt.GetUserFmt() == CParamFmt::eTSQL) {
741  if (fmt.GetDriverFmt() == CParamFmt::eQmark) {
742  string::size_type pos = 0;
743  string::size_type prev_pos = pos;
744  int param_len = 0;
745 
746  if ((pos = find_TSQL(m_StmtStr, pos, param_len)) != string::npos) {
747  string tmp_stmt;
748 
749  while (pos != string::npos) {
750  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
751  tmp_stmt += "?";
752  prev_pos = pos + param_len;
753 
754  pos = find_TSQL(m_StmtStr, prev_pos, param_len);
755  }
756 
757  tmp_stmt += m_StmtStr.substr(prev_pos);
758  m_StmtStr = tmp_stmt;
759  }
760 
761  return;
762  } else if (fmt.GetDriverFmt() == CParamFmt::eNumeric) {
763  string::size_type pos = 0;
764  string::size_type prev_pos = pos;
765  int param_len = 0;
766 
767  if ((pos = find_TSQL(m_StmtStr, pos, param_len)) != string::npos) {
768  string tmp_stmt;
769  int pos_num = 1;
770  typedef map<string, string> name_map_t;
771  name_map_t name2num;
772 
773  while (pos != string::npos) {
774  string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
775  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
776  tmp_stmt += ":";
777 
778  // Get number ...
779  name_map_t::iterator it = name2num.find(param_name);
780  if (it == name2num.end()) {
781  it = name2num.insert(
783  param_name,
784  NStr::IntToString(pos_num++)
785  )
786  ).first;
787  }
788  tmp_stmt += it->second;
789 
790  prev_pos = pos + param_len;
791 
792  pos = find_TSQL(m_StmtStr, prev_pos, param_len);
793  }
794 
795  tmp_stmt += m_StmtStr.substr(prev_pos);
796  m_StmtStr = tmp_stmt;
797  }
798 
799  return;
800  } else if (fmt.GetDriverFmt() == CParamFmt::eNamed) {
801  string::size_type pos = 0;
802  string::size_type prev_pos = pos;
803  int param_len = 0;
804 
805  if ((pos = find_TSQL(m_StmtStr, pos, param_len)) != string::npos) {
806  string tmp_stmt;
807 
808  while (pos != string::npos) {
809  string param_name = m_StmtStr.substr(pos + 1, param_len - 1);
810  tmp_stmt += m_StmtStr.substr(prev_pos, pos - prev_pos);
811  tmp_stmt += ":" + param_name;
812  prev_pos = pos + param_len;
813 
814  pos = find_TSQL(m_StmtStr, prev_pos, param_len);
815  }
816 
817  tmp_stmt += m_StmtStr.substr(prev_pos);
818  m_StmtStr = tmp_stmt;
819  }
820 
821  return;
822  }
823  }
824 
825  string err = "Cannot convert '";
826  err += CParamFmt::GetName(fmt.GetUserFmt());
827  err += "' parameter format to '";
828  err += CParamFmt::GetName(fmt.GetDriverFmt());
829  err += "'";
830  throw CInterfaceError(err);
831  }
832 }
833 
834 
835 string::size_type
837  string::size_type offset,
838  int& param_len
839  )
840 {
841  string::size_type pos = 0;
842  static const char* num_characters = "0123456789";
843 
844  pos = str.find(':', offset);
845  if ((pos != string::npos) && (pos + 1 != string::npos)) {
846  string::size_type tmp_pos = 0;
847 
848  tmp_pos = str.find_first_not_of(num_characters, pos + 1);
849  if (tmp_pos != string::npos) {
850  // We've got the end of the number ...
851  param_len = tmp_pos - pos;
852  } else if (str.find_first_of(num_characters, pos + 1) == pos + 1) {
853  // Number till the end of the string ...
854  param_len = str.size() - pos;
855  }
856  }
857 
858  return pos;
859 }
860 
861 
862 string::size_type
863 CStmtStr::find_named(const string& str,
864  string::size_type offset,
865  int& param_len
866  )
867 {
868  string::size_type pos = 0;
869  static char const* sep_characters = " \t\n,.()-+<>=";
870 
871  pos = str.find(':', offset);
872  if ((pos != string::npos) && (pos + 1 != string::npos)) {
873  string::size_type tmp_pos = 0;
874 
875  tmp_pos = str.find_first_of(sep_characters, pos + 1);
876  if (tmp_pos != string::npos) {
877  // We've got the end of the number ...
878  param_len = tmp_pos - pos;
879  } else if ((str[pos + 1] >= 'A' && str[pos + 1] <= 'Z') ||
880  (str[pos + 1] >= 'a' && str[pos + 1] <= 'z')
881  ) {
882  // Number till the end of the string ...
883  param_len = str.size() - pos;
884  }
885  }
886 
887  return pos;
888 }
889 
890 string::size_type
891 CStmtStr::find_TSQL(const string& str,
892  string::size_type offset,
893  int& param_len
894  )
895 {
896  string::size_type pos = 0;
897  static char const* sep_characters = " \t\n,.()-+<>=";
898 
899  pos = str.find('@', offset);
900  if ((pos != string::npos) && (pos + 1 != string::npos)) {
901  string::size_type tmp_pos = 0;
902 
903  tmp_pos = str.find_first_of(sep_characters, pos + 1);
904  if (tmp_pos != string::npos) {
905  // We've got the end of the number ...
906  param_len = tmp_pos - pos;
907  } else if ((str[pos + 1] >= 'A' && str[pos + 1] <= 'Z') ||
908  (str[pos + 1] >= 'a' && str[pos + 1] <= 'z')
909  ) {
910  // Number till the end of the string ...
911  param_len = str.size() - pos;
912  }
913  }
914 
915  return pos;
916 }
917 
918 /* Future development
919 //////////////////////////////////////////////////////////////////////////////
920 struct DataSourceDeleter
921 {
922  /// Default delete function.
923  static void Delete(ncbi::IDataSource* const object)
924  {
925  CDriverManager::DeleteDs( object );
926  }
927 };
928 
929 //////////////////////////////////////////////////////////////////////////////
930 class CDataSourcePool
931 {
932 public:
933  CDataSourcePool(void);
934  ~CDataSourcePool(void);
935 
936 public:
937  static CDataSourcePool& GetInstance(void);
938 
939 public:
940  IDataSource& GetDataSource(
941  const string& driver_name,
942  const TPluginManagerParamTree* const params = NULL);
943 
944 private:
945  typedef CPluginManager<I_DriverContext> TContextManager;
946  typedef CPluginManagerGetter<I_DriverContext> TContextManagerStore;
947  typedef map<string, AutoPtr<IDataSource, DataSourceDeleter> > TDSMap;
948 
949  CRef<TContextManager> m_ContextManager;
950  TDSMap m_DataSourceMap;
951 };
952 
953 CDataSourcePool::CDataSourcePool(void)
954 {
955  m_ContextManager.Reset( TContextManagerStore::Get() );
956  _ASSERT( m_ContextManager );
957 
958 #if defined(NCBI_OS_MSWIN)
959  // Add an additional search path ...
960 #endif
961 }
962 
963 CDataSourcePool::~CDataSourcePool(void)
964 {
965 }
966 
967 void
968 DataSourceCleanup(void* ptr)
969 {
970  CDriverManager::DeleteDs( static_cast<ncbi::IDataSource *const>(ptr) );
971 }
972 
973 CDataSourcePool&
974 CDataSourcePool::GetInstance(void)
975 {
976  static CSafeStatic<CDataSourcePool> ds_pool;
977 
978  return *ds_pool;
979 }
980 
981 IDataSource&
982 CDataSourcePool::GetDataSource(
983  const string& driver_name,
984  const TPluginManagerParamTree* const params)
985 {
986  TDSMap::const_iterator citer = m_DataSourceMap.find( driver_name );
987 
988  if ( citer != m_DataSourceMap.end() ) {
989  return *citer->second;
990  }
991 
992  // Build a new context ...
993  I_DriverContext* drv = NULL;
994 
995  try {
996  drv = m_ContextManager->CreateInstance(
997  driver_name,
998  NCBI_INTERFACE_VERSION(I_DriverContext),
999  params
1000  );
1001  _ASSERT( drv );
1002  }
1003  catch( const CPluginManagerException& e ) {
1004  throw CDatabaseError( e.what() );
1005  }
1006  catch ( const exception& e ) {
1007  throw CDatabaseError( driver_name + " is not available :: " + e.what() );
1008  }
1009  catch( ... ) {
1010  throw CDatabaseError( driver_name + " was unable to load due an unknown error" );
1011  }
1012 
1013  // Store new value
1014  IDataSource* ds = CDriverManager::CreateDs( drv );
1015  m_DataSourceMap[driver_name] = ds;
1016 
1017  return *ds;
1018 }
1019  */
1020 
1021 //////////////////////////////////////////////////////////////////////////////
1022 static
1024 {
1025  string file_name;
1026 
1027 #if defined(NCBI_OS_CYGWIN)
1028  // no dladdr; just return the standard location
1029  file_name = NCBI_GetDefaultRunpath() + string("libpython_ncbi_dbapi.a");
1030 
1031 #elif defined(NCBI_OS_MSWIN)
1032  // Add an additional search path ...
1033  const DWORD buff_size = 1024;
1034  DWORD cur_size = 0;
1035  char buff[buff_size];
1036  HMODULE mh = NULL;
1037  const char* module_name = NULL;
1038 
1039 // #ifdef NDEBUG
1040 // module_name = "python_ncbi_dbapi.pyd";
1041 // #else
1042 // module_name = "python_ncbi_dbapi_d.pyd";
1043 // #endif
1044 
1045  // Get module handle ...
1046  MEMORY_BASIC_INFORMATION mbi;
1047  VirtualQuery((const void*)RetrieveModuleFileName, &mbi, sizeof(mbi));
1048  mh = (HINSTANCE)mbi.AllocationBase;
1049 
1050 // if ( mh = GetModuleHandle( module_name ) ) {
1051  if (mh) {
1052  if ( cur_size = GetModuleFileNameA( mh, buff, buff_size ) ) {
1053  if ( cur_size < buff_size ) {
1054  file_name = buff;
1055  }
1056  }
1057  }
1058 
1059 #else
1060 
1061  ::Dl_info dli;
1062 
1063  // if (::dladdr(&ncbi::python::CConnection::CConnection, &dli) != 0) {
1064  void* method_ptr = (void*)RetrieveModuleFileName;
1065  if (::dladdr(method_ptr, &dli) != 0) {
1066  file_name = dli.dli_fname;
1067  }
1068 
1069 #endif
1070 
1071  return file_name;
1072 }
1073 
1074 //////////////////////////////////////////////////////////////////////////////
1075 
1076 // Attempt to reclassify C++ DBAPI exceptions per the Python DBAPI
1077 // ontology from PEP 249. It's not always clear which classification
1078 // is most appropriate; these tables take the approach of using
1079 // InterfaceError only for generic initial setup considerations, and
1080 // ProgrammingError for other issues caught at the client side even if
1081 // they'd be a problem for any DB or server. The line between
1082 // internal and operational errors is even less clear.
1083 
1084 typedef void (*FRethrow)(const CDB_Exception&);
1087 
1088 #define DB_ERR_CODE(value, type) { value, &C##type##Error::Rethrow }
1089 
1090 static const TDBErrCodePair kClientErrCodes[] =
1091 {
1092  DB_ERR_CODE(0, Database), // no specific code given
1093  DB_ERR_CODE(1, Programming), // malformatted name
1094  DB_ERR_CODE(2, Programming), // unknown or wrong type
1095  DB_ERR_CODE(100, Programming), // illegal precision
1096  DB_ERR_CODE(101, Programming), // scale > precision
1097  DB_ERR_CODE(102, Data), // string cannot be converted
1098  DB_ERR_CODE(103, Data), // conversion overflow
1099  DB_ERR_CODE(300, Interface), // couldn't find/load driver
1100  DB_ERR_CODE(10005, Programming), // bit params not supported here
1101  DB_ERR_CODE(20001, Database), // disparate uses
1102  DB_ERR_CODE(100012, Interface), // circular dep. in resource info file
1103  DB_ERR_CODE(101100, Data), // invalid type conversion
1104  DB_ERR_CODE(110092, Programming), // wrong (zero) data size
1105  DB_ERR_CODE(110100, Interface), // no server or host name
1106  DB_ERR_CODE(111000, Interface), // no server or pool name
1107  DB_ERR_CODE(120010, Programming), // want result from unsent command
1108  DB_ERR_CODE(122002, NotSupported), // unimplemented by CDB*Params
1109  DB_ERR_CODE(123015, Programming), // bad BCP hint type
1110  DB_ERR_CODE(123016, Programming), // bad BCP hint value
1111  DB_ERR_CODE(125000, NotSupported), // can't cancel BCP w/Sybase ctlib
1112  DB_ERR_CODE(130020, Programming), // wrong CDB_Object type
1113  DB_ERR_CODE(130120, Programming), // wrong CDB_Object type
1114  DB_ERR_CODE(190000, Programming), // wrong (zero) arguments
1115  DB_ERR_CODE(200001, Database), // disparate uses
1116  DB_ERR_CODE(200010, Interface), // insufficient credential info
1117  DB_ERR_CODE(210092, Programming), // wrong (zero) data size
1118  DB_ERR_CODE(220010, Programming), // want result from unsent command
1119  DB_ERR_CODE(221010, Programming), // want result from unsent command
1120  DB_ERR_CODE(230020, Programming), // wrong CDB_Object type
1121  DB_ERR_CODE(230021, Data), // too long for CDB_VarChar
1122  DB_ERR_CODE(290000, Programming), // wrong (zero) arguments
1123  DB_ERR_CODE(300011, Programming), // bad protocol version for FreeTDS
1124  DB_ERR_CODE(410055, Programming), // invalid text encoding
1125  DB_ERR_CODE(420010, Programming), // want result from unsent command
1126  DB_ERR_CODE(430020, Programming), // wrong CDB_Object type
1127  DB_ERR_CODE(500001, NotSupported), // GetLowLevelHandle unimplemented
1128  DB_ERR_CODE(1000010, Programming) // NULL ptr. to driver context
1129 };
1130 
1131 static const TDBErrCodePair kSybaseErrCodes[] =
1132 {
1133  DB_ERR_CODE(102, Programming), // incorrect syntax
1134  DB_ERR_CODE(207, Programming), // invalid column name
1135  DB_ERR_CODE(208, Programming), // invalid object name
1136  DB_ERR_CODE(515, Integrity), // cannot insert NULL
1137  DB_ERR_CODE(547, Integrity), // constraint violation (foreign key?)
1138  DB_ERR_CODE(2601, Integrity), // duplicate key (unique index)
1139  DB_ERR_CODE(2627, Integrity), // dup. key (constr. viol., primary key?)
1140  DB_ERR_CODE(2812, Programming), // unknown stored procedure
1141  DB_ERR_CODE(4104, Programming) // multi-part ID couldn't be bound
1142 };
1143 
1144 #undef DB_ERR_CODE
1145 
1146 DEFINE_STATIC_ARRAY_MAP(TDBErrCodeMap, sc_ClientErrCodes, kClientErrCodes);
1147 DEFINE_STATIC_ARRAY_MAP(TDBErrCodeMap, sc_SybaseErrCodes, kSybaseErrCodes);
1148 
1149 static NCBI_NORETURN
1151 {
1152  const CDB_Exception* dbe = dynamic_cast<const CDB_Exception*>(&e);
1153  if (dbe == NULL) {
1154  if (dynamic_cast<const CInvalidConversionException*>(&e) != NULL) {
1155  throw CDataError(e.what());
1156  } else {
1157  throw CDatabaseError(e.what());
1158  }
1159  }
1160 
1161  if (dbe->GetSybaseSeverity() != 0 || dbe->GetSeverity() == eDiag_Info) {
1162  // Sybase (including OpenServer) or MSSQL. There are theoretical
1163  // false positives in the eDiag_Info case, but (at least with the
1164  // standard drivers) they will only ever arise for the ODBC driver,
1165  // and only accompanied by a DB error code of zero.
1167  = sc_SybaseErrCodes.find(dbe->GetDBErrCode());
1168  if (it != sc_SybaseErrCodes.end()) {
1169  it->second(*dbe);
1170  }
1171  // throw COperationalError(*dbe);
1172  }
1173 
1174  switch (dbe->GetErrCode()) {
1175  // case CDB_Exception::eDeadlock: // Could stem from a programming error
1176  case CDB_Exception::eDS:
1178  throw COperationalError(*dbe);
1179 
1181  {
1183  = sc_SybaseErrCodes.find(dbe->GetDBErrCode());
1184  if (it != sc_SybaseErrCodes.end()) {
1185  it->second(*dbe);
1186  }
1187  throw COperationalError(*dbe);
1188  }
1189 
1190  default:
1191  break;
1192  }
1193 
1194  throw CDatabaseError(*dbe); // no more specific classification
1195 }
1196 
1197 //////////////////////////////////////////////////////////////////////////////
1199  const string& driver_name,
1200  const string& db_type,
1201  const string& server_name,
1202  const string& db_name,
1203  const string& user_name,
1204  const string& user_pswd,
1205  const pythonpp::CObject& extra_params
1206  )
1207 : m_DefParams(server_name, user_name, user_pswd)
1208 , m_Params(m_DefParams)
1209 , m_DM(CDriverManager::GetInstance())
1210 , m_DS(NULL)
1211 , m_DefTransaction( NULL )
1212 , m_ConnectionMode(eSimpleMode)
1213 {
1214  try {
1215  m_DefParams.SetDriverName(driver_name);
1216  m_DefParams.SetDatabaseName(db_name);
1217 
1218  // Set up a server type ...
1219  string db_type_uc = db_type;
1220  NStr::ToUpper(db_type_uc);
1221 
1222  if ( db_type_uc == "SYBASE" || db_type_uc == "SYB" ) {
1224  } else if ( db_type_uc == "MYSQL" ) {
1226  } else if ( db_type_uc == "MSSQL" ||
1227  db_type_uc == "MS_SQL" ||
1228  db_type_uc == "MS SQL")
1229  {
1232  }
1233 
1234 
1235  // Handle extra-parameters ...
1236  if (!pythonpp::CNone::HasSameType(extra_params)) {
1237  if (pythonpp::CDict::HasSameType(extra_params)) {
1238  const pythonpp::CDict dict = extra_params;
1239 
1240  // Iterate over a dict.
1241  pythonpp::py_ssize_t i = 0;
1242  PyObject* key;
1243  PyObject* value;
1244  while ( PyDict_Next(dict, &i, &key, &value) ) {
1245  // Refer to borrowed references in key and value.
1246  const string param_name = pythonpp::CString(key);
1247  const string param_value = pythonpp::CString(value);
1248 
1249  m_DefParams.SetParam(param_name, param_value);
1250  }
1251  } else if (pythonpp::CBool::HasSameType(extra_params)) {
1252  bool support_standard_interface = pythonpp::CBool(extra_params);
1253  m_ConnectionMode = (support_standard_interface ? eStandardMode : eSimpleMode);
1254  } else {
1255  throw CNotSupportedError("Expected dictionary as an argument.");
1256  }
1257  }
1258 
1259  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1260  // Make a datasource ...
1261  m_DS = m_DM.MakeDs(m_Params);
1262 
1263  // Set up message handlers ...
1264  I_DriverContext* drv_context = m_DS->GetDriverContext();
1265 
1266  drv_context->PushCntxMsgHandler(
1269  );
1270 
1271  drv_context->PushDefConnMsgHandler(
1274  );
1275  }
1276  catch(const CException& e) {
1278  }
1279 
1280  ROAttr( "__class__", GetTypeObject() );
1281  PrepareForPython(this);
1282 
1283  try {
1284  // Create a default transaction ...
1285  // m_DefTransaction = new CTransaction(this, pythonpp::eBorrowed, m_ConnectionMode);
1287  }
1288  catch(const CException& e) {
1290  }
1291 }
1292 
1294 {
1295  try {
1296  // This DecRefCount caused a lot of problems for some reason ...
1298  // delete m_DefTransaction;
1299 
1300  _ASSERT( m_TransList.empty() );
1301 
1302  _ASSERT(m_DS);
1303 
1304  // DO NOT destroy data source because there is only one data source per
1305  // driver in Kholodov's API.
1306  // Destroying data source will cause closed and reopened connection to
1307  // crash ...
1308  // m_DM.DestroyDs(m_DS);
1309  m_DS = NULL; // ;-)
1310  }
1312 }
1313 
1314 IConnection*
1316 {
1317  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1318 
1319  _ASSERT(m_DS);
1320  // !!! eTakeOwnership !!!
1321  IConnection* connection = m_DS->CreateConnection( eTakeOwnership );
1322  connection->Connect(m_Params);
1323  return connection;
1324 }
1325 
1326 CTransaction*
1328 {
1329  CTransaction* trans = NULL;
1330 
1331  {{
1332  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1333  trans = new CTransaction(this, pythonpp::eOwned, m_ConnectionMode);
1334  }}
1335 
1336  m_TransList.insert(trans);
1337  return trans;
1338 }
1339 
1340 void
1342 {
1343  if (m_DefTransaction == trans) {
1345  }
1346 
1347  // Python will take care of the object deallocation ...
1348  m_TransList.erase(trans);
1349 }
1350 
1353 {
1354  return pythonpp::CObject(this);
1355 }
1356 
1359 {
1362 
1363  for ( citer = m_TransList.begin(); citer != cend; ++citer) {
1364  (*citer)->close(args);
1365  }
1366  return GetDefaultTransaction().close(args);
1367 }
1368 
1371 {
1372  return GetDefaultTransaction().cursor(args);
1373 }
1374 
1377 {
1378  return GetDefaultTransaction().commit(args);
1379 }
1380 
1383 {
1384  return GetDefaultTransaction().rollback(args);
1385 }
1386 
1389 {
1391 }
1392 
1393 //////////////////////////////////////////////////////////////////////////////
1395 : m_Transaction(trans)
1396 , m_PoolSize(size)
1397 {
1398 }
1399 
1400 IConnection*
1402 {
1403  IConnection* db_conn = NULL;
1404 
1405  if ( m_ConnPool.empty() ) {
1406  db_conn = GetConnection().MakeDBConnection();
1407  m_ConnList.insert(db_conn);
1408  } else {
1409  db_conn = *m_ConnPool.begin();
1411  }
1412 
1413  return db_conn;
1414 }
1415 
1416 void
1418 {
1419  if ( m_ConnPool.size() < m_PoolSize ) {
1420  m_ConnPool.insert(db_conn);
1421  } else {
1422  if ( m_ConnList.erase(db_conn) == 0) {
1423  _ASSERT(false);
1424  }
1425  delete db_conn;
1426  }
1427 }
1428 
1429 void
1431 {
1432  if ( !Empty() ) {
1433  throw CInternalError("Unable to close a transaction. There are open cursors in use.");
1434  }
1435 
1436  if ( !m_ConnList.empty() )
1437  {
1438  // Close all open connections ...
1441 
1442  // Delete all allocated "SELECT" database connections ...
1443  for ( citer = m_ConnList.begin(); citer != cend; ++citer) {
1444  delete *citer;
1445  }
1446  m_ConnList.clear();
1447  m_ConnPool.clear();
1448  }
1449 }
1450 
1451 //////////////////////////////////////////////////////////////////////////////
1453  CTransaction* trans,
1454  ETransType trans_type
1455  )
1456 : m_Transaction( trans )
1457 , m_NumOfActive( 0 )
1458 , m_Started( false )
1459 , m_TransType( trans_type )
1460 {
1461 }
1462 
1463 IConnection*
1465 {
1466  // Delayed connection creation ...
1467  if ( m_DMLConnection.get() == NULL ) {
1468  m_DMLConnection.reset( GetConnection().MakeDBConnection() );
1469  _ASSERT( m_LocalStmt.get() == NULL );
1470 
1471  if ( m_TransType == eImplicitTrans ) {
1472  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1474  // Begin transaction ...
1475  GetLocalStmt().ExecuteUpdate( "BEGIN TRANSACTION" );
1476  m_Started = true;
1477  }
1478  }
1479 
1480  ++m_NumOfActive;
1481  return m_DMLConnection.get();
1482 }
1483 
1484 void
1486 {
1487  --m_NumOfActive;
1488 }
1489 
1490 void
1492 {
1493  if ( !Empty() ) {
1494  throw CInternalError("Unable to close a transaction. There are open cursors in use.");
1495  }
1496 
1497  // Close the DML connection ...
1498  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1499  m_LocalStmt.reset();
1501  m_Started = false;
1502 }
1503 
1504 IStatement&
1506 {
1507  _ASSERT(m_LocalStmt.get() != NULL);
1508  return *m_LocalStmt;
1509 }
1510 
1511 void
1513 {
1514  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1515 
1516  if (
1518  m_Started &&
1519  m_DMLConnection.get() != NULL &&
1521  ) {
1522  try {
1523  GetLocalStmt().ExecuteUpdate( "COMMIT TRANSACTION" );
1524  GetLocalStmt().ExecuteUpdate( "BEGIN TRANSACTION" );
1525  }
1526  catch(const CException& e) {
1528  }
1529  }
1530 }
1531 
1532 void
1534 {
1535  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1536 
1537  if (
1539  m_Started &&
1540  m_DMLConnection.get() != NULL &&
1542  ) {
1543  try {
1544  GetLocalStmt().ExecuteUpdate( "ROLLBACK TRANSACTION" );
1545  GetLocalStmt().ExecuteUpdate( "BEGIN TRANSACTION" );
1546  }
1547  catch(const CException& e) {
1549  }
1550  }
1551 }
1552 
1553 //////////////////////////////////////////////////////////////////////////////
1555  CConnection* conn,
1556  pythonpp::EOwnershipFuture ownnership,
1557  EConnectionMode conn_mode
1558  )
1559 : m_ParentConnection( conn )
1560 , m_DMLConnPool( this, (conn_mode == eSimpleMode ? eExplicitTrans : eImplicitTrans) )
1561 , m_SelectConnPool( this )
1562 , m_ConnectionMode( conn_mode )
1563 {
1564  if ( conn == NULL ) {
1565  throw CInternalError("Invalid CConnection object");
1566  }
1567 
1568  if ( ownnership != pythonpp::eBorrowed ) {
1570  }
1571 
1572  ROAttr( "__class__", GetTypeObject() );
1573  PrepareForPython(this);
1574 }
1575 
1577 {
1578  try {
1579  CloseInternal();
1580 
1581  // Unregister this transaction with the parent connection ...
1583  }
1585 }
1586 
1589 {
1590  return pythonpp::CObject(this);
1591 }
1592 
1595 {
1596  try {
1597  CloseInternal();
1598  }
1599  catch(const CException& e) {
1601  }
1602 
1603  // Unregister this transaction with the parent connection ...
1604  // I'm not absolutely shure about this ... 1/24/2005 5:31PM
1605  // GetConnection().DestroyTransaction(this);
1606 
1607  return pythonpp::CNone();
1608 }
1609 
1612 {
1613  try {
1615  }
1616  catch(const CException& e) {
1618  }
1619 }
1620 
1623 {
1624  try {
1625  CommitInternal();
1626  }
1627  catch(const CException& e) {
1629  }
1630 
1631  return pythonpp::CNone();
1632 }
1633 
1636 {
1637  try {
1638  RollbackInternal();
1639  }
1640  catch(const CException& e) {
1642  }
1643 
1644  return pythonpp::CNone();
1645 }
1646 
1647 void
1649 {
1650  // Close all cursors ...
1651  CloseOpenCursors();
1652 
1653  // Double check ...
1654  // Check for the DML connection also ...
1655  // if ( !m_SelectConnPool.Empty() || !m_DMLConnPool.Empty() ) {
1656  // throw CInternalError("Unable to close a transaction. There are open cursors in use.");
1657  // }
1658 
1659  // Rollback transaction ...
1660  RollbackInternal();
1661 
1662  // Close all open connections ...
1664  // Close the DML connection ...
1665  m_DMLConnPool.Clear();
1666 }
1667 
1668 void
1670 {
1671  if ( !m_CursorList.empty() ) {
1672  // Make a copy of m_CursorList because it will be modified ...
1673  TCursorList tmp_CursorList = m_CursorList;
1675  TCursorList::const_iterator cend = tmp_CursorList.end();
1676 
1677  for ( citer = tmp_CursorList.begin(); citer != cend; ++citer ) {
1678  (*citer)->CloseInternal();
1679  }
1680  }
1681 }
1682 
1683 CCursor*
1685 {
1686  CCursor* cursor = new CCursor(this);
1687 
1688  m_CursorList.insert(cursor);
1689  return cursor;
1690 }
1691 
1692 void
1694 {
1695  // Python will take care of the object deallocation ...
1696  m_CursorList.erase(cursor);
1697 }
1698 
1699 IConnection*
1701 {
1702  IConnection* conn = NULL;
1703 
1704  if ( m_ConnectionMode == eSimpleMode ) {
1705  conn = m_DMLConnPool.Create();
1706  } else {
1707  conn = m_SelectConnPool.Create();
1708  }
1709  return conn;
1710 }
1711 
1712 void
1714 {
1715  if ( m_ConnectionMode == eSimpleMode ) {
1716  m_DMLConnPool.Destroy(db_conn);
1717  } else {
1718  m_SelectConnPool.Destroy(db_conn);
1719  }
1720 }
1721 
1722 //////////////////////////////////////////////////////////////////////////////
1724 RetrieveStatementType(const string& stmt, EStatementType default_type)
1725 {
1726  EStatementType stmtType = default_type;
1727 
1728  string::size_type pos = stmt.find_first_not_of(" \t\n");
1729  if (pos != string::npos)
1730  {
1731  string::size_type pos_end = stmt.find_first_of(" \t\n", pos);
1732  if (pos_end == string::npos)
1733  pos_end = stmt.size();
1734  CTempString first_word(&stmt[pos], pos_end - pos);
1735 
1736  // "CREATE" should be before DML ...
1737  if (NStr::EqualNocase(first_word, "CREATE"))
1738  {
1739  stmtType = estCreate;
1740  } else if (NStr::EqualNocase(first_word, "SELECT"))
1741  {
1742  stmtType = estSelect;
1743  } else if (NStr::EqualNocase(first_word, "UPDATE"))
1744  {
1745  stmtType = estUpdate;
1746  } else if (NStr::EqualNocase(first_word, "DELETE"))
1747  {
1748  stmtType = estDelete;
1749  } else if (NStr::EqualNocase(first_word, "INSERT"))
1750  {
1751  stmtType = estInsert;
1752  } else if (NStr::EqualNocase(first_word, "DROP"))
1753  {
1754  stmtType = estDrop;
1755  } else if (NStr::EqualNocase(first_word, "ALTER"))
1756  {
1757  stmtType = estAlter;
1758  } else if (NStr::EqualNocase(first_word, "BEGIN"))
1759  {
1760  stmtType = estTransaction;
1761  } else if (NStr::EqualNocase(first_word, "COMMIT"))
1762  {
1763  stmtType = estTransaction;
1764  } else if (NStr::EqualNocase(first_word, "ROLLBACK"))
1765  {
1766  stmtType = estTransaction;
1767  }
1768  }
1769 
1770  return stmtType;
1771 }
1772 
1773 //////////////////////////////////////////////////////////////////////////////
1775 : m_ParentTransaction( trans )
1776 , m_RS(NULL)
1777 , m_Executed( false )
1778 , m_ResultStatus( 0 )
1779 , m_ResultStatusAvailable( false )
1780 , m_UserHandler(NULL)
1781 {
1782  if ( m_ParentTransaction == NULL ) {
1783  throw CInternalError("Invalid CTransaction object");
1784  }
1785 }
1786 
1788 : m_ParentTransaction( trans )
1789 , m_StmtStr( stmt )
1790 , m_Executed(false)
1791 , m_ResultStatus( 0 )
1792 , m_ResultStatusAvailable( false )
1793 , m_UserHandler(NULL)
1794 {
1795  if ( m_ParentTransaction == NULL ) {
1796  throw CInternalError("Invalid CTransaction object");
1797  }
1798 
1799  CreateStmt(NULL);
1800 }
1801 
1803 {
1804  try {
1805  Close();
1806  }
1808 }
1809 
1810 void
1812 {
1813  DumpResult();
1814  ReleaseStmt();
1815  m_Executed = false;
1816  m_ResultStatus = 0;
1817  m_ResultStatusAvailable = false;
1818 }
1819 
1820 void
1822 {
1823  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1824 
1825  if ( m_Stmt.get() && m_Executed ) {
1826  while ( m_Stmt->HasMoreResults() ) {
1827  if ( m_Stmt->HasRows() ) {
1829  }
1830  }
1831  }
1832  m_RS.reset();
1833 }
1834 
1835 void
1837 {
1838  if ( m_Stmt.get() ) {
1839  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1840 
1842 
1843  // Release the statement before a connection release because it is a child object for a connection.
1844  m_RS.reset();
1845  m_Stmt.reset();
1846 
1847  _ASSERT( m_StmtStr.GetType() != estNone );
1848 
1849  if (m_UserHandler) {
1851  m_UserHandler = NULL;
1852  }
1853 
1854  if ( m_StmtStr.GetType() == estSelect ) {
1855  // Release SELECT Connection ...
1857  } else {
1858  // Release DML Connection ...
1860  }
1861  m_Executed = false;
1862  m_ResultStatus = 0;
1863  m_ResultStatusAvailable = false;
1864  }
1865 }
1866 
1867 void
1869 {
1870  m_Executed = false;
1871  m_ResultStatus = 0;
1872  m_ResultStatusAvailable = false;
1873 
1874  if ( m_StmtStr.GetType() == estSelect ) {
1875  // Get a SELECT connection ...
1877  } else {
1878  // Get a DML connection ...
1880  }
1881 
1882  if (handler) {
1885  }
1886 }
1887 
1888 void
1890 {
1891  EStatementType oldStmtType = m_StmtStr.GetType();
1892  EStatementType currStmtType = stmt.GetType();
1893  m_StmtStr = stmt;
1894 
1895  if ( m_Stmt.get() ) {
1896  // If a new statement type needs a different connection type then release an old one.
1897  if (
1898  (oldStmtType == estSelect && currStmtType != estSelect) ||
1899  (oldStmtType != estSelect && currStmtType == estSelect)
1900  ) {
1901  DumpResult();
1902  ReleaseStmt();
1903  CreateStmt(handler);
1904  } else {
1905  DumpResult();
1907  }
1908  } else {
1909  CreateStmt(handler);
1910  }
1911 
1912  m_Executed = false;
1913  m_ResultStatus = 0;
1914  m_ResultStatusAvailable = false;
1915 }
1916 
1917 void
1918 CStmtHelper::SetParam(const string& name, const CVariant& value)
1919 {
1920  _ASSERT( m_Stmt.get() );
1921 
1922  string param_name = name;
1923 
1924  if ( param_name.size() > 0) {
1925  if ( param_name[0] != '@') {
1926  param_name = "@" + param_name;
1927  }
1928  } else {
1929  throw CProgrammingError("Invalid SQL parameter name");
1930  }
1931 
1932  try {
1933  m_Stmt->SetParam( value, param_name );
1934  }
1935  catch(const CException& e) {
1937  }
1938 }
1939 
1940 void
1941 CStmtHelper::SetParam(size_t index, const CVariant& value)
1942 {
1943  _ASSERT( m_Stmt.get() );
1944 
1945  try {
1946  m_Stmt->SetParam( value, static_cast<unsigned int>(index) );
1947  }
1948  catch(const CException& e) {
1950  }
1951 }
1952 
1953 void
1955 {
1956  _ASSERT( m_Stmt.get() );
1957 
1958  try {
1959  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
1960 
1961  m_RS.reset();
1962  switch ( m_StmtStr.GetType() ) {
1963  case estSelect :
1964  m_Stmt->Execute ( m_StmtStr.GetStr() );
1965  break;
1966  default:
1968  }
1969  m_Executed = true;
1970  }
1971  catch(const bad_cast&) {
1972  throw CInternalError("std::bad_cast exception within 'CStmtHelper::Execute'");
1973  }
1974  catch(const CException& e) {
1976  }
1977  catch(const exception&) {
1978  throw CInternalError("std::exception exception within 'CStmtHelper::Execute'");
1979  }
1980 }
1981 
1982 long
1984 {
1985  if ( m_Executed ) {
1986  return m_Stmt->GetRowCount();
1987  }
1988  return -1; // As required by the specification ...
1989 }
1990 
1991 IResultSet&
1993 {
1994  if ( m_RS.get() == NULL ) {
1995  throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
1996  }
1997 
1998  return *m_RS;
1999 }
2000 
2001 const IResultSet&
2003 {
2004  if ( m_RS.get() == NULL ) {
2005  throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
2006  }
2007 
2008  return *m_RS;
2009 }
2010 
2011 bool
2013 {
2014  return m_RS.get() != NULL;
2015 }
2016 
2017 int
2019 {
2020  if ( !m_ResultStatusAvailable ) {
2021  throw CProgrammingError("Procedure return code is not defined within this context.");
2022  }
2023  return m_ResultStatus;
2024 }
2025 
2026 bool
2028 {
2029  _ASSERT( m_Stmt.get() );
2030 
2031  try {
2032  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
2033  while ( m_Stmt->HasMoreResults() ) {
2034  if ( m_Stmt->HasRows() ) {
2036  if ( m_RS->GetResultType() == eDB_StatusResult ) {
2037  m_RS->Next();
2039  m_ResultStatusAvailable = true;
2040  m_RS.reset();
2041  }
2042  else {
2043  return true;
2044  }
2045  }
2046  }
2047  }
2048  catch(const CException& e) {
2050  }
2051 
2052  return false;
2053 }
2054 
2055 static void
2057 {
2058  descr.Clear();
2059 
2060  unsigned int cnt = data->GetTotalColumns();
2061  for (unsigned int i = 1; i <= cnt; ++i) {
2062  pythonpp::CList col_list;
2063  IncRefCount(col_list);
2064  col_list.Append(pythonpp::CString(data->GetName(i)));
2065  switch (data->GetType(i)) {
2066  case eDB_Int:
2067  case eDB_SmallInt:
2068  case eDB_TinyInt:
2069  case eDB_BigInt:
2070  case eDB_Float:
2071  case eDB_Double:
2072  case eDB_Bit:
2073  case eDB_Numeric:
2074  col_list.Append((PyObject*) &python::CNumber::GetType());
2075  break;
2076  case eDB_VarChar:
2077  case eDB_Char:
2078  case eDB_LongChar:
2079  case eDB_Text:
2080  case eDB_VarCharMax:
2081  col_list.Append((PyObject*) &python::CStringType::GetType());
2082  break;
2083  case eDB_VarBinary:
2084  case eDB_Binary:
2085  case eDB_LongBinary:
2086  case eDB_Image:
2087  case eDB_VarBinaryMax:
2088  col_list.Append((PyObject*) &python::CBinary::GetType());
2089  break;
2090  case eDB_DateTime:
2091  case eDB_SmallDateTime:
2092  col_list.Append((PyObject*) &python::CDateTimeType::GetType());
2093  break;
2094  default:
2095  throw CInternalError("Invalid type of the column: "
2096  + NStr::IntToString(int(data->GetType(i))));
2097  };
2098  col_list.Append(pythonpp::CNone()); // display_size
2099  col_list.Append(pythonpp::CInt(data->GetMaxSize(i))); // internal_size
2100  col_list.Append(pythonpp::CNone()); // precision
2101  col_list.Append(pythonpp::CNone()); // scale
2102  col_list.Append(pythonpp::CNone()); // null_ok
2103 
2104  descr.Append(col_list);
2105  }
2106 }
2107 
2108 void
2110 {
2111  s_FillDescription(descr, m_RS->GetMetaData());
2112 }
2113 
2114 //////////////////////////////////////////////////////////////////////////////
2116 : m_ParentTransaction( trans )
2117 , m_Executed( false )
2118 , m_ResultStatus( 0 )
2119 , m_ResultStatusAvailable( false )
2120 , m_UserHandler(NULL)
2121 {
2122  if ( m_ParentTransaction == NULL ) {
2123  throw CInternalError("Invalid CTransaction object");
2124  }
2125 }
2126 
2128 : m_ParentTransaction( trans )
2129 , m_StmtStr( stmt )
2130 , m_Executed( false )
2131 , m_ResultStatus( 0 )
2132 , m_ResultStatusAvailable( false )
2133 , m_UserHandler(NULL)
2134 {
2135  if ( m_ParentTransaction == NULL ) {
2136  throw CInternalError("Invalid CTransaction object");
2137  }
2138 
2139  CreateStmt(NULL);
2140 }
2141 
2143 {
2144  try {
2145  Close();
2146  }
2148 }
2149 
2150 void
2152 {
2153  DumpResult();
2154  ReleaseStmt();
2155  m_Executed = false;
2156  m_ResultStatus = 0;
2157  m_ResultStatusAvailable = false;
2158 }
2159 
2160 void
2162 {
2163  if ( m_Stmt.get() ) {
2164  if (m_RSProxy.get()) {
2165  m_RSProxy->DumpResult();
2166  }
2167  }
2168 }
2169 
2170 void
2172 {
2173  if ( m_Stmt.get() ) {
2174  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
2175 
2177 
2178  // Release the statement before a connection release because it is a child object for a connection.
2179  m_Stmt.reset();
2180 
2181  _ASSERT( m_StmtStr.GetType() != estNone );
2182 
2183  if (m_UserHandler) {
2185  m_UserHandler = NULL;
2186  }
2187 
2188  // Release DML Connection ...
2190  m_Executed = false;
2191  m_ResultStatus = 0;
2192  m_ResultStatusAvailable = false;
2193  }
2194 }
2195 
2196 void
2198 {
2200 
2201  ReleaseStmt();
2203 
2204  if (handler) {
2207  }
2208 }
2209 
2210 void
2212 {
2213  m_StmtStr = stmt;
2214 
2215  DumpResult();
2216  CreateStmt(handler);
2217 
2218  m_Executed = false;
2219  m_ResultStatus = 0;
2220  m_ResultStatusAvailable = false;
2221 }
2222 
2223 void
2224 CCallableStmtHelper::SetParam(const string& name, const CVariant& value, bool& output_param)
2225 {
2226  _ASSERT( m_Stmt.get() );
2227 
2228  string param_name = name;
2229 
2230  if ( param_name.size() > 0) {
2231  if ( param_name[0] != '@') {
2232  param_name = "@" + param_name;
2233  }
2234  } else {
2235  throw CProgrammingError("Invalid SQL parameter name");
2236  }
2237 
2238  try {
2240  m_Stmt->SetParam( value, param_name );
2241  output_param = false;
2242  } else {
2243  if (value.IsNull()) {
2244  CVariant temp_val(m_Stmt->GetParamsMetaData().GetType(name));
2245  m_Stmt->SetOutputParam( temp_val, param_name );
2246  }
2247  else {
2248  m_Stmt->SetOutputParam( value, param_name );
2249  }
2250  output_param = true;
2251  }
2252  }
2253  catch(const CException& e) {
2255  }
2256 }
2257 
2258 void
2259 CCallableStmtHelper::SetParam(size_t index, const CVariant& value, bool& output_param)
2260 {
2261  _ASSERT( m_Stmt.get() );
2262 
2263  try {
2264  unsigned int ind = static_cast<unsigned int>(index);
2266  m_Stmt->SetParam( value, ind );
2267  output_param = false;
2268  } else {
2269  if (value.IsNull()) {
2270  CVariant temp_val(m_Stmt->GetParamsMetaData().GetType(ind));
2271  m_Stmt->SetOutputParam( temp_val, ind );
2272  }
2273  else {
2274  m_Stmt->SetOutputParam( value, ind );
2275  }
2276  output_param = true;
2277  }
2278  }
2279  catch(const CException& e) {
2281  }
2282 }
2283 
2284 void
2285 CCallableStmtHelper::Execute(bool cache_results)
2286 {
2287  _ASSERT( m_Stmt.get() );
2288 
2289  try {
2290  m_ResultStatus = 0;
2291  m_ResultStatusAvailable = false;
2292 
2293  {{
2294  pythonpp::CThreadingGuard ALLOW_OTHER_THREADS;
2295  m_Stmt->Execute();
2296  }}
2297 
2298  // Retrieve a resut if there is any ...
2299  if (cache_results) {
2300  m_RSProxy.reset(new CVariantSetProxy(*m_Stmt));
2301  } else {
2302  m_RSProxy.reset(new CRealSetProxy(*m_Stmt));
2303  }
2304  m_Executed = true;
2305  }
2306  catch(const bad_cast&) {
2307  throw CInternalError("std::bad_cast exception within 'CCallableStmtHelper::Execute'");
2308  }
2309  catch(const CException& e) {
2311  }
2312  catch(const exception&) {
2313  throw CInternalError("std::exception exception within 'CCallableStmtHelper::Execute'");
2314  }
2315 }
2316 
2317 long
2319 {
2320  if ( m_Executed ) {
2321  return m_Stmt->GetRowCount();
2322  }
2323  return -1; // As required by the specification ...
2324 }
2325 
2326 CVariantSet&
2328 {
2329  if ( m_RSProxy.get() == NULL ) {
2330  throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
2331  }
2332 
2333  return m_RSProxy->GetRS();
2334 }
2335 
2336 const CVariantSet&
2338 {
2339  if ( m_RSProxy.get() == NULL ) {
2340  throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
2341  }
2342 
2343  return m_RSProxy->GetRS();
2344 }
2345 
2346 bool
2348 {
2349  if (m_RSProxy.get()) {
2350  return m_RSProxy->HasRS();
2351  }
2352 
2353  return false;
2354 }
2355 
2356 int
2358 {
2359  if ( !m_ResultStatusAvailable ) {
2360  throw CProgrammingError("Procedure return code is not defined within this context.");
2361  }
2362  return m_Stmt->GetReturnStatus();
2363 }
2364 
2365 bool
2367 {
2368  if ( m_RSProxy.get() == NULL ) {
2369  throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
2370  }
2371 
2372  bool result = m_RSProxy->MoveToNextRS();
2373 
2374  if (!result) {
2375  m_ResultStatusAvailable = true;
2376  }
2377 
2378  return result;
2379 }
2380 
2381 bool
2383 {
2384  if ( m_RSProxy.get() == NULL ) {
2385  throw CProgrammingError("The previous call to executeXXX() did not produce any result set or no call was issued yet");
2386  }
2387 
2388  return m_RSProxy->MoveToLastRS();
2389 }
2390 
2391 void
2393 {
2394  s_FillDescription(descr, &m_RSProxy->GetRS().GetMetaData());
2395 }
2396 
2397 
2398 //////////////////////////////////////////////////////////////////////////////
2401 {
2402  if ( value.IsNull() ) {
2403  return pythonpp::CObject();
2404  }
2405 
2406  switch ( value.GetType() ) {
2407  case eDB_Int :
2408  return pythonpp::CInt( value.GetInt4() );
2409  case eDB_SmallInt :
2410  return pythonpp::CInt( value.GetInt2() );
2411  case eDB_TinyInt :
2412  return pythonpp::CInt( value.GetByte() );
2413  case eDB_BigInt :
2414  return pythonpp::CLong( value.GetInt8() );
2415  case eDB_Float :
2416  return pythonpp::CFloat( value.GetFloat() );
2417  case eDB_Double :
2418  return pythonpp::CFloat( value.GetDouble() );
2419  case eDB_Bit :
2420  // BIT --> BOOL ...
2421  return pythonpp::CBool( value.GetBit() );
2422 #if PY_VERSION_HEX >= 0x02040000
2423  case eDB_DateTime :
2424  case eDB_SmallDateTime :
2425  {
2426  const CTime& cur_time = value.GetCTime();
2427  return pythonpp::CDateTime(
2428  cur_time.Year(),
2429  cur_time.Month(),
2430  cur_time.Day(),
2431  cur_time.Hour(),
2432  cur_time.Minute(),
2433  cur_time.Second(),
2434  cur_time.NanoSecond() / 1000
2435  );
2436  }
2437 #endif
2438  case eDB_VarChar :
2439  case eDB_Char :
2440  case eDB_LongChar :
2441  {
2442  string str = value.GetString();
2443  return pythonpp::CString( str );
2444  }
2445  case eDB_LongBinary :
2446  case eDB_VarBinary :
2447  case eDB_Binary :
2448  case eDB_Numeric :
2449  return pythonpp::CString( value.GetString() );
2450  case eDB_Text :
2451  case eDB_Image :
2452  case eDB_VarCharMax:
2453  case eDB_VarBinaryMax:
2454  {
2455  size_t lob_size = value.GetBlobSize();
2456  string tmp_str;
2457 
2458  tmp_str.resize(lob_size);
2459  value.Read( (void*)tmp_str.data(), lob_size );
2460  return pythonpp::CString(tmp_str);
2461  }
2462  case eDB_UnsupportedType :
2463  break;
2464  default:
2465  // All cases are supposed to be handled.
2466  // In case of PY_VERSION_HEX < 0x02040000 eDB_DateTime and
2467  // eDB_SmallDateTime will be missed.
2468  break;
2469  }
2470 
2471  return pythonpp::CObject();
2472 }
2473 
2474 //////////////////////////////////////////////////////////////////////////////
2477 {
2478  // Previous implementation of GetColumnNo/GetTotalColumns used to return
2479  // invalid value ...
2480  // col_num = (col_num > 0 ? col_num - 1 : col_num);
2481 
2482  // Set data. Make a sequence (tuple) ...
2483  int col_num = rs.GetTotalColumns();
2484 
2485  pythonpp::CTuple tuple(col_num);
2486 
2487  for ( int i = 0; i < col_num; ++i) {
2488  const CVariant& value = rs.GetVariant (i + 1);
2489 
2490  tuple[i] = ConvertCVariant2PCObject(value);
2491  }
2492 
2493  return tuple;
2494 }
2495 
2496 //////////////////////////////////////////////////////////////////////////////
2499 {
2500  // Set data. Make a sequence (tuple) ...
2501  int col_num = rs.GetTotalColumns();
2502 
2503  pythonpp::CTuple tuple(col_num);
2504 
2505  for ( int i = 0; i < col_num; ++i) {
2506  const CVariant& value = rs.GetVariant (i + 1);
2507 
2508  tuple[i] = ConvertCVariant2PCObject(value);
2509  }
2510 
2511  return tuple;
2512 }
2513 
2514 
2516 {
2517  if (ex->GetSybaseSeverity() <= 10) {
2518  m_Cursor->AddInfoMessage(ex->GetMsg());
2519  return true;
2520  }
2521 
2522  return false;
2523 }
2524 
2525 
2526 //////////////////////////////////////////////////////////////////////////////
2528 : m_PythonConnection( &trans->GetParentConnection() )
2529 , m_PythonTransaction( trans )
2530 , m_ParentTransaction( trans )
2531 , m_NumOfArgs( 0 )
2532 , m_RowsNum( -1 )
2533 , m_InfoHandler( this )
2534 , m_ArraySize( 1 )
2535 , m_StmtHelper( trans )
2536 , m_CallableStmtHelper( trans )
2537 , m_AllDataFetched( false )
2538 , m_AllSetsFetched( false )
2539 , m_Closed( false )
2540 {
2541  if ( trans == NULL ) {
2542  throw CInternalError("Invalid CTransaction object");
2543  }
2544 
2545  ROAttr( "__class__", GetTypeObject() );
2546  // The following list should reflect exactly members set to CCursor type
2547  // in init_common().
2548  ROAttr( "rowcount", m_RowsNum );
2549  ROAttr( "messages", m_InfoMessages );
2550  ROAttr( "description", m_Description );
2551 
2554 
2556 
2557  PrepareForPython(this);
2558 }
2559 
2561 {
2562  try {
2563  CloseInternal();
2564 
2565  // Unregister this cursor with the parent transaction ...
2566  GetTransaction().DestroyCursor(this);
2567  }
2569 }
2570 
2571 void
2573 {
2574  m_StmtHelper.Close();
2576  m_RowsNum = -1; // As required by the specification ...
2577  m_AllDataFetched = false;
2578  m_AllSetsFetched = false;
2579  m_Closed = true;
2580 }
2581 
2582 void
2583 CCursor::AddInfoMessage(const string& message)
2584 {
2586 }
2587 
2590 {
2591  if (m_Closed) {
2592  throw CProgrammingError("Cursor is closed");
2593  }
2594 
2595  try {
2596  const size_t args_size = args.size();
2597 
2598  m_RowsNum = -1; // As required by the specification ...
2599  m_AllDataFetched = false;
2600  m_AllSetsFetched = false;
2601  vector<size_t> out_params;
2602 
2603  if ( args_size == 0 ) {
2604  throw CProgrammingError("A stored procedure name is expected as a parameter");
2605  } else if ( args_size > 0 ) {
2606  pythonpp::CObject obj(args[0]);
2607 
2608  if ( pythonpp::CString::HasSameType(obj) ) {
2610  } else {
2611  throw CProgrammingError("A stored procedure name is expected as a parameter");
2612  }
2613 
2614  m_StmtHelper.Close();
2616 
2617  // Setup parameters ...
2618  if ( args_size > 1 ) {
2619  pythonpp::CObject obj( args[1] );
2620 
2621  if ( pythonpp::CDict::HasSameType(obj) ) {
2622  const pythonpp::CDict dict(obj);
2624  // Put any number as below only size is used in this case
2625  out_params.push_back(0);
2626  }
2627  } else if ( pythonpp::CList::HasSameType(obj)
2629  {
2630  const pythonpp::CSequence seq(obj);
2631  SetupParameters(seq, m_CallableStmtHelper, &out_params);
2632  } else {
2633  throw CNotSupportedError("Inappropriate type for parameter binding");
2634  }
2635  }
2636  }
2637 
2639  m_CallableStmtHelper.Execute(out_params.size() != 0);
2641 
2642  pythonpp::CObject output_args;
2643  if (args_size > 1 && out_params.size() != 0) {
2644  // If we have input parameters ...
2645  output_args.Set(args[1]);
2646 
2648  // We can have out/inout arguments ...
2650 
2651  if ( rs.GetResultType() == eDB_ParamResult ) {
2652  // We've got ParamResult with output arguments ...
2653  if ( rs.Next() ) {
2654  int col_num = rs.GetTotalColumns();
2655  const IResultSetMetaData& md = rs.GetMetaData();
2656 
2657  for ( int i = 0; i < col_num; ++i) {
2658  const CVariant& value = rs.GetVariant (i + 1);
2659 
2660  if ( pythonpp::CDict::HasSameType(output_args) ) {
2661  // Dictionary ...
2662  pythonpp::CDict dict(output_args);
2663  const string param_name = md.GetName(i + 1);
2664 
2665  dict.SetItem(param_name, ConvertCVariant2PCObject(value));
2666  } else if ( pythonpp::CList::HasSameType(output_args) ) {
2667  pythonpp::CList lst(output_args);
2668  lst.SetItem(out_params[i], ConvertCVariant2PCObject(value));
2669  } else {
2670  throw CNotSupportedError("Inappropriate type for parameter binding");
2671  }
2672  }
2673  }
2674  }
2675  }
2676  }
2677 
2678  // Get RowResultSet ...
2682  }
2683  else {
2686  }
2687 
2688  return output_args;
2689  }
2690  catch(const CException& e) {
2692  }
2693 }
2694 
2697 {
2698  return pythonpp::CObject(this);
2699 }
2700 
2703 {
2704  try {
2705  CloseInternal();
2706 
2707  // Unregister this cursor with the parent transaction ...
2708  GetTransaction().DestroyCursor(this);
2709  }
2710  catch(const CException& e) {
2712  }
2713 
2714  return pythonpp::CNone();
2715 }
2716 
2719 {
2720  if (m_Closed) {
2721  throw CProgrammingError("Cursor is closed");
2722  }
2723 
2724  try {
2725  const size_t args_size = args.size();
2726 
2727  m_AllDataFetched = false;
2728  m_AllSetsFetched = false;
2729 
2730  // Process function's arguments ...
2731  if ( args_size == 0 ) {
2732  throw CProgrammingError("An SQL statement string is expected as a parameter");
2733  } else if ( args_size > 0 ) {
2734  pythonpp::CObject obj(args[0]);
2735 
2736  if ( pythonpp::CString::HasSameType(obj) ) {
2738  } else {
2739  throw CProgrammingError("An SQL statement string is expected as a parameter");
2740  }
2741 
2744 
2745  // Setup parameters ...
2746  if ( args_size > 1 ) {
2747  pythonpp::CObject obj(args[1]);
2748 
2749  if ( pythonpp::CDict::HasSameType(obj) ) {
2750  const pythonpp::CDict dict = obj;
2752  } else if ( pythonpp::CList::HasSameType(obj)
2754  {
2755  const pythonpp::CSequence seq = obj;
2757  } else {
2758  throw CNotSupportedError("Inappropriate type for parameter binding");
2759  }
2760  }
2761  }
2762 
2766 
2767  if (m_StmtHelper.MoveToNextRS()) {
2770  }
2771  else {
2774  }
2775  }
2776  catch(const CException& e) {
2778  }
2779 
2780  return pythonpp::CObject(this);
2781 }
2782 
2783 PyObject*
2785 {
2786  return new CCursorIter(this);
2787 }
2788 
2789 void
2791 {
2792  // Iterate over a dict.
2793  pythonpp::py_ssize_t i = 0;
2794  PyObject* key;
2795  PyObject* value;
2796  while ( PyDict_Next(dict, &i, &key, &value) ) {
2797  // Refer to borrowed references in key and value.
2798  const pythonpp::CObject key_obj(key);
2799  const pythonpp::CObject value_obj(value);
2800  string param_name = pythonpp::CString(key_obj);
2801 
2802  stmt.SetParam(param_name, GetCVariant(value_obj));
2803  }
2804 }
2805 
2806 void
2808 {
2809  // Iterate over a sequence.
2810  size_t sz = seq.size();
2811  for (size_t i = 0; i < sz; ++i) {
2812  const pythonpp::CObject value_obj(seq.GetItem(i));
2813  stmt.SetParam(i + 1, GetCVariant(value_obj));
2814  }
2815 }
2816 
2817 bool
2819 {
2820  // Iterate over a dict.
2821  pythonpp::py_ssize_t i = 0;
2822  PyObject* key;
2823  PyObject* value;
2824  bool result = false;
2825  bool output_param = false;
2826 
2827  while ( PyDict_Next(dict, &i, &key, &value) ) {
2828  // Refer to borrowed references in key and value.
2829  const pythonpp::CObject key_obj(key);
2830  const pythonpp::CObject value_obj(value);
2831  string param_name = pythonpp::CString(key_obj);
2832 
2833  stmt.SetParam(param_name, GetCVariant(value_obj), output_param);
2834  result |= output_param;
2835  }
2836  return result;
2837 }
2838 
2839 void
2842  vector<size_t>* out_params)
2843 {
2844  // Iterate over a sequence.
2845  size_t sz = seq.size();
2846 
2847  for (size_t i = 0; i < sz; ++i) {
2848  // Refer to borrowed references in key and value.
2849  const pythonpp::CObject value_obj(seq.GetItem(i));
2850 
2851  bool output_param = false;
2852  stmt.SetParam(i + 1, GetCVariant(value_obj), output_param);
2853  if (output_param)
2854  out_params->push_back(i);
2855  }
2856 }
2857 
2858 CVariant
2860 {
2861  if ( pythonpp::CNone::HasSameType(obj) ) {
2862  return CVariant(eDB_VarChar);
2863  } else if ( pythonpp::CBool::HasSameType(obj) ) {
2864  return CVariant( pythonpp::CBool(obj) );
2865  } else if ( pythonpp::CInt::HasSameType(obj) ) {
2866  return CVariant( static_cast<int>(pythonpp::CInt(obj)) );
2867  } else if ( pythonpp::CLong::HasSameType(obj) ) {
2868  return CVariant( static_cast<Int8>(pythonpp::CLong(obj)) );
2869  } else if ( pythonpp::CFloat::HasSameType(obj) ) {
2870  return CVariant( pythonpp::CFloat(obj) );
2871  } else if ( pythonpp::CString::HasSameType(obj) ) {
2872  const pythonpp::CString python_str(obj);
2873  const string std_str(python_str);
2874  return CVariant( std_str );
2875 #if PY_VERSION_HEX >= 0x02040000
2876  } else if ( pythonpp::CDateTime::HasSameType(obj) ) {
2877  const pythonpp::CDateTime python_date(obj);
2878  const CTime std_date(python_date.GetYear(),
2879  python_date.GetMonth(),
2880  python_date.GetDay(),
2881  python_date.GetHour(),
2882  python_date.GetMinute(),
2883  python_date.GetSecond(),
2884  python_date.GetMicroSecond() * 1000);
2885  return CVariant( std_date, eLong );
2886  } else if ( pythonpp::CDate::HasSameType(obj) ) {
2887  const pythonpp::CDate python_date(obj);
2888  const CTime std_date(python_date.GetYear(),
2889  python_date.GetMonth(),
2890  python_date.GetDay());
2891  return CVariant( std_date, eLong );
2892  } else if ( pythonpp::CTime::HasSameType(obj) ) {
2893  const pythonpp::CTime python_time(obj);
2894  CTime std_date(CTime::eCurrent);
2895  std_date.SetHour(python_time.GetHour());
2896  std_date.SetMinute(python_time.GetMinute());
2897  std_date.SetSecond(python_time.GetSecond());
2898  std_date.SetMicroSecond(python_time.GetMicroSecond());
2899  return CVariant( std_date, eLong );
2900 #endif
2901  } else if (obj == CBinary::GetType()) {
2902  const string value = static_cast<CBinary*>(obj.Get())->GetValue();
2903  return CVariant::VarBinary(value.data(), value.size());
2904  }
2905 
2906  return CVariant(eDB_UnsupportedType);
2907 }
2908 
2911 {
2912  if (m_Closed) {
2913  throw CProgrammingError("Cursor is closed");
2914  }
2915 
2916  try {
2917  const size_t args_size = args.size();
2918 
2919  m_AllDataFetched = false;
2920  m_AllSetsFetched = false;
2921 
2922  // Process function's arguments ...
2923  if ( args_size == 0 ) {
2924  throw CProgrammingError("A SQL statement string is expected as a parameter");
2925  } else if ( args_size > 0 ) {
2926  pythonpp::CObject obj(args[0]);
2927 
2928  if ( pythonpp::CString::HasSameType(obj) ) {
2930  } else {
2931  throw CProgrammingError("A SQL statement string is expected as a parameter");
2932  }
2933 
2934  // Setup parameters ...
2935  if ( args_size > 1 ) {
2936  pythonpp::CObject obj(args[1]);
2937 
2939  const pythonpp::CSequence params(obj);
2941  pythonpp::CList::const_iterator cend = params.end();
2942 
2943  //
2946  m_RowsNum = 0;
2948 
2949  for ( citer = params.begin(); citer != cend; ++citer ) {
2950  if ( pythonpp::CDict::HasSameType(*citer) ) {
2951  const pythonpp::CDict dict = *citer;
2953  } else if ( pythonpp::CList::HasSameType(*citer)
2954  || pythonpp::CTuple::HasSameType(*citer) )
2955  {
2956  const pythonpp::CSequence seq = *citer;
2958  } else {
2959  throw CNotSupportedError("Inappropriate type for parameter binding");
2960  }
2963  }
2964 
2965  if (m_StmtHelper.MoveToNextRS()) {
2968  }
2969  else {
2972  }
2973  } else {
2974  throw CProgrammingError("Sequence of parameters should be provided either as a list or as a tuple data type");
2975  }
2976  } else {
2977  throw CProgrammingError("A sequence of parameters is expected with the 'executemany' function");
2978  }
2979  }
2980  }
2981  catch(const CException& e) {
2983  }
2984 
2985  return pythonpp::CNone();
2986 }
2987 
2990 {
2991  try {
2992  if ( m_AllDataFetched ) {
2993  return pythonpp::CNone();
2994  }
2995  if ( m_StmtStr.GetType() == estFunction ) {
2997 
2998  if ( rs.Next() ) {
3000  return MakeTupleFromResult( rs );
3001  }
3002  } else {
3003  IResultSet& rs = m_StmtHelper.GetRS();
3004 
3005  if ( rs.Next() ) {
3007  return MakeTupleFromResult( rs );
3008  }
3009  }
3010  }
3011  catch (const CException& e) {
3013  }
3014 
3015  m_AllDataFetched = true;
3016  return pythonpp::CNone();
3017 }
3018 
3021 {
3022  size_t array_size = m_ArraySize;
3023 
3024  try {
3025  if ( args.size() > 0 ) {
3026  array_size = static_cast<unsigned long>(pythonpp::CLong(args[0]));
3027  }
3028  } catch (const pythonpp::CError&) {
3029  throw CProgrammingError("Invalid parameters within 'CCursor::fetchmany' function");
3030  }
3031 
3032  pythonpp::CList py_list;
3033  try {
3034  if ( m_AllDataFetched ) {
3035  return py_list;
3036  }
3037  if ( m_StmtStr.GetType() == estFunction ) {
3039 
3040  size_t i = 0;
3041  for ( ; i < array_size && rs.Next(); ++i ) {
3042  py_list.Append(MakeTupleFromResult(rs));
3043  }
3044 
3045  // We fetched less than expected ...
3046  if ( i < array_size ) {
3047  m_AllDataFetched = true;
3048  }
3049 
3051  } else {
3052  IResultSet& rs = m_StmtHelper.GetRS();
3053 
3054  size_t i = 0;
3055  for ( ; i < array_size && rs.Next(); ++i ) {
3056  py_list.Append(MakeTupleFromResult(rs));
3057  }
3058 
3059  // We fetched less than expected ...
3060  if ( i < array_size ) {
3061  m_AllDataFetched = true;
3062  }
3063 
3065  }
3066  }
3067  catch (const CException& e) {
3069  }
3070 
3071  return py_list;
3072 }
3073 
3076 {
3077  pythonpp::CList py_list;
3078 
3079  try {
3080  if ( m_AllDataFetched ) {
3081  return py_list;
3082  }
3083 
3084  if ( m_StmtStr.GetType() == estFunction ) {
3085  if (m_CallableStmtHelper.HasRS()) {
3087 
3088  while ( rs.Next() ) {
3089  py_list.Append(MakeTupleFromResult(rs));
3090  }
3091 
3093  }
3094  } else {
3095  if (m_StmtHelper.HasRS()) {
3096  IResultSet& rs = m_StmtHelper.GetRS();
3097 
3098  while ( rs.Next() ) {
3099  py_list.Append(MakeTupleFromResult(rs));
3100  }
3101 
3103  }
3104  }
3105  }
3106  catch (const CException& e) {
3108  }
3109 
3110  m_AllDataFetched = true;
3111  return py_list;
3112 }
3113 
3114 bool
3116 {
3117  try {
3118  m_RowsNum = 0;
3119 
3120  if ( !m_AllSetsFetched ) {
3121  if ( m_StmtStr.GetType() == estFunction ) {
3122  if (m_CallableStmtHelper.HasRS()) {
3124  m_AllDataFetched = false;
3125  return true;
3126  }
3127  } else {
3128  return false;
3129  }
3130  } else {
3131  if (m_StmtHelper.HasRS()) {
3132  if ( m_StmtHelper.MoveToNextRS() ) {
3133  m_AllDataFetched = false;
3134  return true;
3135  }
3136  } else {
3137  return false;
3138  }
3139  }
3140  }
3141  }
3142  catch (const CException& e) {
3144  }
3145 
3146  m_AllDataFetched = true;
3147  m_AllSetsFetched = true;
3148 
3149  return false;
3150 }
3151 
3154 {
3155  try {
3156  if ( NextSetInternal() ) {
3157  if (m_StmtStr.GetType() == estFunction) {
3159  }
3160  else {
3162  }
3164  return pythonpp::CBool(true);
3165  }
3167  }
3168  catch (const CException& e) {
3170  }
3171 
3172  return pythonpp::CNone();
3173 }
3174 
3177 {
3178  return pythonpp::CNone();
3179 }
3180 
3183 {
3184  return pythonpp::CNone();
3185 }
3186 
3189 {
3190  if (m_Closed) {
3191  throw CProgrammingError("Cursor is closed");
3192  }
3193 
3194  try {
3195  if ( !m_AllDataFetched ) {
3196  throw CProgrammingError("Call get_proc_return_status after you retrieve all data.");
3197  }
3198 
3199  NextSetInternal();
3200 
3201  if ( !m_AllSetsFetched ) {
3202  throw CProgrammingError("Call get_proc_return_status after you retrieve all data.");
3203  }
3204 
3205  if ( m_StmtStr.GetType() == estFunction ) {
3207  } else {
3209  }
3210  }
3211  catch (const CException& e) {
3213  }
3214 
3215  return pythonpp::CNone();
3216 }
3217 
3218 
3219 extern "C"
3220 PyObject*
3221 s_GetCursorIter(PyObject* curs_obj)
3222 {
3223  CCursor* cursor = (CCursor*)curs_obj;
3224  return cursor->CreateIter();
3225 }
3226 
3227 
3229  : m_PythonCursor(cursor),
3230  m_Cursor(cursor),
3231  m_StopIter(false)
3232 {
3233  PrepareForPython(this);
3234 }
3235 
3237 {}
3238 
3239 PyObject*
3241 {
3242  if (!m_StopIter) {
3245  return IncRefCount(row);
3246  m_StopIter = true;
3247  }
3248  return NULL;
3249 }
3250 
3251 
3252 extern "C"
3253 PyObject*
3254 s_GetCursorIterFromIter(PyObject* iter_obj)
3255 {
3256  return iter_obj;
3257 }
3258 
3259 extern "C"
3260 PyObject*
3261 s_CursorIterNext(PyObject* iter_obj)
3262 {
3263  CCursorIter* iter = (CCursorIter*)iter_obj;
3264  return iter->GetNext();
3265 }
3266 
3267 
3268 ///////////////////////////////////////////////////////////////////////////////
3269 CWarning::CWarning(const string& msg)
3270 : pythonpp::CUserError<CWarning>( msg )
3271 {
3272 }
3273 
3274 ///////////////////////////////////////////////////////////////////////////////
3275 CError::CError(const string& msg, PyObject* err_type)
3276 : pythonpp::CUserError<CError>(msg, err_type)
3277 {
3278 }
3279 
3280 void CError::x_Init(const CDB_Exception& e, PyObject* err_type)
3281 {
3282  const CException* cur_exception = &e;
3283  string srv_msg;
3284 
3285  for (; cur_exception; cur_exception = cur_exception->GetPredecessor()) {
3286  /* Collect all messages ...
3287  if (!srv_msg.empty() && !cur_exception->GetMsg().empty()) {
3288  srv_msg += " ";
3289  }
3290 
3291  srv_msg += cur_exception->GetMsg();
3292  */
3293 
3294  // Get the last message only ...
3295  srv_msg = cur_exception->GetMsg();
3296  }
3297 
3298  x_Init(e.what(), e.GetDBErrCode(), srv_msg, err_type);
3299 }
3300 
3301 void CError::x_Init(const string& msg, long db_errno, const string& db_msg,
3302  PyObject* err_type)
3303 {
3304  PyObject *exc_ob = NULL;
3305  PyObject *errno_ob = NULL;
3306  PyObject *msg_ob = NULL;
3307 
3308  // Make an integer for the error code.
3309 #if PY_MAJOR_VERSION >= 3
3310  errno_ob = PyLong_FromLong(db_errno);
3311 #else
3312  errno_ob = PyInt_FromLong(db_errno);
3313 #endif
3314  if (errno_ob == NULL) {
3315  return;
3316  }
3317 
3318 #if PY_MAJOR_VERSION >= 3
3319  msg_ob = PyUnicode_FromStringAndSize(db_msg.data(), db_msg.size());
3320 #else
3321  msg_ob = PyString_FromStringAndSize(db_msg.data(), db_msg.size());
3322 #endif
3323  if (errno_ob == NULL) {
3324  Py_DECREF(errno_ob);
3325  return;
3326  }
3327 
3328  // Instantiate a Python exception object.
3329  exc_ob = PyObject_CallFunction(err_type, (char *)"s", (char*)msg.c_str());
3330  if (exc_ob == NULL)
3331  {
3332  Py_DECREF(errno_ob);
3333  Py_DECREF(msg_ob);
3334  return;
3335  }
3336 
3337  // Set the "db_errno" attribute of the exception to our error code.
3338  if (PyObject_SetAttrString(exc_ob, (char *)"srv_errno", errno_ob) == -1)
3339  {
3340  Py_DECREF(errno_ob);
3341  Py_DECREF(msg_ob);
3342  Py_DECREF(exc_ob);
3343  return;
3344  }
3345 
3346  // Finished with the errno_ob object.
3347  Py_DECREF(errno_ob);
3348 
3349  // Set the "db_msg" attribute of the exception to our message.
3350  if (PyObject_SetAttrString(exc_ob, (char *)"srv_msg", msg_ob) == -1)
3351  {
3352  Py_DECREF(msg_ob);
3353  Py_DECREF(exc_ob);
3354  return;
3355  }
3356 
3357  // Finished with the msg_ob object.
3358  Py_DECREF(msg_ob);
3359 
3360  // Set the error state to our exception object.
3361  PyErr_SetObject(err_type, exc_ob);
3362 
3363  // Finished with the exc_ob object.
3364  Py_DECREF(exc_ob);
3365 }
3366 
3367 ///////////////////////////////////////////////////////////////////////////////
3368 /* Future development ... 2/4/2005 12:05PM
3369 //////////////////////////////////////////////////////////////////////////////
3370 // Future development ...
3371 class CModuleDBAPI : public pythonpp::CExtModule<CModuleDBAPI>
3372 {
3373 public:
3374  CModuleDBAPI(const char* name, const char* descr = 0)
3375  : pythonpp::CExtModule<CModuleDBAPI>(name, descr)
3376  {
3377  PrepareForPython(this);
3378  }
3379 
3380 public:
3381  // connect(driver_name, db_type, db_name, user_name, user_pswd)
3382  pythonpp::CObject connect(const pythonpp::CTuple& args);
3383  pythonpp::CObject Binary(const pythonpp::CTuple& args);
3384  pythonpp::CObject TimestampFromTicks(const pythonpp::CTuple& args);
3385  pythonpp::CObject TimeFromTicks(const pythonpp::CTuple& args);
3386  pythonpp::CObject DateFromTicks(const pythonpp::CTuple& args);
3387  pythonpp::CObject Timestamp(const pythonpp::CTuple& args);
3388  pythonpp::CObject Time(const pythonpp::CTuple& args);
3389  pythonpp::CObject Date(const pythonpp::CTuple& args);
3390 };
3391 
3392 pythonpp::CObject
3393 CModuleDBAPI::connect(const pythonpp::CTuple& args)
3394 {
3395  string driver_name;
3396  string db_type;
3397  string server_name;
3398  string db_name;
3399  string user_name;
3400  string user_pswd;
3401 
3402  try {
3403  try {
3404  const pythonpp::CTuple func_args(args);
3405 
3406  driver_name = pythonpp::CString(func_args[0]);
3407  db_type = pythonpp::CString(func_args[1]);
3408  server_name = pythonpp::CString(func_args[2]);
3409  db_name = pythonpp::CString(func_args[3]);
3410  user_name = pythonpp::CString(func_args[4]);
3411  user_pswd = pythonpp::CString(func_args[5]);
3412  } catch (const pythonpp::CError&) {
3413  throw CProgrammingError("Invalid parameters within 'connect' function");
3414  }
3415 
3416  CConnection* conn = new CConnection( CConnParam(
3417  driver_name,
3418  db_type,
3419  server_name,
3420  db_name,
3421  user_name,
3422  user_pswd
3423  ));
3424 
3425  // Feef the object to the Python interpreter ...
3426  return pythonpp::CObject(conn, pythonpp::eTakeOwnership);
3427  }
3428  catch (const CException& e) {
3429  s_ThrowDatabaseError(e);
3430  }
3431 
3432  // Return a dummy object ...
3433  return pythonpp::CNone();
3434 }
3435 
3436 // This function constructs an object holding a date value.
3437 // Date(year,month,day)
3438 pythonpp::CObject
3439 CModuleDBAPI::Date(const pythonpp::CTuple& args)
3440 {
3441  try {
3442  int year;
3443  int month;
3444  int day;
3445 
3446  try {
3447  const pythonpp::CTuple func_args(args);
3448 
3449  year = pythonpp::CInt(func_args[0]);
3450  month = pythonpp::CInt(func_args[1]);
3451  day = pythonpp::CInt(func_args[2]);
3452  } catch (const pythonpp::CError&) {
3453  throw CProgrammingError("Invalid parameters within 'Date' function");
3454  }
3455 
3456  // Feef the object to the Python interpreter ...
3457  return pythonpp::CDate(year, month, day);
3458  }
3459  catch (const CDB_Exception& e) {
3460  s_ThrowDatabaseError(e);
3461  }
3462  catch (const CException& e) {
3463  pythonpp::CError::SetString(e.what());
3464  }
3465 
3466  // Return a dummy object ...
3467  return pythonpp::CNone();
3468 }
3469 
3470 // This function constructs an object holding a time value.
3471 // Time(hour,minute,second)
3472 pythonpp::CObject
3473 CModuleDBAPI::Time(const pythonpp::CTuple& args)
3474 {
3475  try {
3476  int hour;
3477  int minute;
3478  int second;
3479 
3480  try {
3481  const pythonpp::CTuple func_args(args);
3482 
3483  hour = pythonpp::CInt(func_args[0]);
3484  minute = pythonpp::CInt(func_args[1]);
3485  second = pythonpp::CInt(func_args[2]);
3486  } catch (const pythonpp::CError&) {
3487  throw CProgrammingError("Invalid parameters within 'Time' function");
3488  }
3489 
3490  // Feef the object to the Python interpreter ...
3491  return pythonpp::CTime(hour, minute, second, 0);
3492  }
3493  catch (const CDB_Exception& e) {
3494  s_ThrowDatabaseError(e);
3495  }
3496  catch (const CException& e) {
3497  pythonpp::CError::SetString(e.what());
3498  }
3499 
3500  // Return a dummy object ...
3501  return pythonpp::CNone();
3502 }
3503 
3504 // This function constructs an object holding a time stamp
3505 // value.
3506 // Timestamp(year,month,day,hour,minute,second)
3507 pythonpp::CObject
3508 CModuleDBAPI::Timestamp(const pythonpp::CTuple& args)
3509 {
3510  try {
3511  int year;
3512  int month;
3513  int day;
3514  int hour;
3515  int minute;
3516  int second;
3517 
3518  try {
3519  const pythonpp::CTuple func_args(args);
3520 
3521  year = pythonpp::CInt(func_args[0]);
3522  month = pythonpp::CInt(func_args[1]);
3523  day = pythonpp::CInt(func_args[2]);
3524  hour = pythonpp::CInt(func_args[3]);
3525  minute = pythonpp::CInt(func_args[4]);
3526  second = pythonpp::CInt(func_args[5]);
3527  } catch (const pythonpp::CError&) {
3528  throw CProgrammingError("Invalid parameters within 'Timestamp' function");
3529  }
3530 
3531  // Feef the object to the Python interpreter ...
3532  return pythonpp::CDateTime(year, month, day, hour, minute, second, 0);
3533  }
3534  catch (const CDB_Exception& e) {
3535  s_ThrowDatabaseError(e);
3536  }
3537  catch (const CException& e) {
3538  pythonpp::CError::SetString(e.what());
3539  }
3540 
3541  // Return a dummy object ...
3542  return pythonpp::CNone();
3543 }
3544 
3545 // This function constructs an object holding a date value
3546 // from the given ticks value (number of seconds since the
3547 // epoch; see the documentation of the standard Python time
3548 // module for details).
3549 // DateFromTicks(ticks)
3550 pythonpp::CObject
3551 CModuleDBAPI::DateFromTicks(const pythonpp::CTuple& args)
3552 {
3553  try {
3554  }
3555  catch (const CDB_Exception& e) {
3556  s_ThrowDatabaseError(e);
3557  }
3558  catch (const CException& e) {
3559  pythonpp::CError::SetString(e.what());
3560  }
3561 
3562  // Return a dummy object ...
3563  return pythonpp::CNone();
3564 }
3565 
3566 // This function constructs an object holding a time value
3567 // from the given ticks value (number of seconds since the
3568 // epoch; see the documentation of the standard Python time
3569 // module for details).
3570 // TimeFromTicks(ticks)
3571 pythonpp::CObject
3572 CModuleDBAPI::TimeFromTicks(const pythonpp::CTuple& args)
3573 {
3574  try {
3575  }
3576  catch (const CDB_Exception& e) {
3577  s_ThrowDatabaseError(e);
3578  }
3579  catch (const CException& e) {
3580  pythonpp::CError::SetString(e.what());
3581  }
3582 
3583  // Return a dummy object ...
3584  return pythonpp::CNone();
3585 }
3586 
3587 // This function constructs an object holding a time stamp
3588 // value from the given ticks value (number of seconds since
3589 // the epoch; see the documentation of the standard Python
3590 // time module for details).
3591 // TimestampFromTicks(ticks)
3592 pythonpp::CObject
3593 CModuleDBAPI::TimestampFromTicks(const pythonpp::CTuple& args)
3594 {
3595  try {
3596  }
3597  catch (const CDB_Exception& e) {
3598  s_ThrowDatabaseError(e);
3599  }
3600  catch (const CException& e) {
3601  pythonpp::CError::SetString(e.what());
3602  }
3603 
3604  // Return a dummy object ...
3605  return pythonpp::CNone();
3606 }
3607 
3608 // This function constructs an object capable of holding a
3609 // binary (long) string value.
3610 // Binary(string)
3611 pythonpp::CObject
3612 CModuleDBAPI::Binary(const pythonpp::CTuple& args)
3613 {
3614 
3615  try {
3616  string value;
3617 
3618  try {
3619  const pythonpp::CTuple func_args(args);
3620 
3621  value = pythonpp::CString(func_args[0]);
3622  } catch (const pythonpp::CError&) {
3623  throw CProgrammingError("Invalid parameters within 'Binary' function");
3624  }
3625 
3626  CBinary* obj = new CBinary(
3627  );
3628 
3629  // Feef the object to the Python interpreter ...
3630  return pythonpp::CObject(obj, pythonpp::eTakeOwnership);
3631  }
3632  catch (const CDB_Exception& e) {
3633  s_ThrowDatabaseError(e);
3634  }
3635  catch (const CException& e) {
3636  pythonpp::CError::SetString(e.what());
3637  }
3638 
3639  return pythonpp::CNone();
3640 }
3641 
3642 */
3643 
3644 }
3645 
3646 /* Future development ... 2/4/2005 12:05PM
3647 // Module initialization
3648 PYDBAPI_MODINIT_FUNC(initpython_ncbi_dbapi)
3649 {
3650  // Initialize DateTime module ...
3651  PyDateTime_IMPORT;
3652 
3653  // Declare CBinary
3654  python::CBinary::Declare("python_ncbi_dbapi.BINARY");
3655 
3656  // Declare CNumber
3657  python::CNumber::Declare("python_ncbi_dbapi.NUMBER");
3658 
3659  // Declare CRowID
3660  python::CRowID::Declare("python_ncbi_dbapi.ROWID");
3661 
3662  // Declare CConnection
3663  python::CConnection::
3664  Def("close", &python::CConnection::close, "close").
3665  Def("commit", &python::CConnection::commit, "commit").
3666  Def("rollback", &python::CConnection::rollback, "rollback").
3667  Def("cursor", &python::CConnection::cursor, "cursor").
3668  Def("transaction", &python::CConnection::transaction, "transaction");
3669  python::CConnection::Declare("python_ncbi_dbapi.Connection");
3670 
3671  // Declare CTransaction
3672  python::CTransaction::
3673  Def("close", &python::CTransaction::close, "close").
3674  Def("cursor", &python::CTransaction::cursor, "cursor").
3675  Def("commit", &python::CTransaction::commit, "commit").
3676  Def("rollback", &python::CTransaction::rollback, "rollback");
3677  python::CTransaction::Declare("python_ncbi_dbapi.Transaction");
3678 
3679  // Declare CCursor
3680  python::CCursor::
3681  Def("callproc", &python::CCursor::callproc, "callproc").
3682  Def("close", &python::CCursor::close, "close").
3683  Def("execute", &python::CCursor::execute, "execute").
3684  Def("executemany", &python::CCursor::executemany, "executemany").
3685  Def("fetchone", &python::CCursor::fetchone, "fetchone").
3686  Def("fetchmany", &python::CCursor::fetchmany, "fetchmany").
3687  Def("fetchall", &python::CCursor::fetchall, "fetchall").
3688  Def("nextset", &python::CCursor::nextset, "nextset").
3689  Def("setinputsizes", &python::CCursor::setinputsizes, "setinputsizes").
3690  Def("setoutputsize", &python::CCursor::setoutputsize, "setoutputsize");
3691  python::CCursor::Declare("python_ncbi_dbapi.Cursor");
3692 
3693 
3694  // Declare CModuleDBAPI
3695  python::CModuleDBAPI::
3696  Def("connect", &python::CModuleDBAPI::connect, "connect").
3697  Def("Date", &python::CModuleDBAPI::Date, "Date").
3698  Def("Time", &python::CModuleDBAPI::Time, "Time").
3699  Def("Timestamp", &python::CModuleDBAPI::Timestamp, "Timestamp").
3700  Def("DateFromTicks", &python::CModuleDBAPI::DateFromTicks, "DateFromTicks").
3701  Def("TimeFromTicks", &python::CModuleDBAPI::TimeFromTicks, "TimeFromTicks").
3702  Def("TimestampFromTicks", &python::CModuleDBAPI::TimestampFromTicks, "TimestampFromTicks").
3703  Def("Binary", &python::CModuleDBAPI::Binary, "Binary");
3704 // python::CModuleDBAPI module_("python_ncbi_dbapi");
3705  // Python interpreter will tale care of deleting module object ...
3706  python::CModuleDBAPI* module2 = new python::CModuleDBAPI("python_ncbi_dbapi");
3707 }
3708 */
3709 
3710 // Genetal declarations ...
3711 namespace python
3712 {
3713 //////////////////////////////////////////////////////////////////////////////
3714 // return_strs_as_unicode(flag_value)
3715 static
3716 PyObject*
3717 ReturnStrsAsUnicode(PyObject *self, PyObject *args)
3718 {
3719  try{
3720  const pythonpp::CTuple func_args(args);
3721  g_PythonStrDefToUnicode = pythonpp::CBool(func_args[0]);
3722  }
3723  catch (const pythonpp::CError&) {
3724  // An error message is already set by an exception ...
3725  return NULL;
3726  }
3727  catch (...) {
3728  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Connect");
3729  }
3730 
3731  return pythonpp::CNone().Get();
3732 }
3733 
3734 static
3735 PyObject*
3736 ReleaseGlobalLock(PyObject *self, PyObject *args)
3737 {
3738  try{
3739  const pythonpp::CTuple func_args(args);
3741  (pythonpp::CBool(func_args[0]));
3742  }
3743  catch (const pythonpp::CError&) {
3744  // An error message is already set by an exception ...
3745  return NULL;
3746  }
3747  catch (...) {
3749  ("Unknown error in python_ncbi_dbapi::ReleaseGlobalLock");
3750  }
3751 
3752  return pythonpp::CNone().Get();
3753 }
3754 
3755 //////////////////////////////////////////////////////////////////////////////
3756 // connect(driver_name, db_type, db_name, user_name, user_pswd)
3757 static
3758 PyObject*
3759 Connect(PyObject *self, PyObject *args)
3760 {
3761  CConnection* conn = NULL;
3762 
3763  try {
3764  // Debugging ...
3765  // throw python::CDatabaseError("oops ...");
3766  // throw python::CDatabaseError("oops ...", 200, "Blah-blah-blah");
3767 
3768  string driver_name;
3769  string db_type;
3770  string server_name;
3771  string db_name;
3772  string user_name;
3773  string user_pswd;
3774  pythonpp::CObject extra_params = pythonpp::CNone();
3775 
3776  try {
3777  const pythonpp::CTuple func_args(args);
3778 
3779  driver_name = pythonpp::CString(func_args[0]);
3780  db_type = pythonpp::CString(func_args[1]);
3781  server_name = pythonpp::CString(func_args[2]);
3782  db_name = pythonpp::CString(func_args[3]);
3783  user_name = pythonpp::CString(func_args[4]);
3784  user_pswd = pythonpp::CString(func_args[5]);
3785  if ( func_args.size() > 6 ) {
3786  extra_params = func_args[6];
3787  }
3788  } catch (const pythonpp::CError&) {
3789  throw CProgrammingError("Invalid parameters within 'connect' function");
3790  }
3791 
3792  conn = new CConnection(
3793  driver_name,
3794  db_type,
3795  server_name,
3796  db_name,
3797  user_name,
3798  user_pswd,
3799  extra_params
3800  );
3801  }
3802  catch (const CDB_Exception& e) {
3804  }
3805  catch (const CException& e) {
3807  }
3808  catch (const pythonpp::CError&) {
3809  // An error message is already set by an exception ...
3810  return NULL;
3811  }
3812  catch (...) {
3813  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Connect");
3814  }
3815 
3816  return conn;
3817 }
3818 
3819 // This function constructs an object holding a date value.
3820 // Date(year,month,day)
3821 static
3822 PyObject*
3823 Date(PyObject *self, PyObject *args)
3824 {
3825 #if PY_VERSION_HEX < 0x02040000
3826  pythonpp::CError::SetString("python_ncbi_dbapi::Date requires Python 2.4 or newer.");
3827 #else
3828  try {
3829  int year;
3830  int month;
3831  int day;
3832 
3833  try {
3834  const pythonpp::CTuple func_args(args);
3835 
3836  year = pythonpp::CInt(func_args[0]);
3837  month = pythonpp::CInt(func_args[1]);
3838  day = pythonpp::CInt(func_args[2]);
3839  } catch (const pythonpp::CError&) {
3840  throw CProgrammingError("Invalid parameters within 'Date' function");
3841  }
3842 
3843  return IncRefCount(pythonpp::CDate(year, month, day));
3844  }
3845  catch (const CDB_Exception& e) {
3847  }
3848  catch (const CException& e) {
3850  }
3851  catch(const pythonpp::CError&) {
3852  // An error message is already set by an exception ...
3853  return NULL;
3854  }
3855  catch(...) {
3856  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Date");
3857  }
3858 #endif
3859 
3860  return NULL;
3861 }
3862 
3863 // This function constructs an object holding a time value.
3864 // Time(hour,minute,second)
3865 static
3866 PyObject*
3867 Time(PyObject *self, PyObject *args)
3868 {
3869 #if PY_VERSION_HEX < 0x02040000
3870  pythonpp::CError::SetString("python_ncbi_dbapi::Time requires Python 2.4 or newer.");
3871 #else
3872  try {
3873  int hour;
3874  int minute;
3875  int second;
3876 
3877  try {
3878  const pythonpp::CTuple func_args(args);
3879 
3880  hour = pythonpp::CInt(func_args[0]);
3881  minute = pythonpp::CInt(func_args[1]);
3882  second = pythonpp::CInt(func_args[2]);
3883  } catch (const pythonpp::CError&) {
3884  throw CProgrammingError("Invalid parameters within 'Time' function");
3885  }
3886 
3887  return IncRefCount(pythonpp::CTime(hour, minute, second, 0));
3888  }
3889  catch (const CDB_Exception& e) {
3891  }
3892  catch (const CException& e) {
3894  }
3895  catch(const pythonpp::CError&) {
3896  // An error message is already set by an exception ...
3897  return NULL;
3898  }
3899  catch(...) {
3900  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Time");
3901  }
3902 #endif
3903 
3904  return NULL;
3905 }
3906 
3907 // This function constructs an object holding a time stamp
3908 // value.
3909 // Timestamp(year,month,day,hour,minute,second)
3910 static
3911 PyObject*
3912 Timestamp(PyObject *self, PyObject *args)
3913 {
3914 #if PY_VERSION_HEX < 0x02040000
3915  pythonpp::CError::SetString("python_ncbi_dbapi::Timestamp requires Python 2.4 or newer.");
3916 #else
3917  try {
3918  int year;
3919  int month;
3920  int day;
3921  int hour;
3922  int minute;
3923  int second;
3924 
3925  try {
3926  const pythonpp::CTuple func_args(args);
3927 
3928  year = pythonpp::CInt(func_args[0]);
3929  month = pythonpp::CInt(func_args[1]);
3930  day = pythonpp::CInt(func_args[2]);
3931  hour = pythonpp::CInt(func_args[3]);
3932  minute = pythonpp::CInt(func_args[4]);
3933  second = pythonpp::CInt(func_args[5]);
3934  } catch (const pythonpp::CError&) {
3935  throw CProgrammingError("Invalid parameters within 'Timestamp' function");
3936  }
3937 
3938  return IncRefCount(pythonpp::CDateTime(year, month, day, hour, minute, second, 0));
3939  }
3940  catch (const CDB_Exception& e) {
3942  }
3943  catch (const CException& e) {
3945  }
3946  catch(const pythonpp::CError&) {
3947  // An error message is already set by an exception ...
3948  return NULL;
3949  }
3950  catch(...) {
3951  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Timestamp");
3952  }
3953 #endif
3954 
3955  return NULL;
3956 }
3957 
3958 // This function constructs an object holding a date value
3959 // from the given ticks value (number of seconds since the
3960 // epoch; see the documentation of the standard Python time
3961 // module for details).
3962 // DateFromTicks(ticks)
3963 static
3964 PyObject*
3965 DateFromTicks(PyObject *self, PyObject *args)
3966 {
3967  try {
3968  throw CNotSupportedError("Function DateFromTicks");
3969  }
3970  catch (const CDB_Exception& e) {
3972  }
3973  catch (const CException& e) {
3975  }
3976  catch(const pythonpp::CError&) {
3977  // An error message is already set by an exception ...
3978  return NULL;
3979  }
3980  catch(...) {
3981  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::DateFromTicks");
3982  }
3983 
3984  return NULL;
3985 }
3986 
3987 // This function constructs an object holding a time value
3988 // from the given ticks value (number of seconds since the
3989 // epoch; see the documentation of the standard Python time
3990 // module for details).
3991 // TimeFromTicks(ticks)
3992 static
3993 PyObject*
3994 TimeFromTicks(PyObject *self, PyObject *args)
3995 {
3996  try {
3997  throw CNotSupportedError("Function TimeFromTicks");
3998  }
3999  catch (const CDB_Exception& e) {
4001  }
4002  catch (const CException& e) {
4004  }
4005  catch(const pythonpp::CError&) {
4006  // An error message is already set by an exception ...
4007  return NULL;
4008  }
4009  catch(...) {
4010  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::TimeFromTicks");
4011  }
4012 
4013  return NULL;
4014 }
4015 
4016 // This function constructs an object holding a time stamp
4017 // value from the given ticks value (number of seconds since
4018 // the epoch; see the documentation of the standard Python
4019 // time module for details).
4020 // TimestampFromTicks(ticks)
4021 static
4022 PyObject*
4023 TimestampFromTicks(PyObject *self, PyObject *args)
4024 {
4025  try {
4026  throw CNotSupportedError("Function TimestampFromTicks");
4027  }
4028  catch (const CDB_Exception& e) {
4030  }
4031  catch (const CException& e) {
4033  }
4034  catch(const pythonpp::CError&) {
4035  // An error message is already set by an exception ...
4036  return NULL;
4037  }
4038  catch(...) {
4039  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::TimestampFromTicks");
4040  }
4041 
4042  return NULL;
4043 }
4044 
4045 // This function constructs an object capable of holding a
4046 // binary (long) string value.
4047 // Binary(string)
4048 static
4049 PyObject*
4050 Binary(PyObject *self, PyObject *args)
4051 {
4052  CBinary* obj = NULL;
4053 
4054  try {
4055  string value;
4056 
4057  try {
4058  const pythonpp::CTuple func_args(args);
4059 
4060  value = pythonpp::CString(func_args[0]);
4061  } catch (const pythonpp::CError&) {
4062  throw CProgrammingError("Invalid parameters within 'Binary' function");
4063  }
4064 
4065  obj = new CBinary(value);
4066  }
4067  catch (const CDB_Exception& e) {
4069  }
4070  catch (const CException& e) {
4072  }
4073  catch(const pythonpp::CError&) {
4074  // An error message is already set by an exception ...
4075  return NULL;
4076  }
4077  catch(...) {
4078  pythonpp::CError::SetString("Unknown error in python_ncbi_dbapi::Binary");
4079  }
4080 
4081  return obj;
4082 }
4083 
4085 {
4086 public:
4087  static void Declare(const char* name, PyMethodDef* methods);
4088 
4089 private:
4090  static PyObject* m_Module;
4091 #if PY_MAJOR_VERSION >= 3
4092  static struct PyModuleDef m_ModuleDef;
4093 #endif
4094 };
4095 PyObject* CDBAPIModule::m_Module = NULL;
4096 
4097 #if PY_MAJOR_VERSION >= 3
4098 struct PyModuleDef CDBAPIModule::m_ModuleDef = {
4099  PyModuleDef_HEAD_INIT,
4100  "", // m_name
4101  "", // m_doc
4102  -1, // m_size
4103  NULL, // m_methods
4104  NULL, // m_reload
4105  NULL, // m_traverse
4106  NULL, // m_clear
4107  NULL // m_free
4108 };
4109 #endif
4110 
4111 void
4112 CDBAPIModule::Declare(const char* name, PyMethodDef* methods)
4113 {
4114 #if PY_MAJOR_VERSION >= 3
4115  m_ModuleDef.m_name = name;
4116  m_ModuleDef.m_methods = methods;
4117  m_Module = PyModule_Create(&m_ModuleDef);
4118 #else
4119  m_Module = Py_InitModule(const_cast<char*>(name), methods);
4120 #endif
4121 }
4122 
4123 }
4124 
4125 static struct PyMethodDef python_ncbi_dbapi_methods[] = {
4126  {(char*)"return_strs_as_unicode", (PyCFunction) python::ReturnStrsAsUnicode, METH_VARARGS, (char*)
4127  "return_strs_as_unicode(bool_flag_value) "
4128  "-- set global flag indicating that all strings returned from database "
4129  "should be presented to Python as unicode strings (if value is True) or "
4130  " as regular strings in UTF-8 encoding (if value is False - the default one). "
4131  "NOTE: This is not a part of the Python Database API Specification v2.0."
4132  },
4133  {(char*)"release_global_lock", (PyCFunction) python::ReleaseGlobalLock, METH_VARARGS, (char*)
4134  "release_global_lock(bool_flag_value) "
4135  "-- set global flag indicating that blocking database operations "
4136  "should run with Python's global interpreter lock released (if value "
4137  "is True) or with it held (if value is False, the default for now)."
4138  "NOTE: This is not a part of the Python Database API Specification "
4139  "v2.0."
4140  },
4141  {(char*)"connect", (PyCFunction) python::Connect, METH_VARARGS, (char*)
4142  "connect(driver_name, db_type, server_name, database_name, userid, password) "
4143  "-- connect to the "
4144  "driver_name; db_type; server_name; database_name; userid; password;"
4145  },
4146  {(char*)"Date", (PyCFunction) python::Date, METH_VARARGS, (char*)"Date"},
4147  {(char*)"Time", (PyCFunction) python::Time, METH_VARARGS, (char*)"Time"},
4148  {(char*)"Timestamp", (PyCFunction) python::Timestamp, METH_VARARGS, (char*)"Timestamp"},
4149  {(char*)"DateFromTicks", (PyCFunction) python::DateFromTicks, METH_VARARGS, (char*)"DateFromTicks"},
4150  {(char*)"TimeFromTicks", (PyCFunction) python::TimeFromTicks, METH_VARARGS, (char*)"TimeFromTicks"},
4151  {(char*)"TimestampFromTicks", (PyCFunction) python::TimestampFromTicks, METH_VARARGS, (char*)"TimestampFromTicks"},
4152  {(char*)"Binary", (PyCFunction) python::Binary, METH_VARARGS, (char*)"Binary"},
4153  { NULL, NULL }
4154 };
4155 
4156 ///////////////////////////////////////////////////////////////////////////////
4157 // DatabaseErrorExt extends PyBaseExceptionObject
4158 /* DO NOT delete this code ...
4159 struct PyDatabaseErrorExtObject : public PyBaseExceptionObject
4160 {
4161  PyObject *db_message;
4162  PyObject *db_code;
4163 };
4164 
4165 
4166 static int
4167 DatabaseErrorExt_init(PyDatabaseErrorExtObject *self, PyObject *args, PyObject *kwds)
4168 {
4169  if (PyExc_BaseException->ob_type->tp_init((PyObject *)self, args, kwds) < 0) {
4170  return -1;
4171  }
4172 
4173  PyObject* message = NULL;
4174  PyObject *db_message = NULL, *db_code = NULL, *tmp;
4175 
4176  static char *kwlist[] = {"message", "db_message", "db_code", NULL};
4177 
4178  if (! PyArg_ParseTupleAndKeywords(
4179  args,
4180  kwds,
4181  "S|SO",
4182  kwlist,
4183  &message,
4184  &db_message,
4185  &db_code
4186  )
4187  )
4188  {
4189  return -1;
4190  }
4191 
4192  if (db_message) {
4193  tmp = self->db_message;
4194  Py_INCREF(db_message);
4195  self->db_message = db_message;
4196  Py_DECREF(tmp);
4197  }
4198 
4199  if (db_code) {
4200  // We are reading an object. Let us check the type.
4201  if (! PyInt_CheckExact(db_code)) {
4202  PyErr_SetString(PyExc_TypeError,
4203  "The second attribute value must be an int or a long");
4204  return -1;
4205  }
4206 
4207  tmp = self->db_code;
4208  Py_INCREF(db_code);
4209  self->db_code = db_code;
4210  Py_DECREF(tmp);
4211  }
4212 
4213  return 0;
4214 }
4215 
4216 static PyObject *
4217 DatabaseErrorExt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
4218 {
4219  PyDatabaseErrorExtObject *self;
4220 
4221  self = (PyDatabaseErrorExtObject *)type->tp_alloc(type, 0);
4222  // self = (PyDatabaseErrorExtObject *)type->tp_new(type, args, kwds);
4223  if (self != NULL) {
4224  self->db_message = PyString_FromString("");
4225  if (self->db_message == NULL)
4226  {
4227  Py_DECREF(self);
4228  return NULL;
4229  }
4230 
4231  self->db_code = PyLong_FromLong(0);
4232  if (self->db_code == NULL)
4233  {
4234  Py_DECREF(self);
4235  return NULL;
4236  }
4237  }
4238 
4239  return (PyObject *)self;
4240 }
4241 
4242 static PyObject *
4243 DatabaseErrorExt_get_db_message(PyDatabaseErrorExtObject *self, void* )
4244 {
4245  Py_INCREF(self->db_message);
4246  return self->db_message;
4247 }
4248 
4249 static int
4250 DatabaseErrorExt_set_db_message(PyDatabaseErrorExtObject *self, PyObject *value, void* )
4251 {
4252  if (value == NULL) {
4253  PyErr_SetString(PyExc_TypeError, "Cannot delete the db_message attribute");
4254  return -1;
4255  }
4256 
4257  if (! PyString_Check(value)) {
4258  PyErr_SetString(PyExc_TypeError,
4259  "The first attribute value must be a string");
4260  return -1;
4261  }
4262 
4263  Py_DECREF(self->db_message);
4264  Py_INCREF(value);
4265  self->db_message = value;
4266 
4267  return 0;
4268 }
4269 
4270 static PyObject *
4271 DatabaseErrorExt_get_db_code(PyDatabaseErrorExtObject *self, void *closure)
4272 {
4273  Py_INCREF(self->db_code);
4274  return self->db_code;
4275 }
4276 
4277 static int
4278 DatabaseErrorExt_set_db_code(PyDatabaseErrorExtObject *self, PyObject *value, void *closure)
4279 {
4280  if (value == NULL) {
4281  PyErr_SetString(PyExc_TypeError, "Cannot delete the db_code attribute");
4282  return -1;
4283  }
4284 
4285  if (! PyLong_Check(value)) {
4286  PyErr_SetString(PyExc_TypeError,
4287  "The second attribute value must be a long");
4288  return -1;
4289  }
4290 
4291  Py_DECREF(self->db_code);
4292  Py_INCREF(value);
4293  self->db_code = value;
4294 
4295  return 0;
4296 }
4297 
4298 static PyGetSetDef DatabaseErrorExt_getseters[] = {
4299  {"db_message", (getter)DatabaseErrorExt_get_db_message, (setter)DatabaseErrorExt_set_db_message, "Database message", NULL},
4300  {"db_code", (getter)DatabaseErrorExt_get_db_code, (setter)DatabaseErrorExt_set_db_code, "Database error code", NULL},
4301  {NULL}
4302 };
4303 
4304 static int
4305 DatabaseErrorExt_traverse(PyDatabaseErrorExtObject *self, visitproc visit, void *arg)
4306 {
4307  Py_VISIT(self->db_message);
4308  Py_VISIT(self->db_code);
4309 
4310  return 0;
4311 }
4312 
4313 static int
4314 DatabaseErrorExt_clear(PyDatabaseErrorExtObject *self)
4315 {
4316  Py_CLEAR(self->db_message);
4317  Py_CLEAR(self->db_code);
4318 
4319  return 0;
4320 }
4321 
4322 static void
4323 DatabaseErrorExt_dealloc(PyDatabaseErrorExtObject *self)
4324 {
4325  // ???
4326  // PyExc_BaseException->ob_type->tp_dealloc((PyObject *)self);
4327 
4328  DatabaseErrorExt_clear(self);
4329 
4330  self->ob_type->tp_free((PyObject *)self);
4331 }
4332 */
4333 
4334 
4335 // static PyTypeObject DatabaseErrorExtType = {
4336 // PyObject_HEAD_INIT(NULL)
4337 // 0, /* ob_size */
4338 // "python_ncbi_dbapi.DatabaseErrorExt", /* tp_name */
4339 // sizeof(PyDatabaseErrorExtObject), /* tp_basicsize */
4340 // 0, /* tp_itemsize */
4341 // (destructor)DatabaseErrorExt_dealloc, /* tp_dealloc */
4342 // 0, /* tp_print */
4343 // 0, /* tp_getattr */
4344 // 0, /* tp_setattr */
4345 // 0, /* tp_compare */
4346 // 0, /* tp_repr */
4347 // 0, /* tp_as_number */
4348 // 0, /* tp_as_sequence */
4349 // 0, /* tp_as_mapping */
4350 // 0, /* tp_hash */
4351 // 0, /* tp_call */
4352 // 0, /* tp_str */
4353 // 0, /* tp_getattro */
4354 // 0, /* tp_setattro */
4355 // 0, /* tp_as_buffer */
4356 // Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
4357 // "Database error", /* tp_doc */
4358 // (traverseproc)DatabaseErrorExt_traverse, /* tp_traverse */
4359 // (inquiry)DatabaseErrorExt_clear, /* tp_clear */
4360 // 0, /* tp_richcompare */
4361 // 0, /* tp_weaklistoffset */
4362 // 0, /* tp_iter */
4363 // 0, /* tp_iternext */
4364 // 0, /* tp_methods */
4365 // 0, /* tp_members */
4366 // DatabaseErrorExt_getseters, /* tp_getset */
4367 // 0, /* tp_base */
4368 // 0, /* tp_dict */
4369 // 0, /* tp_descr_get */
4370 // 0, /* tp_descr_set */
4371 // 0, /* tp_dictoffset */
4372 // (initproc)DatabaseErrorExt_init, /* tp_init */
4373 // 0, /* tp_alloc */
4374 // 0, // DatabaseErrorExt_new, /* tp_new */
4375 // };
4376 // static PyObject *PyExc_DatabaseErrorExtType = (PyObject *)&DatabaseErrorExtType;
4377 // static PyObject* PyExc_DatabaseErrorExt = NULL;
4378 
4379 ///////////////////////////////////////////////////////////////////////////////
4380 static
4381 PyObject* init_common(const string& module_name)
4382 {
4384 
4385  const char* rev_str = "$Revision: 72088 $";
4386  PyObject *module;
4387 
4388  // Fix plugin manager ...
4390  string module_dir = file.GetDir() + PYDBAPI_SUPPORT_DIR;
4392 
4393 
4394  pythonpp::CModuleExt::Declare(module_name, python_ncbi_dbapi_methods);
4395 
4396  // Define module attributes ...
4397  pythonpp::CModuleExt::AddConst("apilevel", "2.0");
4398  pythonpp::CModuleExt::AddConst("__version__", string( rev_str + 11, strlen( rev_str + 11 ) - 2 ));
4399  pythonpp::CModuleExt::AddConst("threadsafety", 1);
4400  pythonpp::CModuleExt::AddConst("paramstyle", "named");
4401 
4403 
4404  ///////////////////////////////////
4405 
4406 #if PY_VERSION_HEX >= 0x02040000
4407  // Initialize DateTime module ...
4408  PyDateTime_IMPORT; // NCBI_FAKE_WARNING
4409 #endif
4410 
4411  // Declare CBinary
4412  python::CBinary::Declare(module_name + ".BINARY");
4413  python::CBinary::GetType().SetName("BINARY");
4414 
4415  // Declare CNumber
4416  python::CNumber::Declare(module_name + ".NUMBER");
4417  python::CNumber::GetType().SetName("NUMBER");
4418 
4419  // Declare CRowID
4420  python::CRowID::Declare(module_name + ".ROWID");
4421  python::CRowID::GetType().SetName("ROWID");
4422 
4423  // Declare CString
4424  python::CStringType::Declare(module_name + ".STRING");
4426 
4427  // Declare CString
4428  python::CDateTimeType::Declare(module_name + ".DATETIME");
4430 
4431  // Declare CConnection
4432  const string connection_name(module_name + ".Connection");
4434  Def("__enter__", &python::CConnection::__enter__, "__enter__").
4435  Def("__exit__", &python::CConnection::close, "__exit__").
4436  Def("close", &python::CConnection::close, "close").
4437  Def("commit", &python::CConnection::commit, "commit").
4438  Def("rollback", &python::CConnection::rollback, "rollback").
4439  Def("cursor", &python::CConnection::cursor, "cursor").
4440  Def("transaction", &python::CConnection::transaction, "transaction");
4441  python::CConnection::Declare(connection_name);
4442 
4443  // Declare CTransaction
4444  const string transaction_name(module_name + ".Transaction");
4446  Def("__enter__", &python::CTransaction::__enter__, "__enter__").
4447  Def("__exit__", &python::CTransaction::close, "__exit__").
4448  Def("close", &python::CTransaction::close, "close").
4449  Def("cursor", &python::CTransaction::cursor, "cursor").
4450  Def("commit", &python::CTransaction::commit, "commit").
4451  Def("rollback", &python::CTransaction::rollback, "rollback");
4452  python::CTransaction::Declare(transaction_name);
4453 
4454  // Declare CCursor
4455  const string cursor_name(module_name + ".Cursor");
4457  Def("callproc", &python::CCursor::callproc, "callproc").
4458  Def("__enter__", &python::CCursor::__enter__, "__enter__").
4459  Def("__exit__", &python::CCursor::close, "__exit__").
4460  Def("close", &python::CCursor::close, "close").
4461  Def("execute", &python::CCursor::execute, "execute").
4462  Def("executemany", &python::CCursor::executemany, "executemany").
4463  Def("fetchone", &python::CCursor::fetchone, "fetchone").
4464  Def("fetchmany", &python::CCursor::fetchmany, "fetchmany").
4465  Def("fetchall", &python::CCursor::fetchall, "fetchall").
4466  Def("nextset", &python::CCursor::nextset, "nextset").
4467  Def("setinputsizes", &python::CCursor::setinputsizes, "setinputsizes").
4468  Def("setoutputsize", &python::CCursor::setoutputsize, "setoutputsize").
4469  Def("get_proc_return_status", &python::CCursor::get_proc_return_status, "get_proc_return_status");
4470  python::CCursor::Declare(cursor_name);
4471 
4472  // Declare CCursorIter
4473  const string cursor_iter_name(module_name + ".__CursorIterator__");
4474  python::CCursorIter::Declare(cursor_iter_name);
4475 
4476  ///////////////////////////////////
4477  // Declare types ...
4478 
4479  // Declare BINARY
4480  if ( PyType_Ready(&python::CBinary::GetType()) == -1 ) {
4481  return NULL;
4482  }
4483  if ( PyModule_AddObject(module, const_cast<char*>("BINARY"), (PyObject*)&python::CBinary::GetType() ) == -1 ) {
4484  return NULL;
4485  }
4486 
4487  // Declare NUMBER
4488  if ( PyType_Ready(&python::CNumber::GetType()) == -1 ) {
4489  return NULL;
4490  }
4491  if ( PyModule_AddObject(module, const_cast<char*>("NUMBER"), (PyObject*)&python::CNumber::GetType() ) == -1 ) {
4492  return NULL;
4493  }
4494 
4495  // Declare ROWID
4496  if ( PyType_Ready(&python::CRowID::GetType()) == -1 ) {
4497  return NULL;
4498  }
4499  if ( PyModule_AddObject(module, const_cast<char*>("ROWID"), (PyObject*)&python::CRowID::GetType() ) == -1 ) {
4500  return NULL;
4501  }
4502 
4503  // Declare STRING
4504  if ( PyType_Ready(&python::CStringType::GetType()) == -1 ) {
4505  return NULL;
4506  }
4507  if ( PyModule_AddObject(module, const_cast<char*>("STRING"), (PyObject*)&python::CStringType::GetType() ) == -1 ) {
4508  return NULL;
4509  }
4510 
4511  // Declare DATETIME
4512  if ( PyType_Ready(&python::CDateTimeType::GetType()) == -1 ) {
4513  return NULL;
4514  }
4515  if ( PyModule_AddObject(module, const_cast<char*>("DATETIME"), (PyObject*)&python::CDateTimeType::GetType() ) == -1 ) {
4516  return NULL;
4517  }
4518 
4520  static char str_class[] = "__class__";
4521  static PyMemberDef conn_members[] = {
4522  {str_class, T_OBJECT_EX, 0, READONLY, NULL},
4523  {NULL}
4524  };
4525  extt->tp_members = conn_members;
4526  if ( PyType_Ready(extt) == -1 ) {
4527  return NULL;
4528  }
4529  if ( PyModule_AddObject(module, const_cast<char*>("Connection"), (PyObject*)extt ) == -1 ) {
4530  return NULL;
4531  }
4533  extt->tp_members = conn_members;
4534  if ( PyType_Ready(extt) == -1 ) {
4535  return NULL;
4536  }
4537  if ( PyModule_AddObject(module, const_cast<char*>("Transaction"), (PyObject*)extt ) == -1 ) {
4538  return NULL;
4539  }
4540  extt = &python::CCursor::GetType();
4541  // This list should reflect exactly attributes added in CCursor constructor
4542  static char str_rowcount[] = "rowcount";
4543  static char str_messages[] = "messages";
4544  static char str_description[] = "description";
4545  static PyMemberDef members[] = {
4546  {str_rowcount, T_LONG, 0, READONLY, NULL},
4547  {str_messages, T_OBJECT_EX, 0, READONLY, NULL},
4548  {str_description, T_OBJECT_EX, 0, READONLY, NULL},
4549  {str_class, T_OBJECT_EX, 0, READONLY, NULL},
4550  {NULL}
4551  };
4552  extt->tp_members = members;
4553  extt->tp_iter = &python::s_GetCursorIter;
4554  if ( PyType_Ready(extt) == -1 ) {
4555  return NULL;
4556  }
4557  if ( PyModule_AddObject(module, const_cast<char*>("Cursor"), (PyObject*)extt ) == -1 ) {
4558  return NULL;
4559  }
4560  extt = &python::CCursorIter::GetType();
4561  extt->tp_iter = &python::s_GetCursorIterFromIter;
4562  extt->tp_iternext = &python::s_CursorIterNext;
4563  if ( PyType_Ready(extt) == -1 ) {
4564  return NULL;
4565  }
4566  if ( PyModule_AddObject(module, const_cast<char*>("__CursorIterator__"), (PyObject*)extt ) == -1 ) {
4567  return NULL;
4568  }
4569 
4570  ///////////////////////////////////
4571  // Add exceptions ...
4572 
4573  /* DO NOT delete this code ...
4574  {
4575  DatabaseErrorExtType.tp_new = DatabaseErrorExt_new;
4576  DatabaseErrorExtType.tp_base = python::CError::GetPyException()->ob_type;
4577 
4578  if (PyType_Ready(&DatabaseErrorExtType) < 0) {
4579  Py_FatalError("exceptions bootstrapping error.");
4580  return NULL;
4581  }
4582 
4583  PyObject* dict = PyModule_GetDict(module);
4584  if (dict == NULL) {
4585  Py_FatalError("exceptions bootstrapping error.");
4586  }
4587 
4588  Py_INCREF(PyExc_DatabaseErrorExtType);
4589  PyModule_AddObject(module, "DatabaseErrorExt", PyExc_DatabaseErrorExtType);
4590  if (PyDict_SetItemString(dict, "DatabaseErrorExt", PyExc_DatabaseErrorExtType)) {
4591  Py_FatalError("Module dictionary insertion problem.");
4592  }
4593 
4594  PyExc_DatabaseErrorExt = (PyObject*) PyErr_NewException("python_ncbi_dbapi.DatabaseErrorExt2", PyExc_DatabaseErrorExtType, NULL);
4595  python::CError::Check( PyExc_DatabaseErrorExt );
4596  if ( PyModule_AddObject( module, "DatabaseErrorExt2", PyExc_DatabaseErrorExt ) == -1 ) {
4597  throw pythonpp::CSystemError( "Unable to add an object to a module" );
4598  }
4599  if (PyDict_SetItemString(dict, "DatabaseErrorExt2", PyExc_DatabaseErrorExt)) {
4600  Py_FatalError("Module dictionary insertion problem.");
4601  }
4602  }
4603  */
4604 
4605  /* DO NOT delete this code ...
4606 
4607  python::CDatabaseError::Declare(
4608  module_name + ".DatabaseErrorExt",
4609  NULL,
4610  python::CError::GetPyException()->ob_type
4611  );
4612  */
4613 
4614  python::CWarning::Declare("Warning");
4615  python::CError::Declare("Error");
4616  python::CInterfaceError::Declare("InterfaceError");
4617  python::CDatabaseError::Declare("DatabaseError");
4618  python::CInternalError::Declare("InternalError");
4619  python::COperationalError::Declare("OperationalError");
4620  python::CProgrammingError::Declare("ProgrammingError");
4621  python::CIntegrityError::Declare("IntegrityError");
4622  python::CDataError::Declare("DataError");
4623  python::CNotSupportedError::Declare("NotSupportedError");
4624 
4625  return module;
4626 }
4627 
4628 // Module initialization
4629 PYDBAPI_MODINIT_FUNC(python_ncbi_dbapi)
4630 {
4631  PYDBAPI_MOD_RETURN init_common("python_ncbi_dbapi");
4632 }
4633 
4635 {
4636  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi");
4637 }
4638 
4639 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_current)
4640 {
4641  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_current");
4642 }
4643 
4644 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_frozen)
4645 {
4646  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_frozen");
4647 }
4648 
4649 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_metastable)
4650 {
4651  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_metastable");
4652 }
4653 
4654 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_potluck)
4655 {
4656  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_potluck");
4657 }
4658 
4659 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_production)
4660 {
4661  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_production");
4662 }
4663 
4664 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_stable)
4665 {
4666  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_stable");
4667 }
4668 
4669 
4670 #ifdef NCBI_OS_DARWIN
4671 // force more of corelib to make it in
4672 PYDBAPI_MODINIT_FUNC(ncbi_dbapi_darwin_kludge)
4673 {
4676  PYDBAPI_MOD_RETURN init_common("ncbi_dbapi_darwin_kludge");
4677 }
4678 #endif
4679 
4681 
4682 
static PyObject * Binary(PyObject *self, PyObject *args)
CVariantSetProxy(ICallableStatement &stmt)
CWarning(const string &msg)
static string RetrieveModuleFileName(void)
auto_ptr< CResultSetProxy > m_RSProxy
int GetDay(void) const
void rollback(void) const
double value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:228
Definition: dbpivot.c:60
CSafeStatic<>::
IConnection * CreateDMLConnection(void)
EStatementType RetrieveStatementType(const string &stmt, EStatementType default_type)
string::size_type find_numeric(const string &str, string::size_type offset, int &param_len)
TBase::const_iterator const_iterator
Definition: static_map.hpp:179
#define DBLB_INSTALL_DEFAULT()
Easy-to-use macro to install the default DBAPI service mapper.
virtual int GetRowCount()=0
Get total of rows returned.
virtual void SetOutputParam(const CVariant &v, const CDBParamVariant &param)=0
Set output parameter, which will be returned as resultset.
void Set(PyObject *obj, EOwnership ownership=eAcquireOwnership)
Not exception-safe this time.
struct config_s config
virtual void Connect(const string &user, const string &password, const string &server, const string &database=kEmptyStr)=0
Connect to a database.
PyObject * s_CursorIterNext(PyObject *iter_obj)
void CommitInternal(void) const
size_type size(void) const
int GetMinute(void) const
pythonpp::CObject close(const pythonpp::CTuple &args)
auto_ptr< IStatement > m_Stmt
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:62
No ownership is assumed.
Definition: ncbi_types.h:135
static const TDBErrCodePair kClientErrCodes[]
PyObject * GetNext(void)
static unsigned cnt[256]
static bool HasSameType(PyObject *obj)
CCursor * CreateCursor(void)
static PyObject * ReturnStrsAsUnicode(PyObject *self, PyObject *args)
virtual bool MoveToLastRS(void)
int GetHour(void) const
DEFINE_STATIC_ARRAY_MAP(TDBErrCodeMap, sc_ClientErrCodes, kClientErrCodes)
void SetDatabaseName(const string &name)
CTransaction *const m_ParentTransaction
void SetItem(const string &key, const CObject &obj)
pythonpp::CObject cursor(const pythonpp::CTuple &args)
void x_Init(const CDB_Exception &e, PyObject *err_type)
const unsigned int m_ColumsNum
static void handler(int)
virtual const IResultSetMetaData & GetMetaData(void) const
Get Metadata.
virtual void SetParam(const CVariant &v, const CDBParamVariant &param)=0
Set input/output parameter.
virtual const CVariant & GetVariant(const CDBParamVariant &param)
Retrieve a CVariant class describing the data stored in a given column.
pythonpp::CObject close(const pythonpp::CTuple &args)
Close the cursor now (rather than whenever __del__ is called).
static PyObject * DateFromTicks(PyObject *self, PyObject *args)
CParamFmt(TFormat user_fmt=eTSQL, TFormat drv_fmt=eTSQL)
#define NCBI_NORETURN
Definition: ncbiconf_msvc.h:75
virtual void ExecuteUpdate(const string &sql)=0
Executes SQL statement with no results returned.
EDB_Type GetType() const
Definition: variant.hpp:254
void FillDescription(pythonpp::CList &descr)
pythonpp::CObject fetchall(const pythonpp::CTuple &args)
Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e...
virtual bool MoveToNextRS(void)
pythonpp::CList m_InfoMessages
static CVariant VarBinary(const void *p, size_t len)
Definition: variant.cpp:146
virtual string GetName(const CDBParamVariant &param) const =0
Get name of column.
IResultSet & GetRS(void)
virtual const CVariant & GetVariant(const CDBParamVariant &param)=0
Retrieve a CVariant class describing the data stored in a given column.
virtual unsigned int GetTotalColumns(void)=0
Get total columns.
pythonpp::CObject commit(const pythonpp::CTuple &args)
bool HasRS(void) const
virtual bool Next()=0
Get next row.
int Second(void) const
Get second.
Definition: ncbitime.hpp:2235
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
int GetMinute(void) const
string GetDir(EIfEmptyPath mode=eIfEmptyPath_Current) const
Get the directory component for this directory entry.
Definition: ncbifile.cpp:461
virtual bool MoveToLastRS(void)
PyObject * s_GetCursorIter(PyObject *curs_obj)
virtual I_DriverContext * GetDriverContext()=0
Returns the pointer to the general driver interface.
const EConnectionMode m_ConnectionMode
void SetServerType(EServerType type)
string
Definition: cgiapp.hpp:437
X * get(void) const
Get pointer value.
Definition: ncbimisc.hpp:397
virtual const CVariant & GetVariant(const CDBParamVariant &param)
Retrieve a CVariant class describing the data stored in a given column.
pythonpp::CObject rollback(const pythonpp::CTuple &args)
virtual const IResultSetMetaData & GetParamsMetaData(void)=0
Get input parameters metadata.
CCallableStmtHelper m_CallableStmtHelper
size_type size() const
Definition: set.hpp:132
virtual unsigned int GetTotalColumns(void) const =0
Get total number of columns in resultset.
CTransaction * CreateTransaction(void)
Int8 GetInt8(void) const
Definition: variant.cpp:469
CCachedResultSet(IResultSet &other)
void DestroyCursor(CCursor *cursor)
virtual EDB_Type GetType(const CDBParamVariant &param) const =0
Get data type for column in the resultset.
ICallableStatement –.
Definition: dbapi.hpp:497
const TSeqPos offset(200)
virtual int GetReturnStatus()=0
Get return status from the stored procedure.
void * HINSTANCE
Definition: sqltypes.h:116
virtual const CVariant & GetVariant(const CDBParamVariant &param)=0
Retrieve a CVariant class describing the data stored in a given column.
void SetParam(const string &name, const CVariant &value, bool &output_param)
const CConnection & GetConnection(void) const
virtual bool MoveToNextRS(void)
CStmtHelper m_StmtHelper
class CStaticArrayMap<> provides access to a static array in much the same way as CStaticArraySet<>...
Definition: Seq_gap.hpp:54
#define NULL
Definition: ncbistd.hpp:225
void SetItem(int offset, const CObject &obj)
virtual const char * what(void) const
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:324
CRef< CVariantSet > m_CurResultSet
const_iterator end() const
Definition: set.hpp:136
virtual bool HasMoreResults()=0
Check for more results available.
int Month(void) const
Get month.
Definition: ncbitime.hpp:2223
#define DB_ERR_CODE(value, type)
pythonpp::CObject cursor(const pythonpp::CTuple &args)
static const TDBErrCodePair kSybaseErrCodes[]
Int2 GetInt2(void) const
Definition: variant.cpp:508
CThreadingGuard – "Anti-guard" for Python's global interpreter lock, which it temporarily releases t...
Static variables safety - create on demand, destroy on application termination.
static bool HasSameType(PyObject *obj)
void SetParam(const string &name, const CVariant &value)
CVariant GetCVariant(const pythonpp::CObject &obj) const
IConnection * MakeDBConnection(void) const
static void SetMayRelease(bool may_release)
virtual const IResultSetMetaData & GetMetaData(void) const
Get Metadata.
int i
void Execute(bool cache_results=false)
bool empty() const
Definition: set.hpp:133
int GetYear(void) const
int Hour(void) const
Get hour.
Definition: ncbitime.hpp:2229
void DestroySelectConnection(IConnection *db_conn)
SStaticPair< int, FRethrow > TDBErrCodePair
int GetMicroSecond(void) const
CRealSetProxy(ICallableStatement &stmt)
FILE * file
void SetName(const char *name)
pythonpp::CObject executemany(const pythonpp::CTuple &args)
Prepare a database operation (query or command) and then execute it against all parameter sequences o...
static PyObject * TimestampFromTicks(PyObject *self, PyObject *args)
const CConnection & GetConnection(void) const
virtual bool HasRS(void) const
EDB_ResType
EDB_ResType::
Definition: interfaces.hpp:379
static bool HasSameType(PyObject *obj)
void SetSecond(int second)
Set second.
Definition: ncbitime.cpp:1108
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:4942
static bool HasSameType(PyObject *obj)
CVariant –.
Definition: variant.hpp:94
CDB_UserHandler * m_UserHandler
int GetMonth(void) const
const CException * GetPredecessor(void) const
Get "previous" exception from the backlog.
Definition: ncbiexpt.hpp:874
void FillDescription(pythonpp::CList &descr)
#define NCBI_CURRENT_FUNCTION
Get current function name.
Definition: ncbidiag.hpp:141
static PyObject * GetPyModule(void)
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:101
deque< CRef< CVariantSet > > TCachedSet
#define PYDBAPI_SUPPORT_DIR
IConnection * Create(void)
pythonpp::CObject setoutputsize(const pythonpp::CTuple &args)
Set a column buffer size for fetches of large columns (e.g.
CCursorIter(CCursor *cursor)
unsigned int GetPosition(void) const
Definition: interfaces.hpp:112
unsigned int DWORD
Definition: sqltypes.h:98
pythonpp::CObject __enter__(const pythonpp::CTuple &args)
int GetMicroSecond(void) const
pythonpp::CObject transaction(const pythonpp::CTuple &args)
void Destroy(IConnection *db_conn)
static bool HasSameType(PyObject *obj)
virtual void SetParam(const CVariant &v, const CDBParamVariant &param)=0
Set input parameters.
bool Empty(void) const
const_iterator begin() const
Definition: set.hpp:135
EStatementType m_StmType
virtual IResultSet * GetResultSet()=0
Get resulset.
int Year(void) const
Get year.
Definition: ncbitime.hpp:2220
virtual size_type size() const
Informational message.
Definition: ncbidiag.hpp:645
static bool HasSameType(PyObject *obj)
void CreateStmt(CDB_UserHandler *handler)
CFile –.
Definition: ncbifile.hpp:1523
virtual EDB_ResType GetResultType(void)=0
Get result type.
int GetSecond(void) const
CSelectConnPool m_SelectConnPool
static PyObject * Date(PyObject *self, PyObject *args)
virtual void Execute()=0
Execute stored procedure.
CTransaction & GetDefaultTransaction(void)
virtual void DumpResult(void)
void reset(X *p=0)
Reset pointer.
Definition: ncbimisc.hpp:405
static HSTMT stmt
Definition: rebindpar.c:12
#define PYDBAPI_MODINIT_FUNC(name)
static PyObject * init_common(const string &module_name)
static bool HasSameType(PyObject *obj)
CTransaction & GetTransaction(void)
void Clear(void)
static void Declare(const string &name)
CCursor(CTransaction *trans)
IConnection * CreateSelectConnection(void)
pythonpp::CObject rollback(const pythonpp::CTuple &args)
virtual EDB_ResType GetResultType()=0
Get result type.
const CConnection & GetParentConnection(void) const
PyObject * IncRefCount(PyObject *obj)
Template structure SStaticPair is simlified replacement of STL pair<> Main reason of introducing this...
Definition: static_set.hpp:59
virtual void DumpResult(void)
auto_ptr< IStatement > m_LocalStmt
void SetupParameters(const pythonpp::CDict &dict, CStmtHelper &stmt)
IStatement & GetLocalStmt(void) const
virtual void PushCntxMsgHandler(CDB_UserHandler *h, EOwnership ownership=eNoOwnership)=0
Add message handler "h" to process 'context-wide' (not bound to any particular connection) error mess...
CTransaction(CConnection *conn, pythonpp::EOwnershipFuture ownnership=pythonpp::eOwned, EConnectionMode conn_mode=eSimpleMode)
virtual void PushDefConnMsgHandler(CDB_UserHandler *h, EOwnership ownership=eNoOwnership)=0
Add `per-connection' err.message handler "h" to the stack of default handlers which are inherited by ...
static SSystemFastMutex & GetMutex(void)
int Day(void) const
Get day.
Definition: ncbitime.hpp:2226
EStatementType GetType(void) const
virtual const IResultSetMetaData & GetMetaData(void) const =0
Get Metadata.
long GetRowCount(void) const
virtual ~CVariantSet(void)
Destructor.
virtual unsigned int GetTotalColumns(void)
Get total columns.
virtual CDBParams::EDirection GetDirection(const CDBParamVariant &param) const =0
Get parameter's direction (in/out/inout).
virtual IConnection * CreateConnection(EOwnership ownership=eNoOwnership)=0
auto_ptr< CVariantSet > m_VariantSet
virtual CDB_Connection * GetCDB_Connection()=0
Returns the internal driver connection object.
string GetString(void) const
Definition: variant.cpp:370
int Minute(void) const
Get minute.
Definition: ncbitime.hpp:2232
int size
CConnection(const string &driver_name, const string &db_type, const string &server_name, const string &db_name, const string &user_name, const string &user_pswd, const pythonpp::CObject &extra_params)
size_t GetBlobSize() const
Definition: variant.cpp:688
virtual bool Next(void)=0
Get next row.
void DestroyTransaction(CTransaction *trans)
void commit(void) const
virtual unsigned int GetTotalColumns(void)
Get total columns.
virtual void ClearParamList()=0
Clear parameter list.
static bool HasSameType(PyObject *obj)
Int4 GetInt4(void) const
Definition: variant.cpp:490
parent_type::const_iterator const_iterator
Definition: set.hpp:79
TFormat GetUserFmt(void) const
Uint1 GetByte(void) const
Definition: variant.cpp:524
void Destroy(IConnection *db_conn)
CTime –.
Definition: ncbitime.hpp:290
static CExtType & GetType(void)
const ETransType m_TransType
static string & ToUpper(string &str)
Convert string to upper case – string& version.
Definition: ncbistr.cpp:317
if(yy_accept[yy_current_state])
virtual bool HandleIt(CDB_Exception *ex)
Handle the exceptions resulting from a native API call, one-by-one.
CDB_Exception –.
Definition: exception.hpp:116
TFormat GetDriverFmt(void) const
char value[7]
Definition: config.c:428
pythonpp::CObject nextset(const pythonpp::CTuple &args)
This method will make the cursor skip to the next available set, discarding any remaining rows from t...
string GetStr(void) const
auto_ptr< IResultSet > m_RS
void erase(iterator pos)
Definition: set.hpp:151
bool GetBit(void) const
Definition: variant.cpp:578
const char * NCBI_GetDefaultRunpath(void)
Get default run path.
static PyObject * TimeFromTicks(PyObject *self, PyObject *args)
virtual bool Next(void)
Get next row.
void SetStr(const CStmtStr &stmt, CDB_UserHandler *handler)
pythonpp::CObject get_proc_return_status(const pythonpp::CTuple &args)
pythonpp::CTuple MakeTupleFromResult(IResultSet &rs)
virtual class IConnection * GetParentConn()=0
Get the parent connection.
static PyObject * Time(PyObject *self, PyObject *args)
virtual unsigned int GetTotalColumns()=0
Get total columns.
void AddDllSearchPath(const string &path)
Add path for the DLL lookup.
Definition: driver_mgr.cpp:317
virtual const IResultSetMetaData * GetMetaData(EOwnership ownership=eNoOwnership)=0
Get Metadata.
static bool HasSameType(PyObject *obj)
void SetDriverName(const string &name)
PyObject * DecRefCount(PyObject *obj)
CException –.
Definition: ncbiexpt.hpp:709
PyObject * CreateIter(void)
static void PrepareForPython(CExtObject< CBinary > *self)
string::size_type find_named(const string &str, string::size_type offset, int &param_len)
static PyObject * Timestamp(PyObject *self, PyObject *args)
void ROAttr(const string &name, long &value)
virtual void Execute(const string &sql)=0
Sends one or more SQL statements to the SQL server (NOTE: replaced by the SendSql()) ...
CRef –.
Definition: ncbiobj.hpp:616
CInfoHandler_CursorCollect m_InfoHandler
auto_ptr< ICallableStatement > m_Stmt
static CDriverManager & GetInstance()
Definition: driver_mgr.cpp:54
static CClass< 1 > Def(const char *name, TMethodVarArgsFunc func, const char *doc=0)
virtual bool HasRows()=0
Check if resultset has rows.
CTransaction *const m_ParentTransaction
int GetHour(void) const
static const char * str(char *buf, int n)
Definition: stats.c:84
bool IsPositional(void) const
Definition: interfaces.hpp:108
virtual int GetMaxSize(const CDBParamVariant &param) const =0
Get maximum size in bytes for column.
static void SetString(const string &msg)
virtual void PopMsgHandler(CDB_UserHandler *h)
Remove the message handler (and all above it) from the stack.
Definition: public.cpp:488
CObject –.
Definition: ncbiobj.hpp:180
void SetStr(const CStmtStr &stmt, CDB_UserHandler *handler)
pythonpp::CObject m_PythonConnection
string::size_type find_TSQL(const string &str, string::size_type offset, int &param_len)
IConnection * Create(void)
void DestroyDMLConnection(IConnection *db_conn)
static CS_CONNECTION * conn
Definition: get_send_data.c:18
An object can take ownership of another.
Definition: ncbi_types.h:136
void RollbackInternal(void) const
const char * file_name[]
pythonpp::CObject commit(const pythonpp::CTuple &args)
else result
Definition: token2.c:20
void clear()
Definition: set.hpp:153
CStaticArrayMap< int, FRethrow > TDBErrCodeMap
CDBDefaultConnParams m_DefParams
#define PYDBAPI_MOD_RETURN
int GetSybaseSeverity(void) const
Definition: exception.hpp:228
void(* FRethrow)(const CDB_Exception &)
pythonpp::CObject fetchmany(const pythonpp::CTuple &args)
Fetch the next set of rows of a query result, returning a sequence of sequences (e.g.
float GetFloat(void) const
Definition: variant.cpp:538
int GetDBErrCode(void) const
Definition: exception.hpp:184
#define _ASSERT
static void Declare(const char *name, const char *descr=0, PyTypeObject *base=&PyBaseObject_Type)
pythonpp::CObject m_Description
static PyObject * m_Module
static bool HasExactSameType(PyObject *obj)
pythonpp::CObject ConvertCVariant2PCObject(const CVariant &value)
bool IsNull() const
Definition: variant.cpp:624
virtual void PushMsgHandler(CDB_UserHandler *h, EOwnership ownership=eNoOwnership)
Put the message handler into message handler stack.
Definition: public.cpp:481
bool g_PythonStrDefToUnicode
Flag showing whether all pythonpp::CString objects should be created as Python unicode strings (TRUE ...
static bool EqualNocase(const CTempString str, SIZE_TYPE pos, SIZE_TYPE n, const char *pattern)
Case-insensitive equality of a substring with a pattern.
Definition: ncbistr.hpp:5221
void SetStr(const string &str, EStatementType default_type=estSelect, const CParamFmt &fmt=CParamFmt())
virtual IStatement * GetStatement()=0
Get statement object for regular SQL queries.
size_t Read(void *buf, size_t len) const
Definition: variant.cpp:635
Use current time.
Definition: ncbitime.hpp:295
pythonpp::CObject setinputsizes(const pythonpp::CTuple &args)
This can be used before a call to executeXXX() to predefine memory areas for the operation's paramete...
void Cleanup(CVariant &value)
virtual EDB_ResType GetResultType(void)
Get result type.
CSelectConnPool(CTransaction *trans, size_t size=3)
EConnectionMode m_ConnectionMode
void SetHour(int hour)
Set hour.
Definition: ncbitime.cpp:1094
void SetMinute(int minute)
Set minute.
Definition: ncbitime.cpp:1101
ICallableStatement * m_Stmt
virtual bool HasRS(void) const
pythonpp::CList m_DescrList
static void Declare(const char *name, PyMethodDef *methods)
void SetEncoding(EEncoding encoding)
void SetParam(const string &key, const string &value)
IDataSource * MakeDs(const CDBConnParams &params, const string &tag=kEmptyStr)
Definition: driver_mgr.cpp:157
static struct PyMethodDef python_ncbi_dbapi_methods[]
void AddInfoMessage(const string &message)
virtual bool Next(void)
Get next row.
CCPPToolkitConnParams m_Params
Definition: python_ncbi_db