mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-08-02 03:16:11 -04:00
Added sharedDatabaseInterface and oci implementation libraries
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
DbBindableVarray.cpp
|
||||
DbBindableVarray.h
|
||||
OciQueryImplementation.cpp
|
||||
OciQueryImplementation.h
|
||||
OciServer.cpp
|
||||
OciServer.h
|
||||
OciSession.cpp
|
||||
OciSession.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSynchronization/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
|
||||
)
|
||||
|
||||
add_library(sharedDatabaseInterface_oci STATIC
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
@@ -0,0 +1,591 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbBindableVarray.cpp
|
||||
// copyright (c) 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "DbBindableVarray.h"
|
||||
|
||||
#include "OciServer.h"
|
||||
#include "OciSession.h"
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include <oci.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
BindableVarray::BindableVarray() :
|
||||
m_initialized(false),
|
||||
m_tdo (NULL),
|
||||
m_data (NULL),
|
||||
m_session (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BindableVarray::~BindableVarray()
|
||||
{
|
||||
if (m_initialized)
|
||||
free();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarray::create(DB::Session *session, const std::string &name, const std::string &schema)
|
||||
{
|
||||
m_initialized = true;
|
||||
NOT_NULL(session);
|
||||
m_session = session;
|
||||
OCISession *localSession = safe_cast<OCISession*>(session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCITypeByName (localSession->envhp,
|
||||
localSession->errhp,
|
||||
localSession->svchp,
|
||||
reinterpret_cast<OraText*>(const_cast<char*>(schema.c_str())),
|
||||
schema.length(),
|
||||
reinterpret_cast<OraText*>(const_cast<char*>(name.c_str())),
|
||||
name.length(),
|
||||
NULL,
|
||||
0,
|
||||
OCI_DURATION_SESSION,
|
||||
OCI_TYPEGET_HEADER,
|
||||
&m_tdo))))
|
||||
return false;
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession,
|
||||
OCIObjectNew (localSession->envhp,
|
||||
localSession->errhp,
|
||||
localSession->svchp,
|
||||
OCI_TYPECODE_VARRAY,
|
||||
m_tdo, NULL,
|
||||
OCI_DURATION_DEFAULT,
|
||||
true,
|
||||
reinterpret_cast<void**>(&m_data)))))
|
||||
return false;
|
||||
|
||||
NOT_NULL(m_tdo);
|
||||
NOT_NULL(m_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BindableVarray::free()
|
||||
{
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
IGNORE_RETURN(localSession->m_server->checkerr(*localSession,
|
||||
OCIObjectFree (localSession->envhp,
|
||||
localSession->errhp, m_data, 0)));
|
||||
m_initialized = false;
|
||||
m_tdo=NULL;
|
||||
m_data=NULL;
|
||||
m_session=NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BindableVarray::clear()
|
||||
{
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
sb4 size=0;
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size))))
|
||||
return;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollTrim(localSession->envhp, localSession->errhp, size, m_data))))
|
||||
return;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
OCIArray** BindableVarray::getBuffer()
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
OCIType* BindableVarray::getTDO()
|
||||
{
|
||||
return m_tdo;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(int value)
|
||||
{
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator (OCI_IND_NOTNULL);
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(long int value)
|
||||
{
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator (OCI_IND_NOTNULL);
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(int64 value)
|
||||
{
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator (OCI_IND_NOTNULL);
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(double value)
|
||||
{
|
||||
if (finite(value)==0)
|
||||
{
|
||||
if (DB::Server::getFatalOnDataError())
|
||||
{
|
||||
FATAL(true,("DatabaseError: Attempt to save a non-finite value to the database."));
|
||||
}
|
||||
else
|
||||
{
|
||||
value=0;
|
||||
WARNING_STACK_DEPTH(true,(INT_MAX,"DatabaseError: Attempt to save a non-finite value to the database."));
|
||||
}
|
||||
}
|
||||
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator (OCI_IND_NOTNULL);
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromReal(localSession->errhp, &value, sizeof(value), &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(bool IsNULL, int value)
|
||||
{
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator;
|
||||
|
||||
if ( IsNULL )
|
||||
{
|
||||
buffer_indicator = OCI_IND_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_indicator = OCI_IND_NOTNULL;
|
||||
}
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(bool IsNULL, long int value)
|
||||
{
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator;
|
||||
|
||||
if ( IsNULL )
|
||||
{
|
||||
buffer_indicator = OCI_IND_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_indicator = OCI_IND_NOTNULL;
|
||||
}
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(bool IsNULL, int64 value)
|
||||
{
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator;
|
||||
|
||||
if ( IsNULL )
|
||||
{
|
||||
buffer_indicator = OCI_IND_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_indicator = OCI_IND_NOTNULL;
|
||||
}
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromInt(localSession->errhp, &value, sizeof(value), OCI_NUMBER_SIGNED, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayNumber::push_back(bool IsNULL, double value)
|
||||
{
|
||||
if (!IsNULL && finite(value)==0)
|
||||
{
|
||||
if (DB::Server::getFatalOnDataError())
|
||||
{
|
||||
FATAL(true,("DatabaseError: Attempt to save a non-finite value to the database."));
|
||||
}
|
||||
else
|
||||
{
|
||||
value=0;
|
||||
WARNING_STACK_DEPTH(true,(INT_MAX,"DatabaseError: Attempt to save a non-finite value to the database."));
|
||||
}
|
||||
}
|
||||
|
||||
OCINumber buffer;
|
||||
|
||||
OCIInd buffer_indicator;
|
||||
|
||||
if ( IsNULL )
|
||||
{
|
||||
buffer_indicator = OCI_IND_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_indicator = OCI_IND_NOTNULL;
|
||||
}
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCINumberFromReal(localSession->errhp, &value, sizeof(value), &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, &buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
BindableVarrayString::BindableVarrayString() :
|
||||
BindableVarray(),
|
||||
m_maxLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string BindableVarrayNumber::outputValue() const
|
||||
{
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
sb4 size;
|
||||
std::string result("[");
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size))))
|
||||
return "[*ERROR*]";
|
||||
|
||||
for (sb4 i=0; i < size; ++i)
|
||||
{
|
||||
OCINumber *element;
|
||||
OCIInd *indicator;
|
||||
boolean exists;
|
||||
|
||||
if (i!=0)
|
||||
result += ", ";
|
||||
|
||||
if (localSession->m_server->checkerr(*localSession, OCICollGetElem(localSession->envhp, localSession->errhp, m_data, i, &exists, reinterpret_cast<dvoid**>(&element), reinterpret_cast<dvoid**>(&indicator))))
|
||||
{
|
||||
if (exists)
|
||||
{
|
||||
if (*indicator == OCI_IND_NULL)
|
||||
result += "NULL";
|
||||
else
|
||||
{
|
||||
double value;
|
||||
if (localSession->m_server->checkerr(*localSession, OCINumberToReal(localSession->errhp, element, sizeof(value), &value)))
|
||||
{
|
||||
char buffer[100];
|
||||
snprintf(buffer,sizeof(buffer),"%f",value);
|
||||
buffer[sizeof(buffer)-1]='\0';
|
||||
result += buffer;
|
||||
}
|
||||
else
|
||||
result += "*ERROR*";
|
||||
}
|
||||
}
|
||||
else
|
||||
result += "*NO ELEMENT*";
|
||||
}
|
||||
else
|
||||
result += "*ERROR*";
|
||||
}
|
||||
result+=']';
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::create(DB::Session *session, const std::string &name, const std::string &schema, size_t maxLength)
|
||||
{
|
||||
m_maxLength=maxLength;
|
||||
return BindableVarray::create(session,name,schema);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(const Unicode::String &value)
|
||||
{
|
||||
std::string str;
|
||||
str = Unicode::wideToUTF8(value, str);
|
||||
return push_back(str);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(const std::string &value)
|
||||
{
|
||||
OCIString *buffer = NULL;
|
||||
OCIInd buffer_indicator (OCI_IND_NOTNULL);
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
size_t effectiveLength=value.length();
|
||||
if (effectiveLength > m_maxLength)
|
||||
{
|
||||
if (DB::Server::getFatalOnDataError())
|
||||
{
|
||||
FATAL(true,("DatabaseError: Attempt to save too long a string to the database: \"%s\"",value.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_STACK_DEPTH(true,(INT_MAX, "DatabaseError: Attempt to save too long a string to the database. (Text is in the log output.)"));
|
||||
LogManager::logLongText("DatabaseError",std::string("String from previous error is \"")+value+"\"");
|
||||
effectiveLength = m_maxLength;
|
||||
}
|
||||
}
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast<OraText*>(const_cast<char*>(value.c_str())), effectiveLength, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(bool bvalue)
|
||||
{
|
||||
std::string value;
|
||||
if (bvalue)
|
||||
value = "Y";
|
||||
else
|
||||
value = "N";
|
||||
|
||||
OCIString *buffer = NULL;
|
||||
OCIInd buffer_indicator (OCI_IND_NOTNULL);
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast<OraText*>(const_cast<char*>(value.c_str())), value.length(), &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(const NetworkId &value)
|
||||
{
|
||||
return push_back(value.getValueString());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(bool IsNULL, const Unicode::String &value)
|
||||
{
|
||||
std::string str;
|
||||
str = Unicode::wideToUTF8(value, str);
|
||||
return push_back(IsNULL, str);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(bool IsNULL, const std::string &value)
|
||||
{
|
||||
OCIString *buffer = NULL;
|
||||
OCIInd buffer_indicator;
|
||||
if ( IsNULL )
|
||||
{
|
||||
buffer_indicator = OCI_IND_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_indicator = OCI_IND_NOTNULL;
|
||||
}
|
||||
|
||||
size_t effectiveLength=value.length();
|
||||
if (effectiveLength > m_maxLength)
|
||||
{
|
||||
if (DB::Server::getFatalOnDataError())
|
||||
{
|
||||
FATAL(true,("DatabaseError: Attempt to save too long a string to the database: \"%s\"",value.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_STACK_DEPTH(true,(INT_MAX, "DatabaseError: Attempt to save too long a string to the database. (Text is in the log output.)"));
|
||||
LogManager::logLongText("DatabaseError",std::string("String from previous error is \"")+value+"\"");
|
||||
effectiveLength = m_maxLength;
|
||||
}
|
||||
}
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast<OraText*>(const_cast<char*>(value.c_str())), effectiveLength, &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(bool IsNULL, bool bvalue)
|
||||
{
|
||||
std::string value;
|
||||
if (bvalue)
|
||||
value = "Y";
|
||||
else
|
||||
value = "N";
|
||||
|
||||
OCIString *buffer = NULL;
|
||||
OCIInd buffer_indicator;
|
||||
if ( IsNULL )
|
||||
{
|
||||
buffer_indicator = OCI_IND_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_indicator = OCI_IND_NOTNULL;
|
||||
}
|
||||
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCIStringAssignText(localSession->envhp, localSession->errhp, reinterpret_cast<OraText*>(const_cast<char*>(value.c_str())), value.length(), &buffer))))
|
||||
return false;
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollAppend(localSession->envhp, localSession->errhp, buffer, &buffer_indicator, m_data))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool BindableVarrayString::push_back(bool IsNULL, const NetworkId &value)
|
||||
{
|
||||
return push_back(IsNULL, value.getValueString());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string BindableVarrayString::outputValue() const
|
||||
{
|
||||
OCISession *localSession = safe_cast<OCISession*>(m_session);
|
||||
sb4 size;
|
||||
std::string result("[");
|
||||
|
||||
if (! (localSession->m_server->checkerr(*localSession, OCICollSize(localSession->envhp, localSession->errhp, m_data, &size))))
|
||||
return "[*ERROR*]";
|
||||
|
||||
for (sb4 i=0; i < size; ++i)
|
||||
{
|
||||
OCIString **element;
|
||||
OCIInd *indicator;
|
||||
boolean exists;
|
||||
|
||||
if (i!=0)
|
||||
result += ", ";
|
||||
|
||||
if (localSession->m_server->checkerr(*localSession, OCICollGetElem(localSession->envhp, localSession->errhp, m_data, i, &exists, reinterpret_cast<dvoid**>(&element), reinterpret_cast<dvoid**>(&indicator))))
|
||||
{
|
||||
if (exists)
|
||||
{
|
||||
if (*indicator == OCI_IND_NULL)
|
||||
result += "NULL";
|
||||
else
|
||||
{
|
||||
OraText * text = OCIStringPtr(localSession->envhp, *element);
|
||||
if (text)
|
||||
result += '"' + std::string(reinterpret_cast<char*>(text)) + '"';
|
||||
else
|
||||
result += "NULL";
|
||||
}
|
||||
}
|
||||
else
|
||||
result += "*NO ELEMENT*";
|
||||
}
|
||||
else
|
||||
result += "*ERROR*";
|
||||
}
|
||||
result+=']';
|
||||
return result;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,101 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbBindableVarray.h
|
||||
// copyright (c) 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DbBindableVarray_H
|
||||
#define INCLUDED_DbBindableVarray_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/Bindable.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
struct OCIColl;
|
||||
typedef OCIColl OCIArray;
|
||||
struct OCIType;
|
||||
class NetworkId;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class Session;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* Bindable array type. Note: only usable in OCI. In ODBC, calling
|
||||
* any function on this class will FATAL.
|
||||
*/
|
||||
class BindableVarray : public Bindable
|
||||
{
|
||||
public:
|
||||
BindableVarray();
|
||||
~BindableVarray();
|
||||
|
||||
bool create(DB::Session *session, const std::string &name, const std::string &schema);
|
||||
|
||||
void free();
|
||||
void clear();
|
||||
|
||||
OCIArray ** getBuffer();
|
||||
OCIType * getTDO();
|
||||
|
||||
protected:
|
||||
bool m_initialized;
|
||||
OCIType *m_tdo;
|
||||
OCIArray *m_data;
|
||||
Session *m_session;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class BindableVarrayNumber : public BindableVarray
|
||||
{
|
||||
public:
|
||||
bool push_back(bool IsNULL, int value);
|
||||
bool push_back(bool IsNULL, double value);
|
||||
bool push_back(bool IsNULL, long int value);
|
||||
bool push_back(bool IsNULL, int64 value);
|
||||
bool push_back(int value);
|
||||
bool push_back(double value);
|
||||
bool push_back(long int value);
|
||||
bool push_back(int64 value);
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class BindableVarrayString : public BindableVarray
|
||||
{
|
||||
public:
|
||||
BindableVarrayString();
|
||||
bool create(DB::Session *session, const std::string &name, const std::string &schema, size_t maxLength);
|
||||
|
||||
bool push_back(bool IsNULL, const Unicode::String &value);
|
||||
bool push_back(bool IsNULL, const std::string &value);
|
||||
bool push_back(bool IsNULL, bool value);
|
||||
bool push_back(bool IsNULL, const NetworkId &value);
|
||||
bool push_back(const Unicode::String &value);
|
||||
bool push_back(const std::string &value);
|
||||
bool push_back(bool value);
|
||||
bool push_back(const NetworkId &value);
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
|
||||
private:
|
||||
size_t m_maxLength;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
} //namespace
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,753 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCIQueryImpl.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "OciQueryImplementation.h"
|
||||
|
||||
#include <oci.h>
|
||||
|
||||
#include "sharedDatabaseInterface/Bindable.h"
|
||||
#include "sharedDatabaseInterface/DbBindableVarray.h"
|
||||
#include "sharedDatabaseInterface/DbProtocol.def"
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
#include "OciServer.h"
|
||||
#include "OciSession.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DB::OCIQueryImpl::OCIQueryImpl(Query *query, bool autocommit) :
|
||||
QueryImpl(query), m_stmthp(0), m_cursorhp(0), m_procBind(0), m_session(0), m_server(0), m_inUse(false), numRowsFetched(0),
|
||||
nextColumn(1), nextParameter(1), m_endOfData(false), m_dataReady(false), m_autocommit(autocommit),
|
||||
m_skipSize(0),
|
||||
m_numElements(1),
|
||||
m_sql()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::OCIQueryImpl::~OCIQueryImpl()
|
||||
{
|
||||
if (m_stmthp)
|
||||
done();
|
||||
|
||||
for (BindRecListType::iterator i=bindRecList.begin(); i!=bindRecList.end(); ++i)
|
||||
{
|
||||
delete (*i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::setup(Session *session)
|
||||
{
|
||||
// setSession(session);
|
||||
|
||||
DEBUG_FATAL(m_session!=0,("m_session was not NULL"));
|
||||
DEBUG_FATAL(m_server!=0,("m_server was not NULL"));
|
||||
DEBUG_FATAL(m_stmthp!=0,("m_stmthp was not 0"));
|
||||
DEBUG_FATAL(m_cursorhp!=0,("m_cursorhp was not 0"));
|
||||
|
||||
m_session=dynamic_cast<DB::OCISession*>(session);
|
||||
FATAL((m_session==0),("Must pass a non-NULL OCISession to setup()."));
|
||||
|
||||
m_server=m_session->m_server;
|
||||
NOT_NULL(m_server);
|
||||
|
||||
if (!m_server->checkerr(*m_session, OCIHandleAlloc( m_session->envhp,
|
||||
reinterpret_cast<void**>(&m_stmthp),
|
||||
OCI_HTYPE_STMT, 0, 0)))
|
||||
return false;
|
||||
|
||||
|
||||
m_cursorhp=m_stmthp; // later on, we'll separate these two if needed
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::prepare()
|
||||
{
|
||||
NOT_NULL(m_server);
|
||||
NOT_NULL(m_stmthp);
|
||||
|
||||
m_query->getSQL(m_sql); // note: do not change m_sql until done() is called, because Oracle keeps a pointer to it
|
||||
DEBUG_FATAL(m_sql.size()==0,("Query did not set a SQL statement.\n"));
|
||||
|
||||
if (!m_server->checkerr(*m_session,
|
||||
OCIStmtPrepare(m_stmthp,
|
||||
m_session->errhp,
|
||||
reinterpret_cast<OraText*>(const_cast<char*>(m_sql.c_str())),
|
||||
strlen(m_sql.c_str()),
|
||||
(ub4) OCI_NTV_SYNTAX,
|
||||
(ub4) OCI_DEFAULT)))
|
||||
return false;
|
||||
if (m_query->getMode()==Query::MODE_PLSQL_REFCURSOR)
|
||||
{
|
||||
m_cursorhp=0; // may not be necessary -- OCI docs unclear
|
||||
if (!m_server->checkerr(*m_session, OCIHandleAlloc( m_session->envhp, (dvoid **) &m_cursorhp,
|
||||
OCI_HTYPE_STMT, 0, 0)))
|
||||
return false;
|
||||
|
||||
if (!m_server->checkerr(*m_session,
|
||||
OCIBindByPos (m_stmthp,
|
||||
&m_procBind,
|
||||
m_session->errhp,
|
||||
nextParameter++, // 1st parameter must be the cursor
|
||||
&m_cursorhp,
|
||||
0,
|
||||
SQLT_RSET,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DB::OCIQueryImpl::preprocessBinds()
|
||||
{
|
||||
//Preprocess binds & defines
|
||||
for (BindRecListType::iterator i=bindRecList.begin(); i!=bindRecList.end(); ++i)
|
||||
{
|
||||
if ((*i)->owner->isNull())
|
||||
(*i)->indicator=-1;
|
||||
else
|
||||
{
|
||||
(*i)->length=(unsigned short)*((*i)->owner->getIndicator()); //TODO: something better
|
||||
(*i)->indicator=1;
|
||||
if ((*i)->stringAdjust)
|
||||
++(*i)->length; //TODO: This feels like a hack
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::exec()
|
||||
{
|
||||
NOT_NULL(m_server);
|
||||
NOT_NULL(m_stmthp);
|
||||
|
||||
Query::QueryMode mode=m_query->getMode();
|
||||
FATAL((mode!=Query::MODE_SQL) && (mode!=Query::MODE_DML) && (mode!=Query::MODE_PROCEXEC) && (mode!=Query::MODE_PLSQL_REFCURSOR),
|
||||
("OCI query is in mode %i, not supported.\n",mode));
|
||||
|
||||
if (!m_inUse) // if the query was just run, we don't need to do the setup again
|
||||
{
|
||||
if (!prepare()) return false;
|
||||
if (!m_query->bindParameters()) return false;
|
||||
}
|
||||
|
||||
if (mode==Query::MODE_SQL)
|
||||
if (!m_query->bindColumns()) return false;
|
||||
|
||||
preprocessBinds();
|
||||
|
||||
if (m_server->isPrefetchEnabled())
|
||||
{
|
||||
int numRowsToPrefetch=m_server->getPrefetchRows();
|
||||
int prefetchMemory=m_server->getPrefetchMemory();
|
||||
if (!m_server->checkerr(*m_session, OCIAttrSet((dvoid *) m_stmthp, (ub4) OCI_HTYPE_STMT,
|
||||
&numRowsToPrefetch, sizeof(int),
|
||||
(ub4) OCI_ATTR_PREFETCH_ROWS, m_session->errhp)))
|
||||
{
|
||||
LOG("DatabaseError", ("Unable to set OCI_ATTR_PREFETCH_ROWS to %i", numRowsToPrefetch));
|
||||
return false;
|
||||
}
|
||||
if (!m_server->checkerr(*m_session, OCIAttrSet((dvoid *) m_stmthp, (ub4) OCI_HTYPE_STMT,
|
||||
&prefetchMemory, sizeof(int),
|
||||
(ub4) OCI_ATTR_PREFETCH_MEMORY, m_session->errhp)))
|
||||
{
|
||||
LOG("DatabaseError", ("Unable to set OCI_ATTR_PREFETCH_MEMORY to %i", prefetchMemory));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_session->setOkToFetch();
|
||||
m_session->setLastQueryStatement(m_sql);
|
||||
sword status=OCIStmtExecute(m_session->svchp, m_stmthp, m_session->errhp, 1, 0,
|
||||
NULL, NULL, OCI_DEFAULT);
|
||||
|
||||
if (status == OCI_NO_DATA)
|
||||
{
|
||||
if (mode==Query::MODE_PLSQL_REFCURSOR)
|
||||
{
|
||||
WARNING_STRICT_FATAL(!m_session->isOkToFetch(),("Calling fetch after commit, without an execute in between (may cause Oracle to crash)."));
|
||||
sword status=OCIStmtFetch (m_cursorhp, m_session->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
|
||||
if (!m_server->checkerr(*m_session,status))
|
||||
return false;
|
||||
}
|
||||
m_endOfData=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_server->checkerr(*m_session,status))
|
||||
{
|
||||
if (mode==Query::MODE_PLSQL_REFCURSOR)
|
||||
{
|
||||
if (!m_query->bindColumns()) return false;
|
||||
|
||||
m_dataReady=false; // in this mode, Oracle doesn't implicitly fetch a row
|
||||
m_endOfData=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
postProcessResults(); // in this mode, Oracle implicitly fetches the first row
|
||||
|
||||
m_endOfData=false;
|
||||
m_dataReady=true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
m_inUse=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int DB::OCIQueryImpl::fetch()
|
||||
{
|
||||
DEBUG_FATAL((m_query->getMode()!=Query::MODE_SQL) && (m_query->getMode()!=Query::MODE_PLSQL_REFCURSOR),
|
||||
("Called fetch() on a query not in a fetch-compatible mode."));
|
||||
|
||||
if (m_dataReady) // a row was already fetched implicitly by exec
|
||||
{
|
||||
m_dataReady = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m_endOfData) return 0;
|
||||
|
||||
WARNING_STRICT_FATAL(!m_session->isOkToFetch(),("Calling fetch after commit, without an execute in between (may cause Oracle to crash)."));
|
||||
sword status=OCIStmtFetch (m_cursorhp, m_session->errhp, m_numElements, OCI_FETCH_NEXT, OCI_DEFAULT);
|
||||
|
||||
if (status == OCI_NO_DATA)
|
||||
{
|
||||
ub4 rows;
|
||||
ub4 sizep = sizeof(ub4);
|
||||
OCIAttrGet((dvoid *) m_cursorhp, (ub4) OCI_HTYPE_STMT,
|
||||
(dvoid *)& rows, (ub4 *) &sizep, OCI_ATTR_ROWS_FETCHED, m_session->errhp);
|
||||
|
||||
sword status=OCIStmtFetch (m_cursorhp, m_session->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); // cancel the cursor
|
||||
if (!m_server->checkerr(*m_session,status))
|
||||
return -1;
|
||||
m_endOfData=true;
|
||||
if (rows!=0)
|
||||
{
|
||||
postProcessResults();
|
||||
return rows; // last batch of data
|
||||
}
|
||||
else
|
||||
return 0; // no more data
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_server->checkerr(*m_session,status))
|
||||
return -1;
|
||||
}
|
||||
|
||||
ub4 rows;
|
||||
ub4 sizep = sizeof(ub4);
|
||||
OCIAttrGet((dvoid *) m_cursorhp, (ub4) OCI_HTYPE_STMT,
|
||||
(dvoid *)& rows, (ub4 *) &sizep, OCI_ATTR_ROWS_FETCHED, m_session->errhp);
|
||||
|
||||
m_endOfData=false;
|
||||
postProcessResults();
|
||||
return rows;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
void DB::OCIQueryImpl::postProcessResults()
|
||||
{
|
||||
if (m_numElements == 1)
|
||||
{
|
||||
for (BindRecListType::iterator i=bindRecList.begin(); i!=bindRecList.end(); ++i)
|
||||
{
|
||||
if ((*i)->indicator==-1)
|
||||
(*i)->owner->setNull();
|
||||
else
|
||||
*((*i)->owner->getIndicator())=(*i)->length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (BindRecListType::iterator i=bindRecList.begin(); i!=bindRecList.end(); ++i)
|
||||
{
|
||||
if ((*i)->m_indicatorArray)
|
||||
{
|
||||
for (size_t j=0; j<m_numElements; ++j)
|
||||
{
|
||||
Bindable *owner = reinterpret_cast<Bindable*>(reinterpret_cast<char*>((*i)->owner) + m_skipSize * j); // if OCI can do something this ugly, so can I
|
||||
|
||||
if ((*i)->m_indicatorArray[j]==-1)
|
||||
owner->setNull();
|
||||
else
|
||||
*(owner->getIndicator())=(*i)->m_lengthArray[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this query involves bulk binds, but this parameter is not one of them. Treat it as a single bind.
|
||||
if ((*i)->indicator==-1)
|
||||
(*i)->owner->setNull();
|
||||
else
|
||||
*((*i)->owner->getIndicator())=(*i)->length;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DB::OCIQueryImpl::done()
|
||||
{
|
||||
NOT_NULL(m_stmthp);
|
||||
|
||||
if (m_autocommit)
|
||||
m_server->checkerr(*m_session, OCITransCommit(m_session->svchp, m_session->errhp, 0));
|
||||
|
||||
OCIHandleFree(m_stmthp, OCI_HTYPE_STMT);
|
||||
if (m_cursorhp!=m_stmthp)
|
||||
OCIHandleFree(m_cursorhp, OCI_HTYPE_STMT);
|
||||
|
||||
for (BindRecListType::iterator i=bindRecList.begin(); i!=bindRecList.end(); ++i)
|
||||
{
|
||||
delete (*i);
|
||||
}
|
||||
bindRecList.clear();
|
||||
|
||||
m_session=0;
|
||||
m_server=0;
|
||||
m_stmthp=0;
|
||||
m_cursorhp=0;
|
||||
nextColumn=1;
|
||||
nextParameter=1;
|
||||
m_endOfData=true;
|
||||
m_inUse=false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int DB::OCIQueryImpl::rowCount()
|
||||
{
|
||||
NOT_NULL(m_stmthp);
|
||||
|
||||
int value;
|
||||
|
||||
m_server->checkerr(*m_session, OCIAttrGet (m_cursorhp, OCI_HTYPE_STMT,&value,0,OCI_ATTR_ROW_COUNT,m_session->errhp));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::OCIQueryImpl::BindRec *DB::OCIQueryImpl::addBindRec(Bindable &owner)
|
||||
{
|
||||
BindRec *br=new BindRec(m_numElements);
|
||||
br->owner=&owner;
|
||||
bindRecList.push_back(br);
|
||||
return br;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::Protocol DB::OCIQueryImpl::getProtocol() const
|
||||
{
|
||||
return DB::PROTOCOL_OCI;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DB::OCIQueryImpl::setColArrayMode(size_t skipSize, size_t numElements)
|
||||
{
|
||||
m_skipSize = skipSize;
|
||||
m_numElements = numElements;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DB::OCIQueryImpl::BindRec::BindRec(size_t numElements) :
|
||||
defnp(0),
|
||||
bindp(0),
|
||||
indicator(-1),
|
||||
length(0),
|
||||
stringAdjust(false),
|
||||
m_numElements(numElements),
|
||||
m_indicatorArray(NULL),
|
||||
m_lengthArray(NULL)
|
||||
{
|
||||
// This is ugly, but it avoids having to create two different kinds of bindrecs that inherit from an abstract base class
|
||||
if (m_numElements > 1)
|
||||
{
|
||||
m_indicatorArray = new int16[m_numElements];
|
||||
m_lengthArray = new uint16[m_numElements];
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::OCIQueryImpl::BindRec::~BindRec()
|
||||
{
|
||||
delete[] m_indicatorArray;
|
||||
delete[] m_lengthArray;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int16 * DB::OCIQueryImpl::BindRec::getIndicatorPointer()
|
||||
{
|
||||
if (m_numElements > 1)
|
||||
return m_indicatorArray;
|
||||
else
|
||||
return &indicator;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
uint16 * DB::OCIQueryImpl::BindRec::getLengthPointer()
|
||||
{
|
||||
if (m_numElements > 1)
|
||||
return m_lengthArray;
|
||||
else
|
||||
return &length;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
size_t DB::OCIQueryImpl::BindRec::getIndicatorSkipSize()
|
||||
{
|
||||
return reinterpret_cast<char*>(&(m_indicatorArray[1])) - reinterpret_cast<char*>(&(m_indicatorArray[0]));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
size_t DB::OCIQueryImpl::BindRec::getLengthSkipSize()
|
||||
{
|
||||
return reinterpret_cast<char*>(&(m_lengthArray[1])) - reinterpret_cast<char*>(&(m_lengthArray[0]));
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
bool DB::OCIQueryImpl::bindCol(BindableLong &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp,
|
||||
&(br->defnp),
|
||||
m_session->errhp,
|
||||
nextColumn++,
|
||||
buffer.getBuffer(),
|
||||
sizeof(long),
|
||||
SQLT_INT,
|
||||
br->getIndicatorPointer(),
|
||||
br->getLengthPointer(),
|
||||
(ub2 *)0,
|
||||
OCI_DEFAULT));
|
||||
|
||||
if (m_numElements > 1)
|
||||
{
|
||||
m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp,
|
||||
m_session->errhp,
|
||||
m_skipSize,
|
||||
br->getIndicatorSkipSize(),
|
||||
br->getLengthSkipSize(),
|
||||
0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindParameter(BindableLong &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp,
|
||||
&(br->bindp),
|
||||
m_session->errhp,
|
||||
nextParameter++,
|
||||
buffer.getBuffer(),
|
||||
sizeof(long),
|
||||
SQLT_INT,
|
||||
&(br->indicator),
|
||||
&(br->length),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindCol(BindableStringBase &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp,
|
||||
&(br->defnp),
|
||||
m_session->errhp,
|
||||
nextColumn++,
|
||||
buffer.getBuffer(),
|
||||
buffer.getS()+1,
|
||||
SQLT_STR,
|
||||
br->getIndicatorPointer(),
|
||||
br->getLengthPointer(),
|
||||
(ub2 *)0,
|
||||
OCI_DEFAULT));
|
||||
|
||||
if (m_numElements > 1)
|
||||
{
|
||||
m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp,
|
||||
m_session->errhp,
|
||||
m_skipSize,
|
||||
br->getIndicatorSkipSize(),
|
||||
br->getLengthSkipSize(),
|
||||
0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindParameter(BindableStringBase &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
br->stringAdjust=true;
|
||||
return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp,
|
||||
&(br->bindp),
|
||||
m_session->errhp,
|
||||
nextParameter++,
|
||||
buffer.getBuffer(),
|
||||
buffer.getS()+1,
|
||||
SQLT_STR,
|
||||
&(br->indicator),
|
||||
&(br->length),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindCol(BindableUnicodeBase &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp,
|
||||
&(br->defnp),
|
||||
m_session->errhp,
|
||||
nextColumn++,
|
||||
buffer.getBuffer(),
|
||||
buffer.getS()+1,
|
||||
SQLT_STR,
|
||||
br->getIndicatorPointer(),
|
||||
br->getLengthPointer(),
|
||||
(ub2 *)0,
|
||||
OCI_DEFAULT));
|
||||
|
||||
if (m_numElements > 1)
|
||||
{
|
||||
m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp,
|
||||
m_session->errhp,
|
||||
m_skipSize,
|
||||
br->getIndicatorSkipSize(),
|
||||
br->getLengthSkipSize(),
|
||||
0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindParameter(BindableUnicodeBase &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
br->stringAdjust=true;
|
||||
br->length=static_cast<uint16>(*(buffer.getIndicator()));
|
||||
return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp,
|
||||
&(br->bindp),
|
||||
m_session->errhp,
|
||||
nextParameter++,
|
||||
buffer.getBuffer(),
|
||||
buffer.getS()+1,
|
||||
SQLT_STR,
|
||||
&(br->indicator),
|
||||
&(br->length),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT));
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
bool DB::OCIQueryImpl::bindCol(BindableDouble &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp,
|
||||
&(br->defnp),
|
||||
m_session->errhp,
|
||||
nextColumn++,
|
||||
buffer.getBuffer(),
|
||||
sizeof(double),
|
||||
SQLT_FLT,
|
||||
br->getIndicatorPointer(),
|
||||
br->getLengthPointer(),
|
||||
(ub2 *)0,
|
||||
OCI_DEFAULT));
|
||||
if (m_numElements > 1)
|
||||
{
|
||||
m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp,
|
||||
m_session->errhp,
|
||||
m_skipSize,
|
||||
br->getIndicatorSkipSize(),
|
||||
br->getLengthSkipSize(),
|
||||
0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindParameter(BindableDouble &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp,
|
||||
&(br->bindp),
|
||||
m_session->errhp,
|
||||
nextParameter++,
|
||||
buffer.getBuffer(),
|
||||
sizeof(double),
|
||||
SQLT_FLT,
|
||||
&(br->indicator),
|
||||
&(br->length),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindCol(BindableBool &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
m_server->checkerr(*m_session, OCIDefineByPos(m_cursorhp,
|
||||
&(br->defnp),
|
||||
m_session->errhp,
|
||||
nextColumn++,
|
||||
buffer.getBuffer(),
|
||||
2,
|
||||
SQLT_STR,
|
||||
br->getIndicatorPointer(),
|
||||
br->getLengthPointer(),
|
||||
(ub2 *)0,
|
||||
OCI_DEFAULT));
|
||||
|
||||
if (m_numElements > 1)
|
||||
{
|
||||
m_server->checkerr(*m_session, OCIDefineArrayOfStruct(br->defnp,
|
||||
m_session->errhp,
|
||||
m_skipSize,
|
||||
br->getIndicatorSkipSize(),
|
||||
br->getLengthSkipSize(),
|
||||
0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindParameter(BindableBool &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
br->stringAdjust=true;
|
||||
return m_server->checkerr(*m_session, OCIBindByPos (m_stmthp,
|
||||
&(br->bindp),
|
||||
m_session->errhp,
|
||||
nextParameter++,
|
||||
buffer.getBuffer(),
|
||||
2,
|
||||
SQLT_STR,
|
||||
&(br->indicator),
|
||||
&(br->length),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIQueryImpl::bindParameter(BindableVarray &buffer)
|
||||
{
|
||||
BindRec *br=addBindRec(buffer);
|
||||
|
||||
bool result = m_server->checkerr(*m_session, OCIBindByPos (m_stmthp,
|
||||
&(br->bindp),
|
||||
m_session->errhp,
|
||||
nextParameter++,
|
||||
NULL,
|
||||
0,
|
||||
SQLT_NTY,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OCI_DEFAULT));
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
return m_server->checkerr(*m_session, OCIBindObject (br->bindp,
|
||||
m_session->errhp,
|
||||
buffer.getTDO(),
|
||||
reinterpret_cast<void**>(buffer.getBuffer()),
|
||||
0,
|
||||
0,
|
||||
0));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string DB::OCIQueryImpl::outputDataValues() const
|
||||
{
|
||||
std::string results;
|
||||
for (BindRecListType::const_iterator i=bindRecList.begin(); i!=bindRecList.end(); ++i)
|
||||
{
|
||||
if (i!=bindRecList.begin())
|
||||
results += ", ";
|
||||
results += (*i)->owner->outputValue();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,133 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCIQueryImpl.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_OCIQueryImpl_H
|
||||
#define INCLUDED_OCIQueryImpl_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbQueryImplementation.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class BindableVarray;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
struct OCIStmt;
|
||||
struct OCIDefine;
|
||||
struct OCIBind;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class Bindable;
|
||||
class OCISession;
|
||||
class OCIServer;
|
||||
|
||||
class OCIQueryImpl : public QueryImpl
|
||||
{
|
||||
public:
|
||||
OCIQueryImpl(Query *query, bool autocommit);
|
||||
virtual ~OCIQueryImpl();
|
||||
|
||||
virtual bool setup(Session *session);
|
||||
virtual bool prepare();
|
||||
virtual int fetch();
|
||||
virtual void done();
|
||||
virtual int rowCount();
|
||||
virtual bool exec();
|
||||
|
||||
virtual Protocol getProtocol() const;
|
||||
|
||||
virtual void setColArrayMode(size_t skipSize, size_t numElements);
|
||||
|
||||
virtual bool bindCol(BindableLong &buffer);
|
||||
virtual bool bindParameter(BindableLong &buffer);
|
||||
virtual bool bindCol(BindableDouble &buffer);
|
||||
virtual bool bindParameter(BindableDouble &buffer);
|
||||
virtual bool bindCol(BindableStringBase &buffer);
|
||||
virtual bool bindParameter(BindableStringBase &buffer);
|
||||
virtual bool bindCol(BindableUnicodeBase &buffer);
|
||||
virtual bool bindParameter(BindableUnicodeBase &buffer);
|
||||
virtual bool bindCol(BindableBool &buffer);
|
||||
virtual bool bindParameter(BindableBool &buffer);
|
||||
virtual bool bindParameter(BindableVarray &buffer);
|
||||
|
||||
std::string outputDataValues() const;
|
||||
|
||||
protected:
|
||||
struct BindRec
|
||||
{
|
||||
BindRec(size_t numElements);
|
||||
~BindRec();
|
||||
|
||||
int16 * getIndicatorPointer();
|
||||
uint16 * getLengthPointer();
|
||||
|
||||
size_t getIndicatorSkipSize();
|
||||
size_t getLengthSkipSize();
|
||||
|
||||
Bindable *owner;
|
||||
OCIDefine *defnp;
|
||||
OCIBind *bindp;
|
||||
int16 indicator;
|
||||
uint16 length;
|
||||
bool stringAdjust;
|
||||
size_t m_numElements;
|
||||
int16 *m_indicatorArray;
|
||||
uint16 *m_lengthArray;
|
||||
};
|
||||
|
||||
typedef std::list<BindRec*> BindRecListType;
|
||||
|
||||
protected:
|
||||
|
||||
BindRec *addBindRec(Bindable &owner);
|
||||
void preprocessBinds();
|
||||
void postProcessResults();
|
||||
|
||||
protected:
|
||||
/** The OCIStmt handle representing the query.
|
||||
*/
|
||||
::OCIStmt *m_stmthp;
|
||||
/** The handle representing the cursor containing the results of the query. Usually,
|
||||
* this is set to the same as stmthp.
|
||||
*/
|
||||
::OCIStmt *m_cursorhp;
|
||||
::OCIBind *m_procBind;
|
||||
|
||||
DB::OCISession *m_session;
|
||||
DB::OCIServer *m_server;
|
||||
|
||||
bool m_inUse;
|
||||
int numRowsFetched;
|
||||
int nextColumn;
|
||||
int nextParameter;
|
||||
bool m_endOfData;
|
||||
bool m_dataReady;
|
||||
BindRecListType bindRecList;
|
||||
bool m_autocommit;
|
||||
size_t m_skipSize;
|
||||
size_t m_numElements;
|
||||
|
||||
std::string m_sql;
|
||||
|
||||
private:
|
||||
OCIQueryImpl(const OCIQueryImpl&);
|
||||
OCIQueryImpl & operator = (const OCIQueryImpl &);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCIServer.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "OciServer.h"
|
||||
|
||||
#include "OciSession.h"
|
||||
#include "sharedDatabaseInterface/DbException.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
#include <oci.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DB::OCIServer::OCIServer(const char *_dsn, const char *_uid, const char *_pwd, bool useMemoryManager) :
|
||||
DB::Server(_dsn,_uid,_pwd, useMemoryManager)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Server destructor
|
||||
DB::OCIServer::~OCIServer()
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::Session *DB::OCIServer::createSession()
|
||||
{
|
||||
return new DB::OCISession(this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool DB::OCIServer::checkerr(OCISession const & session, int status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case OCI_SUCCESS:
|
||||
return true;
|
||||
case OCI_SUCCESS_WITH_INFO:
|
||||
REPORT_LOG(true,("Error - OCI_SUCCESS_WITH_INFO\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error."));
|
||||
return false;
|
||||
case OCI_NEED_DATA:
|
||||
REPORT_LOG(true,("Error - OCI_NEED_DATA\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error."));
|
||||
return false;
|
||||
case OCI_NO_DATA:
|
||||
REPORT_LOG(true,("Error - OCI_NODATA\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error."));
|
||||
return false;
|
||||
case OCI_ERROR:
|
||||
{
|
||||
text errbuf[512];
|
||||
sb4 errcode = 0;
|
||||
|
||||
OCIErrorGet((dvoid *)(session.errhp), (ub4) 1, (text *) NULL, &errcode,
|
||||
errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
|
||||
|
||||
WARNING(true,("Database error: %.*s",512,errbuf));
|
||||
LOG("DatabaseError",("Database error: %.*s",512,errbuf));
|
||||
FATAL(DB::Server::getFatalOnError() || session.getFatalOnError(),("Database error: %.*s",512,errbuf));
|
||||
|
||||
return false;
|
||||
|
||||
/*
|
||||
switch (errcode)
|
||||
{
|
||||
case 1013:
|
||||
FATAL(true,("Cancelled by user request (ctrl-c or kill signal).\n"));
|
||||
break;
|
||||
|
||||
case 12541:
|
||||
REPORT_LOG(true,("Database Error - %.*s\n", 512, errbuf));
|
||||
return false;
|
||||
|
||||
default:
|
||||
FATAL(true,("Unhandled Database Error - %.*s\n", 512, errbuf));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
case OCI_INVALID_HANDLE:
|
||||
REPORT_LOG(true,("Error - OCI_INVALID_HANDLE\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error - OCI_INVALID_HANDLE"));
|
||||
return false;
|
||||
case OCI_STILL_EXECUTING:
|
||||
REPORT_LOG(true,("Error - OCI_STILL_EXECUTE\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error."));
|
||||
return false;
|
||||
case OCI_CONTINUE:
|
||||
REPORT_LOG(true,("Error - OCI_CONTINUE\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error."));
|
||||
return false;
|
||||
default:
|
||||
REPORT_LOG(true,("Error - unrecognized OCI error state\n"));
|
||||
LOG("DatabaseError", ("Unhandled database error."));
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,53 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCIServer.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_OCIServer_H
|
||||
#define INCLUDED_OCIServer_H
|
||||
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
struct OCIEnv;
|
||||
struct OCIError;
|
||||
struct OCIServer;
|
||||
struct OCISvcCtx;
|
||||
|
||||
namespace DB {
|
||||
class OCISession;
|
||||
|
||||
class OCIServer : public Server
|
||||
{
|
||||
public:
|
||||
|
||||
OCIServer(const char *_dsn, const char *_uid, const char *_pwd, bool useMemoryManager);
|
||||
virtual ~OCIServer();
|
||||
|
||||
virtual Session *createSession();
|
||||
|
||||
/** Check the results from an ODBC call to identify whether the call succeeded. Returns TRUE if everything is OK, i.e.
|
||||
the call returned SQL_SUCCESS, or it returned SQL_SUCCESS_WITH_INFO and the additional information does not indicate
|
||||
a problem.
|
||||
*/
|
||||
// static bool checkError(int rc, SQLSMALLINT handleType, SQLHANDLE handle);
|
||||
|
||||
static bool checkerr(OCISession const & session, int status);
|
||||
|
||||
private:
|
||||
|
||||
// OCI requires sharing so many handles at different levels that it's easiest to just make everybody friends.
|
||||
friend class OCISession;
|
||||
friend class OCIQueryImpl;
|
||||
OCIServer(const OCIServer &);
|
||||
OCIServer & operator = (const OCIServer &);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,289 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCISession.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "OciSession.h"
|
||||
|
||||
#include "OciQueryImplementation.h"
|
||||
#include "OciServer.h"
|
||||
#include "sharedDatabaseInterface/DbException.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedSynchronization/RecursiveMutex.h"
|
||||
|
||||
#include <oci.h>
|
||||
#include <time.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace OCISessionNamespace
|
||||
{
|
||||
RecursiveMutex connectLock;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace DB::OCISessionNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
static dvoid *mallocHook(dvoid *, size_t size)
|
||||
{
|
||||
return reinterpret_cast<dvoid *>(new char[size]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static dvoid *reallocHook(dvoid *, dvoid *memptr, size_t newsize)
|
||||
{
|
||||
return reinterpret_cast<dvoid *>(MemoryManager::reallocate(memptr, newsize));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static void freeHook(dvoid *, dvoid *memptr)
|
||||
{
|
||||
if (memptr)
|
||||
delete [] reinterpret_cast<char *>(memptr);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DB::OCISession::OCISession(DB::OCIServer *server) :
|
||||
m_server(server),
|
||||
envhp(NULL),
|
||||
errhp(NULL),
|
||||
srvhp(NULL),
|
||||
sesp(NULL),
|
||||
svchp(NULL),
|
||||
autoCommitMode(true),
|
||||
m_resetTime(server->getReconnectTime()==0 ? 0 : time(0) + server->getReconnectTime()),
|
||||
m_okToFetch(true)
|
||||
{
|
||||
}
|
||||
|
||||
DB::OCISession::~OCISession()
|
||||
{
|
||||
if (connected)
|
||||
disconnect();
|
||||
}
|
||||
|
||||
bool DB::OCISession::connect()
|
||||
{
|
||||
connectLock.enter();
|
||||
|
||||
// Create OCI environment. We're creating one environment per session,
|
||||
// so that each session can be used by a different thread concurrently.
|
||||
|
||||
sword result=OCI_ERROR;
|
||||
if (m_server->getUseMemoryManager())
|
||||
{
|
||||
result = OCIEnvCreate(&envhp, // OCIEnv **envhpp,
|
||||
OCI_THREADED | OCI_OBJECT, //ub4 mode, //TODO: do we have to use threaded mode?
|
||||
0, // CONST dvoid *ctxp,
|
||||
&mallocHook, // CONST dvoid *(*malocfp)
|
||||
// (dvoid *ctxp,
|
||||
// size_t size),
|
||||
&reallocHook, // CONST dvoid *(*ralocfp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr,
|
||||
// size_t newsize),
|
||||
&freeHook, // CONST void (*mfreefp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr))
|
||||
0, //size_t xtramemsz,
|
||||
0 ); //dvoid **usrmempp );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = OCIEnvCreate(&envhp, // OCIEnv **envhpp,
|
||||
OCI_THREADED | OCI_OBJECT, //ub4 mode, //TODO: do we have to use threaded mode?
|
||||
0, // CONST dvoid *ctxp,
|
||||
0, // CONST dvoid *(*malocfp)
|
||||
// (dvoid *ctxp,
|
||||
// size_t size),
|
||||
0, // CONST dvoid *(*ralocfp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr,
|
||||
// size_t newsize),
|
||||
0, // CONST void (*mfreefp)
|
||||
// (dvoid *ctxp,
|
||||
// dvoid *memptr))
|
||||
0, //size_t xtramemsz,
|
||||
0 ); //dvoid **usrmempp );
|
||||
|
||||
}
|
||||
FATAL(result != OCI_SUCCESS,("OciEnvCreate failed with error code %hd",result));
|
||||
|
||||
// Create error handle.
|
||||
OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR,
|
||||
(size_t) 0, (dvoid **) 0);
|
||||
|
||||
// Create handle to the server and establish connection
|
||||
OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER,
|
||||
(size_t) 0, (dvoid **) 0);
|
||||
|
||||
int retryCount = 0;
|
||||
connected = false;
|
||||
while (!connected && retryCount < 5)
|
||||
{
|
||||
LOG("DatabaseConnect", ("calling OCIServerAttach() for OCISession=[%p] with dsn=[%s], uid=[%s], pwd=[%s]", this, m_server->getDSN(), m_server->uid, m_server->pwd));
|
||||
|
||||
connected = DB::OCIServer::checkerr(*this,
|
||||
OCIServerAttach( srvhp, errhp, reinterpret_cast<OraText*>(const_cast<char*>(m_server->getDSN())), strlen(m_server->getDSN()), 0));
|
||||
|
||||
if (! connected)
|
||||
{
|
||||
++retryCount;
|
||||
DEBUG_REPORT_LOG(retryCount<5,("Retrying database connection\n"));
|
||||
Os::sleep(1000);
|
||||
}
|
||||
}
|
||||
if (!connected)
|
||||
{
|
||||
LOG("DatabaseError", ("Database error, Failed to connect to database after 5 tries"));
|
||||
disconnect(); // cleanup
|
||||
connectLock.leave();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a session, set userid & password
|
||||
OCIHandleAlloc(envhp, (void**) &sesp,
|
||||
(ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0);
|
||||
|
||||
OCIAttrSet((dvoid *) sesp, (ub4) OCI_HTYPE_SESSION,
|
||||
(dvoid *) m_server->uid, strlen(m_server->uid),
|
||||
(ub4) OCI_ATTR_USERNAME, errhp);
|
||||
|
||||
OCIAttrSet((dvoid *) sesp, (ub4) OCI_HTYPE_SESSION,
|
||||
(dvoid *) m_server->pwd, strlen(m_server->pwd),
|
||||
(ub4) OCI_ATTR_PASSWORD, errhp);
|
||||
|
||||
// create service context (Wtf is a service context? Don't know, but you gotta have one.)
|
||||
OCIHandleAlloc( envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX,
|
||||
(size_t) 0, (dvoid **) 0);
|
||||
|
||||
// Service context has pointers to Server and Session
|
||||
OCIAttrSet( (dvoid *) svchp, OCI_HTYPE_SVCCTX, srvhp,
|
||||
(ub4) 0, OCI_ATTR_SERVER, errhp);
|
||||
|
||||
OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX,
|
||||
(dvoid *) sesp, (ub4) 0,
|
||||
(ub4) OCI_ATTR_SESSION, errhp);
|
||||
|
||||
// Establish session (i.e. check password)
|
||||
if (DB::OCIServer::checkerr(*this, OCISessionBegin ( svchp, errhp, sesp, OCI_CRED_RDBMS, (ub4) OCI_DEFAULT)))
|
||||
{
|
||||
connected=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(); // cleanup
|
||||
connected=false;
|
||||
}
|
||||
|
||||
connectLock.leave();
|
||||
return connected;
|
||||
}
|
||||
|
||||
bool DB::OCISession::disconnect()
|
||||
{
|
||||
connectLock.enter();
|
||||
|
||||
bool success = true;
|
||||
|
||||
connected=false;
|
||||
|
||||
if (srvhp && errhp && !DB::OCIServer::checkerr(*this,OCIServerDetach( srvhp, errhp, OCI_DEFAULT)))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIDetach returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (svchp && (OCIHandleFree(svchp,OCI_HTYPE_SVCCTX) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_SVCCTX returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (sesp && (OCIHandleFree(sesp,OCI_HTYPE_SESSION) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_SESSION returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (srvhp && (OCIHandleFree(srvhp,OCI_HTYPE_SERVER) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_SERVER returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (errhp && (OCIHandleFree(errhp,OCI_HTYPE_ERROR) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_ERROR returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (envhp && (OCIHandleFree(envhp,OCI_HTYPE_ENV) != OCI_SUCCESS))
|
||||
{
|
||||
LOG("DatabaseError", ("OCIHandleFree OCI_HTYPE_ENV returned an error."));
|
||||
success = false;
|
||||
}
|
||||
|
||||
svchp = NULL;
|
||||
sesp = NULL;
|
||||
srvhp = NULL;
|
||||
errhp = NULL;
|
||||
envhp = NULL;
|
||||
|
||||
connectLock.leave();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool DB::OCISession::setAutoCommitMode(bool autocommit)
|
||||
{
|
||||
autoCommitMode=autocommit;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DB::OCISession::commitTransaction()
|
||||
{
|
||||
m_okToFetch = false;
|
||||
return m_server->checkerr(*this, OCITransCommit(svchp, errhp, 0));
|
||||
}
|
||||
|
||||
bool DB::OCISession::rollbackTransaction()
|
||||
{
|
||||
return m_server->checkerr(*this, OCITransRollback(svchp, errhp, 0));
|
||||
}
|
||||
|
||||
bool DB::OCISession::reset()
|
||||
{
|
||||
autoCommitMode = true;
|
||||
if (m_resetTime !=0 && time(0) > m_resetTime)
|
||||
{
|
||||
LOG("Reconnections",("Reconnecting"));
|
||||
commitTransaction(); // just to be safe -- there shouldn't be an oustanding transaction now anyway
|
||||
disconnect();
|
||||
connect();
|
||||
m_resetTime = time(0) + m_server->getReconnectTime();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DB::QueryImpl *DB::OCISession::createQueryImpl(Query *owner) const
|
||||
{
|
||||
return new DB::OCIQueryImpl(owner, autoCommitMode);
|
||||
}
|
||||
|
||||
void DB::OCISession::setOkToFetch()
|
||||
{
|
||||
m_okToFetch = true;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,76 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// OCISession.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_OCISession_H
|
||||
#define INCLUDED_OCISession_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbSession.h"
|
||||
|
||||
struct OCIEnv;
|
||||
struct OCIError;
|
||||
struct OCIServer;
|
||||
struct OCISession;
|
||||
struct OCISvcCtx;
|
||||
|
||||
namespace DB {
|
||||
class OCIServer; // not to be confused with ::OCIServer
|
||||
|
||||
class OCISession : public Session
|
||||
{
|
||||
OCIServer *m_server;
|
||||
|
||||
::OCIEnv *envhp;
|
||||
::OCIError *errhp;
|
||||
::OCIServer *srvhp;
|
||||
::OCISession *sesp;
|
||||
::OCISvcCtx *svchp;
|
||||
|
||||
bool autoCommitMode;
|
||||
time_t m_resetTime;
|
||||
bool m_okToFetch;
|
||||
|
||||
// following are disallowed:
|
||||
OCISession(const OCISession& rhs);
|
||||
OCISession &operator=(const OCISession& rhs);
|
||||
|
||||
public:
|
||||
OCISession(OCIServer *server);
|
||||
virtual ~OCISession();
|
||||
|
||||
virtual bool connect();
|
||||
virtual bool disconnect();
|
||||
virtual bool reset();
|
||||
virtual bool setAutoCommitMode(bool autocommit);
|
||||
virtual bool commitTransaction();
|
||||
virtual bool rollbackTransaction();
|
||||
virtual QueryImpl *createQueryImpl(Query *owner) const;
|
||||
void setOkToFetch();
|
||||
bool isOkToFetch() const;
|
||||
|
||||
// OCI requires sharing so many handles at different levels that it's easiest to just make everybody friends.
|
||||
friend class OCIQueryImpl;
|
||||
friend class OCIServer;
|
||||
friend class BindableVarray;
|
||||
friend class BindableVarrayNumber;
|
||||
friend class BindableVarrayString;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline bool DB::OCISession::isOkToFetch() const
|
||||
{
|
||||
return m_okToFetch;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user