1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-21 20:27:46 +00:00
sapphire/deps/mysqlConnector/ResultBind.cpp
2018-10-24 23:31:26 +11:00

146 lines
5 KiB
C++

#include "ResultBind.h"
#include "mysql_util.h"
#include "ResultBind.h"
#include <string.h>
namespace Mysql
{
struct st_buffer_size_type
{
char * buffer;
size_t size;
enum_field_types type;
st_buffer_size_type( char * b, size_t s, enum_field_types t )
: buffer( b ),
size( s ),
type( t )
{
}
};
using BufferSizePair = std::pair< char*, size_t >;
static struct st_buffer_size_type
allocate_buffer_for_field( const MYSQL_FIELD * const field )
{
switch( field->type )
{
case MYSQL_TYPE_NULL:
return st_buffer_size_type( nullptr, 0, field->type );
case MYSQL_TYPE_TINY:
return st_buffer_size_type( new char[1], 1, field->type );
case MYSQL_TYPE_SHORT:
return st_buffer_size_type( new char[2], 2, field->type );
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_FLOAT:
return st_buffer_size_type( new char[4], 4, field->type );
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_LONGLONG:
return st_buffer_size_type( new char[8], 8, field->type );
case MYSQL_TYPE_YEAR:
return st_buffer_size_type( new char[2], 2, MYSQL_TYPE_SHORT );
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
return st_buffer_size_type( new char[sizeof( MYSQL_TIME )], sizeof( MYSQL_TIME ), field->type );
case MYSQL_TYPE_TINY_BLOB:
return st_buffer_size_type( new char[256], 256, field->type );
case MYSQL_TYPE_LONG_BLOB:
return st_buffer_size_type( new char[16777215], 16777215, field->type );
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
return st_buffer_size_type( new char[65535], 65535, field->type );
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
return st_buffer_size_type( new char[64], 64, field->type );
#if A1
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_YEAR:
return st_buffer_size_type(new char[10], 10, field->type);
#endif
#if A0
// There two are not sent over the wire
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
#endif
case MYSQL_TYPE_BIT:
return st_buffer_size_type( new char[8], 8, MYSQL_TYPE_BIT );
case MYSQL_TYPE_GEOMETRY:
default:
throw std::runtime_error( "allocate_buffer_for_field: invalid rbind data type" );
}
}
ResultBind::ResultBind( MYSQL_STMT* pStmt )
: m_pStmt( pStmt ),
m_numFields( 0 ),
m_isNull( nullptr ),
m_err( nullptr ),
m_len( nullptr ),
m_pBind( nullptr )
{
}
ResultBind::~ResultBind()
{
if( m_pBind.get() )
{
for( uint32_t i = 0; i < m_numFields; ++i )
delete[] ( char* ) m_pBind[i].buffer;
}
}
void ResultBind::bindResult()
{
for( uint32_t i = 0; i < m_numFields; ++i )
delete[] ( char* ) m_pBind[i].buffer;
m_pBind.reset( nullptr );
m_isNull.reset( nullptr );
m_err.reset( nullptr );
m_len.reset( nullptr );
m_numFields = mysql_stmt_field_count( m_pStmt );
if( !m_numFields )
return;
m_pBind.reset( new MYSQL_BIND[m_numFields] );
memset( m_pBind.get(), 0, sizeof( MYSQL_BIND ) * m_numFields );
m_isNull.reset( new my_bool[m_numFields] );
memset( m_isNull.get(), 0, sizeof( my_bool ) * m_numFields );
m_err.reset( new my_bool[m_numFields] );
memset( m_err.get(), 0, sizeof( my_bool ) * m_numFields );
m_len.reset( new unsigned long[m_numFields] );
memset( m_len.get(), 0, sizeof( unsigned long ) * m_numFields );
MYSQL_RES* info = mysql_stmt_result_metadata( m_pStmt );
for( uint32_t i = 0; i < m_numFields; ++i )
{
// MYSQL_FIELD * field = resultMeta->fetch_field();
MYSQL_FIELD * field = mysql_fetch_field_direct( info, i );
struct st_buffer_size_type p = allocate_buffer_for_field(field);
m_pBind[i].buffer_type = p.type;
m_pBind[i].buffer = p.buffer;
m_pBind[i].buffer_length = static_cast< unsigned long >( p.size );
m_pBind[i].length = &m_len[i];
m_pBind[i].is_null = &m_isNull[i];
m_pBind[i].error = &m_err[i];
m_pBind[i].is_unsigned = field->flags & UNSIGNED_FLAG;
}
if( mysql_stmt_bind_result( m_pStmt, m_pBind.get() ) )
throw std::runtime_error( "Couldn't bind : " + std::to_string( mysql_stmt_errno( m_pStmt ) ) );
}
}