首先如何判断被调用者跟调用者使用的是同一数据库链接?
# query = "select sid from v$mystat where rownum=1" query = "select userenv('sid') from dual"
两种方法都可,可能其中有些方法有oracle版本要求。
在pro c主程序中使用sql exec connect to建立连接后,执行上述语句,打印出sid 值,然后在被调用的python子程序中,尝试引用主程序传入的数据库连接,然后再打印一次sid值,如果多次运行后两个sid值都相同,可以认为引用成功,若每次运行两个sid值都不同,则可认为是两个不同的连接,即引用未成功。
现在pro c 程序中,首先要取得一个值OCISvcCtx *svchp; 此值实际就是数据库的连接句柄。此值及稍后用到的函数在oracle头文件sql2oci.h中定义,然后使用函数:
rc = SQLSvcCtxGet(0, (text *)0, (sb4)0, (OCISvcCtx **) &svchp); if (rc) { vLog(LOG_ERROR, "获取sql句柄时出错,错误码[%d]",rc); TRACE_END(DO_FAIL); }
获取svchp,注意也有更简单的调用方法:
retcode=SQLSvcCtxGet(0,0,-1,&svchp); // get an OCI formatted service // context handle from the // primary connection if(retcode!=SQL_SUCCESS){ cerr<<"Failed to get the service context handle!!!"<<endl; return 1; }
也有更严谨的方法,此处不提。
此时,获得一个svchp指针,注意在64位编译环境下(RHEL 5.5 64位版默认编译器64位,等同于-m64选项)此指针值为8字节,需用一个long型8字节数保存。
然后就是将此值传入以嵌入方法调用的python子程序,此处有个问题,若是非嵌入方式调用,能否通过传入此数据连接的句柄,使进程外的另一进程使用此进程内的数据连接?没试过,等遇到再说吧。
简单的使用Py_BuildValue(“l”,svchp),将此句柄作为一个长整型数处理。传入子程序的testlong参数。
然后在cx_Oracle连接创建语句中:
# db=cx_Oracle.connect('bidb','bidb','BI155') db=cx_Oracle.connect('bidb','bidb','BI155',handle=testlong)
注意两者区别,仅在于是否使用了handle参数,事实上,将前几个参数省略掉可否?既已有句柄,不就拥有数据库操作所需的一切了?未测试过。或者connect会用前三个参数作些校验也未可知。
然后用本文开始处的方法,调用sql语句显示sid,分别用加handle和不加handle的connect方法,证实了handle参数确实起到了作用。
原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/419.html