mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
Added sharedDatabaseInterface and oci implementation libraries
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
add_subdirectory(sharedCollision)
|
||||
add_subdirectory(sharedCommandParser)
|
||||
add_subdirectory(sharedCompression)
|
||||
add_subdirectory(sharedDatabaseInterface)
|
||||
add_subdirectory(sharedDebug)
|
||||
add_subdirectory(sharedFile)
|
||||
add_subdirectory(sharedFoundation)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(sharedDatabaseInterface)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(src_oci)
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/Bindable.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/BindableImplementation.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/BindableNetworkId.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/BufferString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBatchQuery.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableBase.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableBitArray.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableBool.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableDouble.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableInt64.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableLong.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBindableUnicode.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src_oci/DbBindableVarray.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbBufferRow.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbException.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/logger/DbLogEvent.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/logger/DbLogger.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbModeQuery.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbProfiler.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbProtocol.def"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbQuery.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbQueryImplementation.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbRow.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbServer.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/DbSession.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/queue/DbTaskQueue.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/queue/DbTaskRequest.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/logger/DbTaskSaveLog.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/queue/DbTestQuery.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/FirstSharedDatabaseInterface.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/NullEncodedStandardString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/core/NullEncodedUnicodeString.h"
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#if defined(PLATFORM_WIN32)
|
||||
#include "../../src/win32/SQLC_Defs.h"
|
||||
#elif defined(PLATFORM_LINUX)
|
||||
#include "../../src/linux/SQLC_Defs.h"
|
||||
#else
|
||||
#error unsupported platform
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
shared/core/Bindable.cpp
|
||||
shared/core/Bindable.h
|
||||
shared/core/BindableImplementation.h
|
||||
shared/core/BindableNetworkId.cpp
|
||||
shared/core/BindableNetworkId.h
|
||||
shared/core/BufferString.cpp
|
||||
shared/core/BufferString.h
|
||||
shared/core/DbBatchQuery.h
|
||||
shared/core/DbBindableBase.cpp
|
||||
shared/core/DbBindableBase.h
|
||||
shared/core/DbBindableBitArray.cpp
|
||||
shared/core/DbBindableBitArray.h
|
||||
shared/core/DbBindableBool.cpp
|
||||
shared/core/DbBindableBool.h
|
||||
shared/core/DbBindableDouble.cpp
|
||||
shared/core/DbBindableDouble.h
|
||||
shared/core/DbBindableInt64.cpp
|
||||
shared/core/DbBindableInt64.h
|
||||
shared/core/DbBindableLong.cpp
|
||||
shared/core/DbBindableLong.h
|
||||
shared/core/DbBindableString.cpp
|
||||
shared/core/DbBindableString.h
|
||||
shared/core/DbBindableUnicode.cpp
|
||||
shared/core/DbBindableUnicode.h
|
||||
shared/core/DbBufferRow.cpp
|
||||
shared/core/DbBufferRow.h
|
||||
shared/core/DbException.cpp
|
||||
shared/core/DbException.h
|
||||
shared/core/DbModeQuery.cpp
|
||||
shared/core/DbModeQuery.h
|
||||
shared/core/DbProfiler.cpp
|
||||
shared/core/DbProfiler.h
|
||||
shared/core/DbProtocol.def
|
||||
shared/core/DbQuery.cpp
|
||||
shared/core/DbQuery.h
|
||||
shared/core/DbQueryImplementation.h
|
||||
shared/core/DbRow.cpp
|
||||
shared/core/DbRow.h
|
||||
shared/core/DbServer.cpp
|
||||
shared/core/DbServer.h
|
||||
shared/core/DbSession.cpp
|
||||
shared/core/DbSession.h
|
||||
shared/core/FirstSharedDatabaseInterface.h
|
||||
shared/core/NullEncodedUnicodeString.cpp
|
||||
shared/core/NullEncodedUnicodeString.h
|
||||
shared/core/NullEncodedStandardString.cpp
|
||||
shared/core/NullEncodedStandardString.h
|
||||
|
||||
shared/logger/DbLogEvent.cpp
|
||||
shared/logger/DbLogEvent.h
|
||||
shared/logger/DbLogger.cpp
|
||||
shared/logger/DbLogger.h
|
||||
shared/logger/DbTaskSaveLog.cpp
|
||||
shared/logger/DbTaskSaveLog.h
|
||||
|
||||
shared/queue/DbTaskQueue.cpp
|
||||
shared/queue/DbTaskQueue.h
|
||||
shared/queue/DbTestQuery.cpp
|
||||
shared/queue/DbTestQuery.h
|
||||
shared/queue/DbTaskRequest.cpp
|
||||
shared/queue/DbTaskRequest.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/FirstSharedDatabaseInterface.cpp
|
||||
win32/SQLC_Defs.h
|
||||
)
|
||||
else()
|
||||
set(PLATFORM_SOURCES
|
||||
linux/SQLC_Defs.h
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shared
|
||||
${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_ENGINE_SOURCE_DIR}/shared/library/sharedThread/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
|
||||
)
|
||||
|
||||
add_library(sharedDatabaseInterface STATIC
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SQLC_Defs.h
|
||||
*
|
||||
* This file includes common definitions needed by the other SQLClasses header files.
|
||||
* (Don't include this file directly -- files that require it will include it.)
|
||||
*
|
||||
* Note that this file is specific to each OS, because what header files are
|
||||
* needed varies in each OS. In particular, Unix versions don't want windows.h.
|
||||
*
|
||||
* ODBC versions: includes definitions of ODBC datatypes needed by the various
|
||||
* SQLClasses
|
||||
*/
|
||||
|
||||
#ifndef _SQLC_DEFS_H
|
||||
#define _SQLC_DEFS_H
|
||||
|
||||
#include <sqltypes.h>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Bindable.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/Bindable.h"
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Bindable.h
|
||||
*
|
||||
* Defines classes based on built-in simple types that know how to bind themselves to
|
||||
* database queries and support null values.
|
||||
*
|
||||
* Each class supports the following functions:
|
||||
* bool isNull -- test whether the value is null
|
||||
* void setToNull -- set the value to null
|
||||
* getValue -- return the value (make sure you test for null before calling this. The results
|
||||
* are undefined if the Bindable is null.)
|
||||
* setValue -- set the value
|
||||
*
|
||||
* ODBC version
|
||||
*
|
||||
* Including this header brings in all the bindable types.
|
||||
*/
|
||||
|
||||
#ifndef _BINDABLE_H
|
||||
#define _BINDABLE_H
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
#include "sharedDatabaseInterface/DbBindableBitArray.h"
|
||||
#include "sharedDatabaseInterface/DbBindableBool.h"
|
||||
#include "sharedDatabaseInterface/DbBindableDouble.h"
|
||||
#include "sharedDatabaseInterface/DbBindableInt64.h"
|
||||
#include "sharedDatabaseInterface/DbBindableLong.h"
|
||||
#include "sharedDatabaseInterface/DbBindableString.h"
|
||||
#include "sharedDatabaseInterface/DbBindableUnicode.h"
|
||||
|
||||
#endif
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// BindableImpl.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_BindableImpl_H
|
||||
#define INCLUDED_BindableImpl_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class Bindable;
|
||||
|
||||
class BindableImpl
|
||||
{
|
||||
public:
|
||||
BindableImpl(Bindable *owner);
|
||||
virtual ~BindableImpl();
|
||||
|
||||
virtual bool isNull() const =0;
|
||||
virtual void setNull() =0;
|
||||
|
||||
protected:
|
||||
Bindable *m_owner;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// BindableNetworkId.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/BindableNetworkId.h"
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
BindableNetworkId::BindableNetworkId()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BindableNetworkId::BindableNetworkId (const NetworkId &rhs) : BindableInt64(rhs.getValue())
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BindableNetworkId::setValue(const NetworkId &buffer)
|
||||
{
|
||||
BindableInt64::setValue(buffer.getValue());
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,75 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// BindableNetworkId.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_BindableNetworkId_H
|
||||
#define INCLUDED_BindableNetworkId_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableInt64.h"
|
||||
#include "sharedFoundation/NetworkId.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* A Bindable type for an object Id.
|
||||
* This class is intended to provide a layer between NetworkId and
|
||||
* the database type, so that if the implementation of NetworkId is
|
||||
* changed, only this class and the database schema need to be changed.
|
||||
*
|
||||
* Also, this class allows the code for persisting NetworkId's to follow
|
||||
* the same form as the code persisting other types.
|
||||
*/
|
||||
class BindableNetworkId:public BindableInt64
|
||||
{
|
||||
public:
|
||||
BindableNetworkId (const NetworkId &rhs);
|
||||
BindableNetworkId();
|
||||
|
||||
BindableNetworkId &operator=(const NetworkId &rhs);
|
||||
|
||||
void getValue(NetworkId &buffer) const;
|
||||
NetworkId getValue() const;
|
||||
|
||||
void setValue(const NetworkId &buffer);
|
||||
};
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline DB::BindableNetworkId &DB::BindableNetworkId::operator=(const NetworkId &rhs)
|
||||
{
|
||||
BindableInt64::setValue(rhs.getValue());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableNetworkId::getValue(NetworkId &buffer) const
|
||||
{
|
||||
if (isNull())
|
||||
buffer.m_value = NetworkId::cms_invalid.getValue();
|
||||
else
|
||||
buffer.m_value = BindableInt64::getValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline NetworkId DB::BindableNetworkId::getValue() const
|
||||
{
|
||||
if (isNull())
|
||||
return NetworkId::cms_invalid;
|
||||
else
|
||||
return NetworkId(BindableInt64::getValue());
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,157 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// BufferString.cpp
|
||||
// copyright (c) 2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/BufferString.h"
|
||||
|
||||
#include "UnicodeUtils.h"
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
#include "sharedDatabaseInterface/NullEncodedStandardString.h"
|
||||
#include "sharedDatabaseInterface/NullEncodedUnicodeString.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
BufferString::BufferString(size_t maxSize) :
|
||||
Bindable(),
|
||||
m_value(),
|
||||
m_maxSize(maxSize)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BufferString::getValue(std::string & value) const
|
||||
{
|
||||
if (isNull())
|
||||
value.clear();
|
||||
else
|
||||
value=m_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BufferString::getValue(Unicode::String & value) const
|
||||
{
|
||||
if (isNull())
|
||||
value.clear();
|
||||
else
|
||||
value=Unicode::utf8ToWide(m_value);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Unicode::String BufferString::getValue() const
|
||||
{
|
||||
static const Unicode::String empty;
|
||||
|
||||
if (isNull())
|
||||
return empty;
|
||||
else
|
||||
return Unicode::utf8ToWide(m_value);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BufferString & BufferString::operator=(const std::string & value)
|
||||
{
|
||||
setValue(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BufferString & BufferString::operator=(const Unicode::String & value)
|
||||
{
|
||||
setValue(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BufferString::setValue(const std::string & value)
|
||||
{
|
||||
if (value.size() > m_maxSize)
|
||||
{
|
||||
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+"\"");
|
||||
m_value=std::string(value,0,m_maxSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_value=value;
|
||||
|
||||
indicator=m_value.size();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BufferString::setValue(const Unicode::String & value)
|
||||
{
|
||||
setValue(Unicode::wideToUTF8(value));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const std::string & BufferString::getValueASCII() const
|
||||
{
|
||||
static const std::string empty;
|
||||
|
||||
if (isNull())
|
||||
return empty;
|
||||
else
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BufferString & BufferString::operator=(const NullEncodedUnicodeString & value)
|
||||
{
|
||||
return operator=(value.getValueEncoded());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BufferString::getValue(NullEncodedUnicodeString & value) const
|
||||
{
|
||||
Unicode::String temp;
|
||||
getValue(temp);
|
||||
value.setValueEncoded(temp);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BufferString & BufferString::operator=(const NullEncodedStandardString & value)
|
||||
{
|
||||
return operator=(value.getValueEncoded());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BufferString::getValue(NullEncodedStandardString & value) const
|
||||
{
|
||||
std::string temp;
|
||||
getValue(temp);
|
||||
value.setValueEncoded(temp);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string BufferString::outputValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,80 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbBufferString.h
|
||||
// copyright (c) 2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DbBufferString_H
|
||||
#define INCLUDED_DbBufferString_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
#include "sharedDatabaseInterface/DbBindableString.h"
|
||||
#include "sharedDatabaseInterface/DbBindableUnicode.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class NullEncodedUnicodeString;
|
||||
class NullEncodedStandardString;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
/**
|
||||
* A nullable string class similar to DB::BindableString, but uses std::string
|
||||
* internally. Unlike DB::BindableString, it does not allocate the maximum
|
||||
* size for the buffer if the data is shorter. This class will save memory
|
||||
* over DB::BindableString if used in a buffer that stores a lot of rows.
|
||||
* However, it cannot be bound directly in a query. It must be copied
|
||||
* to a varray or a DB::BindableString first.
|
||||
*/
|
||||
class BufferString : public Bindable
|
||||
{
|
||||
public:
|
||||
BufferString(size_t maxSize);
|
||||
template<int S>
|
||||
BufferString(const BindableString<S> & rhs)
|
||||
{
|
||||
rhs.getValue(m_value);
|
||||
indicator=m_value.size();
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BufferString(const BindableUnicode<S> & rhs)
|
||||
{
|
||||
m_value = Unicode::wideToUTF8(rhs.getValue());
|
||||
indicator=m_value.size();
|
||||
}
|
||||
|
||||
public:
|
||||
void getValue(std::string & value) const;
|
||||
void getValue(Unicode::String & value) const;
|
||||
void getValue(NullEncodedUnicodeString & value) const;
|
||||
void getValue(NullEncodedStandardString & value) const;
|
||||
Unicode::String getValue() const;
|
||||
const std::string & getValueASCII() const;
|
||||
BufferString & operator=(const std::string & value);
|
||||
BufferString & operator=(const Unicode::String & value);
|
||||
BufferString & operator=(const NullEncodedUnicodeString & value);
|
||||
BufferString & operator=(const NullEncodedStandardString & value);
|
||||
void setValue(const std::string & value);
|
||||
void setValue(const Unicode::String & value);
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
size_t m_maxSize;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
} // namespace
|
||||
|
||||
// ======================================================================
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
/* DBBatchQuery.h
|
||||
*
|
||||
* Templates for defining batch queries (queries that return multiple
|
||||
* rows, read from the database in batches). See SQLClasses
|
||||
* documentation for more details.
|
||||
*
|
||||
* ODBC version
|
||||
*/
|
||||
|
||||
#ifndef _DBBATCHQUERY_H
|
||||
#define _DBBATCHQUERY_H
|
||||
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
|
||||
namespace DB {
|
||||
|
||||
/** Template representing a Query that returns an array of data
|
||||
|
||||
The template parameter R represent the structure that holds the data of one
|
||||
row of the results. BatchQuery will contain an array of R's. (R will
|
||||
usually be a struct holding a few Bindable types.)
|
||||
*/
|
||||
template <class R>
|
||||
class BatchQuery : public Query
|
||||
{
|
||||
R *data;
|
||||
SQLUSMALLINT *rowStatus;
|
||||
int numRows;
|
||||
|
||||
public:
|
||||
BatchQuery(int _numRows);
|
||||
~BatchQuery();
|
||||
|
||||
bool bind();
|
||||
|
||||
const R &operator[](int index) const;
|
||||
R &operator[](int index);
|
||||
|
||||
/** Count how many rows in the array were filled in by the last call to
|
||||
Fetch().
|
||||
*/
|
||||
int getNumDefinedRows() const;
|
||||
|
||||
/** Is a particular row in the result array defined? A row is defined if the
|
||||
database filled it in with values. If a row is not defined, the values
|
||||
returned for that row by operator[] are not meaningful.
|
||||
*/
|
||||
bool isRowDefined(int index) const;
|
||||
|
||||
/** Returns the SQL string for the query. The user must define this function; the
|
||||
template does not create it.
|
||||
*/
|
||||
char *getSQL();
|
||||
|
||||
/** Bind the first row of data. The user must define this function; the template
|
||||
does not create it.
|
||||
|
||||
Implement this function as if it is binding the first element of the array
|
||||
(the array is called data). The template will take care of binding the rest of
|
||||
the array. It should contain something like
|
||||
|
||||
data[0].member.BindCol(1,this)
|
||||
*/
|
||||
bool bindFirstRow();
|
||||
};
|
||||
|
||||
template <class R>
|
||||
BatchQuery<R>::BatchQuery(int _numRows) : numRows(_numRows)
|
||||
{
|
||||
data = new R[numRows];
|
||||
rowStatus = new SQLUSMALLINT[numRows];
|
||||
}
|
||||
|
||||
template <class R>
|
||||
BatchQuery<R>::~BatchQuery()
|
||||
{
|
||||
delete[] data;
|
||||
delete[] rowStatus;
|
||||
}
|
||||
|
||||
template <class R>
|
||||
const R &BatchQuery<R>::operator[](int index) const
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
template <class R>
|
||||
R &BatchQuery<R>::operator[](int index)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
template <class R>
|
||||
int BatchQuery<R>::getNumDefinedRows() const
|
||||
// TODO: hmmm, might be better to figure this once and store it
|
||||
// in a mutable variable -- but how to know when it changes
|
||||
// without overriding Fetch()?
|
||||
{
|
||||
for (int num=numRows;num>0;--num)
|
||||
{
|
||||
if (isRowDefined(num))
|
||||
return num+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class R>
|
||||
bool BatchQuery<R>::isRowDefined(int index) const
|
||||
{
|
||||
return (rowStatus[index]==0);
|
||||
}
|
||||
|
||||
template <class R>
|
||||
bool BatchQuery<R>::bind()
|
||||
{
|
||||
if (!setArrayMode(sizeof(data[0]),numRows,rowStatus))
|
||||
return false;
|
||||
return bindFirstRow();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableBase.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Bindable::Bindable() : indicator(-1)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Bindable::~Bindable()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Bindable::Bindable(int _indicator) :
|
||||
indicator(_indicator)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Bindable::isNull() const
|
||||
{
|
||||
return (indicator==-1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Bindable::setNull()
|
||||
{
|
||||
indicator=-1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int *Bindable::getIndicator()
|
||||
{
|
||||
return &indicator; //lint !e1536 // Exposing private member. This is done because various functions in the DB interfaces want to set the indicator directly.
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,43 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableBase.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableBase_H
|
||||
#define INCLUDED_DBBindableBase_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
class Bindable
|
||||
{
|
||||
public:
|
||||
Bindable();
|
||||
//Bindable(const Bindable &rhs); // auto-generated version is fine
|
||||
//Bindable &operator=(const Bindable &rhs);
|
||||
virtual ~Bindable();
|
||||
|
||||
bool isNull() const;
|
||||
void setNull();
|
||||
|
||||
int *getIndicator(); //TODO: enforce that only QueryImpl uses this
|
||||
|
||||
virtual std::string outputValue() const = 0; // For debugging or reporting errors, output the value(s) stored in this Bindable object
|
||||
|
||||
protected:
|
||||
explicit Bindable(int _indicator);
|
||||
|
||||
/**
|
||||
* The size of the data, or -1 for NULL.
|
||||
*/
|
||||
int indicator;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbBindableBitArray.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableBitArray.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,114 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableBitArray.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableBitArray_H
|
||||
#define INCLUDED_DBBindableBitArray_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableString.h"
|
||||
#include "sharedFoundation/BitArray.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
/**
|
||||
* Bindable BitArray class
|
||||
*
|
||||
* Template parameter S is the maximum size of the BitArray
|
||||
* The BitArray will be stored in the database using (S+3)/4 chars
|
||||
* Each char is a hex value for 4 bits from the BitArray
|
||||
*/
|
||||
template<int S>
|
||||
class BindableBitArray : public BindableString<int((S+3)>>2)>
|
||||
{
|
||||
public:
|
||||
BindableBitArray();
|
||||
explicit BindableBitArray(const BitArray &bitArray);
|
||||
|
||||
void setValue(const BitArray &bitArray);
|
||||
BindableBitArray &operator=(const BitArray &bitArray);
|
||||
|
||||
void getValue(BitArray &bitArray) const;
|
||||
BitArray getValue() const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<int S>
|
||||
BindableBitArray<S>::BindableBitArray()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<int S>
|
||||
BindableBitArray<S>::BindableBitArray(const BitArray &bitArray)
|
||||
{
|
||||
setValue(bitArray);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<int S>
|
||||
void BindableBitArray<S>::setValue(const BitArray &bitArray)
|
||||
{
|
||||
std::string buf;
|
||||
bitArray.getAsDbTextString(buf, int((S+3)>>2));
|
||||
|
||||
// if no bits are set in the BitArray, we must
|
||||
// put a character into buf, because BindableString
|
||||
// won't save an empty string; empty string means
|
||||
// don't overwrite current value in DB
|
||||
if (buf.empty())
|
||||
buf.push_back('0');
|
||||
|
||||
BindableString<int((S+3)>>2)>::setValue(buf);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<int S>
|
||||
BindableBitArray<S> &BindableBitArray<S>::operator=(const BitArray &bitArray)
|
||||
{
|
||||
setValue(bitArray);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<int S>
|
||||
void BindableBitArray<S>::getValue(BitArray &bitArray) const
|
||||
{
|
||||
bitArray=getValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<int S>
|
||||
BitArray BindableBitArray<S>::getValue() const
|
||||
{
|
||||
// Each char in the string is a hex value from 0-F
|
||||
char buf[((S+3)>>2) + 1];
|
||||
BindableString<int((S+3)>>2)>::getValue(buf,((S+3)>>2));
|
||||
BitArray temp;
|
||||
|
||||
// indicator is the number of chars read from the database
|
||||
if (indicator > 0)
|
||||
{
|
||||
buf[indicator] = 0;
|
||||
temp.setFromDbTextString(buf);
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
} // end namespace DB
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableBool.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableBool.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
BindableBool::BindableBool() : Bindable()
|
||||
{
|
||||
value[1]='\0';
|
||||
}
|
||||
|
||||
BindableBool::BindableBool(bool _value) :
|
||||
Bindable(1)
|
||||
{
|
||||
value[0]=_value?'Y':'N';
|
||||
value[1]='\0';
|
||||
}
|
||||
|
||||
|
||||
std::string BindableBool::getValueASCII() const
|
||||
{
|
||||
if (isNull())
|
||||
{
|
||||
return std::string(); // TODO should this be defaulted to N
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::string(1,value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
bool BindableBool::getValue() const
|
||||
{
|
||||
return (value[0]=='Y');
|
||||
}
|
||||
|
||||
void BindableBool::setValue(bool _value)
|
||||
{
|
||||
indicator=1;
|
||||
value[0]=_value?'Y':'N';
|
||||
}
|
||||
|
||||
BindableBool &BindableBool::operator=(bool _value)
|
||||
{
|
||||
setValue(_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void *BindableBool::getBuffer()
|
||||
{
|
||||
return value; //lint !e1536 // exposing private member (because DB interface will set it directly)
|
||||
}
|
||||
|
||||
std::string BindableBool::outputValue() const
|
||||
{
|
||||
if (getValue())
|
||||
return std::string("true");
|
||||
else
|
||||
return std::string("false");
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,58 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableBool.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableBool_H
|
||||
#define INCLUDED_DBBindableBool_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
/** Represents a bool in C++, bound to a CHAR(1) column. The column can have the values 'Y' or 'N'.
|
||||
* TODO: use a boolean type in the database, if we can find one that allows NULL's and is fairly
|
||||
* portable. (May not exist -- according to the docs, Oracle does not have a boolean datatype.)
|
||||
*/
|
||||
class BindableBool : public Bindable
|
||||
{
|
||||
char value[2];
|
||||
public:
|
||||
explicit BindableBool(bool _value);
|
||||
BindableBool();
|
||||
|
||||
std::string getValueASCII() const;
|
||||
bool getValue() const;
|
||||
void getValue(bool &buffer) const;
|
||||
void setValue(bool _value);
|
||||
BindableBool &operator=(bool _value);
|
||||
|
||||
void *getBuffer();
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
}; //lint !e1721 !e1509 // no virtual destructor, unusual operator =
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* There are places where it's more convenient to have a getValue() that
|
||||
* takes a reference, for consistancy with more complicated types.
|
||||
*/
|
||||
inline void DB::BindableBool::getValue(bool &buffer) const
|
||||
{
|
||||
buffer=getValue();
|
||||
}
|
||||
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableDouble.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableDouble.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
BindableDouble::BindableDouble() : Bindable(), value(-999.0)
|
||||
{
|
||||
}
|
||||
|
||||
BindableDouble::BindableDouble(const double &_value) :
|
||||
Bindable(sizeof(value)),
|
||||
value(_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."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double BindableDouble::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void BindableDouble::setValue(const double &_value)
|
||||
{
|
||||
indicator=sizeof(value);
|
||||
value=_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."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BindableDouble &BindableDouble::operator=(const double &_value)
|
||||
{
|
||||
setValue(_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void *BindableDouble::getBuffer()
|
||||
{
|
||||
return &value; //lint !e1536 // exposing private member (because DB interface will set it directly)
|
||||
}
|
||||
|
||||
std::string BindableDouble::outputValue() const
|
||||
{
|
||||
char temp[255];
|
||||
snprintf(temp,sizeof(temp),"%f",value);
|
||||
temp[sizeof(temp)-1]='\0';
|
||||
return std::string(temp);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,61 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableDouble.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableDouble_H
|
||||
#define INCLUDED_DBBindableDouble_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
/**
|
||||
* Represents a double in C++, bound to a FLOAT(nn) or a NUMBER database column
|
||||
* TODO: make variations of this for different precisions (when it is determined what precisions we need)
|
||||
*/
|
||||
class BindableDouble : public Bindable
|
||||
{
|
||||
double value;
|
||||
public:
|
||||
explicit BindableDouble(const double &_value);
|
||||
BindableDouble();
|
||||
|
||||
double getValue() const;
|
||||
void setValue(const double &_value);
|
||||
BindableDouble &operator=(const double &_value);
|
||||
|
||||
void getValue(double &buffer) const;
|
||||
void getValue(real &buffer) const;
|
||||
|
||||
void *getBuffer();
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
|
||||
}; //lint !e1721 !e1509 // no virtual destructor, unusual operator =
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableDouble::getValue(double &buffer) const
|
||||
{
|
||||
buffer=getValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableDouble::getValue(real &buffer) const
|
||||
{
|
||||
buffer=static_cast<real>(getValue());
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableInt64.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableInt64.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
BindableInt64::BindableInt64()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BindableInt64::BindableInt64(int64 value)
|
||||
{
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int64 BindableInt64::getValue() const
|
||||
{
|
||||
int64 temp;
|
||||
char buffer[BindableInt64BufferSize+1];
|
||||
BindableString<BindableInt64BufferSize>::getValue(buffer,BindableInt64BufferSize+1);
|
||||
sscanf(buffer,INT64_FORMAT_SPECIFIER,&temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BindableInt64 &BindableInt64::operator=(int64 rhs)
|
||||
{
|
||||
setValue(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BindableInt64::setValue(int64 rhs)
|
||||
{
|
||||
char buffer[BindableInt64BufferSize+1];
|
||||
sprintf(buffer,INT64_FORMAT_SPECIFIER,rhs);
|
||||
BindableString<BindableInt64BufferSize>::setValue(buffer);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,56 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableInt64.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableInt64_H
|
||||
#define INCLUDED_DBBindableInt64_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableString.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#define BindableInt64BufferSize 21 // big enough to hold -(2^63)
|
||||
|
||||
namespace DB {
|
||||
|
||||
/**
|
||||
* Represents an int64 in C++
|
||||
*/
|
||||
class BindableInt64 : public BindableString<BindableInt64BufferSize>
|
||||
{
|
||||
public:
|
||||
BindableInt64();
|
||||
explicit BindableInt64(int64 value);
|
||||
|
||||
int64 getValue() const;
|
||||
void setValue(const int64 rhs);
|
||||
BindableInt64 &operator=(const int64 rhs);
|
||||
|
||||
void getValue(int64 &buffer) const;
|
||||
void getValue(uint64 &buffer) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableInt64::getValue(int64 &buffer) const
|
||||
{
|
||||
buffer=getValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableInt64::getValue(uint64 &buffer) const
|
||||
{
|
||||
buffer=static_cast<uint64>(getValue());
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableLong.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableLong.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
BindableLong::BindableLong() : Bindable(), value(-999)
|
||||
{
|
||||
}
|
||||
|
||||
BindableLong::BindableLong(long int _value) : Bindable(sizeof(value)), value(_value)
|
||||
{
|
||||
}
|
||||
|
||||
void *BindableLong::getBuffer()
|
||||
{
|
||||
return &value; //lint !e1536 // exposing private member
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
long int BindableLong::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
BindableLong &BindableLong::operator=(long int rhs)
|
||||
{
|
||||
indicator=sizeof(value);
|
||||
value=rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void BindableLong::setValue(long int rhs)
|
||||
{
|
||||
indicator=sizeof(value);
|
||||
value=rhs;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string BindableLong::outputValue() const
|
||||
{
|
||||
char temp[255];
|
||||
snprintf(temp,sizeof(temp),"%li",value);
|
||||
temp[sizeof(temp)-1]='\0';
|
||||
return std::string(temp);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,95 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableLong.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableLong_H
|
||||
#define INCLUDED_DBBindableLong_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
/**
|
||||
* Represents a long in C++, bound to an INTEGER or NUMBER database column
|
||||
*/
|
||||
class BindableLong : public Bindable
|
||||
{
|
||||
public:
|
||||
BindableLong();
|
||||
explicit BindableLong(long int _value);
|
||||
|
||||
long int getValue() const;
|
||||
void setValue(const long int rhs);
|
||||
BindableLong &operator=(const long int rhs);
|
||||
|
||||
// following alternate getValue's are provided for convenience, particularly in
|
||||
// the auto-generated code:
|
||||
void getValue(unsigned int &buffer) const;
|
||||
void getValue(uint32 &buffer) const; // for some reason, our compiler is convinced that uint32 != unsigned int
|
||||
void getValue(long int &buffer) const;
|
||||
void getValue(int &buffer) const;
|
||||
void getValue(int8 &buffer) const;
|
||||
void getValue(uint8 &buffer) const;
|
||||
|
||||
void *getBuffer();
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
|
||||
private:
|
||||
long int value;
|
||||
}; //lint !e1721 !e1509 // no virtual destructor, unusual operator =
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableLong::getValue(unsigned int &buffer) const
|
||||
{
|
||||
buffer=static_cast<unsigned int>(getValue());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableLong::getValue(uint32 &buffer) const
|
||||
{
|
||||
buffer=static_cast<uint32>(getValue());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableLong::getValue(long int &buffer) const
|
||||
{
|
||||
buffer=getValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableLong::getValue(int &buffer) const
|
||||
{
|
||||
buffer=getValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableLong::getValue(int8 &buffer) const
|
||||
{
|
||||
buffer=static_cast<int8>(getValue());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::BindableLong::getValue(uint8 &buffer) const
|
||||
{
|
||||
buffer=static_cast<uint8>(getValue());
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableString.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableString.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
std::string DB::BindableStringBase::outputValue() const
|
||||
{
|
||||
const std::string quote("\"");
|
||||
return quote + std::string(m_buffer) + quote;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,326 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableString.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableString_H
|
||||
#define INCLUDED_DBBindableString_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
|
||||
#include "UnicodeUtils.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
/**
|
||||
* A large instrument resembling a cello.
|
||||
*/
|
||||
class BindableStringBase : public Bindable
|
||||
{
|
||||
public:
|
||||
|
||||
~BindableStringBase();
|
||||
|
||||
void *getBuffer();
|
||||
int getS();
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
|
||||
protected:
|
||||
|
||||
BindableStringBase(char *buffer, int s);
|
||||
BindableStringBase(char *buffer, int s, const BindableStringBase &rhs);
|
||||
void operator=(const BindableStringBase &rhs);
|
||||
|
||||
private:
|
||||
|
||||
BindableStringBase();
|
||||
BindableStringBase(const BindableStringBase &rhs); // disable
|
||||
|
||||
private:
|
||||
|
||||
char *m_buffer;
|
||||
int m_s;
|
||||
};
|
||||
|
||||
inline BindableStringBase::BindableStringBase(char *buffer, int s) :
|
||||
m_buffer(buffer),
|
||||
m_s(s)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This takes the place of a copy contructor.
|
||||
* It gets buffer and s from the derived class, instead of from rhs.
|
||||
*/
|
||||
inline BindableStringBase::BindableStringBase(char *buffer, int s, const BindableStringBase &rhs) :
|
||||
Bindable(rhs),
|
||||
m_buffer(buffer),
|
||||
m_s(s)
|
||||
{
|
||||
DEBUG_FATAL(m_s!=rhs.m_s,("Cannot use BindableString copy constructor on different size strings.\n")); // compiler shouldn't allow this, but just to make sure...
|
||||
}
|
||||
|
||||
inline BindableStringBase::~BindableStringBase()
|
||||
{
|
||||
m_buffer = 0;
|
||||
}
|
||||
|
||||
inline void *BindableStringBase::getBuffer()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
inline int BindableStringBase::getS()
|
||||
{
|
||||
return m_s;
|
||||
}
|
||||
|
||||
inline void BindableStringBase::operator=(const BindableStringBase &rhs)
|
||||
{
|
||||
//does not copy m_buffer or m_s
|
||||
DEBUG_FATAL(m_s!=rhs.m_s,("Cannot use BindableString::operator= on different size strings.\n")); // compiler shouldn't allow this, but just to make sure...
|
||||
Bindable::operator=(rhs);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
/** Template that allows creating a class representing a C++ char[] array
|
||||
bound to a VARCHAR in the database.
|
||||
|
||||
BindableString is a template so that the size can be specified when it
|
||||
is instantiated. The template parameter S represents the size of the
|
||||
array.
|
||||
|
||||
Question: Why is this a template? Couldn't S be a parameter to the
|
||||
constructor?
|
||||
|
||||
Short answer: Because of the way ODBC works, the size must be known at
|
||||
compile time
|
||||
|
||||
Long answer: We want to be able to use these things in arrays that are
|
||||
bound. The functions for binding an array do not allow an element of the
|
||||
array to be a pointer to another location. Therefore, to work with ODBC,
|
||||
the buffer for the string must be part of the class, not a pointer.
|
||||
|
||||
TODO: Currently this template represents 8-bit characters. Make it support
|
||||
Unicode.
|
||||
TODO: We have both setValue() functions and operator='s. Should just pick
|
||||
one and use it.
|
||||
*/
|
||||
template<int S>
|
||||
class BindableString : public BindableStringBase
|
||||
{
|
||||
public:
|
||||
BindableString();
|
||||
explicit BindableString(const Unicode::String &_value);
|
||||
explicit BindableString(const std::string &_value);
|
||||
BindableString(const BindableString<S> &rhs);
|
||||
|
||||
/** Copy the string to another string
|
||||
*/
|
||||
char *getValue(char *buffer, size_t bufsize) const;
|
||||
/** Copy the string to a Unicode String class
|
||||
*/
|
||||
Unicode::String getValue() const;
|
||||
/** Copy the string to an 8-bit String class
|
||||
*/
|
||||
std::string getValueASCII() const;
|
||||
|
||||
/** Allocate a new string and copy the buffer to it. The caller takes responsibility
|
||||
for delete[]ing it later. (If the string is NULL, this returns a null pointer.)
|
||||
*/
|
||||
char *makeCopyOfValue() const;
|
||||
|
||||
/** Set the value of the bindable string from another (null-terminated) string
|
||||
|
||||
If the source buffer is too big, it FATAL's. Another alternative would be to have
|
||||
it truncate the string. Right now, it's better to FATAL to avoid hard-to-find bugs
|
||||
caused by the database fields being too small. However, might want to revist this
|
||||
later.
|
||||
*/
|
||||
void setValue(const char *buffer);
|
||||
|
||||
/** Set the value of the bindable string from a String class. See also setValue(const char*).
|
||||
*/
|
||||
void setValue(const Unicode::String &buffer);
|
||||
|
||||
/**
|
||||
* Set the value of the bindable string from a std::string.
|
||||
*/
|
||||
void setValue(const std::string &buffer);
|
||||
|
||||
/** Same as setValue
|
||||
*/
|
||||
BindableString &operator=(const Unicode::String &buffer);
|
||||
BindableString &operator=(const std::string &buffer);
|
||||
|
||||
// Alternate forms of getValue, useful for auto-generated code (because of type conversion issues)
|
||||
void getValue(Unicode::String &buffer) const;
|
||||
void getValue(std::string &buffer) const;
|
||||
|
||||
int getS() const;
|
||||
|
||||
private:
|
||||
|
||||
char m_value[S+1]; // column of size S, plus one byte for a trailing null
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// Template functions
|
||||
|
||||
template<int S>
|
||||
BindableString<S>::BindableString()
|
||||
: BindableStringBase(m_value, S)
|
||||
{
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableString<S>::BindableString(const Unicode::String &value)
|
||||
: BindableStringBase(m_value, S)
|
||||
{
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableString<S>::BindableString(const std::string &value)
|
||||
: BindableStringBase(m_value, S)
|
||||
{
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableString<S>::BindableString(const BindableString<S> &rhs)
|
||||
: BindableStringBase(m_value, S, rhs)
|
||||
{
|
||||
strncpy(m_value,rhs.m_value,S+1);
|
||||
}
|
||||
|
||||
template<int S>
|
||||
char *BindableString<S>::getValue(char *buffer, size_t bufsize) const
|
||||
{
|
||||
if (isNull())
|
||||
{
|
||||
return strncpy(buffer,"\0",1); // in the database, a zero-length string and a NULL aren't really
|
||||
// the same thing, but this is the closest we can do here.
|
||||
}
|
||||
return strncpy(buffer,m_value,(bufsize>(S+1))?(S+1):bufsize);
|
||||
}
|
||||
|
||||
template<int S>
|
||||
Unicode::String BindableString<S>::getValue() const
|
||||
{
|
||||
if (isNull())
|
||||
{
|
||||
return Unicode::String();
|
||||
}
|
||||
else
|
||||
{
|
||||
//-- Justin Randall [4/11/2001 5:56:56 PM] --
|
||||
// @todo : value is currently a char, should be an short or Unicode::String::value_type or wchar_t
|
||||
return Unicode::String(Unicode::narrowToWide(m_value));
|
||||
}
|
||||
}
|
||||
|
||||
template<int S>
|
||||
std::string BindableString<S>::getValueASCII() const
|
||||
{
|
||||
if (isNull())
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::string(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableString<S>::setValue(const char *buffer)
|
||||
{
|
||||
if (buffer==0)
|
||||
{
|
||||
setNull();
|
||||
return;
|
||||
}
|
||||
|
||||
// the following is strncpy, but keeps a count of the number of characters
|
||||
unsigned int i;
|
||||
for (i=0;i<S+1;++i)
|
||||
{
|
||||
m_value[i]=buffer[i];
|
||||
if (m_value[i]=='\0')
|
||||
break;
|
||||
}
|
||||
FATAL((i==S+1) && (m_value[S]!='\0'),("Attempt to save string \"%s\" to the database. It is too long for the column.",buffer));
|
||||
indicator=i; // set indicator to actual length of string
|
||||
// m_value[S]='\0'; // guarantee null terminator -- uncomment if you remove the above FATAL
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableString<S>::setValue(const Unicode::String &buffer)
|
||||
{
|
||||
FATAL(buffer.size()>S,("Attempt to save a Unicode::String \"%s\"that is too long to the database.", Unicode::wideToNarrow(buffer).c_str()));
|
||||
strncpy(m_value, Unicode::wideToNarrow(buffer).c_str(), S+1);
|
||||
indicator=buffer.size();
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableString<S>::setValue(const std::string &buffer)
|
||||
{
|
||||
FATAL(strlen(buffer.c_str())>S,("Attempt to save a std::string \"%s\"that is too long to the database.", buffer.c_str()));
|
||||
strncpy(m_value, buffer.c_str(), S+1);
|
||||
indicator=strlen(buffer.c_str());
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableString<S> &BindableString<S>::operator=(const Unicode::String &buffer)
|
||||
{
|
||||
setValue(buffer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableString<S> &BindableString<S>::operator=(const std::string &buffer)
|
||||
{
|
||||
setValue(buffer.c_str());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<int S>
|
||||
char *BindableString<S>::makeCopyOfValue() const
|
||||
{
|
||||
if (isNull()) return 0;
|
||||
|
||||
char *target=new char[indicator+1];
|
||||
strncpy(target,m_value,indicator+1);
|
||||
return target;
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableString<S>::getValue(Unicode::String &buffer) const
|
||||
{
|
||||
buffer=getValue();
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableString<S>::getValue(std::string &buffer) const
|
||||
{
|
||||
buffer=getValueASCII();
|
||||
}
|
||||
|
||||
template<int S>
|
||||
int BindableString<S>::getS() const
|
||||
{
|
||||
return S;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableUnicode.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBindableUnicode.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
std::string DB::BindableUnicodeBase::outputValue() const
|
||||
{
|
||||
const std::string quote("\"");
|
||||
return quote + std::string(m_buffer) + quote;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,226 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBindableUnicode.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBBindableUnicode_H
|
||||
#define INCLUDED_DBBindableUnicode_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbBindableBase.h"
|
||||
|
||||
#include "UnicodeUtils.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
/**
|
||||
* A large instrument resembling a cello.
|
||||
*/
|
||||
class BindableUnicodeBase : public Bindable
|
||||
{
|
||||
public:
|
||||
|
||||
~BindableUnicodeBase();
|
||||
|
||||
void *getBuffer();
|
||||
int getS();
|
||||
|
||||
virtual std::string outputValue() const;
|
||||
|
||||
protected:
|
||||
|
||||
BindableUnicodeBase(char *buffer, int s);
|
||||
BindableUnicodeBase(char *buffer, int s, const BindableUnicodeBase &rhs);
|
||||
void operator=(const BindableUnicodeBase &rhs);
|
||||
|
||||
private:
|
||||
|
||||
BindableUnicodeBase();
|
||||
BindableUnicodeBase(const BindableUnicodeBase &rhs); // disable
|
||||
|
||||
private:
|
||||
|
||||
char *m_buffer;
|
||||
int m_s;
|
||||
};
|
||||
|
||||
inline BindableUnicodeBase::BindableUnicodeBase(char *buffer, int s) :
|
||||
m_buffer(buffer),
|
||||
m_s(s)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This takes the place of a copy contructor.
|
||||
* It gets buffer and s from the derived class, instead of from rhs.
|
||||
*/
|
||||
inline BindableUnicodeBase::BindableUnicodeBase(char *buffer, int s, const BindableUnicodeBase &rhs) :
|
||||
Bindable(rhs),
|
||||
m_buffer(buffer),
|
||||
m_s(s)
|
||||
{
|
||||
DEBUG_FATAL(m_s!=rhs.m_s,("Cannot use BindableUnicode copy constructor on different size strings.\n")); // compiler shouldn't allow this, but just to make sure...
|
||||
}
|
||||
|
||||
inline BindableUnicodeBase::~BindableUnicodeBase()
|
||||
{
|
||||
m_buffer = 0;
|
||||
}
|
||||
|
||||
inline void *BindableUnicodeBase::getBuffer()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
inline int BindableUnicodeBase::getS()
|
||||
{
|
||||
return m_s;
|
||||
}
|
||||
|
||||
inline void BindableUnicodeBase::operator=(const BindableUnicodeBase &rhs)
|
||||
{
|
||||
//does not copy m_buffer or m_s
|
||||
DEBUG_FATAL(m_s!=rhs.m_s,("Cannot use BindableUnicode::operator= on different size strings.\n")); // compiler shouldn't allow this, but just to make sure...
|
||||
Bindable::operator=(rhs);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
/** Template that allows creating a class representing a C++ char[] array
|
||||
bound to a VARCHAR in the database.
|
||||
|
||||
BindableUnicode is a template so that the size can be specified when it
|
||||
is instantiated. The template parameter S represents the size of the
|
||||
array.
|
||||
|
||||
Question: Why is this a template? Couldn't S be a parameter to the
|
||||
constructor?
|
||||
|
||||
Short answer: Because of the way ODBC works, the size must be known at
|
||||
compile time
|
||||
|
||||
Long answer: We want to be able to use these things in arrays that are
|
||||
bound. The functions for binding an array do not allow an element of the
|
||||
array to be a pointer to another location. Therefore, to work with ODBC,
|
||||
the buffer for the string must be part of the class, not a pointer.
|
||||
|
||||
TODO: Currently this template represents 8-bit characters. Make it support
|
||||
Unicode.
|
||||
TODO: We have both setValue() functions and operator='s. Should just pick
|
||||
one and use it.
|
||||
*/
|
||||
template<int S>
|
||||
class BindableUnicode : public BindableUnicodeBase
|
||||
{
|
||||
public:
|
||||
BindableUnicode();
|
||||
explicit BindableUnicode(const Unicode::String &_value);
|
||||
BindableUnicode(const BindableUnicode<S> &rhs);
|
||||
|
||||
/** Copy the string to another string
|
||||
*/
|
||||
//char *getValue(char *buffer, size_t bufsize) const;
|
||||
/** Copy the string to a Unicode String class
|
||||
*/
|
||||
Unicode::String getValue() const;
|
||||
|
||||
/** Set the value of the bindable string from a String class. See also setValue(const char*).
|
||||
*/
|
||||
void setValue(const Unicode::String &buffer);
|
||||
|
||||
/** Same as setValue
|
||||
*/
|
||||
BindableUnicode &operator=(const Unicode::String &buffer);
|
||||
|
||||
// Alternate forms of getValue, useful for auto-generated code (because of type conversion issues)
|
||||
void getValue(Unicode::String &buffer) const;
|
||||
|
||||
int getS() const;
|
||||
|
||||
private:
|
||||
|
||||
char m_value[S+1]; // column of size S, plus one byte for a trailing null
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// Template functions
|
||||
|
||||
template<int S>
|
||||
BindableUnicode<S>::BindableUnicode()
|
||||
: BindableUnicodeBase(m_value, S)
|
||||
{
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableUnicode<S>::BindableUnicode(const Unicode::String &value)
|
||||
: BindableUnicodeBase(m_value, S)
|
||||
{
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableUnicode<S>::BindableUnicode(const BindableUnicode<S> &rhs)
|
||||
: BindableUnicodeBase(m_value, S, rhs)
|
||||
{
|
||||
strncpy(m_value,rhs.m_value,S+1);
|
||||
}
|
||||
|
||||
template<int S>
|
||||
Unicode::String BindableUnicode<S>::getValue() const
|
||||
{
|
||||
if (isNull())
|
||||
{
|
||||
return Unicode::String();
|
||||
}
|
||||
else
|
||||
{
|
||||
Unicode::String str;
|
||||
std::basic_string<char> cstr (m_value, m_value + indicator);
|
||||
str = Unicode::utf8ToWide(cstr);
|
||||
return str;
|
||||
|
||||
//-- Justin Randall [4/11/2001 5:56:56 PM] --
|
||||
// @todo : value is currently a char, should be an short or Unicode::String::value_type or wchar_t
|
||||
//return Unicode::String(Unicode::narrowToWide(m_value));
|
||||
}
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableUnicode<S>::setValue(const Unicode::String &buffer)
|
||||
{
|
||||
FATAL(buffer.size()>S,("Attempt to save a Unicode::String \"%s\"that is too long to the database.", Unicode::wideToNarrow(buffer).c_str()));
|
||||
|
||||
std::string str;
|
||||
str = Unicode::wideToUTF8(buffer, str);
|
||||
indicator = (str.size()>S ? S : str.size());
|
||||
memcpy(m_value, str.c_str(),indicator);
|
||||
m_value[indicator] = '\0';
|
||||
}
|
||||
|
||||
template<int S>
|
||||
BindableUnicode<S> &BindableUnicode<S>::operator=(const Unicode::String &buffer)
|
||||
{
|
||||
setValue(buffer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<int S>
|
||||
void BindableUnicode<S>::getValue(Unicode::String &buffer) const
|
||||
{
|
||||
buffer.assign(getValue());
|
||||
}
|
||||
|
||||
template<int S>
|
||||
int BindableUnicode<S>::getS() const
|
||||
{
|
||||
return S;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBufferRow.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbBufferRow.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,53 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBBufferRow.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
//TODO: Is this file obsolete?
|
||||
|
||||
#ifndef INCLUDED_DBBufferRow_H
|
||||
#define INCLUDED_DBBufferRow_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbRow.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* A BufferRow is a Row that works with the TableBuffer class.
|
||||
*
|
||||
* A BufferRow is a Row that represents a Row from a table (not a view
|
||||
* or a query that joins multiple tables). It implements various
|
||||
* virtual functions that the TableBuffer class uses.
|
||||
*/
|
||||
struct BufferRow:public Row
|
||||
{
|
||||
|
||||
/**
|
||||
* Combines the values in this row with the values in newRow.
|
||||
*
|
||||
* For each column:
|
||||
* If the column is null in newRow, do nothing. (Leave the value
|
||||
* in this row unchanged.)
|
||||
* If the column is not null in newRow, replace the value in this
|
||||
* row with the value in newRow.
|
||||
*/
|
||||
virtual void combine(const DB::Row &newRow) =0;
|
||||
|
||||
/**
|
||||
* Makes a new copy of this row.
|
||||
*/
|
||||
virtual BufferRow *copy(void) const =0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbException.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbException.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
Exception::Exception(int errorNumber, const std::string &errorDescription, const std::string &contextDescription) :
|
||||
m_errorNumber(errorNumber),
|
||||
m_errorDescription(errorDescription),
|
||||
m_contextDescription(contextDescription)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Exception::Exception(int errorNumber, const std::string &errorDescription) :
|
||||
m_errorNumber(errorNumber),
|
||||
m_errorDescription(errorDescription),
|
||||
m_contextDescription()
|
||||
{
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,62 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbException.h
|
||||
// copyright (c) 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DbException_H
|
||||
#define INCLUDED_DbException_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include <string>
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class Exception
|
||||
{
|
||||
public:
|
||||
Exception(int errorNumber, const std::string &errorDescription, const std::string &contextDescription);
|
||||
Exception(int errorNumber, const std::string &errorDescription);
|
||||
|
||||
public:
|
||||
int getErrorNumber() const;
|
||||
const std::string & getErrorDescription() const;
|
||||
const std::string & getContextDescription() const;
|
||||
|
||||
private:
|
||||
int m_errorNumber;
|
||||
std::string m_errorDescription;
|
||||
std::string m_contextDescription;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline int Exception::getErrorNumber() const
|
||||
{
|
||||
return m_errorNumber;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const std::string & Exception::getErrorDescription() const
|
||||
{
|
||||
return m_errorDescription;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline const std::string & Exception::getContextDescription() const
|
||||
{
|
||||
return m_contextDescription;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
} // namespace
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBModeQuery.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbModeQuery.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
DB::ModeQuery::~ModeQuery()
|
||||
{
|
||||
delete data;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/* DBModeQuery.h
|
||||
*
|
||||
* Query objects that support different modes of operation
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DBMODEQUERY_H
|
||||
#define _DBMODEQUERY_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
#include "sharedDatabaseInterface/DbRow.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* A ModeQuery is a Query that can be in update, insert, select, or delete mode.
|
||||
*
|
||||
* This class is designed to work with the TableBuffer class.
|
||||
*
|
||||
* Derive from this class to make a query for a specific purpose.
|
||||
* Implement the following in the derived class:
|
||||
* 1) A constructor that initializes _data_ to point to a row of the appropriate type.
|
||||
* 2) A bind function (will need to dynamic_cast _data_ to the appropriate type of row)
|
||||
* 3) A getSQL() function
|
||||
*
|
||||
* Note that the copy() function must be defined for the type of row used.
|
||||
*
|
||||
* Note also that getSQL() will need to return different values depending on the mode. Bind()
|
||||
* may also need to behave differently in different modes, depending on the query. The default
|
||||
* destructor deletes _data_, so it is not necessary to do so in a derived destructor.
|
||||
*/
|
||||
class ModeQuery : public Query
|
||||
{
|
||||
public:
|
||||
enum Mode {mode_UPDATE,mode_INSERT,mode_DELETE,mode_SELECT,mode_INVALID};
|
||||
Mode mode; //TODO: rename to m_mode
|
||||
|
||||
protected:
|
||||
Row *data;
|
||||
|
||||
public:
|
||||
explicit ModeQuery(Row *derivedRow);
|
||||
virtual ~ModeQuery();
|
||||
|
||||
void setData(const Row &_data);
|
||||
const Row &getData(void) const;
|
||||
|
||||
void updateMode();
|
||||
void insertMode();
|
||||
void deleteMode();
|
||||
void selectMode();
|
||||
|
||||
private:
|
||||
ModeQuery(); //disable
|
||||
ModeQuery(const ModeQuery &); //disable
|
||||
ModeQuery & operator=(const ModeQuery &); //disable
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Inline functions
|
||||
|
||||
inline ModeQuery::ModeQuery(Row *derivedRow) :
|
||||
Query(),
|
||||
mode (mode_INVALID),
|
||||
data(derivedRow)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
inline void ModeQuery::insertMode()
|
||||
{
|
||||
mode=mode_INSERT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
inline void ModeQuery::updateMode()
|
||||
{
|
||||
mode=mode_UPDATE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
inline void ModeQuery::deleteMode()
|
||||
{
|
||||
mode=mode_DELETE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
inline void ModeQuery::selectMode()
|
||||
{
|
||||
mode=mode_SELECT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
inline const Row &ModeQuery::getData() const
|
||||
{
|
||||
return *data;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void ModeQuery::setData(const Row &_data)
|
||||
{
|
||||
data->copy(_data);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbProfiler.cpp
|
||||
// copyright (c) 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbProfiler.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
Profiler::Profiler() :
|
||||
m_queryDataMap(new QueryDataMapType)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Profiler::~Profiler()
|
||||
{
|
||||
delete m_queryDataMap;
|
||||
m_queryDataMap = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Profiler::addQueryProfileData(const std::string &queryName, int execTime, int fetchTime, int execCount, int fetchCount)
|
||||
{
|
||||
QueryData &data = (*m_queryDataMap)[queryName];
|
||||
data.m_execTime += execTime;
|
||||
data.m_fetchTime += fetchTime;
|
||||
data.m_execCount += execCount;
|
||||
data.m_fetchCount += fetchCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Profiler::debugOutput()
|
||||
{
|
||||
// DEBUG_REPORT_LOG(true,("Query profile:\n"));
|
||||
for (QueryDataMapType::const_iterator i=m_queryDataMap->begin(); i!=m_queryDataMap->end(); ++i)
|
||||
{
|
||||
LOG("QueryProfile",("\t%s\t%i ms/exec (%i execs in %i ms, %i fetches in %i ms)\n",
|
||||
i->first.c_str(), (i->second.m_execTime / i->second.m_execCount), i->second.m_execCount,
|
||||
i->second.m_execTime, i->second.m_fetchCount, i->second.m_fetchTime));
|
||||
}
|
||||
// DEBUG_REPORT_LOG(true,("End query profile\n"));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Profiler::QueryData::QueryData() :
|
||||
m_execTime(0),
|
||||
m_fetchTime(0),
|
||||
m_execCount(0),
|
||||
m_fetchCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,43 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DbProfiler.h
|
||||
// copyright (c) 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DbProfiler_H
|
||||
#define INCLUDED_DbProfiler_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class Profiler
|
||||
{
|
||||
public:
|
||||
Profiler();
|
||||
~Profiler();
|
||||
void addQueryProfileData(const std::string &queryName, int execTime, int fetchTime, int execCount, int fetchCount);
|
||||
void debugOutput();
|
||||
|
||||
private:
|
||||
class QueryData
|
||||
{
|
||||
public:
|
||||
QueryData();
|
||||
|
||||
public:
|
||||
int m_execTime;
|
||||
int m_fetchTime;
|
||||
int m_execCount;
|
||||
int m_fetchCount;
|
||||
};
|
||||
|
||||
typedef stdmap<std::string, QueryData>::fwd QueryDataMapType;
|
||||
QueryDataMapType *m_queryDataMap;
|
||||
};
|
||||
|
||||
} //namespace
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBProtocol.def
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBProtocol_DEF
|
||||
#define INCLUDED_DBProtocol_DEF
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
const int PROTOCOL_DEFAULT=0;
|
||||
const int PROTOCOL_ODBC=1;
|
||||
const int PROTOCOL_OCI=2;
|
||||
|
||||
typedef int Protocol;
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,334 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbException.h"
|
||||
#include "sharedDatabaseInterface/DbQueryImplementation.h"
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
#include "sharedDatabaseInterface/DbSession.h"
|
||||
#include "sharedFoundation/Clock.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace DB;
|
||||
|
||||
namespace DBQueryNamespace
|
||||
{
|
||||
void logLargeText(std::string const & logSection, std::string const & text);
|
||||
}
|
||||
|
||||
Query::Query() :
|
||||
impl(0),
|
||||
m_session(0),
|
||||
inUse(false),
|
||||
m_execTime(0),
|
||||
m_fetchTime(0),
|
||||
m_execCount(0),
|
||||
m_fetchCount(0),
|
||||
m_rowsFetched(0),
|
||||
m_debugName(0),
|
||||
m_queryMode(MODE_SQL)
|
||||
{
|
||||
}
|
||||
|
||||
Query::~Query()
|
||||
{
|
||||
if (inUse)
|
||||
done();
|
||||
|
||||
delete impl;
|
||||
delete m_debugName;
|
||||
impl = 0;
|
||||
m_debugName = 0;
|
||||
} //lint !e1740 // dtor doesn't delete m_session (because we don't own it)
|
||||
|
||||
int Query::fetch()
|
||||
{
|
||||
int startTime = 0;
|
||||
if (Server::isProfilingEnabled())
|
||||
startTime = Clock::timeMs();
|
||||
|
||||
NOT_NULL(impl);
|
||||
m_rowsFetched = impl->fetch();
|
||||
|
||||
if (Server::isProfilingEnabled())
|
||||
{
|
||||
m_fetchTime += Clock::timeMs() - startTime;
|
||||
}
|
||||
if (m_rowsFetched >= 0)
|
||||
{
|
||||
m_fetchCount += m_rowsFetched;
|
||||
return m_rowsFetched;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Query::done()
|
||||
{
|
||||
if (inUse) // so that it's safe to call Done() on a query that hasn't been used
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
NOT_NULL(m_session);
|
||||
|
||||
impl->done();
|
||||
m_session->queryDone();
|
||||
m_session->addQueryCount(m_execCount, m_fetchCount);
|
||||
if (Server::isProfilingEnabled())
|
||||
{
|
||||
NOT_NULL(m_debugName); // should have been set by setup()
|
||||
Server::addQueryProfileData(*m_debugName, m_execTime, m_fetchTime, m_execCount, m_fetchCount);
|
||||
|
||||
// reset the profiler data in case we run this query again:
|
||||
m_execTime=0;
|
||||
m_fetchTime=0;
|
||||
m_execCount=0;
|
||||
m_fetchCount=0;
|
||||
}
|
||||
inUse=false;
|
||||
m_session=0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the number of rows affected by the most recent query. (Only applies
|
||||
* to DML queries.)
|
||||
*/
|
||||
int Query::rowCount()
|
||||
{
|
||||
if (!inUse)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->rowCount();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Query::setup(Session *session)
|
||||
{
|
||||
if (impl == 0)
|
||||
{
|
||||
impl=session->createQueryImpl(this);
|
||||
}
|
||||
NOT_NULL(impl);
|
||||
NOT_NULL(session);
|
||||
m_session=session;
|
||||
|
||||
if (Server::isProfilingEnabled() && !m_debugName)
|
||||
{
|
||||
m_debugName = new std::string;
|
||||
getDebugName(*m_debugName);
|
||||
}
|
||||
|
||||
if (impl->setup(session))
|
||||
{
|
||||
inUse=true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Query::prepare()
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->prepare();
|
||||
}
|
||||
|
||||
bool Query::exec()
|
||||
{
|
||||
int startTime = 0;
|
||||
if (Server::isProfilingEnabled())
|
||||
startTime = Clock::timeMs();
|
||||
|
||||
m_queryMode=getExecutionMode();
|
||||
|
||||
NOT_NULL(impl);
|
||||
if (Server::isVerboseModeEnabled())
|
||||
{
|
||||
std::string context;
|
||||
getDebugName(context);
|
||||
DEBUG_REPORT_LOG(true,("query: %s\n",context.c_str()));
|
||||
}
|
||||
bool result = impl->exec();
|
||||
|
||||
if (Server::isProfilingEnabled())
|
||||
{
|
||||
m_execTime += Clock::timeMs() - startTime;
|
||||
}
|
||||
++m_execCount;
|
||||
|
||||
if (! result)
|
||||
{
|
||||
std::string data = outputDataValues();
|
||||
LOG("DatabaseError",("Data from previous error:"));
|
||||
DBQueryNamespace::logLargeText("DatabaseError", data);
|
||||
done();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Query::setColArrayMode(size_t skipSize, size_t numElements)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
impl->setColArrayMode(skipSize, numElements);
|
||||
}
|
||||
|
||||
bool Query::bindCol(BindableLong &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindCol(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindParameter(BindableLong &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindParameter(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindCol(BindableDouble &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindCol(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindParameter(BindableDouble &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindParameter(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindCol(BindableStringBase &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindCol(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindParameter(BindableStringBase &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindParameter(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindCol(BindableUnicodeBase &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindCol(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindParameter(BindableUnicodeBase &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindParameter(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindCol(BindableBool &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindCol(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindParameter(BindableBool &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindParameter(buffer);
|
||||
}
|
||||
|
||||
bool Query::bindParameter(BindableVarray &buffer)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->bindParameter(buffer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get the protocol being used to communicate with the database.
|
||||
*
|
||||
* @returns The protocol being used, or PROTOCOL_DEFAULT if the query is not
|
||||
* associated with a database connection.
|
||||
*/
|
||||
Protocol Query::getProtocol() const
|
||||
{
|
||||
if (inUse)
|
||||
{
|
||||
NOT_NULL(impl);
|
||||
return impl->getProtocol();
|
||||
}
|
||||
else
|
||||
return PROTOCOL_DEFAULT;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Override this function to change the execution mode for the query.
|
||||
*
|
||||
* This function gets invoked after the QueryImpl has been created, so
|
||||
* it can return different values depending on the protocol used.
|
||||
*
|
||||
* The default implementation returns MODE_SQL, which is suitable for
|
||||
* most purposes.
|
||||
*/
|
||||
Query::QueryMode Query::getExecutionMode() const
|
||||
{
|
||||
return MODE_SQL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/** Override this function to return the debugging name for the query.
|
||||
* The non-overriden version calls getSQL() and uses the result as the query name.
|
||||
* Not const because getSQL() isn't const.
|
||||
*/
|
||||
|
||||
void Query::getDebugName(std::string &debugName)
|
||||
{
|
||||
getSQL(debugName);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string Query::outputDataValues() const
|
||||
{
|
||||
return impl->outputDataValues();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DBQueryNamespace::logLargeText(std::string const & logSection, std::string const & text)
|
||||
{
|
||||
int const targetLineSize = 80;
|
||||
int const maxLineSize = 100;
|
||||
char buffer[maxLineSize+1];
|
||||
buffer[sizeof(buffer)-1]='\0';
|
||||
|
||||
int linePos = 0;
|
||||
for (std::string::const_iterator sourcePos = text.begin(); sourcePos != text.end(); ++sourcePos)
|
||||
{
|
||||
if (*sourcePos < 27)
|
||||
buffer[linePos++]='*'; // Hide unprintable/garbage/control characters
|
||||
else
|
||||
buffer[linePos++]=*sourcePos;
|
||||
if ((linePos >= targetLineSize && *sourcePos == ' ') || (linePos >= maxLineSize))
|
||||
{
|
||||
buffer[linePos]='\0';
|
||||
LOG(logSection.c_str(),(buffer));
|
||||
linePos=0;
|
||||
}
|
||||
}
|
||||
if (linePos != 0)
|
||||
{
|
||||
buffer[linePos]='\0';
|
||||
LOG(logSection.c_str(),(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,157 @@
|
||||
/* DBQuery.h
|
||||
*
|
||||
* Definition of the base query class. Override this class to make
|
||||
* queries for specific purposes.
|
||||
*
|
||||
* ODBC version
|
||||
*/
|
||||
|
||||
#ifndef _DBQUERY_H
|
||||
#define _DBQUERY_H
|
||||
|
||||
//#include "sharedDatabaseInterface/SQLC_Defs.h"
|
||||
#include "sharedDatabaseInterface/DbQueryImplementation.h" //TODO: Do we want to include this?
|
||||
#include "sharedDatabaseInterface/DbProtocol.def"
|
||||
|
||||
namespace DB {
|
||||
|
||||
class Session;
|
||||
class QueryImpl;
|
||||
class BindableLong;
|
||||
class BindableVarray;
|
||||
|
||||
class Query
|
||||
{
|
||||
public:
|
||||
enum QueryMode {MODE_SQL, MODE_DML, MODE_PROCEXEC, MODE_PLSQL_REFCURSOR};
|
||||
|
||||
private:
|
||||
QueryImpl *impl;
|
||||
|
||||
Session *m_session;
|
||||
bool inUse;
|
||||
int m_execTime;
|
||||
int m_fetchTime;
|
||||
int m_execCount;
|
||||
int m_fetchCount;
|
||||
int m_rowsFetched;
|
||||
std::string *m_debugName;
|
||||
|
||||
/**
|
||||
* Flag for the type of statement the query will run.
|
||||
*
|
||||
* Depending on the mode of operation, the query may need to be executed differently.
|
||||
* In particular, some types of queries do not need to call bindColumns(), or may need to
|
||||
* call it at different times.
|
||||
*
|
||||
* MODE_SQL is a query that may return rows. (The system allows DML statements to be sent using MODE_SQL, provided
|
||||
* they bind no columns and never invoke fetch().)
|
||||
* MODE_DML is a statement that updates rows. It will not return rows.
|
||||
* MODE_PROCEXEC is a statement that invokes a stored procedure. It will not return rows, but it may alter
|
||||
* parameters bound with bindParameter().
|
||||
* MODE_PLSQL_REFCURSOR is Oracle-specific.
|
||||
*/
|
||||
QueryMode m_queryMode;
|
||||
bool m_useProcFetch;
|
||||
|
||||
/** Because database results are bound to the memory location of members
|
||||
of Query, copying them is not allowed. Do not define this function.
|
||||
*/
|
||||
Query(const Query &rhs);
|
||||
|
||||
/** Because database results are bound to the memory location of members
|
||||
of Query, copying them is not allowed. Do not define this function.
|
||||
*/
|
||||
Query &operator=(const Query &rhs);
|
||||
|
||||
protected:
|
||||
/** Switches to array mode to return an array of results, rather than a single row.
|
||||
* Call this first, then call the bindCol functions with the first element in the array.
|
||||
*/
|
||||
void setColArrayMode(size_t skipSize, size_t numElements);
|
||||
|
||||
bool bindCol(BindableLong &buffer);
|
||||
bool bindParameter(BindableLong &buffer);
|
||||
bool bindCol(BindableDouble &buffer);
|
||||
bool bindParameter(BindableDouble &buffer);
|
||||
bool bindCol(BindableStringBase &buffer);
|
||||
bool bindParameter(BindableStringBase &buffer);
|
||||
bool bindCol(BindableUnicodeBase &buffer);
|
||||
bool bindParameter(BindableUnicodeBase &buffer);
|
||||
bool bindCol(BindableBool &buffer);
|
||||
bool bindParameter(BindableBool &buffer);
|
||||
bool bindParameter(BindableVarray &buffer);
|
||||
|
||||
Protocol getProtocol() const;
|
||||
|
||||
public:
|
||||
// functions to use as-is:
|
||||
Query();
|
||||
virtual ~Query();
|
||||
|
||||
int fetch();
|
||||
int getNumRowsFetched() const;
|
||||
void done();
|
||||
|
||||
int rowCount();
|
||||
|
||||
QueryMode getMode() const;
|
||||
void setMode(QueryMode newMode);
|
||||
|
||||
std::string outputDataValues() const;
|
||||
|
||||
// functions to override:
|
||||
/** Override this function to return the SQL command for the query.
|
||||
*/
|
||||
virtual void getSQL(std::string &sql)=0;
|
||||
/** Override this function to bind the results returned by the query to
|
||||
variables or to bind parameters in the query.
|
||||
|
||||
See the Database Library documentation for more information, or refer to
|
||||
the various Bindable types. An implementation of bind will probably
|
||||
include lines like
|
||||
|
||||
<pre>
|
||||
mydata.BindCol(1,this);
|
||||
myparameter.BindParameter(1,this);
|
||||
</pre>
|
||||
*/
|
||||
virtual bool bindParameters()=0;
|
||||
virtual bool bindColumns()=0;
|
||||
|
||||
virtual QueryMode getExecutionMode() const;
|
||||
|
||||
virtual void getDebugName(std::string &debugName);
|
||||
|
||||
bool setup(Session *session);
|
||||
bool prepare();
|
||||
bool exec();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline Query::QueryMode Query::getMode() const
|
||||
{
|
||||
return m_queryMode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void Query::setMode(Query::QueryMode newMode)
|
||||
{
|
||||
m_queryMode=newMode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int Query::getNumRowsFetched() const
|
||||
{
|
||||
return m_rowsFetched;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
} //namespace
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBQueryImpl.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBQueryImpl_H
|
||||
#define INCLUDED_DBQueryImpl_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbProtocol.def"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class BindableBool;
|
||||
class BindableDouble;
|
||||
class BindableInt64;
|
||||
class BindableLong;
|
||||
class BindableStringBase;
|
||||
class BindableUnicodeBase;
|
||||
class BindableVarray;
|
||||
class Query;
|
||||
class Session;
|
||||
|
||||
/**
|
||||
* A class to contain the database-specific implementation of a
|
||||
* query.
|
||||
*
|
||||
* The constructor of Query creates an instance of QueryImpl. This
|
||||
* allows the library user to derive classes from Query without
|
||||
* knowing specifics of the implementation.
|
||||
*/
|
||||
class QueryImpl
|
||||
{
|
||||
protected:
|
||||
Query *m_query;
|
||||
|
||||
public:
|
||||
explicit QueryImpl(Query *query);
|
||||
virtual ~QueryImpl() {}; //lint !e1540 //We don't delete m_query (because we don't own it)
|
||||
|
||||
virtual bool setup(Session *session) =0;
|
||||
virtual bool prepare() =0;
|
||||
virtual int fetch() =0;
|
||||
virtual void done() =0;
|
||||
virtual int rowCount() =0; //TODO: Should be getRowCount() to be more consistent
|
||||
virtual bool exec() =0;
|
||||
|
||||
virtual Protocol getProtocol() const =0;
|
||||
|
||||
virtual void setColArrayMode(size_t skipSize, size_t numElements)=0;
|
||||
|
||||
virtual bool bindCol(BindableLong &buffer) =0;
|
||||
virtual bool bindParameter(BindableLong &buffer) =0;
|
||||
virtual bool bindCol(BindableDouble &buffer) =0;
|
||||
virtual bool bindParameter(BindableDouble &buffer) =0;
|
||||
virtual bool bindCol(BindableStringBase &buffer) =0;
|
||||
virtual bool bindParameter(BindableStringBase &buffer) =0;
|
||||
virtual bool bindCol(BindableUnicodeBase &buffer) =0;
|
||||
virtual bool bindParameter(BindableUnicodeBase &buffer) =0;
|
||||
virtual bool bindCol(BindableBool &buffer) =0;
|
||||
virtual bool bindParameter(BindableBool &buffer) =0;
|
||||
virtual bool bindParameter(BindableVarray &buffer) =0;
|
||||
|
||||
virtual std::string outputDataValues() const =0;
|
||||
|
||||
private:
|
||||
QueryImpl(); // disable
|
||||
QueryImpl(const QueryImpl &); // disable
|
||||
QueryImpl & operator=(const QueryImpl &); // disable
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline DB::QueryImpl::QueryImpl(DB::Query *query) :
|
||||
m_query(query)
|
||||
{
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBRow.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbRow.h"
|
||||
|
||||
volatile int DB::Row::m_sRowsCreated = 0;
|
||||
volatile int DB::Row::m_sRowsDeleted = 0;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::Row::Row()
|
||||
{
|
||||
++m_sRowsCreated;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
DB::Row::Row( const Row& )
|
||||
{
|
||||
++m_sRowsCreated;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DB::Row::~Row()
|
||||
{
|
||||
++m_sRowsDeleted;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DB::Row::copy(const Row &rhs)
|
||||
{
|
||||
UNREF(rhs);
|
||||
FATAL(true,("Row::copy() invoked. This error probably means that copy() was not implemented for a class derived from Row."));
|
||||
}
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBRow.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBRow_H
|
||||
#define INCLUDED_DBRow_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* This is the base class for classes that represent a row of data returned
|
||||
* from the database.
|
||||
*
|
||||
* The goal is that in many cases, classes derived from Row will be generated
|
||||
* directly from the database schema. Therefore, the class is kept as simple
|
||||
* as possible.
|
||||
*/
|
||||
struct Row
|
||||
{
|
||||
Row();
|
||||
Row( const Row& );
|
||||
|
||||
virtual ~Row();
|
||||
/**
|
||||
* This function is like a virtual operator=.
|
||||
*
|
||||
* Implement this function in derived classes. It should do something
|
||||
* equivalent to *this = dynamic_cast<const derived_class_name&>(rhs)
|
||||
*
|
||||
* This function is not pure virtual so that derived classes do not need
|
||||
* to define it if they do not plan to use it. However, the default
|
||||
* implementation will FATAL.
|
||||
*
|
||||
* @todo We could make a CopyableRow class derived from Row that has
|
||||
* this function as pure virtual. However, that might limit our ability
|
||||
* to generate Row's directly from the database schema without regards to
|
||||
* how they will be used.
|
||||
*/
|
||||
virtual void copy(const Row &rhs);
|
||||
|
||||
static int getRowsCreated() { return m_sRowsCreated; }
|
||||
static int getRowsDeleted() { return m_sRowsDeleted; }
|
||||
|
||||
private:
|
||||
static volatile int m_sRowsCreated;
|
||||
static volatile int m_sRowsDeleted;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// ======================================================================
|
||||
#endif
|
||||
@@ -0,0 +1,410 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBServer.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
|
||||
#include <string>
|
||||
#include "sharedDatabaseInterface/DbSession.h"
|
||||
#include "sharedDatabaseInterface/DbProfiler.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
#ifdef DBLIBRARY_ODBC
|
||||
#include "OdbcServer.h" //TODO: is this the best way to do DBServer::create()
|
||||
#endif
|
||||
#ifdef DBLIBRARY_OCI
|
||||
#include "OciServer.h"
|
||||
#endif
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
Mutex Server::ms_profileMutex;
|
||||
bool Server::ms_enableProfiling = false;
|
||||
bool Server::ms_enableVerboseMode = false;
|
||||
DB::Profiler *Server::ms_profiler = NULL;
|
||||
int Server::ms_reconnectTime=0;
|
||||
int Server::ms_maxErrorCountBeforeDisconnect=5;
|
||||
int Server::ms_maxErrorCountBeforeBailout=10;
|
||||
int Server::ms_errorSleepTime=5000;
|
||||
int Server::ms_disconnectSleepTime=45000;
|
||||
int Server::ms_execCount=0;
|
||||
int Server::ms_fetchCount=0;
|
||||
int Server::ms_prefetchNumRows=0;
|
||||
int Server::ms_prefetchMemory=0;
|
||||
bool Server::ms_fatalOnError=false;
|
||||
bool Server::ms_fatalOnDataError=false;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
Server::SesListElem::SesListElem (Session *_ses, SesListElem *_next) : ses (_ses), next (_next)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Server::Server(const char *_dsn, const char *_uid, const char *_pwd, bool useMemoryManager) :
|
||||
sessionList (NULL),
|
||||
sessionListLock(),
|
||||
m_useMemoryManager(useMemoryManager)
|
||||
{
|
||||
strncpy(dsn,_dsn,sizeof(dsn)-1);
|
||||
strncpy(uid,_uid,sizeof(uid)-1);
|
||||
strncpy(pwd,_pwd,sizeof(pwd)-1);
|
||||
|
||||
//insure terminating \0:
|
||||
dsn[sizeof(dsn)-1]='\0';
|
||||
uid[sizeof(uid)-1]='\0';
|
||||
pwd[sizeof(pwd)-1]='\0';
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Server destructor
|
||||
// TODO: what to do if deallocating handles failes? (This could happen if connection isn't closed properly, etc.)
|
||||
Server::~Server()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Establish connections to the database server.
|
||||
* Sessions will be pre-connected and put in the pool of sessions. The
|
||||
* caller can later request up to that number of sessions by calling
|
||||
* GetSession(), with no blocking. Requests for additional sessions may
|
||||
* block.
|
||||
*
|
||||
* @param numSessions The number of sessions to establish.
|
||||
*/
|
||||
|
||||
bool Server::connect(int numSessions)
|
||||
{
|
||||
disconnect();
|
||||
|
||||
for (int i=0;i<numSessions;i++)
|
||||
{
|
||||
Session *ses=createSession();
|
||||
if (!ses->connect())
|
||||
{
|
||||
ses->disconnect();
|
||||
LOG("DatabaseError", ("Failed to connect to database in getSession()"));
|
||||
FATAL(true, ("Failed to connect to database in getSession()"));
|
||||
}
|
||||
pushSession (ses);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Drop all the sessions in the pool of sessions.
|
||||
* After calling Disconnect(), any call to GetSession() will require
|
||||
* establishing a new connection to the database server.
|
||||
* Note that this call only affects Sessions in the pool. Sessions that
|
||||
* are currently in use are not affected.
|
||||
*/
|
||||
bool Server::disconnect()
|
||||
{
|
||||
Session *ses=popSession();
|
||||
while(ses)
|
||||
{
|
||||
delete ses;
|
||||
ses=popSession();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get a Session object, representing a session on the database server.
|
||||
* Will return a Session object from the pool, if one is avaiable.
|
||||
* Otherwise, it will establish a new session. Warning: establishing
|
||||
* a new session may require a database roundtrip. (i.e. It may block.)
|
||||
* To avoid blocking, use connect() ahead of time to establish all the
|
||||
* needed Sessions.
|
||||
*/
|
||||
Session *Server::getSession()
|
||||
{
|
||||
Session *ses=popSession();
|
||||
|
||||
if (!ses) // pool was empty, so make a new one. TODO: set a limit on max # of sessions
|
||||
{
|
||||
ses=createSession();
|
||||
while (!ses->connect())
|
||||
{
|
||||
ses->disconnect();
|
||||
LOG("DatabaseError", ("Failed to connect to database in getSession(). Will reconnect in 30 seconds."));
|
||||
Os::sleep(30000);
|
||||
}
|
||||
}
|
||||
return ses;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Call when finished with a Session object.
|
||||
* Returns the Session object to the pool.
|
||||
* @todo for debugging, make sure the session released actually came from this server
|
||||
*/
|
||||
void Server::releaseSession(Session *session)
|
||||
{
|
||||
session->reset();
|
||||
pushSession(session);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::pushSession(Session *session)
|
||||
{
|
||||
sessionListLock.enter();
|
||||
|
||||
SesListElem *e=new SesListElem(session, sessionList);
|
||||
sessionList=e;
|
||||
|
||||
sessionListLock.leave();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Session *Server::popSession()
|
||||
{
|
||||
sessionListLock.enter();
|
||||
|
||||
SesListElem *e=sessionList;
|
||||
if (e)
|
||||
{
|
||||
Session *ses=e->ses;
|
||||
sessionList=e->next;
|
||||
delete e;
|
||||
sessionListLock.leave();
|
||||
return ses;
|
||||
}
|
||||
else
|
||||
{
|
||||
sessionListLock.leave();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Server *Server::create(const char *_dsn, const char *_uid, const char *_pwd, Protocol protocol, bool useMemoryManager)
|
||||
{
|
||||
UNREF(_dsn);
|
||||
UNREF(_uid);
|
||||
UNREF(_pwd);
|
||||
|
||||
switch (protocol)
|
||||
{
|
||||
|
||||
#ifdef DBLIBRARY_ODBC
|
||||
case PROTOCOL_ODBC:
|
||||
return new ODBCServer(_dsn,_uid,_pwd);
|
||||
#endif
|
||||
|
||||
#ifdef DBLIBRARY_OCI
|
||||
case PROTOCOL_OCI:
|
||||
return new OCIServer(_dsn,_uid,_pwd, useMemoryManager);
|
||||
#endif
|
||||
|
||||
case PROTOCOL_DEFAULT:
|
||||
// Create any kind of server we can, prefering ODBCServer
|
||||
#ifdef DBLIBRARY_ODBC
|
||||
return new ODBCServer(_dsn,_uid,_pwd);
|
||||
#endif
|
||||
|
||||
#ifdef DBLIBRARY_OCI
|
||||
return new OCIServer(_dsn,_uid,_pwd, useMemoryManager);
|
||||
#endif
|
||||
|
||||
default:
|
||||
FATAL(true,("Database protocol specified in Server::create() is not available in this build of the library.\n"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Protocol Server::getProtocolByName(const std::string &name)
|
||||
{
|
||||
|
||||
#ifdef DBLIBRARY_ODBC
|
||||
if (name=="ODBC")
|
||||
return PROTOCOL_ODBC;
|
||||
#endif
|
||||
|
||||
#ifdef DBLIBRARY_OCI
|
||||
if (name=="OCI")
|
||||
return PROTOCOL_OCI;
|
||||
#endif
|
||||
|
||||
if (name=="DEFAULT")
|
||||
return PROTOCOL_DEFAULT;
|
||||
|
||||
FATAL(true,("Specified protocol (%s) is not available in this version of the database library.",name.c_str()));
|
||||
return PROTOCOL_DEFAULT;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::addQueryProfileData(const std::string &queryName, int execTime, int fetchTime, int execCount, int fetchCount)
|
||||
{
|
||||
ms_profileMutex.enter();
|
||||
|
||||
DEBUG_FATAL(!isProfilingEnabled(),("Programmer bug: you're supposed to check whether profiling is enabled before calling DB::Server::addProfileData (or there could be a race condition that is disabling profiling while queries are running).\n"));
|
||||
if (!ms_profiler)
|
||||
{
|
||||
ms_profiler = new DB::Profiler;
|
||||
}
|
||||
|
||||
ms_profiler->addQueryProfileData(queryName,execTime,fetchTime,execCount,fetchCount);
|
||||
ms_profileMutex.leave();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::debugOutputProfile()
|
||||
{
|
||||
ms_profileMutex.enter();
|
||||
if (ms_profiler)
|
||||
ms_profiler->debugOutput();
|
||||
else
|
||||
DEBUG_REPORT_LOG(true,("No database profiler.\n"));
|
||||
ms_profileMutex.leave();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stop collecting profile data and delete the Profiler.
|
||||
*/
|
||||
void Server::endProfiling()
|
||||
{
|
||||
ms_profileMutex.enter();
|
||||
delete ms_profiler;
|
||||
ms_profiler = NULL;
|
||||
ms_enableProfiling = false;
|
||||
ms_profileMutex.leave();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set a timeout for server connections. If a connection to the database
|
||||
* has been open for more than reconnectTime, it will drop the connection
|
||||
* and reestablish it the next time Session::reset() is called.
|
||||
*/
|
||||
void Server::setReconnectTime(int reconnectTime)
|
||||
{
|
||||
ms_reconnectTime = reconnectTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Count the total number of queries executed and the total number of fetches
|
||||
* for profiling. (This level of profiling is always enabled. The
|
||||
* per-query profiling is optionally enabled.)
|
||||
*/
|
||||
void Server::addQueryCount(int execCount, int fetchCount)
|
||||
{
|
||||
ms_profileMutex.enter();
|
||||
|
||||
ms_execCount+=execCount;
|
||||
ms_fetchCount+=fetchCount;
|
||||
|
||||
ms_profileMutex.leave();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::enablePrefetch(int numRows, int memory)
|
||||
{
|
||||
ms_prefetchNumRows = numRows;
|
||||
ms_prefetchMemory = memory;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::disablePrefetch()
|
||||
{
|
||||
ms_prefetchNumRows = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Server::isPrefetchEnabled()
|
||||
{
|
||||
return (ms_prefetchNumRows > 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int Server::getPrefetchRows()
|
||||
{
|
||||
return ms_prefetchNumRows;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int Server::getPrefetchMemory()
|
||||
{
|
||||
return ms_prefetchMemory;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::getAndResetQueryCount(int &execCount, int &fetchCount)
|
||||
{
|
||||
ms_profileMutex.enter();
|
||||
|
||||
execCount=ms_execCount;
|
||||
fetchCount=ms_fetchCount;
|
||||
|
||||
ms_execCount=0;
|
||||
ms_fetchCount=0;
|
||||
|
||||
ms_profileMutex.leave();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::setFatalOnError(bool fatalOnError)
|
||||
{
|
||||
ms_fatalOnError=fatalOnError;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Server::getFatalOnError()
|
||||
{
|
||||
return ms_fatalOnError;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Server::setFatalOnDataError(bool fatalOnDataError)
|
||||
{
|
||||
ms_fatalOnDataError=fatalOnDataError;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Server::getFatalOnDataError()
|
||||
{
|
||||
return ms_fatalOnDataError;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,274 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBServer.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBServer_H
|
||||
#define INCLUDED_DBServer_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/DbProtocol.def"
|
||||
#include "sharedSynchronization/Mutex.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
class Session;
|
||||
class Profiler;
|
||||
|
||||
/**
|
||||
* The Server class handles connecting to an external database server. It knows how to establish connections,
|
||||
* do error handling, etc. Create a Server object for each database you with to connect to. Then, call getSession()
|
||||
* to get a Session object, which represents an individual session on the database server. Queries can be passed
|
||||
* to the Session object.
|
||||
*
|
||||
* The Server class does session pooling. Call the Connect() method to pre-allocate some Sessions in a pool.
|
||||
* getSession() will return one of the Sessions from the pool, without blocking. If the pool is empty, getSession()
|
||||
* will establish a new Session, which may require some blocking while the underlying network connection is set up.
|
||||
*
|
||||
* The Server class is threadsafe. Servers can be shared between threads. Sessions and Queries should not be shared.
|
||||
* @todo Actually, it isn't threadsafe. Need to fix that.
|
||||
*/
|
||||
class Server
|
||||
{
|
||||
/** A sub-class to hold the elements in the list of Sessions making up the Session pool
|
||||
*/
|
||||
struct SesListElem {
|
||||
Session *ses;
|
||||
SesListElem *next;
|
||||
|
||||
SesListElem (Session *_ses, SesListElem *_next);
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
char dsn[80],uid[80],pwd[80];
|
||||
|
||||
private:
|
||||
|
||||
/** Pool of available Sessions.
|
||||
*/
|
||||
SesListElem *sessionList;
|
||||
|
||||
Mutex sessionListLock;
|
||||
bool m_useMemoryManager;
|
||||
|
||||
static Mutex ms_profileMutex;
|
||||
static bool ms_enableProfiling;
|
||||
static bool ms_enableVerboseMode;
|
||||
static Profiler *ms_profiler;
|
||||
|
||||
static int ms_prefetchNumRows;
|
||||
static int ms_prefetchMemory;
|
||||
|
||||
static int ms_reconnectTime;
|
||||
static int ms_maxErrorCountBeforeDisconnect;
|
||||
static int ms_maxErrorCountBeforeBailout;
|
||||
static int ms_errorSleepTime;
|
||||
static int ms_disconnectSleepTime;
|
||||
|
||||
static int ms_execCount;
|
||||
static int ms_fetchCount;
|
||||
|
||||
static bool ms_fatalOnError;
|
||||
static bool ms_fatalOnDataError;
|
||||
|
||||
public:
|
||||
|
||||
Server(const char *_dsn, const char *_uid, const char *_pwd, bool useMemoryManager); // TODO: should be protected?
|
||||
virtual ~Server();
|
||||
|
||||
static Server *create(const char *_dsn, const char *_uid, const char *_pwd, Protocol protocol, bool useMemoryManager);
|
||||
static Protocol getProtocolByName(const std::string &name);
|
||||
|
||||
Session *getSession();
|
||||
void releaseSession(Session *session);
|
||||
|
||||
bool connect(int numSessions=1);
|
||||
bool disconnect();
|
||||
|
||||
const char *getDSN() const;
|
||||
bool getUseMemoryManager() const;
|
||||
|
||||
static void enableProfiling();
|
||||
static void disableProfiling();
|
||||
static void endProfiling();
|
||||
static bool isProfilingEnabled();
|
||||
static void enableVerboseMode();
|
||||
static void disableVerboseMode();
|
||||
static bool isVerboseModeEnabled();
|
||||
static void enablePrefetch(int numRows, int memory);
|
||||
static void disablePrefetch();
|
||||
static bool isPrefetchEnabled();
|
||||
static int getPrefetchRows();
|
||||
static int getPrefetchMemory();
|
||||
static void addQueryProfileData(const std::string &queryName, int execTime, int fetchTime, int execCount, int fetchCount);
|
||||
static void debugOutputProfile();
|
||||
|
||||
static void addQueryCount(int execCount, int fetchCount);
|
||||
static void getAndResetQueryCount(int &execCount, int &fetchCount);
|
||||
|
||||
static void setReconnectTime(int reconnectTime);
|
||||
static int getReconnectTime();
|
||||
|
||||
static void setMaxErrorCountBeforeDisconnect(int maxErrorCountBeforeDisconnect);
|
||||
static int getMaxErrorCountBeforeDisconnect();
|
||||
|
||||
static void setMaxErrorCountBeforeBailout(int maxErrorCountBeforeBailout);
|
||||
static int getMaxErrorCountBeforeBailout();
|
||||
|
||||
static void setErrorSleepTime(int errorSleepTime);
|
||||
static int getErrorSleepTime();
|
||||
|
||||
static void setDisconnectSleepTime(int disconnectSleepTime);
|
||||
static int getDisconnectSleepTime();
|
||||
|
||||
static void setFatalOnError(bool fatalOnError);
|
||||
static bool getFatalOnError();
|
||||
|
||||
static void setFatalOnDataError(bool fatalOnDataError);
|
||||
static bool getFatalOnDataError();
|
||||
|
||||
protected:
|
||||
|
||||
virtual Session *createSession() =0;
|
||||
|
||||
private:
|
||||
|
||||
void pushSession(Session *session);
|
||||
Session *popSession();
|
||||
|
||||
private:
|
||||
Server(); //disable
|
||||
Server(const Server &); //disable
|
||||
Server & operator=(const Server &); //disable
|
||||
}; //lint !e1712 // no default constructor for SesListElem
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline const char *DB::Server::getDSN() const
|
||||
{
|
||||
return dsn;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool DB::Server::isProfilingEnabled()
|
||||
{
|
||||
return ms_enableProfiling;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool DB::Server::isVerboseModeEnabled()
|
||||
{
|
||||
return ms_enableVerboseMode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::enableProfiling()
|
||||
{
|
||||
ms_enableProfiling = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::disableProfiling()
|
||||
{
|
||||
ms_enableProfiling = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::enableVerboseMode()
|
||||
{
|
||||
ms_enableVerboseMode = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::disableVerboseMode()
|
||||
{
|
||||
ms_enableVerboseMode = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int DB::Server::getReconnectTime()
|
||||
{
|
||||
return ms_reconnectTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool DB::Server::getUseMemoryManager() const
|
||||
{
|
||||
return m_useMemoryManager;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::setMaxErrorCountBeforeDisconnect(int maxErrorCountBeforeDisconnect)
|
||||
{
|
||||
ms_maxErrorCountBeforeDisconnect = maxErrorCountBeforeDisconnect;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int DB::Server::getMaxErrorCountBeforeDisconnect()
|
||||
{
|
||||
return ms_maxErrorCountBeforeDisconnect;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::setMaxErrorCountBeforeBailout(int maxErrorCountBeforeBailout)
|
||||
{
|
||||
ms_maxErrorCountBeforeBailout = maxErrorCountBeforeBailout;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int DB::Server::getMaxErrorCountBeforeBailout()
|
||||
{
|
||||
return ms_maxErrorCountBeforeBailout;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::setErrorSleepTime(int errorSleepTime)
|
||||
{
|
||||
ms_errorSleepTime=errorSleepTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int DB::Server::getErrorSleepTime()
|
||||
{
|
||||
return ms_errorSleepTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void DB::Server::setDisconnectSleepTime(int disconnectSleepTime)
|
||||
{
|
||||
ms_disconnectSleepTime=disconnectSleepTime;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline int DB::Server::getDisconnectSleepTime()
|
||||
{
|
||||
return ms_disconnectSleepTime;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBSession.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbSession.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
|
||||
using namespace DB;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* Do not create session objects directly.
|
||||
* Instead, use DB::Server::GetSession().
|
||||
*/
|
||||
Session::Session() : inUse(false), connected(false), lastQuery(0), lastQueryStatement(), m_execCount(0), m_fetchCount(0), m_fatalOnError(false)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Session::~Session()
|
||||
{
|
||||
DEBUG_FATAL(inUse,("Deleted a session that was still in use.\n"));
|
||||
DEBUG_FATAL(connected,("Derived session did not disconnect."));
|
||||
} //lint !e1540 // didn't delete lastQuery
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Execute a database query, represented by a Query object.
|
||||
*/
|
||||
bool Session::exec(Query *query)
|
||||
{
|
||||
NOT_NULL(query);
|
||||
|
||||
if (!inUse) // if the query was just run, we don't need to do the setup again
|
||||
{
|
||||
if (!query->setup(this)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// debugging: make sure this is the _same_ query
|
||||
DEBUG_FATAL(lastQuery!=query,("Called Session::exec() on a query without calling done() on the previous query."));
|
||||
}
|
||||
|
||||
if (!query->exec())
|
||||
{
|
||||
std::string context;
|
||||
query->getDebugName(context);
|
||||
WARNING(true, ("Context from previous database error: %s", context.c_str()));
|
||||
LOG("DatabaseError", ("Context from previous database error: %s", context.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
lastQuery=query;
|
||||
inUse=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/** [Function used by other classes in the database library.] Called when a Query object finishes its work, so that
|
||||
the Session is now free to run another Query.
|
||||
*/
|
||||
void Session::queryDone()
|
||||
{
|
||||
inUse=false;
|
||||
lastQuery=0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Session::addQueryCount(int execCount, int fetchCount)
|
||||
{
|
||||
m_execCount += execCount;
|
||||
m_fetchCount += fetchCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Session::updateServerQueryCount()
|
||||
{
|
||||
Server::addQueryCount(m_execCount, m_fetchCount);
|
||||
m_execCount=0;
|
||||
m_fetchCount=0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Session::setLastQueryStatement(std::string const & queryStatement)
|
||||
{
|
||||
lastQueryStatement = queryStatement;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string Session::getLastQueryStatement() const
|
||||
{
|
||||
return lastQueryStatement;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Session::setFatalOnError(bool fatalOnError)
|
||||
{
|
||||
m_fatalOnError=fatalOnError;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Session::getFatalOnError() const
|
||||
{
|
||||
return m_fatalOnError;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,141 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// DBSession.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_DBSession_H
|
||||
#define INCLUDED_DBSession_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace DB {
|
||||
|
||||
class Server;
|
||||
class Query;
|
||||
class QueryImpl;
|
||||
|
||||
/**
|
||||
* A DBSession is an object representing a connection on which a series
|
||||
* of queries can be performed. A database session is much like a session
|
||||
* at a command prompt in an operating system. Within a session, one query
|
||||
* can be sent at a time and nothing else can be done in that session until
|
||||
* the results of the query are returned. A session may be thought of as a
|
||||
* logical connection to the database.
|
||||
*
|
||||
* Do not create DBSession objects directly. Use the GetSession method on
|
||||
* DBServer instead. Be sure to call DBServer::ReleaseSession() when you
|
||||
* are done with the session, so that others may use it.
|
||||
*
|
||||
* Note that DBSession objects can't be copied. Database libraries do not
|
||||
* allow a session to be cloned, so the semantics of copying a session object
|
||||
* are not clear. Therefore, it is not allowed.
|
||||
*
|
||||
* TODO: Consider making an autoptr-like object to hold sessions. It would
|
||||
* automatically call ReleaseSession() when it goes out of scope.
|
||||
*/
|
||||
class Session
|
||||
{
|
||||
bool inUse;
|
||||
|
||||
// following are disallowed:
|
||||
Session(const Session& rhs);
|
||||
Session &operator=(const Session& rhs);
|
||||
|
||||
protected:
|
||||
bool connected;
|
||||
|
||||
private:
|
||||
Query *lastQuery;
|
||||
std::string lastQueryStatement;
|
||||
int m_execCount;
|
||||
int m_fetchCount;
|
||||
bool m_fatalOnError;
|
||||
|
||||
public:
|
||||
Session(); // TODO: should be private
|
||||
virtual ~Session();
|
||||
|
||||
// functions used by other SQLClasses
|
||||
void queryDone();
|
||||
|
||||
/** [Function used by other classes in the database library.] Establish connection to a database server.
|
||||
*/
|
||||
virtual bool connect() =0;
|
||||
|
||||
/** [Function used by other classes in the database library.] Drop connection to a database server.
|
||||
*/
|
||||
virtual bool disconnect() =0;
|
||||
|
||||
/** [Function used by other classes in the database library.] Reset the session to its default status
|
||||
(e.g. before returning it to the session pool). Undo any special options the user may have set,
|
||||
such as setting manual-commit mode.
|
||||
|
||||
If this returns false, an error occurred trying to restore the state. The best thing to do is
|
||||
probably to drop the session and establish a new one.
|
||||
*/
|
||||
virtual bool reset() =0;
|
||||
|
||||
bool exec(Query *query);
|
||||
|
||||
/** Set the session to auto-commit or manual-commit mode.
|
||||
|
||||
If in auto-commit mode, every query set to Exec() is automatically
|
||||
commited immediately. If in manual commit mode, the changes made
|
||||
by queries passed to Exec() are considered to be part of a transaction.
|
||||
They are remembered by the database, but they don't take effect
|
||||
immediately. When CommitTransaction() is called, the changes all
|
||||
take effect simultaneously.
|
||||
|
||||
(Warning: switching from manual-commit mode to auto-commit mode
|
||||
automatically commits any open transactions.)
|
||||
|
||||
@param autocommit TRUE turns on auto-commit mode (the default),
|
||||
FALSE turns on manual-commit mode
|
||||
*/
|
||||
virtual bool setAutoCommitMode(bool autocommit) =0;
|
||||
|
||||
/** Set the session to FATAL on a database error, rather than returning
|
||||
"false" to the caller.
|
||||
*/
|
||||
void setFatalOnError(bool fatalOnError);
|
||||
bool getFatalOnError() const;
|
||||
|
||||
/** Commit a transaction.
|
||||
Everything done within the transaction will simultaneously take effect.
|
||||
*/
|
||||
virtual bool commitTransaction() =0;
|
||||
|
||||
/** Rollback a transaction
|
||||
Evertyhing done within the transaction will be undone.
|
||||
*/
|
||||
virtual bool rollbackTransaction() =0;
|
||||
|
||||
/** Add to the count of the number of fetches and executes.
|
||||
|
||||
Each query adds to this count as it finishes.
|
||||
*/
|
||||
void addQueryCount(int execCount, int fetchCount);
|
||||
|
||||
/** Update the total count of fetches and executes in the Server object
|
||||
*/
|
||||
void updateServerQueryCount();
|
||||
|
||||
/** Set/Get the last query statement that was run; useful for debugging purposes
|
||||
*/
|
||||
void setLastQueryStatement(std::string const & queryStatement);
|
||||
std::string getLastQueryStatement() const;
|
||||
|
||||
virtual QueryImpl *createQueryImpl(Query *owner) const =0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstServerDatabaseInterface.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_FirstServerDatabaseInterface_H
|
||||
#define INCLUDED_FirstServerDatabaseInterface_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedDebug/FirstSharedDebug.h"
|
||||
#include "sharedMemoryManager/FirstSharedMemoryManager.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NullEncodedStandardString.cpp
|
||||
// copyright (c) 2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/NullEncodedStandardString.h"
|
||||
|
||||
#include "Archive/Archive.h"
|
||||
#include "Archive/ByteStream.h"
|
||||
#include "UnicodeUtils.h"
|
||||
#include "unicodeArchive/UnicodeArchive.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace NullEncodedStandardStringNamespace
|
||||
{
|
||||
std::string s_nullString;
|
||||
std::string s_encodedNull( " " ); // blank space
|
||||
}
|
||||
using namespace NullEncodedStandardStringNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
NullEncodedStandardString::NullEncodedStandardString(std::string const & src) :
|
||||
m_value(src.empty() ? s_encodedNull : src)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
NullEncodedStandardString:: NullEncodedStandardString() :
|
||||
m_value()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NullEncodedStandardString::setValue(std::string const & src)
|
||||
{
|
||||
m_value = src.empty() ? s_encodedNull : src;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string const & NullEncodedStandardString::getValue() const
|
||||
{
|
||||
if (m_value == s_encodedNull)
|
||||
return s_nullString;
|
||||
else
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string const & NullEncodedStandardString::getValueEncoded() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NullEncodedStandardString::setValueEncoded(std::string const & src)
|
||||
{
|
||||
m_value = src;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace Archive
|
||||
{
|
||||
void get(ReadIterator & source, NullEncodedStandardString & target)
|
||||
{
|
||||
std::string temp;
|
||||
get(source, temp);
|
||||
target.setValue(temp);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void put(ByteStream & target, const NullEncodedStandardString & source)
|
||||
{
|
||||
put(target, source.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NullEncodedStandardString.h
|
||||
// copyright (c) 2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_NullEncodedStandardString_H
|
||||
#define INCLUDED_NullEncodedStandardString_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "Unicode.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* A unicode-string-compatible class that encodes a null value as a single space
|
||||
*/
|
||||
class NullEncodedStandardString
|
||||
{
|
||||
public:
|
||||
NullEncodedStandardString();
|
||||
explicit NullEncodedStandardString(std::string const & src);
|
||||
std::string const & getValue() const;
|
||||
void setValue(std::string const & src);
|
||||
std::string const & getValueEncoded() const;
|
||||
void setValueEncoded(std::string const & src);
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace Archive
|
||||
{
|
||||
class ReadIterator;
|
||||
class ByteStream;
|
||||
|
||||
void get(ReadIterator & source, NullEncodedStandardString & target);
|
||||
void put(ByteStream & target, const NullEncodedStandardString & source);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif // INCLUDED_NullEncodedStandardString_H
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NullEncodedUnicodeString.cpp
|
||||
// copyright (c) 2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/NullEncodedUnicodeString.h"
|
||||
|
||||
#include "Archive/Archive.h"
|
||||
#include "Archive/ByteStream.h"
|
||||
#include "UnicodeUtils.h"
|
||||
#include "unicodeArchive/UnicodeArchive.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace NullEncodedUnicodeStringNamespace
|
||||
{
|
||||
Unicode::String s_nullString;
|
||||
Unicode::String s_encodedNull(Unicode::narrowToWide(" "));
|
||||
}
|
||||
using namespace NullEncodedUnicodeStringNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
NullEncodedUnicodeString::NullEncodedUnicodeString(Unicode::String const & src) :
|
||||
m_value(src.empty() ? s_encodedNull : src)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
NullEncodedUnicodeString:: NullEncodedUnicodeString() :
|
||||
m_value()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NullEncodedUnicodeString::setValue(Unicode::String const & src)
|
||||
{
|
||||
m_value = src.empty() ? s_encodedNull : src;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Unicode::String const & NullEncodedUnicodeString::getValue() const
|
||||
{
|
||||
if (m_value == s_encodedNull)
|
||||
return s_nullString;
|
||||
else
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Unicode::String const & NullEncodedUnicodeString::getValueEncoded() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NullEncodedUnicodeString::setValueEncoded(Unicode::String const & src)
|
||||
{
|
||||
m_value = src;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace Archive
|
||||
{
|
||||
void get(ReadIterator & source, NullEncodedUnicodeString & target)
|
||||
{
|
||||
Unicode::String temp;
|
||||
get(source, temp);
|
||||
target.setValue(temp);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void put(ByteStream & target, const NullEncodedUnicodeString & source)
|
||||
{
|
||||
put(target, source.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NullEncodedUnicodeString.h
|
||||
// copyright (c) 2004 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_NullEncodedUnicodeString_H
|
||||
#define INCLUDED_NullEncodedUnicodeString_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "Unicode.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
/**
|
||||
* A unicode-string-compatible class that encodes a null value as a single space
|
||||
*/
|
||||
class NullEncodedUnicodeString
|
||||
{
|
||||
public:
|
||||
NullEncodedUnicodeString();
|
||||
explicit NullEncodedUnicodeString(Unicode::String const & src);
|
||||
Unicode::String const & getValue() const;
|
||||
void setValue(Unicode::String const & src);
|
||||
Unicode::String const & getValueEncoded() const;
|
||||
void setValueEncoded(Unicode::String const & src);
|
||||
|
||||
private:
|
||||
Unicode::String m_value;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace Archive
|
||||
{
|
||||
class ReadIterator;
|
||||
class ByteStream;
|
||||
|
||||
void get(ReadIterator & source, NullEncodedUnicodeString & target);
|
||||
void put(ByteStream & target, const NullEncodedUnicodeString & source);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbLogEvent.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
|
||||
//#include "LogQueries.h"
|
||||
//#include "Schema.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using namespace DB;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LogEvent::LogEvent() :
|
||||
eventTime(Os::getRealSystemTime())
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//bool TestEvent::save(DB::Session *session)
|
||||
//{
|
||||
// DBQuery::SaveTestEvent qry;
|
||||
// DBSchema::ServerLogRow data;
|
||||
|
||||
// qry.setData(&data);
|
||||
// qry.insertMode();
|
||||
|
||||
// data.event_time=eventTime;
|
||||
// data.server=3434;
|
||||
// data.event_id=1;
|
||||
|
||||
// session->exec(&qry);
|
||||
|
||||
// qry.done();
|
||||
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef _LOG_EVENT_H
|
||||
#define _LOG_EVENT_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class Session;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* This is an abstract base class for events that can be logged.
|
||||
*
|
||||
* To create a LogEvent for a particular purpose, derive from this class.
|
||||
* Override the save function to do whatever is needed to record the
|
||||
* particular event.
|
||||
*/
|
||||
class LogEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default constructor stored the current system time in eventTime.
|
||||
*/
|
||||
LogEvent();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Saves the LogEvent to the database.
|
||||
*
|
||||
* Override this function in derived classes to save specific data.
|
||||
*/
|
||||
virtual bool save(DB::Session *session) =0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The time the event occurred, in seconds since the epoch.
|
||||
*/
|
||||
time_t eventTime;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbLogger.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
#include "sharedDatabaseInterface/DbTaskQueue.h"
|
||||
#include "sharedDatabaseInterface/DbTaskSaveLog.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using namespace DB;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Logger::EventsType Logger::events;
|
||||
int Logger::maxQueuedEvents;
|
||||
real Logger::maxTimeBeforeSave;
|
||||
real Logger::timeSinceLastSave=0;
|
||||
TaskQueue *Logger::taskQueue=0;
|
||||
bool Logger::installed=false;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set up the logger.
|
||||
*
|
||||
*
|
||||
* @param server The database server to send events to.
|
||||
* @param _maxQueuedEvents The maximum number of events that can be queued
|
||||
* before a save is forced.
|
||||
* @param _maxTimeBeforeSave The maximum amount of time that can pass before a
|
||||
* save is forced.
|
||||
*/
|
||||
|
||||
void Logger::install(Server *server, int _maxQueuedEvents, real _maxTimeBeforeSave)
|
||||
{
|
||||
maxQueuedEvents=_maxQueuedEvents;
|
||||
maxTimeBeforeSave=_maxTimeBeforeSave;
|
||||
//TODO: establish database connection
|
||||
taskQueue=new TaskQueue(1,server,0);
|
||||
|
||||
installed=true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Logger::remove()
|
||||
{
|
||||
//TODO: wait for task queue to complete - or will destructor handle it?
|
||||
delete taskQueue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Add an event to the queue to be logged.
|
||||
*
|
||||
* @param event The event to be logged. Will be deleted when the logger is done
|
||||
* with it.
|
||||
*/
|
||||
|
||||
void Logger::log(LogEvent *event)
|
||||
{
|
||||
events.push_back(event);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Evaluates whether it is time to save the accumulated log events.
|
||||
*
|
||||
* This should be called periodically, i.e. once per game loop.
|
||||
*
|
||||
* @param time The time in seconds since this function was last invoked.
|
||||
*/
|
||||
|
||||
void Logger::update(real time)
|
||||
{
|
||||
timeSinceLastSave+=time;
|
||||
if ((timeSinceLastSave > 10) || (events.size() > 10))
|
||||
beginSave();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Start an asynchronous task to save the current events.
|
||||
*
|
||||
* We don't care if another save is already in progress, because save tasks
|
||||
* should not conflict with eachother.
|
||||
*/
|
||||
|
||||
void Logger::beginSave()
|
||||
{
|
||||
if (events.size() == 0)
|
||||
return;
|
||||
|
||||
TaskSaveLog *tsl=new TaskSaveLog;
|
||||
|
||||
// Copy events to the new task
|
||||
for (EventsType::iterator i=events.begin(); i!=events.end(); ++i)
|
||||
{
|
||||
tsl->addEvent(*i);
|
||||
}
|
||||
|
||||
events.clear();
|
||||
|
||||
taskQueue->asyncRequest(tsl);
|
||||
} //lint !e429 // didn't free tsl
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef _LOGGER_H
|
||||
#define _LOGGER_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <vector>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class LogEvent;
|
||||
class TaskQueue;
|
||||
class Server;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* A class that organizes sending LogEvents to the database.
|
||||
*
|
||||
* This class will collect LogEvents and periodically send them to
|
||||
* the database to be recorded.
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
static void log(LogEvent *event);
|
||||
// Maybe, in derived class:
|
||||
// logPlayerEvent(int player, ...);
|
||||
// etc.
|
||||
|
||||
static void update(real time);
|
||||
|
||||
public:
|
||||
//TODO: come up with reasonable defaults for these parameters:
|
||||
static void install(Server *server, int _maxQueuedEvents=10, real _maxTimeBeforeSave=10.0);
|
||||
static void remove(void);
|
||||
|
||||
private:
|
||||
static void beginSave(void);
|
||||
|
||||
private:
|
||||
static bool installed;
|
||||
|
||||
static int maxQueuedEvents;
|
||||
static real maxTimeBeforeSave;
|
||||
|
||||
typedef std::vector<LogEvent*> EventsType;
|
||||
static EventsType events;
|
||||
|
||||
static real timeSinceLastSave;
|
||||
|
||||
static TaskQueue *taskQueue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbTaskSaveLog.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbLogEvent.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using namespace DB;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Add a LogEvent to the list to be saved.
|
||||
*/
|
||||
|
||||
void TaskSaveLog::addEvent(LogEvent *event)
|
||||
{
|
||||
events.push_back(event);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool TaskSaveLog::process(DB::Session *session)
|
||||
{
|
||||
for (EventsType::iterator i=events.begin(); i!=events.end(); ++i)
|
||||
{
|
||||
if(! ((*i)->save(session)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TaskSaveLog::onComplete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TaskSaveLog::~TaskSaveLog()
|
||||
{
|
||||
for (EventsType::iterator i=events.begin(); i!=events.end(); ++i)
|
||||
delete (*i);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef _TASK_SAVE_LOG_H
|
||||
#define _TASK_SAVE_LOG_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "sharedDatabaseInterface/DbTaskRequest.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
class LogEvent;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/**
|
||||
* An asynchronous task to save a set of LogEvents.
|
||||
*/
|
||||
class TaskSaveLog:public DB::TaskRequest
|
||||
{
|
||||
public:
|
||||
void addEvent(LogEvent *event);
|
||||
|
||||
public:
|
||||
bool process(DB::Session *session);
|
||||
void onComplete();
|
||||
|
||||
public:
|
||||
virtual ~TaskSaveLog();
|
||||
|
||||
private:
|
||||
typedef std::vector<LogEvent*> EventsType;
|
||||
EventsType events;
|
||||
};
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,273 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbTaskQueue.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
#include "sharedDatabaseInterface/DbTaskRequest.h"
|
||||
#include "sharedDebug/PerformanceTimer.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedThread/RunThread.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace DB;
|
||||
|
||||
volatile int TaskQueue::sm_iTotalNumRequests = 0;
|
||||
volatile int TaskQueue::sm_iTotalNumResults = 0;
|
||||
|
||||
|
||||
bool TaskQueue::ms_workerThreadsLoggingEnabled = false;
|
||||
|
||||
TaskQueue::TaskQueue(unsigned int _numThreads, Server *_server, int _threadGroupId) :
|
||||
numThreads(_numThreads),
|
||||
server(_server),
|
||||
requestQ(),
|
||||
requestQLock(),
|
||||
requestQAdded(requestQLock),
|
||||
resultQ(),
|
||||
resultQLock(),
|
||||
pauseLock(),
|
||||
pauseSignal(pauseLock),
|
||||
workers(),
|
||||
shutdown(false),
|
||||
paused(false),
|
||||
updateCountLock(),
|
||||
activeCount(_numThreads),
|
||||
idleCount(0),
|
||||
threadGroupId(_threadGroupId),
|
||||
numRequests(0),
|
||||
numResults(0),
|
||||
threadIdLock(),
|
||||
nextThreadId(0)
|
||||
{ //lint !e1926 // using default constructors for several members -- is intentional
|
||||
for (unsigned int i=0; i<numThreads; ++i)
|
||||
{
|
||||
Thread * threadObject = new MemberFunctionThreadZero<TaskQueue>("DBTaskQueue", *this, &TaskQueue::workerThreadLoop);
|
||||
ThreadHandle tempThreadHandle(threadObject);
|
||||
workers.push_back(tempThreadHandle);
|
||||
}
|
||||
}
|
||||
|
||||
TaskQueue::~TaskQueue()
|
||||
{
|
||||
shutdown=true;
|
||||
unpause();
|
||||
requestQAdded.signal(); // get the attention of waiting threads
|
||||
for(unsigned int i=0; i<numThreads; ++i)
|
||||
{
|
||||
workers[i]->wait();
|
||||
}
|
||||
|
||||
while (!resultQ.empty())
|
||||
{
|
||||
update(0); // empty out the result queue before quitting
|
||||
}
|
||||
} //lint !e1740 // didn't delete server
|
||||
|
||||
void TaskQueue::asyncRequest(TaskRequest *req)
|
||||
{
|
||||
requestQLock.enter();
|
||||
++numRequests;
|
||||
++sm_iTotalNumRequests;
|
||||
requestQ.push_front(req);
|
||||
requestQAdded.signal();
|
||||
requestQLock.leave();
|
||||
}
|
||||
|
||||
void TaskQueue::workerThreadLoop()
|
||||
{
|
||||
threadIdLock.enter();
|
||||
int threadId=nextThreadId++;
|
||||
threadIdLock.leave();
|
||||
Os::OsPID_t processId=Os::getProcessId();
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) starting",threadGroupId,threadId,processId));
|
||||
|
||||
Session * session = server->getSession();
|
||||
while (!shutdown)
|
||||
{
|
||||
TaskRequest *req;
|
||||
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) about to grab a task",threadGroupId,threadId, processId));
|
||||
requestQLock.enter();
|
||||
|
||||
updateCountLock.enter();
|
||||
--activeCount;
|
||||
++idleCount;
|
||||
updateCountLock.leave();
|
||||
|
||||
while (requestQ.empty())
|
||||
{
|
||||
if (shutdown) // only check for shutdown when there's nothing left to do
|
||||
{
|
||||
// .leave and wake next thread
|
||||
requestQAdded.signal(); // on shutdown, each thread wakes up the next one
|
||||
|
||||
updateCountLock.enter();
|
||||
--idleCount;
|
||||
updateCountLock.leave();
|
||||
|
||||
requestQLock.leave();
|
||||
|
||||
server->releaseSession(session);
|
||||
session=0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) waiting for a task",threadGroupId,threadId,processId));
|
||||
requestQAdded.wait();
|
||||
}
|
||||
|
||||
// locked
|
||||
req=requestQ.back(); // FIFO: added to front, removed from back
|
||||
requestQ.pop_back();
|
||||
--numRequests;
|
||||
--sm_iTotalNumRequests;
|
||||
if (!requestQ.empty())
|
||||
{
|
||||
requestQAdded.signal();
|
||||
}
|
||||
|
||||
updateCountLock.enter();
|
||||
--idleCount;
|
||||
++activeCount;
|
||||
updateCountLock.leave();
|
||||
|
||||
requestQLock.leave();
|
||||
|
||||
// Check for the queue being paused
|
||||
pauseLock.enter();
|
||||
while (paused)
|
||||
{
|
||||
updateCountLock.enter();
|
||||
++idleCount;
|
||||
--activeCount;
|
||||
updateCountLock.leave();
|
||||
|
||||
pauseSignal.wait();
|
||||
|
||||
updateCountLock.enter();
|
||||
--idleCount;
|
||||
++activeCount;
|
||||
updateCountLock.leave();
|
||||
}
|
||||
pauseLock.leave();
|
||||
|
||||
NOT_NULL(session);
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) running",threadGroupId,threadId,processId));
|
||||
req->workerThreadLoop(session);
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) finished a loop (about to enter resultQLock)",threadGroupId,threadId,processId));
|
||||
resultQLock.enter();
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) finished a loop (entered resultQLock)",threadGroupId,threadId,processId));
|
||||
++numResults;
|
||||
++sm_iTotalNumResults;
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) finished a loop (incremented numResults)",threadGroupId,threadId,processId));
|
||||
resultQ.push_front(req);
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) finished a loop (did resultQ.push_front)",threadGroupId,threadId,processId));
|
||||
resultQLock.leave();
|
||||
if (ms_workerThreadsLoggingEnabled)
|
||||
LOG("WorkerThreads",("Thread %d-%d (%d) finished a loop (left resultQLock)",threadGroupId,threadId,processId));
|
||||
}
|
||||
|
||||
server->releaseSession(session);
|
||||
session=0;
|
||||
}
|
||||
|
||||
void TaskQueue::update(float maxTime)
|
||||
{
|
||||
PerformanceTimer timer;
|
||||
timer.start();
|
||||
|
||||
TaskRequest *req;
|
||||
|
||||
resultQLock.enter();
|
||||
|
||||
while (!resultQ.empty() && (maxTime==0 || timer.getSplitTime() < maxTime))
|
||||
{
|
||||
req=resultQ.back();
|
||||
resultQ.pop_back();
|
||||
--numResults;
|
||||
--sm_iTotalNumResults;
|
||||
resultQLock.leave();
|
||||
|
||||
if (req->mainThreadFinish())
|
||||
{
|
||||
req->mainThreadOnComplete();
|
||||
delete req;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if Finish() returns false, more worker thread processing is needed
|
||||
asyncRequest(req);
|
||||
}
|
||||
resultQLock.enter();
|
||||
}
|
||||
resultQLock.leave();
|
||||
}
|
||||
|
||||
void TaskQueue::cancel()
|
||||
{
|
||||
requestQLock.enter();
|
||||
while(!requestQ.empty())
|
||||
{
|
||||
TaskRequest *req=requestQ.back();
|
||||
delete req;
|
||||
requestQ.pop_back();
|
||||
}
|
||||
requestQLock.leave();
|
||||
}
|
||||
|
||||
int TaskQueue::getNumPendingTasks()
|
||||
{
|
||||
return numRequests;
|
||||
}
|
||||
|
||||
int TaskQueue::getNumFinishedTasks()
|
||||
{
|
||||
return numResults;
|
||||
}
|
||||
|
||||
int TaskQueue::getNumActiveTasks()
|
||||
{
|
||||
return activeCount;
|
||||
}
|
||||
|
||||
void TaskQueue::report()
|
||||
{
|
||||
DEBUG_REPORT_LOG(true,("Task queue status: %i threads, %i active, %i idle, %i undelegated tasks\n",numThreads,activeCount,idleCount,getNumPendingTasks()));
|
||||
}
|
||||
|
||||
bool TaskQueue::isIdle()
|
||||
{
|
||||
return (activeCount==0 && getNumPendingTasks()==0 && getNumFinishedTasks()==0 && !paused);
|
||||
}
|
||||
|
||||
void TaskQueue::pause()
|
||||
{
|
||||
pauseLock.enter();
|
||||
paused=true;
|
||||
pauseLock.leave();
|
||||
}
|
||||
|
||||
void TaskQueue::unpause()
|
||||
{
|
||||
pauseLock.enter();
|
||||
if (paused)
|
||||
{
|
||||
paused=false;
|
||||
pauseSignal.broadcast();
|
||||
}
|
||||
pauseLock.leave();
|
||||
}
|
||||
|
||||
void TaskQueue::enableWorkerThreadsLogging(bool enabled)
|
||||
{
|
||||
ms_workerThreadsLoggingEnabled=enabled;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
#ifndef _DB_TASK_QUEUE_H
|
||||
#define _DB_TASK_QUEUE_H
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "sharedSynchronization/Mutex.h"
|
||||
#include "sharedSynchronization/ConditionVariable.h"
|
||||
#include "sharedThread/ThreadHandle.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class Server;
|
||||
class Session;
|
||||
|
||||
class TaskRequest;
|
||||
class TaskWorkerThread;
|
||||
|
||||
/** A class organizing a queue of requests to the database. Worker threads will
|
||||
* perform the requests on a FIFO basis.
|
||||
*/
|
||||
class TaskQueue
|
||||
{
|
||||
unsigned int numThreads;
|
||||
DB::Server *server;
|
||||
|
||||
std::list<TaskRequest*> requestQ;
|
||||
Mutex requestQLock;
|
||||
ConditionVariable requestQAdded;
|
||||
std::list<TaskRequest*> resultQ;
|
||||
Mutex resultQLock;
|
||||
Mutex pauseLock;
|
||||
ConditionVariable pauseSignal;
|
||||
|
||||
std::vector<ThreadHandle> workers;
|
||||
|
||||
/** Set to true when we are trying to delete the queue. Worker
|
||||
* threads test this to see whether to quit.
|
||||
*/
|
||||
bool shutdown;
|
||||
bool paused;
|
||||
|
||||
Mutex updateCountLock;
|
||||
int activeCount;
|
||||
int idleCount;
|
||||
|
||||
int threadGroupId;
|
||||
|
||||
int numRequests;
|
||||
int numResults;
|
||||
|
||||
Mutex threadIdLock;
|
||||
int nextThreadId;
|
||||
|
||||
static bool ms_workerThreadsLoggingEnabled;
|
||||
|
||||
public:
|
||||
TaskQueue(unsigned int _numThreads, Server *_server, int _threadGroupId);
|
||||
~TaskQueue();
|
||||
|
||||
/** Give a request to the task queue. It will hand the request to a
|
||||
* worker thread to be processed.
|
||||
*/
|
||||
void asyncRequest(TaskRequest *req);
|
||||
|
||||
/** Called by the worker thread(s). Pops a request off the queue and
|
||||
* calls Process() on the request. Sleeps until a request is added if
|
||||
* there are none available.
|
||||
*
|
||||
* Always returns true. TODO: Add support for aborting the worker
|
||||
* threads, in which case this will return false when the thread should
|
||||
* stop itself.
|
||||
*
|
||||
* @param session A database session owned by the worker thread. It
|
||||
* will be used for running any queries.
|
||||
*/
|
||||
void workerThreadLoop();
|
||||
|
||||
/**
|
||||
* The user of the queue should call this periodically. It pops all
|
||||
* completed tasks off of the queue and invokes their OnComplete()
|
||||
* functions.
|
||||
*
|
||||
* @param maxTime The maximum time to spend processing, or 0 for unlimited.
|
||||
* If the time limit is reached, tasks will be left on the queue for a
|
||||
* later call to update() .
|
||||
*/
|
||||
void update(float maxTime);
|
||||
|
||||
/**
|
||||
* Remove all pending tasks that have not been started yet.
|
||||
* If a task is currently in progress, it is not affected.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Pause the queue. No new tasks will be processed until the queue is unpaused.
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Unpause the queue.
|
||||
*/
|
||||
void unpause();
|
||||
|
||||
/**
|
||||
* Count the number of tasks that have not yet been assigned to a
|
||||
* worker thread.
|
||||
*/
|
||||
int getNumPendingTasks();
|
||||
|
||||
/**
|
||||
* Count the number of tasks that have been finished but not yet
|
||||
* processed by the main thred.
|
||||
*/
|
||||
int getNumFinishedTasks();
|
||||
|
||||
/**
|
||||
* Count the number of threads that are actively working on a task
|
||||
*/
|
||||
int getNumActiveTasks();
|
||||
|
||||
/**
|
||||
* Return true if the task queue is not doing anything. (No active
|
||||
* threads and no pending tasks.
|
||||
*/
|
||||
bool isIdle();
|
||||
|
||||
void report();
|
||||
|
||||
static void enableWorkerThreadsLogging(bool enabled);
|
||||
|
||||
|
||||
static int getTotalNumRequests() { return (sm_iTotalNumRequests < 0 ? 0 : sm_iTotalNumRequests); }
|
||||
static int getTotalNumResults() { return (sm_iTotalNumResults < 0 ? 0 : sm_iTotalNumResults); }
|
||||
|
||||
private:
|
||||
TaskQueue(); //disable
|
||||
TaskQueue(const TaskQueue &); //disable
|
||||
TaskQueue& operator=(const TaskQueue&); //disable
|
||||
|
||||
|
||||
static volatile int sm_iTotalNumRequests;
|
||||
static volatile int sm_iTotalNumResults;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbTaskRequest.h"
|
||||
|
||||
#include "sharedDatabaseInterface/DbException.h"
|
||||
#include "sharedDatabaseInterface/DbServer.h"
|
||||
#include "sharedDatabaseInterface/DbTestQuery.h"
|
||||
#include "sharedDatabaseInterface/DbSession.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedLog/Log.h"
|
||||
|
||||
DB::TaskRequest::TaskRequest() :
|
||||
needsProcessing(true),
|
||||
errorCount(0),
|
||||
reconnectErrorCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
DB::TaskRequest::~TaskRequest()
|
||||
{
|
||||
}
|
||||
|
||||
void DB::TaskRequest::workerThreadLoop(DB::Session *ses)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (needsProcessing)
|
||||
{
|
||||
i++;
|
||||
if (process(ses))
|
||||
{
|
||||
needsProcessing=false;
|
||||
errorCount=0;
|
||||
if (i > 1)
|
||||
{
|
||||
LOG("DatabaseError", ("Task succeeded after %d tries", i));
|
||||
ses->setFatalOnError(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// save off the failed query statement from the process() that failed
|
||||
// because it will be overwritten by the test query statement
|
||||
std::string failedQuery = ses->getLastQueryStatement();
|
||||
|
||||
ses->rollbackTransaction();
|
||||
Os::sleep(DB::Server::getErrorSleepTime());
|
||||
DBTestQuery qry;
|
||||
if (ses->exec(&qry))
|
||||
{
|
||||
if (qry.fetch() > 0)
|
||||
{
|
||||
int result;
|
||||
qry.value.getValue(result);
|
||||
if (result == 1)
|
||||
{
|
||||
// the connection is good, but the query in process() failed
|
||||
errorCount++;
|
||||
LOG("DatabaseError", (" -- DBTestQuery succeeded, errorCount = %d", errorCount));
|
||||
if (errorCount==2)
|
||||
ses->setFatalOnError(true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
LOG("DatabaseError", (" -- DBTestQuery failed, will disconnect/reconnect"));
|
||||
ses->disconnect();
|
||||
while (! (ses->connect()))
|
||||
{
|
||||
ses->disconnect();
|
||||
Os::sleep(DB::Server::getDisconnectSleepTime());
|
||||
};
|
||||
LOG("DatabaseError", ("Database connection reestablished"));
|
||||
}
|
||||
}
|
||||
ses->updateServerQueryCount();
|
||||
ses->reset();
|
||||
}
|
||||
|
||||
bool DB::TaskRequest::mainThreadFinish()
|
||||
{
|
||||
bool allDone=true;
|
||||
|
||||
if (!isFinished())
|
||||
{
|
||||
allDone=false;
|
||||
needsProcessing=true;
|
||||
}
|
||||
return allDone;
|
||||
}
|
||||
|
||||
void DB::TaskRequest::mainThreadOnComplete()
|
||||
{
|
||||
onComplete();
|
||||
}
|
||||
|
||||
bool DB::TaskRequest::isFinished()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef _DB_TASK_REQUEST_H
|
||||
#define _DB_TASK_REQUEST_H
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
class Session;
|
||||
|
||||
/** Abstract base class representing a request sent to the database task queue.
|
||||
*/
|
||||
class TaskRequest
|
||||
{
|
||||
private:
|
||||
/** Flag to avoid calling Process() twice unexpectedly.
|
||||
*/
|
||||
bool needsProcessing;
|
||||
|
||||
/** Error count to prevent infinite retries of an operation that always fails.
|
||||
*/
|
||||
int errorCount;
|
||||
int reconnectErrorCount;
|
||||
|
||||
/** Called by the database thread. Will invoke Process(). Do not override.
|
||||
*/
|
||||
void workerThreadLoop(DB::Session *session);
|
||||
|
||||
/** Called by the main thread. Will invoke IsFinished(). Do not override.
|
||||
*/
|
||||
bool mainThreadFinish();
|
||||
|
||||
/** Called by the main thread. Will invoke OnComplete(). Do not override.
|
||||
*/
|
||||
void mainThreadOnComplete();
|
||||
|
||||
public:
|
||||
TaskRequest();
|
||||
virtual ~TaskRequest();
|
||||
|
||||
/** Called by the database thread. Should do whatever database work
|
||||
* is needed to handle the request.
|
||||
*
|
||||
* This will only get executed once, unless IsFinished() returns false.
|
||||
*/
|
||||
virtual bool process(DB::Session *session)=0;
|
||||
|
||||
/** Called by the main thread after Process() has completed. Should check the
|
||||
* results. It should return true if the task is done, or false if the task
|
||||
* should be put back on the queue for a worker thread to do more processing.
|
||||
*
|
||||
* It is not guaranteed that OnComplete() will be invoked if IsFinished() returns
|
||||
* true, because a subtask's or parent task's IsFinished() might return false,
|
||||
* requiring the whole set of tasks to be put back on the queue for the worker thread.
|
||||
* Therefore, IsFinished() could be called again even after it returns true. (And, since
|
||||
* things may have changed in the mean time, it may need to do its checks again.)
|
||||
*
|
||||
* The default implementation does nothing and returns true.
|
||||
*/
|
||||
virtual bool isFinished();
|
||||
|
||||
/** Called by the main thread (from DB::TaskQueue::Update()) after the request
|
||||
* has been completed and IsFinished() has returned true. OnComplete() will only
|
||||
* be invoked once.
|
||||
*
|
||||
* It is guaranteed that if OnComplete() is invoked at all, it will be invoked immediately
|
||||
* after IsFinished() returns true. The only things that may happen between IsFinished()
|
||||
* and OnComplete() is IsFinished() or OnComplete() on another task.
|
||||
*
|
||||
* However, it is not guaranteed that OnComplete() will be invoked at all when IsFinished()
|
||||
* returns true, because subtasks might require more procssing.
|
||||
*/
|
||||
virtual void onComplete()=0;
|
||||
|
||||
friend class TaskQueue;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
#include "sharedDatabaseInterface/DbTestQuery.h"
|
||||
|
||||
void DBTestQuery::getSQL(std::string &sql)
|
||||
{
|
||||
sql=std::string("select 1 from dual");
|
||||
}
|
||||
|
||||
bool DBTestQuery::bindParameters()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBTestQuery::bindColumns()
|
||||
{
|
||||
|
||||
if (!bindCol(value)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DB::Query::QueryMode DBTestQuery::getExecutionMode() const
|
||||
{
|
||||
return MODE_SQL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DBTestQuery::DBTestQuery() :
|
||||
Query(),
|
||||
value()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef _DB_TEST_QUERY_H
|
||||
#define _DB_TEST_QUERY_H
|
||||
|
||||
#include "sharedDatabaseInterface/Bindable.h"
|
||||
#include "sharedDatabaseInterface/DbQuery.h"
|
||||
|
||||
class DBTestQuery : public DB::Query
|
||||
{
|
||||
public:
|
||||
DB::BindableLong value;
|
||||
|
||||
DBTestQuery();
|
||||
virtual void getSQL(std::string &sql);
|
||||
virtual bool bindParameters();
|
||||
virtual bool bindColumns();
|
||||
virtual QueryMode getExecutionMode() const;
|
||||
|
||||
private: //disable
|
||||
DBTestQuery(const DBTestQuery&);
|
||||
DBTestQuery& operator=(const DBTestQuery&);
|
||||
};
|
||||
|
||||
#endif
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstServerDatabaseInterface.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* SQLC_Defs.h
|
||||
*
|
||||
* This file includes common definitions needed by the other SQLClasses header files.
|
||||
* (Don't include this file directly -- files that require it will include it.)
|
||||
*
|
||||
* Note that this file is specific to each OS, because what header files are
|
||||
* needed varies in each OS. In particular, Unix versions don't want windows.h.
|
||||
*
|
||||
* ODBC versions: includes definitions of ODBC datatypes needed by the various
|
||||
* SQLClasses
|
||||
*/
|
||||
|
||||
#ifndef _SQLC_DEFS_H
|
||||
#define _SQLC_DEFS_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <sqltypes.h>
|
||||
|
||||
#endif
|
||||
@@ -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}
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user