You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
695 lines
19 KiB
C++
695 lines
19 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
// Precompiled header include. Can't add anything above this line.
|
|
#include "DatabaseSupportPrivatePCH.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogDataBase, Log, All);
|
|
#if USE_REMOTE_INTEGRATION
|
|
|
|
/**
|
|
* Sends a command to the database proxy.
|
|
*
|
|
* @param Cmd The command to be sent.
|
|
*/
|
|
bool ExecuteDBProxyCommand(FSocket *Socket, const TCHAR* Cmd)
|
|
{
|
|
check(Socket);
|
|
check(Cmd);
|
|
|
|
int32 CmdStrLength = FCString::Strlen(Cmd);
|
|
int32 BytesSent = 0;
|
|
|
|
// add 1 so we also send NULL
|
|
++CmdStrLength;
|
|
|
|
TCHAR *SendBuf = (TCHAR*)FMemory::Malloc(CmdStrLength * sizeof(TCHAR));
|
|
|
|
// convert to network byte ordering. This is important for running on the ps3 and xenon
|
|
for(int32 BufIndex = 0; BufIndex < CmdStrLength; ++BufIndex)
|
|
{
|
|
SendBuf[BufIndex] = htons(Cmd[BufIndex]);
|
|
}
|
|
|
|
bool bRet = Socket->Send((uint8*)SendBuf, CmdStrLength * sizeof(TCHAR), BytesSent);
|
|
|
|
FMemory::Free(SendBuf);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
////////////////////////////////////////////// FRemoteDatabaseConnection ///////////////////////////////////////////////////////
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
FRemoteDatabaseConnection::FRemoteDatabaseConnection()
|
|
: Socket(NULL)
|
|
{
|
|
check(GSocketSubsystem);
|
|
// The socket won't work if secure connections are enabled, so don't try
|
|
if (GSocketSubsystem->RequiresEncryptedPackets() == false)
|
|
{
|
|
Socket = GSocketSubsystem->CreateSocket(NAME_Stream, TEXT("remote database connection"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Destructor.
|
|
*/
|
|
FRemoteDatabaseConnection::~FRemoteDatabaseConnection()
|
|
{
|
|
check(GSocketSubsystem);
|
|
|
|
if ( Socket )
|
|
{
|
|
GSocketSubsystem->DestroySocket(Socket);
|
|
Socket = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Opens a connection to the database.
|
|
*
|
|
* @param ConnectionString Connection string passed to database layer
|
|
* @param RemoteConnectionIP The IP address which the RemoteConnection should connect to
|
|
* @param RemoteConnectionStringOverride The connection string which the RemoteConnection is going to utilize
|
|
*
|
|
* @return true if connection was successfully established, false otherwise
|
|
*/
|
|
bool FRemoteDatabaseConnection::Open( const TCHAR* ConnectionString, const TCHAR* RemoteConnectionIP, const TCHAR* RemoteConnectionStringOverride )
|
|
{
|
|
bool bIsValid = false;
|
|
if ( Socket )
|
|
{
|
|
FInternetAddr Address;
|
|
Address.SetIp(RemoteConnectionIP, bIsValid);
|
|
Address.SetPort(10500);
|
|
|
|
if(bIsValid)
|
|
{
|
|
bIsValid = Socket->Connect(Address);
|
|
|
|
if(bIsValid && RemoteConnectionStringOverride)
|
|
{
|
|
SetConnectionString(RemoteConnectionStringOverride);
|
|
}
|
|
}
|
|
}
|
|
return bIsValid;
|
|
}
|
|
|
|
/**
|
|
* Closes connection to database.
|
|
*/
|
|
void FRemoteDatabaseConnection::Close()
|
|
{
|
|
if ( Socket )
|
|
{
|
|
Socket->Close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Executes the passed in command on the database.
|
|
*
|
|
* @param CommandString Command to execute
|
|
*
|
|
* @return true if execution was successful, false otherwise
|
|
*/
|
|
bool FRemoteDatabaseConnection::Execute(const TCHAR* CommandString)
|
|
{
|
|
FString Cmd = FString::Printf(TEXT("<command results=\"false\">%s</command>"), CommandString);
|
|
return ExecuteDBProxyCommand(Socket, *Cmd);
|
|
}
|
|
|
|
/**
|
|
* Executes the passed in command on the database. The caller is responsible for deleting
|
|
* the created RecordSet.
|
|
*
|
|
* @param CommandString Command to execute
|
|
* @param RecordSet Reference to recordset pointer that is going to hold result
|
|
*
|
|
* @return true if execution was successful, false otherwise
|
|
*/
|
|
bool FRemoteDatabaseConnection::Execute(const TCHAR* CommandString, FDataBaseRecordSet*& RecordSet)
|
|
{
|
|
RecordSet = NULL;
|
|
FString Cmd = FString::Printf(TEXT("<command results=\"true\">%s</command>"), CommandString);
|
|
bool bRetVal = ExecuteDBProxyCommand(Socket, *Cmd);
|
|
int32 ResultID = 0;
|
|
int32 BytesRead;
|
|
|
|
if(bRetVal)
|
|
{
|
|
Socket->Recv((uint8*)&ResultID, sizeof(int32), BytesRead);
|
|
bRetVal = BytesRead == sizeof(int32);
|
|
|
|
if(bRetVal)
|
|
{
|
|
RecordSet = new FRemoteDataBaseRecordSet(ResultID, Socket);
|
|
}
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
/**
|
|
* Sets the connection string to be used for this connection in the DB proxy.
|
|
*
|
|
* @param ConnectionString The new connection string to use.
|
|
*/
|
|
bool FRemoteDatabaseConnection::SetConnectionString(const TCHAR* ConnectionString)
|
|
{
|
|
FString Cmd = FString::Printf(TEXT("<connectionString>%s</connectionString>"), ConnectionString);
|
|
return ExecuteDBProxyCommand(Socket, *Cmd);
|
|
}
|
|
|
|
////////////////////////////////////////////// FRemoteDataBaseRecordSet ///////////////////////////////////////////////////////
|
|
|
|
/** Moves to the first record in the set. */
|
|
void FRemoteDataBaseRecordSet::MoveToFirst()
|
|
{
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<movetofirst resultset=\"%s\"/>"), *ID));
|
|
}
|
|
|
|
/** Moves to the next record in the set. */
|
|
void FRemoteDataBaseRecordSet::MoveToNext()
|
|
{
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<movetonext resultset=\"%s\"/>"), *ID));
|
|
}
|
|
|
|
/**
|
|
* Returns whether we are at the end.
|
|
*
|
|
* @return true if at the end, false otherwise
|
|
*/
|
|
bool FRemoteDataBaseRecordSet::IsAtEnd() const
|
|
{
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<isatend resultset=\"%s\"/>"), *ID));
|
|
|
|
int32 BytesRead;
|
|
bool bResult;
|
|
Socket->Recv((uint8*)&bResult, sizeof(bool), BytesRead);
|
|
|
|
if(BytesRead != sizeof(bool))
|
|
{
|
|
bResult = false;
|
|
}
|
|
else
|
|
{
|
|
bResult = ntohl(bResult);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/**
|
|
* Returns a string associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
FString FRemoteDataBaseRecordSet::GetString( const TCHAR* Column ) const
|
|
{
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<getstring resultset=\"%s\">%s</getstring>"), *ID, Column));
|
|
|
|
const int32 BUFSIZE = 2048;
|
|
int32 BytesRead;
|
|
int32 StrLength;
|
|
TCHAR Buf[BUFSIZE];
|
|
|
|
Socket->Recv((uint8*)&StrLength, sizeof(int32), BytesRead);
|
|
|
|
StrLength = ntohl(StrLength);
|
|
|
|
if(BytesRead != sizeof(int32) || StrLength <= 0)
|
|
{
|
|
return TEXT("");
|
|
}
|
|
|
|
if(StrLength > BUFSIZE - 1)
|
|
{
|
|
StrLength = BUFSIZE - 1;
|
|
}
|
|
|
|
Socket->Recv((uint8*)Buf, StrLength * sizeof(TCHAR), BytesRead);
|
|
|
|
// TCHAR is assumed to be wchar_t so if we recv an odd # of bytes something messed up occured. Round down to the nearest wchar_t and then convert to number of TCHAR's.
|
|
BytesRead -= BytesRead & 1; // rounding down
|
|
BytesRead >>= 1; // conversion
|
|
|
|
// convert from network to host byte order
|
|
for(int i = 0; i < BytesRead; ++i)
|
|
{
|
|
Buf[i] = ntohs(Buf[i]);
|
|
}
|
|
|
|
Buf[BytesRead] = 0;
|
|
|
|
return FString(Buf);
|
|
}
|
|
|
|
/**
|
|
* Returns an integer associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
int32 FRemoteDataBaseRecordSet::GetInt( const TCHAR* Column ) const
|
|
{
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<getint resultset=\"%s\">%s</getint>"), *ID, Column));
|
|
|
|
int32 BytesRead;
|
|
int32 Value;
|
|
|
|
Socket->Recv((uint8*)&Value, sizeof(int32), BytesRead);
|
|
|
|
return ntohl(Value);
|
|
}
|
|
|
|
/**
|
|
* Returns a float associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
float FRemoteDataBaseRecordSet::GetFloat( const TCHAR* Column ) const
|
|
{
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<getfloat resultset=\"%s\">%s</getfloat>"), *ID, Column));
|
|
|
|
int32 BytesRead;
|
|
int32 Temp;
|
|
|
|
Socket->Recv((uint8*)&Temp, sizeof(int32), BytesRead);
|
|
|
|
Temp = ntohl(Temp);
|
|
|
|
float Value = *((float*)&Temp);
|
|
|
|
return Value;
|
|
}
|
|
|
|
/** Constructor. */
|
|
FRemoteDataBaseRecordSet::FRemoteDataBaseRecordSet(int32 ResultSetID, FSocket *Connection) : Socket(NULL)
|
|
{
|
|
check(ResultSetID >= 0);
|
|
check(Connection);
|
|
|
|
// NOTE: This socket will be deleted by whatever created it (prob an FRemoteDatabaseConnection), not this class.
|
|
Socket = Connection;
|
|
ID = FString::Printf(TEXT("%i"), ResultSetID);
|
|
}
|
|
|
|
/** Virtual destructor as class has virtual functions. */
|
|
FRemoteDataBaseRecordSet::~FRemoteDataBaseRecordSet()
|
|
{
|
|
// tell the DB proxy to clean up the resources allocated for the result set.
|
|
ExecuteDBProxyCommand(Socket, *FString::Printf(TEXT("<closeresultset resultset=\"%s\"/>"), *ID));
|
|
}
|
|
|
|
#endif
|
|
|
|
#if USE_ADO_INTEGRATION
|
|
#include "AllowWindowsPlatformTypes.h"
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
ADO integration for database connectivity
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
// Using import allows making use of smart pointers easily. Please post to the list if a workaround such as
|
|
// using %COMMONFILES% works to hide the localization issues and non default program file folders.
|
|
//#import "C:\Program files\Common Files\System\Ado\msado15.dll" rename("EOF", "ADOEOF")
|
|
|
|
#import "System\ADO\msado15.dll" rename("EOF", "ADOEOF") //lint !e322
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FADODataBaseRecordSet implementation.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* ADO implementation of database record set.
|
|
*/
|
|
class FADODataBaseRecordSet : public FDataBaseRecordSet
|
|
{
|
|
private:
|
|
ADODB::_RecordsetPtr ADORecordSet;
|
|
|
|
protected:
|
|
/** Moves to the first record in the set. */
|
|
virtual void MoveToFirst()
|
|
{
|
|
if( !ADORecordSet->BOF || !ADORecordSet->ADOEOF )
|
|
{
|
|
ADORecordSet->MoveFirst();
|
|
}
|
|
}
|
|
/** Moves to the next record in the set. */
|
|
virtual void MoveToNext()
|
|
{
|
|
if( !ADORecordSet->ADOEOF )
|
|
{
|
|
ADORecordSet->MoveNext();
|
|
}
|
|
}
|
|
/**
|
|
* Returns whether we are at the end.
|
|
*
|
|
* @return true if at the end, false otherwise
|
|
*/
|
|
virtual bool IsAtEnd() const
|
|
{
|
|
return !!ADORecordSet->ADOEOF;
|
|
}
|
|
|
|
public:
|
|
|
|
/**
|
|
* Returns a count of the number of records in the record set
|
|
*/
|
|
virtual int32 GetRecordCount() const
|
|
{
|
|
return ADORecordSet->RecordCount;
|
|
}
|
|
|
|
/**
|
|
* Returns a string associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
virtual FString GetString( const TCHAR* Column ) const
|
|
{
|
|
FString ReturnString;
|
|
|
|
// Retrieve specified column field value for selected row.
|
|
_variant_t Value = ADORecordSet->GetCollect( Column );
|
|
// Check variant type for validity and cast to specified type. _variant_t has overloaded cast operators.
|
|
if( Value.vt != VT_NULL )
|
|
{
|
|
ReturnString = (TCHAR*)_bstr_t(Value);
|
|
}
|
|
// Unknown column.
|
|
else
|
|
{
|
|
ReturnString = TEXT("Unknown Column");
|
|
}
|
|
|
|
return ReturnString;
|
|
}
|
|
|
|
/**
|
|
* Returns an integer associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
virtual int32 GetInt( const TCHAR* Column ) const
|
|
{
|
|
int32 ReturnValue = 0;
|
|
|
|
// Retrieve specified column field value for selected row.
|
|
_variant_t Value = ADORecordSet->GetCollect( Column );
|
|
// Check variant type for validity and cast to specified type. _variant_t has overloaded cast operators.
|
|
if( Value.vt != VT_NULL )
|
|
{
|
|
ReturnValue = (int32)Value;
|
|
}
|
|
// Unknown column.
|
|
else
|
|
{
|
|
UE_LOG(LogDataBase, Log, TEXT("Failure retrieving int32 value for column [%s]"),Column);
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
/**
|
|
* Returns a float associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
virtual float GetFloat( const TCHAR* Column ) const
|
|
{
|
|
float ReturnValue = 0;
|
|
|
|
// Retrieve specified column field value for selected row.
|
|
_variant_t Value = ADORecordSet->GetCollect( Column );
|
|
// Check variant type for validity and cast to specified type. _variant_t has overloaded cast operators.
|
|
if( Value.vt != VT_NULL )
|
|
{
|
|
ReturnValue = (float)Value;
|
|
}
|
|
// Unknown column.
|
|
else
|
|
{
|
|
UE_LOG(LogDataBase, Log, TEXT("Failure retrieving float value for column [%s]"),Column);
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
/**
|
|
* Returns an int64 associated with the passed in field/ column for the current row.
|
|
*
|
|
* @param Column Name of column to retrieve data for in current row
|
|
*/
|
|
virtual int64 GetBigInt( const TCHAR* Column ) const
|
|
{
|
|
int64 ReturnValue = 0;
|
|
|
|
// Retrieve specified column field value for selected row.
|
|
_variant_t Value = ADORecordSet->GetCollect( Column );
|
|
// Check variant type for validity and cast to specified type. _variant_t has overloaded cast operators.
|
|
if( Value.vt != VT_NULL )
|
|
{
|
|
ReturnValue = (int64)Value;
|
|
}
|
|
// Unknown column.
|
|
else
|
|
{
|
|
UE_LOG(LogDataBase, Log, TEXT("Failure retrieving BIGINT value for column [%s]"),Column);
|
|
}
|
|
|
|
return ReturnValue;
|
|
}
|
|
|
|
/**
|
|
* Returns the set of column names for this Recordset. This is useful for determining
|
|
* what you can actually ask the record set for without having to hard code those ahead of time.
|
|
*/
|
|
virtual TArray<FDatabaseColumnInfo> GetColumnNames() const
|
|
{
|
|
TArray<FDatabaseColumnInfo> Retval;
|
|
|
|
if( !ADORecordSet->BOF || !ADORecordSet->ADOEOF )
|
|
{
|
|
ADORecordSet->MoveFirst();
|
|
|
|
for( int16 i = 0; i < ADORecordSet->Fields->Count; ++i )
|
|
{
|
|
_bstr_t bstrName = ADORecordSet->Fields->Item[i]->Name;
|
|
_variant_t varValue = ADORecordSet->Fields->Item[i]->Value;
|
|
ADODB::DataTypeEnum DataType = ADORecordSet->Fields->Item[i]->Type;
|
|
|
|
FDatabaseColumnInfo NewInfo;
|
|
NewInfo.ColumnName = FString((TCHAR*)_bstr_t(bstrName));
|
|
|
|
// from http://www.w3schools.com/ado/prop_field_type.asp#datatypeenum
|
|
switch( DataType )
|
|
{
|
|
case ADODB::adInteger:
|
|
case ADODB::adBigInt:
|
|
NewInfo.DataType = DBT_INT;
|
|
break;
|
|
case ADODB::adSingle:
|
|
case ADODB::adDouble:
|
|
NewInfo.DataType = DBT_FLOAT;
|
|
break;
|
|
|
|
case ADODB::adWChar:
|
|
case ADODB::adVarWChar:
|
|
NewInfo.DataType = DBT_STRING;
|
|
break;
|
|
|
|
default:
|
|
UE_LOG(LogDataBase, Warning, TEXT("Unable to find a EDataBaseUE3Types (%s) from DODB::DataTypeEnum DataType: %d "), *NewInfo.ColumnName, static_cast<int32>(DataType) );
|
|
NewInfo.DataType = DBT_UNKOWN;
|
|
break;
|
|
}
|
|
|
|
|
|
Retval.Add( NewInfo );
|
|
}
|
|
}
|
|
|
|
// here for debugging as this code is new.
|
|
for( int32 i = 0; i < Retval.Num(); ++i )
|
|
{
|
|
UE_LOG(LogDataBase, Warning, TEXT( "ColumnName %d: Name: %s Type: %d"), i, *Retval[i].ColumnName, static_cast<int32>(Retval[i].DataType) );
|
|
}
|
|
|
|
return Retval;
|
|
}
|
|
|
|
|
|
/**
|
|
* Constructor, used to associate ADO record set with this class.
|
|
*
|
|
* @param InADORecordSet ADO record set to use
|
|
*/
|
|
FADODataBaseRecordSet( ADODB::_RecordsetPtr InADORecordSet )
|
|
: ADORecordSet( InADORecordSet )
|
|
{
|
|
}
|
|
|
|
/** Destructor, cleaning up ADO record set. */
|
|
virtual ~FADODataBaseRecordSet()
|
|
{
|
|
if(ADORecordSet && (ADORecordSet->State & ADODB::adStateOpen))
|
|
{
|
|
// We're using smart pointers so all we need to do is close and assign NULL.
|
|
ADORecordSet->Close();
|
|
}
|
|
|
|
ADORecordSet = NULL;
|
|
}
|
|
};
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FADODataBaseConnection implementation.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Data base connection class using ADO C++ interface to communicate with SQL server.
|
|
*/
|
|
class FADODataBaseConnection : public FDataBaseConnection
|
|
{
|
|
private:
|
|
/** ADO database connection object. */
|
|
ADODB::_ConnectionPtr DataBaseConnection;
|
|
|
|
public:
|
|
/** Constructor, initializing all member variables. */
|
|
FADODataBaseConnection()
|
|
{
|
|
DataBaseConnection = NULL;
|
|
}
|
|
|
|
/** Destructor, tearing down connection. */
|
|
virtual ~FADODataBaseConnection()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
/**
|
|
* Opens a connection to the database.
|
|
*
|
|
* @param ConnectionString Connection string passed to database layer
|
|
* @param RemoteConnectionIP The IP address which the RemoteConnection should connect to
|
|
* @param RemoteConnectionStringOverride The connection string which the RemoteConnection is going to utilize
|
|
*
|
|
* @return true if connection was successfully established, false otherwise
|
|
*/
|
|
virtual bool Open( const TCHAR* ConnectionString, const TCHAR* RemoteConnectionIP, const TCHAR* RemoteConnectionStringOverride )
|
|
{
|
|
if (!FWindowsPlatformMisc::CoInitialize())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Create instance of DB connection object.
|
|
HRESULT hr = DataBaseConnection.CreateInstance(__uuidof(ADODB::Connection));
|
|
if (FAILED(hr))
|
|
{
|
|
FWindowsPlatformMisc::CoUninitialize();
|
|
throw _com_error(hr);
|
|
}
|
|
|
|
// Open the connection. Operation is synchronous.
|
|
DataBaseConnection->Open( ConnectionString, TEXT(""), TEXT(""), ADODB::adConnectUnspecified );
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Closes connection to database.
|
|
*/
|
|
virtual void Close()
|
|
{
|
|
// Close database connection if exists and free smart pointer.
|
|
if( DataBaseConnection && (DataBaseConnection->State & ADODB::adStateOpen))
|
|
{
|
|
DataBaseConnection->Close();
|
|
|
|
FWindowsPlatformMisc::CoUninitialize();
|
|
}
|
|
|
|
DataBaseConnection = NULL;
|
|
}
|
|
|
|
/**
|
|
* Executes the passed in command on the database.
|
|
*
|
|
* @param CommandString Command to execute
|
|
*
|
|
* @return true if execution was successful, false otherwise
|
|
*/
|
|
virtual bool Execute( const TCHAR* CommandString )
|
|
{
|
|
// Execute command, passing in optimization to tell DB to not return records.
|
|
DataBaseConnection->Execute( CommandString, NULL, ADODB::adExecuteNoRecords );
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Executes the passed in command on the database. The caller is responsible for deleting
|
|
* the created RecordSet.
|
|
*
|
|
* @param CommandString Command to execute
|
|
* @param RecordSet Reference to recordset pointer that is going to hold result
|
|
*
|
|
* @return true if execution was successful, false otherwise
|
|
*/
|
|
virtual bool Execute( const TCHAR* CommandString, FDataBaseRecordSet*& RecordSet )
|
|
{
|
|
// Initialize return value.
|
|
RecordSet = NULL;
|
|
|
|
// Create instance of record set.
|
|
ADODB::_RecordsetPtr ADORecordSet = NULL;
|
|
ADORecordSet.CreateInstance(__uuidof(ADODB::Recordset) );
|
|
|
|
// Execute the passed in command on the record set. The recordset returned will be in open state so you can call Get* on it directly.
|
|
ADORecordSet->Open( CommandString, _variant_t((IDispatch *) DataBaseConnection), ADODB::adOpenStatic, ADODB::adLockReadOnly, ADODB::adCmdText );
|
|
|
|
// Create record set from returned data.
|
|
RecordSet = new FADODataBaseRecordSet( ADORecordSet );
|
|
|
|
return RecordSet != NULL;
|
|
}
|
|
};
|
|
|
|
#include "HideWindowsPlatformTypes.h"
|
|
#endif // USE_ADO_INTEGRATION
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FDataBaseConnection implementation.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Static function creating appropriate database connection object.
|
|
*
|
|
* @return instance of platform specific database connection object
|
|
*/
|
|
FDataBaseConnection* FDataBaseConnection::CreateObject()
|
|
{
|
|
if( FParse::Param( FCommandLine::Get(), TEXT("NODATABASE") ) )
|
|
{
|
|
UE_LOG(LogDataBase, Log, TEXT("DB usage disabled, please ignore failure messages."));
|
|
return NULL;
|
|
}
|
|
#if USE_ADO_INTEGRATION
|
|
return new FADODataBaseConnection();
|
|
#elif USE_REMOTE_INTEGRATION
|
|
return new FRemoteDatabaseConnection();
|
|
#else
|
|
return new FDataBaseConnection();
|
|
#endif
|
|
}
|