44 #include "../../ds_impl.hpp"
48 #if defined(NCBI_OS_CYGWIN)
50 #elif !defined(NCBI_OS_MSWIN)
55 #define PYTHONPP_DEFINE_GLOBALS 1
58 #if PY_VERSION_HEX >= 0x02040000
62 #include <structmember.h>
71 #if PY_MAJOR_VERSION >= 3
72 # define PYDBAPI_MOD_RETURN return
73 # define PYDBAPI_MODINIT_FUNC(name) \
74 PyMODINIT_FUNC NCBI_NAME2(PyInit_,name)(void)
76 # define PYDBAPI_MOD_RETURN
77 # define PYDBAPI_MODINIT_FUNC(name) PyMODINIT_FUNC NCBI_NAME2(init,name)(void)
80 #ifndef PYDBAPI_SUPPORT_DIR
81 # define PYDBAPI_SUPPORT_DIR "python_ncbi_dbapi/" NCBI_PACKAGE_VERSION
84 #define NCBI_USE_ERRCODE_X Dbapi_Python
97 static PyObject*
SetLogger(PyObject *
self, PyObject *args);
151 virtual bool Next(
void);
169 : m_ResType(other.GetResultType())
170 , m_ColumsNum(other.GetTotalColumns())
174 while (other.
Next()) {
178 for (
unsigned int col = 1; col <=
m_ColumsNum; ++col) {
255 virtual bool Next(
void);
316 virtual bool HasRS(
void)
const;
399 virtual bool HasRS(
void)
const;
413 while (
stmt.HasMoreResults()) {
414 if (
stmt.HasRows()) {
415 unique_ptr<IResultSet> rs(
stmt.GetResultSet());
532 : m_UserFmt(user_fmt)
600 string::size_type pos = 0;
601 string::size_type prev_pos = pos;
603 if ((pos =
m_StmtStr.find(
'?', pos)) != string::npos) {
607 while (pos != string::npos) {
608 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
621 string::size_type pos = 0;
622 string::size_type prev_pos = pos;
624 if ((pos =
m_StmtStr.find(
'?', pos)) != string::npos) {
628 while (pos != string::npos) {
629 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
644 string::size_type pos = 0;
645 string::size_type prev_pos = pos;
651 while (pos != string::npos) {
652 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
654 prev_pos = pos + param_len;
667 string::size_type pos = 0;
668 string::size_type prev_pos = pos;
674 while (pos != string::npos) {
675 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
677 prev_pos = pos + param_len;
688 string::size_type pos = 0;
689 string::size_type prev_pos = pos;
698 while (pos != string::npos) {
699 string param_name =
m_StmtStr.substr(pos + 1, param_len - 1);
700 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
704 name_map_t::iterator it = name2num.find(param_name);
705 if (it == name2num.end()) {
706 it = name2num.insert(
713 tmp_stmt += it->second;
715 prev_pos = pos + param_len;
726 string::size_type pos = 0;
727 string::size_type prev_pos = pos;
733 while (pos != string::npos) {
734 string param_name =
m_StmtStr.substr(pos + 1, param_len - 1);
735 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
736 tmp_stmt +=
"@" + param_name;
737 prev_pos = pos + param_len;
750 string::size_type pos = 0;
751 string::size_type prev_pos = pos;
757 while (pos != string::npos) {
758 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
760 prev_pos = pos + param_len;
771 string::size_type pos = 0;
772 string::size_type prev_pos = pos;
781 while (pos != string::npos) {
782 string param_name =
m_StmtStr.substr(pos + 1, param_len - 1);
783 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
787 name_map_t::iterator it = name2num.find(param_name);
788 if (it == name2num.end()) {
789 it = name2num.insert(
796 tmp_stmt += it->second;
798 prev_pos = pos + param_len;
809 string::size_type pos = 0;
810 string::size_type prev_pos = pos;
816 while (pos != string::npos) {
817 string param_name =
m_StmtStr.substr(pos + 1, param_len - 1);
818 tmp_stmt +=
m_StmtStr.substr(prev_pos, pos - prev_pos);
819 tmp_stmt +=
":" + param_name;
820 prev_pos = pos + param_len;
833 string err =
"Cannot convert '";
835 err +=
"' parameter format to '";
849 string::size_type pos = 0;
850 static const char* num_characters =
"0123456789";
853 if ((pos != string::npos) && (pos + 1 != string::npos)) {
854 string::size_type tmp_pos = 0;
856 tmp_pos =
str.find_first_not_of(num_characters, pos + 1);
857 if (tmp_pos != string::npos) {
859 param_len = tmp_pos - pos;
860 }
else if (
str.find_first_of(num_characters, pos + 1) == pos + 1) {
862 param_len =
str.size() - pos;
876 string::size_type pos = 0;
877 static char const* sep_characters =
" \t\n,.()-+<>=";
880 if ((pos != string::npos) && (pos + 1 != string::npos)) {
881 string::size_type tmp_pos = 0;
883 tmp_pos =
str.find_first_of(sep_characters, pos + 1);
884 if (tmp_pos != string::npos) {
886 param_len = tmp_pos - pos;
887 }
else if ((
str[pos + 1] >=
'A' &&
str[pos + 1] <=
'Z') ||
888 (
str[pos + 1] >=
'a' &&
str[pos + 1] <=
'z')
891 param_len =
str.size() - pos;
904 string::size_type pos = 0;
905 static char const* sep_characters =
" \t\n,.()-+<>=";
908 if ((pos != string::npos) && (pos + 1 != string::npos)) {
909 string::size_type tmp_pos = 0;
911 tmp_pos =
str.find_first_of(sep_characters, pos + 1);
912 if (tmp_pos != string::npos) {
914 param_len = tmp_pos - pos;
915 }
else if ((
str[pos + 1] >=
'A' &&
str[pos + 1] <=
'Z') ||
916 (
str[pos + 1] >=
'a' &&
str[pos + 1] <=
'z')
919 param_len =
str.size() - pos;
928 struct DataSourceDeleter
931 static void Delete(ncbi::IDataSource* const object)
933 CDriverManager::DeleteDs( object );
938 class CDataSourcePool
941 CDataSourcePool(void);
942 ~CDataSourcePool(void);
945 static CDataSourcePool& GetInstance(void);
948 IDataSource& GetDataSource(
949 const string& driver_name,
950 const TPluginManagerParamTree* const params = NULL);
953 typedef CPluginManager<I_DriverContext> TContextManager;
954 typedef CPluginManagerGetter<I_DriverContext> TContextManagerStore;
955 typedef map<string, AutoPtr<IDataSource, DataSourceDeleter> > TDSMap;
957 CRef<TContextManager> m_ContextManager;
958 TDSMap m_DataSourceMap;
961 CDataSourcePool::CDataSourcePool(void)
963 m_ContextManager.Reset( TContextManagerStore::Get() );
964 _ASSERT( m_ContextManager );
966 #if defined(NCBI_OS_MSWIN)
967 // Add an additional search path ...
971 CDataSourcePool::~CDataSourcePool(void)
976 DataSourceCleanup(void* ptr)
978 CDriverManager::DeleteDs( static_cast<ncbi::IDataSource *const>(ptr) );
982 CDataSourcePool::GetInstance(void)
984 static CSafeStatic<CDataSourcePool> ds_pool;
990 CDataSourcePool::GetDataSource(
991 const string& driver_name,
992 const TPluginManagerParamTree* const params)
994 TDSMap::const_iterator citer = m_DataSourceMap.find( driver_name );
996 if ( citer != m_DataSourceMap.end() ) {
997 return *citer->second;
1000 // Build a new context ...
1001 I_DriverContext* drv = NULL;
1004 drv = m_ContextManager->CreateInstance(
1006 NCBI_INTERFACE_VERSION(I_DriverContext),
1011 catch( const CPluginManagerException& e ) {
1012 throw CDatabaseError( e.what() );
1014 catch ( const exception& e ) {
1015 throw CDatabaseError( driver_name + " is not available :: " + e.what() );
1018 throw CDatabaseError( driver_name + " was unable to load due an unknown error" );
1022 IDataSource* ds = CDriverManager::CreateDs( drv );
1023 m_DataSourceMap[driver_name] = ds;
1035 #if defined(NCBI_OS_CYGWIN)
1039 #elif defined(NCBI_OS_MSWIN)
1041 const DWORD buff_size = 1024;
1043 char buff[buff_size];
1045 const char* module_name =
NULL;
1054 MEMORY_BASIC_INFORMATION mbi;
1060 if ( cur_size = GetModuleFileNameA( mh, buff, buff_size ) ) {
1061 if ( cur_size < buff_size ) {
1073 if (::dladdr(method_ptr, &dli) != 0) {
1096 #define DB_ERR_CODE(value, type) { value, &C##type##Error::Rethrow }
1157 NCBI_NORETURN
static
1176 if (it != sc_SybaseErrCodes.end()) {
1182 switch (dbe->GetErrCode()) {
1192 if (it != sc_SybaseErrCodes.end()) {
1207 const string& driver_name,
1208 const string& db_type,
1209 const string& server_name,
1210 const string& db_name,
1211 const string& user_name,
1212 const string& user_pswd,
1215 : m_DefParams(server_name, user_name, user_pswd)
1216 , m_Params(m_DefParams)
1219 , m_DefTransaction(
NULL )
1227 string db_type_uc = db_type;
1230 if ( db_type_uc ==
"SYBASE" || db_type_uc ==
"SYB" ) {
1232 }
else if ( db_type_uc ==
"MYSQL" ) {
1234 }
else if ( db_type_uc ==
"MSSQL" ||
1235 db_type_uc ==
"MS_SQL" ||
1236 db_type_uc ==
"MS SQL")
1252 while ( PyDict_Next(dict, &
i, &
key, &
value) ) {
1372 (*citer)->close(args);
1403 : m_Transaction(trans)
1441 throw CInternalError(
"Unable to close a transaction. There are open cursors in use.");
1464 : m_Transaction( trans )
1465 , m_NumOfActive( 0 )
1466 , m_Started(
false )
1467 , m_TransType( trans_type )
1502 throw CInternalError(
"Unable to close a transaction. There are open cursors in use.");
1567 : m_ParentConnection(
conn )
1569 , m_SelectConnPool( this )
1570 , m_ConnectionMode( conn_mode )
1685 for ( citer = tmp_CursorList.
begin(); citer != cend; ++citer ) {
1686 (*citer)->CloseInternal();
1737 string::size_type pos =
stmt.find_first_not_of(
" \t\n");
1738 if (pos != string::npos)
1740 string::size_type pos_end =
stmt.find_first_of(
" \t\n", pos);
1741 if (pos_end == string::npos)
1742 pos_end =
stmt.size();
1744 bool output_clause_possible =
false;
1755 output_clause_possible =
true;
1759 output_clause_possible =
true;
1763 output_clause_possible =
true;
1773 output_clause_possible =
true;
1788 && output_clause_possible) {
1792 if (pos + 7 <
stmt.size()
1807 : m_ParentTransaction( trans )
1809 , m_Executed(
false )
1810 , m_ResultStatus( 0 )
1811 , m_ResultStatusAvailable(
false )
1812 , m_UserHandler(
NULL)
1820 : m_ParentTransaction( trans )
1823 , m_ResultStatus( 0 )
1824 , m_ResultStatusAvailable(
false )
1825 , m_UserHandler(
NULL)
1858 while (
m_Stmt->HasMoreResults() ) {
1859 if (
m_Stmt->HasRows() ) {
1915 m_Stmt->GetParentConn()->GetCDB_Connection()->PushMsgHandler(
handler);
1938 m_Stmt->ClearParamList();
1954 string param_name = name;
1956 if ( param_name.size() > 0) {
1957 if ( param_name[0] !=
'@') {
1958 param_name =
"@" + param_name;
1978 m_Stmt->SetParam(
value,
static_cast<unsigned int>(index) );
2003 catch(
const bad_cast&) {
2004 throw CInternalError(
"std::bad_cast exception within 'CStmtHelper::Execute'");
2009 catch(
const exception&) {
2010 throw CInternalError(
"std::exception exception within 'CStmtHelper::Execute'");
2018 return m_Stmt->GetRowCount();
2027 throw CProgrammingError(
"The previous call to executeXXX() did not produce any result set or no call was issued yet");
2037 throw CProgrammingError(
"The previous call to executeXXX() did not produce any result set or no call was issued yet");
2053 throw CProgrammingError(
"Procedure return code is not defined within this context.");
2065 while (
m_Stmt->HasMoreResults() ) {
2066 if (
m_Stmt->HasRows() ) {
2093 for (
unsigned int i = 1;
i <=
cnt; ++
i) {
2149 : m_ParentTransaction( trans )
2150 , m_Executed(
false )
2151 , m_ResultStatus( 0 )
2152 , m_ResultStatusAvailable(
false )
2153 , m_UserHandler(
NULL)
2161 : m_ParentTransaction( trans )
2163 , m_Executed(
false )
2164 , m_ResultStatus( 0 )
2165 , m_ResultStatusAvailable(
false )
2166 , m_UserHandler(
NULL)
2238 m_Stmt->GetParentConn()->GetCDB_Connection()->PushMsgHandler(
handler);
2261 string param_name = name;
2263 if ( param_name.size() > 0) {
2264 if ( param_name[0] !=
'@') {
2265 param_name =
"@" + param_name;
2274 output_param =
false;
2276 if (
value.IsNull()) {
2278 m_Stmt->SetOutputParam( temp_val, param_name );
2283 output_param =
true;
2297 unsigned int ind =
static_cast<unsigned int>(index);
2300 output_param =
false;
2302 if (
value.IsNull()) {
2304 m_Stmt->SetOutputParam( temp_val, ind );
2309 output_param =
true;
2332 if (cache_results) {
2339 catch(
const bad_cast&) {
2340 throw CInternalError(
"std::bad_cast exception within 'CCallableStmtHelper::Execute'");
2345 catch(
const exception&) {
2346 throw CInternalError(
"std::exception exception within 'CCallableStmtHelper::Execute'");
2354 return m_Stmt->GetRowCount();
2363 throw CProgrammingError(
"The previous call to executeXXX() did not produce any result set or no call was issued yet");
2373 throw CProgrammingError(
"The previous call to executeXXX() did not produce any result set or no call was issued yet");
2393 throw CProgrammingError(
"Procedure return code is not defined within this context.");
2395 return m_Stmt->GetReturnStatus();
2402 throw CProgrammingError(
"The previous call to executeXXX() did not produce any result set or no call was issued yet");
2418 throw CProgrammingError(
"The previous call to executeXXX() did not produce any result set or no call was issued yet");
2435 if (
value.IsNull() ) {
2439 switch (
value.GetType() ) {
2455 #if PY_VERSION_HEX >= 0x02040000
2461 #if PY_VERSION_HEX >= 0x03070000
2466 if ( !
offset.IsNull() ) {
2475 (PyDateTime_FromTimestamp(args.
Get()));
2507 size_t lob_size =
value.GetBlobSize();
2510 tmp_str.resize(lob_size);
2511 value.Read( (
void*)tmp_str.data(), lob_size );
2543 for (
int i = 0;
i < col_num; ++
i) {
2561 for (
int i = 0;
i < col_num; ++
i) {
2584 : m_PythonConnection( &trans->GetParentConnection() )
2585 , m_PythonTransaction( trans )
2586 , m_ParentTransaction( trans )
2589 , m_InfoHandler( this )
2591 , m_StmtHelper( trans )
2592 , m_CallableStmtHelper( trans )
2593 , m_AllDataFetched(
false )
2594 , m_AllSetsFetched(
false )
2597 if ( trans ==
NULL ) {
2652 const size_t args_size = args.
size();
2657 vector<size_t> out_params;
2659 if ( args_size == 0 ) {
2661 }
else if ( args_size > 0 ) {
2674 if ( args_size > 1 ) {
2681 out_params.push_back(0);
2699 if (args_size > 1 && out_params.size() != 0) {
2701 output_args.
Set(args[1]);
2713 for (
int i = 0;
i < col_num; ++
i) {
2719 const string param_name =
md.GetName(
i + 1);
2777 PyObject * it = PyDict_GetItemString(kwargs.
Get(),
"output_expected");
2778 if (it ==
nullptr) {
2780 }
else if (PyObject_IsTrue(it)) {
2795 const size_t args_size = args.
size();
2801 if ( args_size == 0 ) {
2803 }
else if ( args_size > 0 ) {
2817 if ( args_size > 1 ) {
2867 while ( PyDict_Next(dict, &
i, &
key, &
value) ) {
2881 size_t sz = seq.
size();
2882 for (
size_t i = 0;
i < sz; ++
i) {
2896 bool output_param =
false;
2898 while ( PyDict_Next(dict, &
i, &
key, &
value) ) {
2913 vector<size_t>* out_params)
2916 size_t sz = seq.
size();
2918 for (
size_t i = 0;
i < sz; ++
i) {
2922 bool output_param =
false;
2925 out_params->push_back(
i);
2933 #if PY_VERSION_HEX >= 0x030a0000
2934 tzinfo = PyDateTime_DATE_GET_TZINFO(dt.
Get());
2936 tzinfo = dt.
GetAttr(
"tzinfo");
2938 if ( !PyTZInfo_Check(tzinfo.
Get()) ) {
2945 #if PY_VERSION_HEX >= 0x03030000
2946 auto days = PyDateTime_DELTA_GET_DAYS(
delta.Get()),
2947 seconds = PyDateTime_DELTA_GET_SECONDS(
delta.Get());
2952 return days * 24 * 60 + seconds / 60;
2962 #if PY_MAJOR_VERSION < 3
2972 const string std_str(python_str);
2974 #if PY_VERSION_HEX >= 0x02040000
2985 if ( !
offset.IsNull() ) {
3023 const size_t args_size = args.
size();
3029 if ( args_size == 0 ) {
3031 }
else if ( args_size > 0 ) {
3042 if ( args_size > 1 ) {
3056 for ( citer = params.
begin(); citer != cend; ++citer ) {
3081 throw CProgrammingError(
"Sequence of parameters should be provided either as a list or as a tuple data type");
3084 throw CProgrammingError(
"A sequence of parameters is expected with the 'executemany' function");
3132 if ( args.
size() > 0 ) {
3136 throw CProgrammingError(
"Invalid parameters within 'CCursor::fetchmany' function");
3148 for ( ;
i < array_size && rs.
Next(); ++
i ) {
3153 if (
i < array_size ) {
3162 for ( ;
i < array_size && rs.
Next(); ++
i ) {
3167 if (
i < array_size ) {
3195 while ( rs.
Next() ) {
3205 while ( rs.
Next() ) {
3303 throw CProgrammingError(
"Call get_proc_return_status after you retrieve all data.");
3309 throw CProgrammingError(
"Call get_proc_return_status after you retrieve all data.");
3336 : m_PythonCursor(cursor),
3392 for (; cur_exception; cur_exception = cur_exception->
GetPredecessor()) {
3402 srv_msg = cur_exception->
GetMsg();
3411 PyObject *exc_ob =
NULL;
3412 PyObject *errno_ob =
NULL;
3413 PyObject *msg_ob =
NULL;
3416 #if PY_MAJOR_VERSION >= 3
3417 errno_ob = PyLong_FromLong(db_errno);
3419 errno_ob = PyInt_FromLong(db_errno);
3421 if (errno_ob ==
NULL) {
3425 #if PY_MAJOR_VERSION >= 3
3426 msg_ob = PyUnicode_FromStringAndSize(db_msg.data(), db_msg.size());
3428 msg_ob = PyString_FromStringAndSize(db_msg.data(), db_msg.size());
3430 if (errno_ob ==
NULL) {
3431 Py_DECREF(errno_ob);
3438 exc_ob = PyObject_CallFunction(err_type, (
char *)
"s", (
char*)msg.c_str());
3441 Py_DECREF(errno_ob);
3447 if (PyObject_SetAttrString(exc_ob, (
char *)
"srv_errno", errno_ob) == -1)
3449 Py_DECREF(errno_ob);
3456 Py_DECREF(errno_ob);
3459 if (PyObject_SetAttrString(exc_ob, (
char *)
"srv_msg", msg_ob) == -1)
3470 PyErr_SetObject(err_type, exc_ob);
3479 // Future development ...
3480 class CModuleDBAPI : public pythonpp::CExtModule<CModuleDBAPI>
3483 CModuleDBAPI(const char* name, const char* descr = 0)
3484 : pythonpp::CExtModule<CModuleDBAPI>(name, descr)
3486 PrepareForPython(this);
3490 // connect(driver_name, db_type, db_name, user_name, user_pswd)
3491 pythonpp::CObject connect(const pythonpp::CTuple& args);
3492 pythonpp::CObject Binary(const pythonpp::CTuple& args);
3493 pythonpp::CObject TimestampFromTicks(const pythonpp::CTuple& args);
3494 pythonpp::CObject TimeFromTicks(const pythonpp::CTuple& args);
3495 pythonpp::CObject DateFromTicks(const pythonpp::CTuple& args);
3496 pythonpp::CObject Timestamp(const pythonpp::CTuple& args);
3497 pythonpp::CObject Time(const pythonpp::CTuple& args);
3498 pythonpp::CObject Date(const pythonpp::CTuple& args);
3502 CModuleDBAPI::connect(const pythonpp::CTuple& args)
3513 const pythonpp::CTuple func_args(args);
3515 driver_name = pythonpp::CString(func_args[0]);
3516 db_type = pythonpp::CString(func_args[1]);
3517 server_name = pythonpp::CString(func_args[2]);
3518 db_name = pythonpp::CString(func_args[3]);
3519 user_name = pythonpp::CString(func_args[4]);
3520 user_pswd = pythonpp::CString(func_args[5]);
3521 } catch (const pythonpp::CError&) {
3522 throw CProgrammingError("Invalid parameters within 'connect' function");
3525 CConnection* conn = new CConnection( CConnParam(
3534 // Feef the object to the Python interpreter ...
3535 return pythonpp::CObject(conn, pythonpp::eTakeOwnership);
3537 catch (const CException& e) {
3538 s_ThrowDatabaseError(e);
3541 // Return a dummy object ...
3542 return pythonpp::CNone();
3545 // This function constructs an object holding a date value.
3546 // Date(year,month,day)
3548 CModuleDBAPI::Date(const pythonpp::CTuple& args)
3556 const pythonpp::CTuple func_args(args);
3558 year = pythonpp::CInt(func_args[0]);
3559 month = pythonpp::CInt(func_args[1]);
3560 day = pythonpp::CInt(func_args[2]);
3561 } catch (const pythonpp::CError&) {
3562 throw CProgrammingError("Invalid parameters within 'Date' function");
3565 // Feef the object to the Python interpreter ...
3566 return pythonpp::CDate(year, month, day);
3568 catch (const CDB_Exception& e) {
3569 s_ThrowDatabaseError(e);
3571 catch (const CException& e) {
3572 pythonpp::CError::SetString(e.what());
3575 // Return a dummy object ...
3576 return pythonpp::CNone();
3579 // This function constructs an object holding a time value.
3580 // Time(hour,minute,second)
3582 CModuleDBAPI::Time(const pythonpp::CTuple& args)
3590 const pythonpp::CTuple func_args(args);
3592 hour = pythonpp::CInt(func_args[0]);
3593 minute = pythonpp::CInt(func_args[1]);
3594 second = pythonpp::CInt(func_args[2]);
3595 } catch (const pythonpp::CError&) {
3596 throw CProgrammingError("Invalid parameters within 'Time' function");
3599 // Feef the object to the Python interpreter ...
3600 return pythonpp::CTime(hour, minute, second, 0);
3602 catch (const CDB_Exception& e) {
3603 s_ThrowDatabaseError(e);
3605 catch (const CException& e) {
3606 pythonpp::CError::SetString(e.what());
3609 // Return a dummy object ...
3610 return pythonpp::CNone();
3613 // This function constructs an object holding a time stamp
3615 // Timestamp(year,month,day,hour,minute,second)
3617 CModuleDBAPI::Timestamp(const pythonpp::CTuple& args)
3628 const pythonpp::CTuple func_args(args);
3630 year = pythonpp::CInt(func_args[0]);
3631 month = pythonpp::CInt(func_args[1]);
3632 day = pythonpp::CInt(func_args[2]);
3633 hour = pythonpp::CInt(func_args[3]);
3634 minute = pythonpp::CInt(func_args[4]);
3635 second = pythonpp::CInt(func_args[5]);
3636 } catch (const pythonpp::CError&) {
3637 throw CProgrammingError("Invalid parameters within 'Timestamp' function");
3640 // Feef the object to the Python interpreter ...
3641 return pythonpp::CDateTime(year, month, day, hour, minute, second, 0);
3643 catch (const CDB_Exception& e) {
3644 s_ThrowDatabaseError(e);
3646 catch (const CException& e) {
3647 pythonpp::CError::SetString(e.what());
3650 // Return a dummy object ...
3651 return pythonpp::CNone();
3654 // This function constructs an object holding a date value
3655 // from the given ticks value (number of seconds since the
3656 // epoch; see the documentation of the standard Python time
3657 // module for details).
3658 // DateFromTicks(ticks)
3660 CModuleDBAPI::DateFromTicks(const pythonpp::CTuple& args)
3664 catch (const CDB_Exception& e) {
3665 s_ThrowDatabaseError(e);
3667 catch (const CException& e) {
3668 pythonpp::CError::SetString(e.what());
3671 // Return a dummy object ...
3672 return pythonpp::CNone();
3675 // This function constructs an object holding a time value
3676 // from the given ticks value (number of seconds since the
3677 // epoch; see the documentation of the standard Python time
3678 // module for details).
3679 // TimeFromTicks(ticks)
3681 CModuleDBAPI::TimeFromTicks(const pythonpp::CTuple& args)
3685 catch (const CDB_Exception& e) {
3686 s_ThrowDatabaseError(e);
3688 catch (const CException& e) {
3689 pythonpp::CError::SetString(e.what());
3692 // Return a dummy object ...
3693 return pythonpp::CNone();
3696 // This function constructs an object holding a time stamp
3697 // value from the given ticks value (number of seconds since
3698 // the epoch; see the documentation of the standard Python
3699 // time module for details).
3700 // TimestampFromTicks(ticks)
3702 CModuleDBAPI::TimestampFromTicks(const pythonpp::CTuple& args)
3706 catch (const CDB_Exception& e) {
3707 s_ThrowDatabaseError(e);
3709 catch (const CException& e) {
3710 pythonpp::CError::SetString(e.what());
3713 // Return a dummy object ...
3714 return pythonpp::CNone();
3717 // This function constructs an object capable of holding a
3718 // binary (long) string value.
3721 CModuleDBAPI::Binary(const pythonpp::CTuple& args)
3728 const pythonpp::CTuple func_args(args);
3730 value = pythonpp::CString(func_args[0]);
3731 } catch (const pythonpp::CError&) {
3732 throw CProgrammingError("Invalid parameters within 'Binary' function");
3735 CBinaryType* obj = new CBinaryType(
3738 // Feef the object to the Python interpreter ...
3739 return pythonpp::CObject(obj, pythonpp::eTakeOwnership);
3741 catch (const CDB_Exception& e) {
3742 s_ThrowDatabaseError(e);
3744 catch (const CException& e) {
3745 pythonpp::CError::SetString(e.what());
3748 return pythonpp::CNone();
3858 (
"Unknown error in python_ncbi_dbapi::ReleaseGlobalLock");
3894 if ( func_args.
size() > 6 ) {
3895 extra_params = func_args[6];
3932 Date(PyObject *
self, PyObject *args)
3934 #if PY_VERSION_HEX < 0x02040000
3976 Time(PyObject *
self, PyObject *args)
3978 #if PY_VERSION_HEX < 0x02040000
4023 #if PY_VERSION_HEX < 0x02040000
4196 static void Declare(
const char* name, PyMethodDef* methods);
4200 #if PY_MAJOR_VERSION >= 3
4201 static struct PyModuleDef m_ModuleDef;
4206 #if PY_MAJOR_VERSION >= 3
4208 PyModuleDef_HEAD_INIT,
4223 #if PY_MAJOR_VERSION >= 3
4224 m_ModuleDef.m_name = name;
4225 m_ModuleDef.m_methods = methods;
4226 m_Module = PyModule_Create(&m_ModuleDef);
4228 m_Module = Py_InitModule(
const_cast<char*
>(name), methods);
4236 "return_strs_as_unicode(bool_flag_value) "
4237 "-- set global flag indicating that all strings returned from database "
4238 "should be presented to Python as unicode strings (if value is True) or "
4239 " as regular strings in UTF-8 encoding (if value is False - the default one). "
4240 "NOTE: This is not a part of the Python Database API Specification v2.0."
4243 "release_global_lock(bool_flag_value) "
4244 "-- set global flag indicating that blocking database operations "
4245 "should run with Python's global interpreter lock released (if value "
4246 "is True) or with it held (if value is False, the default for now)."
4247 "NOTE: This is not a part of the Python Database API Specification "
4250 {(
char*)
"connect", (PyCFunction)
python::Connect, METH_VARARGS, (
char*)
4251 "connect(driver_name, db_type, server_name, database_name, userid, password,"
4252 "[extra/use_std_interface]) "
4253 "-- connect to the "
4254 "driver_name; db_type; server_name; database_name; userid; password;"
4257 (
char*)
"set_logger(logger) "
4258 "-- log through the specified logger. (This module otherwise defaults "
4259 "to going directly through the root logger.) "
4260 "NOTE: This is not a part of the Python Database API Specification "
4262 {(
char*)
"Date", (PyCFunction)
python::Date, METH_VARARGS, (
char*)
"Date"},
4263 {(
char*)
"Time", (PyCFunction)
python::Time, METH_VARARGS, (
char*)
"Time"},
4264 {(
char*)
"Timestamp", (PyCFunction)
python::Timestamp, METH_VARARGS, (
char*)
"Timestamp"},
4265 {(
char*)
"DateFromTicks", (PyCFunction)
python::DateFromTicks, METH_VARARGS, (
char*)
"DateFromTicks"},
4266 {(
char*)
"TimeFromTicks", (PyCFunction)
python::TimeFromTicks, METH_VARARGS, (
char*)
"TimeFromTicks"},
4268 {(
char*)
"Binary", (PyCFunction)
python::Binary, METH_VARARGS, (
char*)
"Binary"},
4509 #if PY_VERSION_HEX >= 0x03020000
4516 : m_LoggingModule(PyImport_ImportModule(
"logging"))
4517 , m_LoggingDict(m_LoggingModule.GetDict()), m_Logger(1)
4518 , m_LoggerClass(m_LoggingDict.GetItem(
"Logger"))
4519 #
if PY_VERSION_HEX >= 0x03020000
4520 , m_HasHandlers(m_LoggerClass.GetAttr(
"hasHandlers"))
4521 , m_IsConfigured(
false)
4527 auto root_logger = get_logger.
Apply();
4570 #if PY_VERSION_HEX >= 0x03020000
4571 if ( !m_IsConfigured ) {
4572 m_IsConfigured = m_HasHandlers.Apply(
m_Logger);
4573 if ( !m_IsConfigured ) {
4579 (
"python_ncbi_dbapi: Allowing automatic logging.basicConfig");
4590 s.erase(0, s.find_first_not_of(
" ", s.find_first_of(
" ") + 1));
4622 "set_logger: expected logging.logger but got " + type_name);
4704 #if PY_VERSION_HEX >= 0x02040000
4730 const string connection_name(module_name +
".Connection");
4742 const string transaction_name(module_name +
".Transaction");
4753 const string cursor_name(module_name +
".Cursor");
4771 const string cursor_iter_name(module_name +
".__CursorIterator__");
4781 if (PyModule_AddObject(module,
const_cast<char*
>(
"BINARY"),
4819 static char str_class[] =
"__class__";
4820 static PyMemberDef conn_members[] = {
4821 {str_class, T_OBJECT_EX, 0, READONLY,
NULL},
4824 extt->tp_members = conn_members;
4825 if ( PyType_Ready(extt) == -1 ) {
4828 if ( PyModule_AddObject(module,
const_cast<char*
>(
"Connection"), (PyObject*)extt ) == -1 ) {
4832 extt->tp_members = conn_members;
4833 if ( PyType_Ready(extt) == -1 ) {
4836 if ( PyModule_AddObject(module,
const_cast<char*
>(
"Transaction"), (PyObject*)extt ) == -1 ) {
4841 static char str_rowcount[] =
"rowcount";
4842 static char str_messages[] =
"messages";
4843 static char str_description[] =
"description";
4844 static PyMemberDef members[] = {
4845 {str_rowcount, T_LONG, 0, READONLY,
NULL},
4846 {str_messages, T_OBJECT_EX, 0, READONLY,
NULL},
4847 {str_description, T_OBJECT_EX, 0, READONLY,
NULL},
4848 {str_class, T_OBJECT_EX, 0, READONLY,
NULL},
4851 extt->tp_members = members;
4853 if ( PyType_Ready(extt) == -1 ) {
4856 if ( PyModule_AddObject(module,
const_cast<char*
>(
"Cursor"), (PyObject*)extt ) == -1 ) {
4862 if ( PyType_Ready(extt) == -1 ) {
4865 if ( PyModule_AddObject(module,
const_cast<char*
>(
"__CursorIterator__"), (PyObject*)extt ) == -1 ) {
4969 #ifdef NCBI_OS_DARWIN
void SetDriverName(const string &name)
void SetDatabaseName(const string &name)
void SetParam(const string &key, const string &value)
void SetServerType(EServerType type)
void SetEncoding(EEncoding encoding)
virtual TSvrRef GetServer(const string &service)
Map a service to a server.
static CNcbiApplication * Instance(void)
Singleton method.
static SSystemFastMutex & GetMutex(void)
vector< pythonpp::CCalable > m_LoggingFunctions
pythonpp::CTuple m_Logger
void Post(const SDiagMessage &mess) override
Post message to handler.
pythonpp::CModule m_LoggingModule
pythonpp::CObject m_LoggerClass
pythonpp::CDict m_LoggingDict
void SetLogger(pythonpp::CObject logger)
class CStaticArrayMap<> provides access to a static array in much the same way as CStaticArraySet<>,...
TBase::const_iterator const_iterator
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
virtual const IResultSetMetaData & GetMetaData(void) const
Get Metadata.
virtual bool Next(void)
Get next row.
CCachedResultSet(IResultSet &other)
virtual ~CCachedResultSet(void)
virtual const CVariant & GetVariant(const CDBParamVariant ¶m)
Retrieve a CVariant class describing the data stored in a given column.
deque< CVariant > TRecord
virtual unsigned int GetTotalColumns(void)
Get total columns.
const EDB_ResType m_ResType
virtual EDB_ResType GetResultType(void)
Get result type.
unique_ptr< const IResultSetMetaData > m_MetaData
deque< TRecord > TRecordSet
const unsigned int m_ColumsNum
CTransaction *const m_ParentTransaction
CCallableStmtHelper(CTransaction *trans)
int GetReturnStatus(void)
long GetRowCount(void) const
unique_ptr< ICallableStatement > m_Stmt
unique_ptr< CResultSetProxy > m_RSProxy
void SetStr(const CStmtStr &stmt, CDB_UserHandler *handler)
void SetParam(const string &name, const CVariant &value, bool &output_param)
void CreateStmt(CDB_UserHandler *handler)
CDB_UserHandler * m_UserHandler
~CCallableStmtHelper(void)
void FillDescription(pythonpp::CList &descr)
void Execute(bool cache_results=false)
CVariantSet & GetRS(void)
bool m_ResultStatusAvailable
CCPPToolkitConnParams m_Params
CTransaction * CreateTransaction(void)
void DestroyTransaction(CTransaction *trans)
EConnectionMode m_ConnectionMode
pythonpp::CObject __enter__(const pythonpp::CTuple &args)
CDBDefaultConnParams m_DefParams
pythonpp::CObject commit(const pythonpp::CTuple &args)
IConnection * MakeDBConnection(void) const
pythonpp::CObject close(const pythonpp::CTuple &args)
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)
pythonpp::CObject rollback(const pythonpp::CTuple &args)
CTransaction * m_DefTransaction
CTransaction & GetDefaultTransaction(void)
pythonpp::CObject cursor(const pythonpp::CTuple &args)
pythonpp::CObject transaction(const pythonpp::CTuple &args)
CCursorIter(CCursor *cursor)
pythonpp::CObject fetchmany(const pythonpp::CTuple &args)
Fetch the next set of rows of a query result, returning a sequence of sequences (e....
pythonpp::CList m_InfoMessages
pythonpp::CObject __enter__(const pythonpp::CTuple &args)
pythonpp::CList m_DescrList
void AddInfoMessage(const string &message)
pythonpp::CObject m_Description
pythonpp::CObject fetchall(const pythonpp::CTuple &args)
Fetch all (remaining) rows of a query result, returning them as a sequence of sequences (e....
CInfoHandler_CursorCollect m_InfoHandler
PyObject * CreateIter(void)
bool NextSetInternal(void)
CCursor(CTransaction *trans)
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...
pythonpp::CObject close(const pythonpp::CTuple &args)
Close the cursor now (rather than whenever __del__ is called).
pythonpp::CObject fetchone(const pythonpp::CTuple &args)
Fetch the next row of a query result set, returning a single sequence, or None when no more data is a...
pythonpp::CObject get_proc_return_status(const pythonpp::CTuple &args)
CCallableStmtHelper m_CallableStmtHelper
pythonpp::CObject execute(const pythonpp::CTuple &args, const pythonpp::CDict &kwargs)
Prepare and execute a database operation (query or command).
void SetupParameters(const pythonpp::CDict &dict, CStmtHelper &stmt)
pythonpp::CObject callproc(const pythonpp::CTuple &args)
Call a stored database procedure with the given name.
CVariant GetCVariant(const pythonpp::CObject &obj) const
pythonpp::CObject setoutputsize(const pythonpp::CTuple &args)
Set a column buffer size for fetches of large columns (e.g.
pythonpp::CObject executemany(const pythonpp::CTuple &args, const pythonpp::CDict &kwargs)
Prepare a database operation (query or command) and then execute it against all parameter sequences o...
CTransaction & GetTransaction(void)
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...
static void Declare(const char *name, PyMethodDef *methods)
static PyObject * m_Module
CDMLConnPool(CTransaction *trans, ETransType trans_type=eImplicitTrans)
void rollback(void) const
const ETransType m_TransType
IStatement & GetLocalStmt(void) const
unique_ptr< IStatement > m_LocalStmt
const CConnection & GetConnection(void) const
IConnection * Create(void)
void Destroy(IConnection *db_conn)
unique_ptr< IConnection > m_DMLConnection
void x_Init(const CDB_Exception &e, PyObject *err_type)
virtual bool HandleIt(CDB_Exception *ex)
Handle the exceptions resulting from a native API call, one-by-one.
TFormat GetDriverFmt(void) const
static const char * GetName(TFormat fmt)
TFormat GetUserFmt(void) const
CParamFmt(TFormat user_fmt=eTSQL, TFormat drv_fmt=eTSQL)
virtual unsigned int GetTotalColumns(void)
Get total columns.
virtual const CVariant & GetVariant(const CDBParamVariant ¶m)
Retrieve a CVariant class describing the data stored in a given column.
virtual EDB_ResType GetResultType(void)
Get result type.
CRealResultSet(IResultSet *other)
virtual bool Next(void)
Get next row.
virtual ~CRealResultSet(void)
virtual const IResultSetMetaData & GetMetaData(void) const
Get Metadata.
virtual bool MoveToLastRS(void)
virtual ~CRealSetProxy(void)
virtual bool HasRS(void) const
virtual CVariantSet & GetRS(void)
unique_ptr< CVariantSet > m_VariantSet
virtual bool MoveToNextRS(void)
CRealSetProxy(ICallableStatement &stmt)
ICallableStatement * m_Stmt
virtual void DumpResult(void)
const CConnection & GetConnection(void) const
TConnectionList m_ConnPool
void Destroy(IConnection *db_conn)
IConnection * Create(void)
CSelectConnPool(CTransaction *trans, size_t size=3)
TConnectionList m_ConnList
int GetReturnStatus(void)
void FillDescription(pythonpp::CList &descr)
CDB_UserHandler * m_UserHandler
void SetParam(const string &name, const CVariant &value)
unique_ptr< IResultSet > m_RS
CStmtHelper(CTransaction *trans)
void SetStr(const CStmtStr &stmt, CDB_UserHandler *handler)
long GetRowCount(void) const
CTransaction *const m_ParentTransaction
unique_ptr< IStatement > m_Stmt
void CreateStmt(CDB_UserHandler *handler)
bool m_ResultStatusAvailable
string::size_type find_named(const string &str, string::size_type offset, int ¶m_len)
EStatementType GetType(void) const
void SetStr(const string &str, EStatementType default_type=estSelect, const CParamFmt &fmt=CParamFmt(), ETriState output_expected=eTriState_Unknown)
string::size_type find_numeric(const string &str, string::size_type offset, int ¶m_len)
string::size_type find_TSQL(const string &str, string::size_type offset, int ¶m_len)
string GetStr(void) const
CDMLConnPool m_DMLConnPool
pythonpp::CObject __enter__(const pythonpp::CTuple &args)
void CloseOpenCursors(void)
IConnection * CreateSelectConnection(void)
pythonpp::CObject commit(const pythonpp::CTuple &args)
pythonpp::CObject rollback(const pythonpp::CTuple &args)
CTransaction(CConnection *conn, pythonpp::EOwnershipFuture ownnership=pythonpp::eOwned, EConnectionMode conn_mode=eSimpleMode)
const CConnection & GetParentConnection(void) const
IConnection * CreateDMLConnection(void)
void RollbackInternal(void) const
CSelectConnPool m_SelectConnPool
CCursor * CreateCursor(void)
pythonpp::CObject close(const pythonpp::CTuple &args)
void DestroyCursor(CCursor *cursor)
void DestroySelectConnection(IConnection *db_conn)
void CommitInternal(void) const
void DestroyDMLConnection(IConnection *db_conn)
const EConnectionMode m_ConnectionMode
pythonpp::CObject m_PythonConnection
pythonpp::CObject cursor(const pythonpp::CTuple &args)
virtual ~CVariantSetProxy(void)
virtual bool MoveToNextRS(void)
virtual bool MoveToLastRS(void)
CRef< CVariantSet > m_CurResultSet
CVariantSetProxy(ICallableStatement &stmt)
deque< CRef< CVariantSet > > TCachedSet
virtual bool HasRS(void) const
virtual CVariantSet & GetRS(void)
virtual void DumpResult(void)
virtual const IResultSetMetaData & GetMetaData(void) const =0
Get Metadata.
virtual EDB_ResType GetResultType(void)=0
Get result type.
virtual bool Next(void)=0
Get next row.
virtual const CVariant & GetVariant(const CDBParamVariant ¶m)=0
Retrieve a CVariant class describing the data stored in a given column.
virtual unsigned int GetTotalColumns(void)=0
Get total columns.
virtual ~CVariantSet(void)
Destructor.
void Cleanup(CVariant &value)
CWarning(const string &msg)
static bool HasSameType(PyObject *obj)
CObject Apply(void) const
Call.
static bool HasSameType(PyObject *obj)
int GetMicroSecond(void) const
int GetMinute(void) const
int GetSecond(void) const
static bool HasSameType(PyObject *obj)
void SetItem(const string &key, const CObject &obj)
CObject GetItem(const string &s) const