Hello,
I am trying to create a migratable session. Having exhaustively reviewed what is available on the subject, this is the code I came up with, which doesn't work:
#include <oci.h>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <stdexcept>
#include <vector>
#include <iostream>
void check(sword status, OCIError* errh)
{
switch (status) {
case OCI_SUCCESS:
break;
case OCI_INVALID_HANDLE:
throw std::logic_error("invalid handle\n");
case OCI_ERROR:
{
sb4 code;
std::vector<OraText> buf(OCI_ERROR_MAXMSG_SIZE);
std::string txt;
switch (const sword s = OCIErrorGet(errh, 1, 0, &code, &buf[0], buf.size() * sizeof (OraText), OCI_HTYPE_ERROR)) {
case OCI_SUCCESS:
if (!std::uncaught_exception())
throw std::runtime_error(reinterpret_cast<const char*>(&buf[0]));
std::clog << reinterpret_cast<const char*>(&buf[0]) << std::endl;
break;
default:
std::clog << "OCIErrorGet: status " << s << std::endl;
}
}
default:
std::clog << "check: status " << status << std::endl;
}
}
int main()
try {
std::clog << "creating environment..." << std::endl;
OCIEnv* envh;
if (OCIEnvCreate(&envh, OCI_DEFAULT, 0, 0, 0, 0, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to create environment\n");
std::clog << "allocating OCIError..." << std::endl;
OCIError* errh;
if (OCIHandleAlloc(envh, (void**)&errh, OCI_HTYPE_ERROR, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate OCIError\n");
std::clog << "allocating OCIServer..." << std::endl;
OCIServer* srvh;
if (OCIHandleAlloc(envh, (void**)&srvh, OCI_HTYPE_SERVER, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate server\n");
std::clog << "attaching server..." << std::endl;
check(OCIServerAttach(srvh, errh, (const OraText*)"server", std::strlen("server"), OCI_DEFAULT), errh);
std::clog << "allocating OCISvcCtx..." << std::endl;
OCISvcCtx* svch;
if (OCIHandleAlloc(envh, (void**)&svch, OCI_HTYPE_SVCCTX, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate context\n");
std::clog << "allocating OCISession..." << std::endl;
OCISession* sesh;
if (OCIHandleAlloc(envh, (void**)&sesh, OCI_HTYPE_SESSION, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate session\n");
check(OCIAttrSet(sesh, OCI_HTYPE_SESSION, (void*)"user_name", std::strlen("user_name"), OCI_ATTR_USERNAME, errh), errh);
check(OCIAttrSet(sesh, OCI_HTYPE_SESSION, (void*)"password", std::strlen("password"), OCI_ATTR_PASSWORD, errh), errh);
check(OCIAttrSet(svch, OCI_HTYPE_SVCCTX, srvh, 0, OCI_ATTR_SERVER, errh), errh);
std::clog << "starting session..." << std::endl;
check(OCISessionBegin(svch, errh, sesh, OCI_CRED_RDBMS, OCI_DEFAULT), errh);
check(OCIAttrSet(svch, OCI_HTYPE_SVCCTX, sesh, 0, OCI_ATTR_SESSION, errh), errh);
std::clog << "session started" << std::endl;
std::clog << "reading session ID..." << std::endl;
ub1* ses_id;
ub4 sz;
check(OCIAttrGet(sesh, OCI_HTYPE_SESSION, &ses_id, &sz, OCI_ATTR_MIGSESSION, errh), errh);
{
std::clog << "allocating new OCISvcCtx..." << std::endl;
OCISvcCtx* svch;
if (OCIHandleAlloc(envh, (void**)&svch, OCI_HTYPE_SVCCTX, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate new context\n");
std::clog << "allocating new OCISession..." << std::endl;
OCISession* sesh;
if (OCIHandleAlloc(envh, (void**)&sesh, OCI_HTYPE_SESSION, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate new session\n");
check(OCIAttrSet(sesh, OCI_HTYPE_SESSION, ses_id, sz, OCI_ATTR_MIGSESSION, errh), errh);
std::clog << "allocating new OCIServer..." << std::endl;
OCIServer* srvh;
if (OCIHandleAlloc(envh, (void**)&srvh, OCI_HTYPE_SERVER, 0, 0) == OCI_INVALID_HANDLE)
throw std::runtime_error("failed to allocate new server\n");
std::clog << "attaching new server..." << std::endl;
check(OCIServerAttach(srvh, errh, (const OraText*)"server", std::strlen("server"), OCI_DEFAULT), errh);
check(OCIAttrSet(svch, OCI_HTYPE_SVCCTX, srvh, 0, OCI_ATTR_SERVER, errh), errh);
std::clog << "starting new session..." << std::endl;
check(OCISessionBegin(svch, errh, sesh, OCI_CRED_EXT, OCI_MIGRATE), errh);
std::clog << "new session started" << std::endl;
}
}
catch (const std::exception& e) {
std::clog << e.what() << std::flush;
}
This is output:
creating environment...
allocating OCIError...
allocating OCIServer...
attaching server...
allocating OCISvcCtx...
allocating OCISession...
starting session...
session started
reading session ID...
allocating new OCISvcCtx...
allocating new OCISession...
allocating new OCIServer...
attaching new server...
starting new session...
ORA-24313: user already authenticated
Any example of code that would work?
Thank you.
Kind regards,
Paul