1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-23 13:17:45 +00:00
sapphire/deps/mysqlConnector/PreparedResultSet.cpp
2018-10-24 23:31:26 +11:00

706 lines
24 KiB
C++

#include "PreparedResultSet.h"
#include "ResultBind.h"
#include "DataType.h"
#include <string>
#include <cctype>
#include <clocale>
#include <string.h>
#include <mysql.h>
#include <algorithm>
namespace
{
static inline char * my_l_to_a(char * buf, size_t buf_size, int64_t a)
{
snprintf(buf, buf_size, "%lld", (long long) a);
return buf;
}
static inline char * my_ul_to_a(char * buf, size_t buf_size, uint64_t a)
{
snprintf(buf, buf_size, "%llu", (unsigned long long) a);
return buf;
}
static inline char * my_f_to_a(char * buf, size_t buf_size, double a)
{
snprintf(buf, buf_size, "%f", a);
return buf;
}
}
uint32_t Mysql::PreparedResultSet::findColumn( const std::string &columnLabel ) const
{
std::string searchColumn = columnLabel;
std::transform( searchColumn.begin(), searchColumn.end(), searchColumn.begin(),
[](unsigned char c){ return std::toupper( c ); } );
auto iter = m_fieldNameToIndex.find( searchColumn );
if( iter == m_fieldNameToIndex.end() )
return 0;
return iter->second + 1;
}
Mysql::PreparedResultSet::PreparedResultSet( std::shared_ptr< ResultBind >& pBind,
std::shared_ptr< Mysql::PreparedStatement > par ) :
ResultSet( nullptr, par ),
m_pResultBind( pBind ),
m_pStmt( par )
{
pBind->bindResult();
m_numRows = mysql_stmt_num_rows( par->getRawStmt() );
m_numFields = mysql_stmt_field_count( par->getRawStmt() );
auto resMeta = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
for( uint32_t i = 0; i < m_numFields; ++i )
{
auto field = resMeta->fields[i];
std::string fieldName( field.name );
std::transform( fieldName.begin(), fieldName.end(), fieldName.begin(),
[]( unsigned char c ){ return std::toupper(c); } );
m_fieldNameToIndex[fieldName] = i;
}
}
bool Mysql::PreparedResultSet::isBeforeFirstOrAfterLast() const
{
return ( m_rowPosition == 0 );
}
Mysql::PreparedResultSet::~PreparedResultSet()
{
free();
}
uint32_t Mysql::PreparedResultSet::getUInt( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getUInt: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getUInt: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if (*m_pResultBind->m_pBind[columnIndex - 1].is_null) {
return 0;
}
return static_cast< uint32_t >( getUInt64_intern( columnIndex, true ) );
}
uint16_t Mysql::PreparedResultSet::getUInt16( const uint32_t columnIndex ) const
{
return static_cast< uint16_t >( getUInt( columnIndex) );
}
uint16_t Mysql::PreparedResultSet::getUInt16( const std::string& columnLabel ) const
{
return static_cast< uint16_t >( getUInt( columnLabel) );
}
uint8_t Mysql::PreparedResultSet::getUInt8( const uint32_t columnIndex ) const
{
return static_cast< uint8_t >( getUInt( columnIndex) );
}
uint8_t Mysql::PreparedResultSet::getUInt8( const std::string& columnLabel ) const
{
return static_cast< uint8_t >( getUInt( columnLabel) );
}
int16_t Mysql::PreparedResultSet::getInt16( const uint32_t columnIndex ) const
{
return static_cast< int16_t >( getInt( columnIndex) );
}
int16_t Mysql::PreparedResultSet::getInt16( const std::string& columnLabel ) const
{
return static_cast< int16_t >( getInt( columnLabel) );
}
int8_t Mysql::PreparedResultSet::getInt8( const uint32_t columnIndex ) const
{
return static_cast< int8_t >( getInt( columnIndex) );
}
int8_t Mysql::PreparedResultSet::getInt8( const std::string& columnLabel ) const
{
return static_cast< int8_t >( getInt( columnLabel) );
}
uint32_t Mysql::PreparedResultSet::getUInt( const std::string& columnLabel ) const
{
return getUInt( findColumn( columnLabel ) );
}
int64_t Mysql::PreparedResultSet::getInt64( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getInt64: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getInt64: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return 0;
return getInt64_intern( columnIndex, true );
}
int64_t Mysql::PreparedResultSet::getInt64( const std::string& columnLabel ) const
{
return getInt64( findColumn( columnLabel ) );
}
uint64_t Mysql::PreparedResultSet::getUInt64_intern( const uint32_t columnIndex, bool ) const
{
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1 );
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::REAL:
case DataType::DOUBLE:
return static_cast< uint64_t >( getDouble( columnIndex ) );
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::TIMESTAMP:
case DataType::DATE:
case DataType::TIME:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
return Mysql::Util::strtoull( getString( columnIndex ).c_str(), nullptr );
case DataType::BIT:
{
uint64_t uval = 0;
/* This length is in bytes, on the contrary to what can be seen in mysql_resultset.cpp where the Meta is used */
switch( *m_pResultBind->m_pBind[columnIndex - 1].length )
{
case 8:uval = (uint64_t) bit_uint8korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 7:uval = (uint64_t) bit_uint7korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 6:uval = (uint64_t) bit_uint6korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 5:uval = (uint64_t) bit_uint5korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 4:uval = (uint64_t) bit_uint4korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 3:uval = (uint64_t) bit_uint3korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 2:uval = (uint64_t) bit_uint2korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 1:uval = (uint64_t) bit_uint1korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
}
return uval;
}
case DataType::YEAR:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
uint64_t ret;
bool is_it_null = *m_pResultBind->m_pBind[columnIndex - 1].is_null != 0;
bool is_it_unsigned = m_pResultBind->m_pBind[columnIndex - 1].is_unsigned != 0;
switch( m_pResultBind->m_pBind[columnIndex - 1].buffer_length )
{
case 1:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 2:
if(is_it_unsigned)
ret = !is_it_null ? *reinterpret_cast< uint16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 4:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 8:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
default:
throw std::runtime_error( "PreparedResultSet::getInt64_intern: invalid type" );
}
return ret;
}
default:
break;
}
throw std::runtime_error( "PreparedResultSet::getUInt64_intern: unhandled type. Please, report" );
return 0;
}
int64_t Mysql::PreparedResultSet::getInt64_intern( const uint32_t columnIndex, bool ) const
{
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1 );
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::REAL:
case DataType::DOUBLE:
return static_cast< int64_t >( getDouble( columnIndex ) );
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::TIMESTAMP:
case DataType::DATE:
case DataType::TIME:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
return Mysql::Util::strtoll( getString( columnIndex ).c_str(), nullptr );
case DataType::BIT:
{
int64_t uval = 0;
switch( *m_pResultBind->m_pBind[columnIndex - 1].length )
{
case 8:uval = ( int64_t ) bit_uint8korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 7:uval = ( int64_t ) bit_uint7korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 6:uval = ( int64_t ) bit_uint6korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 5:uval = ( int64_t ) bit_uint5korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 4:uval = ( int64_t ) bit_uint4korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 3:uval = ( int64_t ) bit_uint3korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 2:uval = ( int64_t ) bit_uint2korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 1:uval = ( int64_t ) bit_uint1korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
}
return uval;
}
case DataType::YEAR:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
int64_t ret;
bool is_it_null = *m_pResultBind->m_pBind[columnIndex - 1].is_null != 0;
bool is_it_unsigned = m_pResultBind->m_pBind[columnIndex - 1].is_unsigned != 0;
switch( m_pResultBind->m_pBind[columnIndex - 1].buffer_length )
{
case 1:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 2:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 4:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer) : 0;
break;
case 8:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
default:
throw std::runtime_error( "PreparedResultSet::getInt64_intern: invalid type" );
}
return ret;
}
default:
break;
}
throw std::runtime_error( "PreparedResultSet::getInt64_intern: unhandled type. Please, report" );
return 0;
}
uint64_t Mysql::PreparedResultSet::getUInt64( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getUInt64: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getUInt64: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return 0;
return getUInt64_intern( columnIndex, true );
}
uint64_t Mysql::PreparedResultSet::getUInt64( const std::string& columnLabel ) const
{
return getUInt64( findColumn( columnLabel ) );
}
std::string Mysql::PreparedResultSet::getString( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getString: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getString: invalid 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return std::string("");
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1 );
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::TIMESTAMP:
{
char buf[28];
MYSQL_TIME * t = static_cast< MYSQL_TIME* >( m_pResultBind->m_pBind[columnIndex - 1].buffer );
if( t->second_part )
snprintf( buf, sizeof(buf) - 1, "%04d-%02d-%02d %02d:%02d:%02d.%06lu",
t->year, t->month, t->day, t->hour, t->minute, t->second, t->second_part );
else
snprintf( buf, sizeof(buf) - 1, "%04d-%02d-%02d %02d:%02d:%02d",
t->year, t->month, t->day, t->hour, t->minute, t->second );
return std::string( buf );
}
case DataType::DATE:
{
char buf[12];
MYSQL_TIME* t = static_cast< MYSQL_TIME* >( m_pResultBind->m_pBind[columnIndex - 1].buffer );
snprintf( buf, sizeof( buf ) - 1, "%02d-%02d-%02d", t->year, t->month, t->day );
return std::string( buf );
}
case DataType::TIME:
{
char buf[18];
MYSQL_TIME* t = static_cast< MYSQL_TIME* >( m_pResultBind->m_pBind[columnIndex - 1].buffer );
if( t->second_part )
snprintf( buf, sizeof( buf ), "%s%02d:%02d:%02d.%06lu", t->neg ? "-" : "", t->hour, t->minute, t->second, t->second_part );
else
snprintf( buf, sizeof( buf ), "%s%02d:%02d:%02d", t->neg ? "-" : "", t->hour, t->minute, t->second );
return std::string( buf );
}
case DataType::BIT:
case DataType::YEAR: // fetched as a SMALLINT
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
char buf[30];
if( m_pResultBind->m_pBind[columnIndex - 1].is_unsigned )
my_ul_to_a( buf, sizeof( buf ) - 1, getUInt64_intern( columnIndex, false ) );
else
my_l_to_a( buf, sizeof( buf ) - 1, getInt64_intern( columnIndex, false ) );
return std::string( buf );
}
case DataType::REAL:
case DataType::DOUBLE:
{
char buf[50];
my_f_to_a( buf, sizeof( buf ) - 1, getDouble( columnIndex ) );
return std::string( buf );
}
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
return std::string( static_cast< char* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ),
*m_pResultBind->m_pBind[columnIndex - 1].length );
default:
break;
}
throw std::runtime_error( " PreparedResultSet::getString: unhandled type. Please, report" );
return 0;
}
std::string Mysql::PreparedResultSet::getString( const std::string& columnLabel) const
{
return getString( findColumn( columnLabel ) );
}
int32_t Mysql::PreparedResultSet::getInt( uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getInt: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getInt: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return 0;
return static_cast< int32_t >( getInt64_intern( columnIndex, true ) );
}
int32_t Mysql::PreparedResultSet::getInt( const std::string& columnLabel ) const
{
return getInt( findColumn( columnLabel ) );
}
long double Mysql::PreparedResultSet::getDouble(const uint32_t columnIndex) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getDouble: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getDouble: invalid 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null)
return 0.0;
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1);
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::BIT:
case DataType::YEAR:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
long double ret;
bool is_it_unsigned = m_pResultBind->m_pBind[columnIndex - 1].is_unsigned != 0;
if( is_it_unsigned )
{
uint64_t ival = getUInt64_intern( columnIndex, false );
ret = static_cast< long double >( ival );
}
else
{
int64_t ival = getInt64_intern( columnIndex, false );
ret = static_cast< long double >( ival );
}
return ret;
}
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::TIMESTAMP:
case DataType::DATE:
case DataType::TIME:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
{
long double ret = Mysql::Util::strtonum( getString( columnIndex ).c_str() );
return ret;
}
case DataType::REAL:
{
long double ret = !*m_pResultBind->m_pBind[columnIndex - 1].is_null ?
*reinterpret_cast< float* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0.;
return ret;
}
case DataType::DOUBLE:
{
long double ret = !*m_pResultBind->m_pBind[columnIndex - 1].is_null ?
*reinterpret_cast< double* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0.;
return ret;
}
}
throw std::runtime_error( "PreparedResultSet::getDouble: unhandled type. Please, report" );
return .0;
}
long double Mysql::PreparedResultSet::getDouble( const std::string& columnLabel ) const
{
return getDouble( findColumn( columnLabel ) );
}
float Mysql::PreparedResultSet::getFloat( const uint32_t columnIndex ) const
{
return static_cast< float >( getDouble( columnIndex ) );
}
float Mysql::PreparedResultSet::getFloat( const std::string& columnLabel ) const
{
return static_cast< float >( getDouble( findColumn( columnLabel ) ) );
}
size_t Mysql::PreparedResultSet::getRow() const
{
return static_cast< size_t >( m_rowPosition );
}
size_t Mysql::PreparedResultSet::rowsCount() const
{
return static_cast< uint32_t >( m_numRows );
}
const std::shared_ptr< Mysql::Statement > Mysql::PreparedResultSet::getStatement() const
{
return m_pStmt;
}
std::istream* Mysql::PreparedResultSet::getBlob( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getBlob: can't fetch because not on result set" );
return new std::istringstream( getString( columnIndex ) );
}
std::istream* Mysql::PreparedResultSet::getBlob( const std::string& columnLabel ) const
{
return new std::istringstream( getString( columnLabel ) );
}
std::vector< char > Mysql::PreparedResultSet::getBlobVector( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getBlobVector: invalid value of 'columnIndex'" );
std::unique_ptr< std::istream > inStr( getBlob( columnIndex ) );
char buff[4196];
std::vector< char > data;
inStr->read( buff, sizeof( buff ) );
if( inStr->gcount() )
{
data.resize( static_cast< uint32_t >( inStr->gcount() ) );
memcpy( data.data(), buff, static_cast< size_t >( inStr->gcount() ) );
}
return data;
}
std::vector< char > Mysql::PreparedResultSet::getBlobVector( const std::string& columnLabel ) const
{
return getBlobVector( findColumn( columnLabel ) );
}
bool Mysql::PreparedResultSet::getBoolean( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getBoolean: can't fetch because not on result set" );
return getInt(columnIndex ) != 0;
}
bool Mysql::PreparedResultSet::getBoolean( const std::string& columnLabel ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error("PreparedResultSet::getBoolean: can't fetch because not on result set");
return getInt(columnLabel ) != 0;
}
bool Mysql::PreparedResultSet::isLast() const
{
return ( m_rowPosition == m_numRows );
}
bool Mysql::PreparedResultSet::isFirst() const
{
return ( m_rowPosition == 1 );
}
bool Mysql::PreparedResultSet::isNull( const uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::isNull: invalid value of 'columnIndex'" );
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::isNull: can't fetch because not on result set" );
return *m_pResultBind->m_pBind[columnIndex - 1].is_null != 0;
}
bool Mysql::PreparedResultSet::isNull( const std::string& columnLabel ) const
{
uint32_t index = findColumn( columnLabel );
if( index == 0 )
throw std::runtime_error( "PreparedResultSet::isNull: invalid value of 'columnLabel'" );
return isNull( index );
}
bool Mysql::PreparedResultSet::next()
{
bool ret = false;
// reset last_queried_column
// m_lastQueriedColumn = std::numeric_limits< uint32_t >::max();
int result = mysql_stmt_fetch( m_pStmt->getRawStmt() );
if( !result || result == MYSQL_DATA_TRUNCATED )
ret = true;
if( result == MYSQL_NO_DATA )
ret = false;
if( result == 1 )
throw std::runtime_error( "PreparedResultSet:next: error getting next result" );
++m_rowPosition;
return ret;
}
void Mysql::PreparedResultSet::clearWarnings()
{
}
void Mysql::PreparedResultSet::free()
{
if( m_pStmt->getRawStmt() )
mysql_stmt_free_result( m_pStmt->getRawStmt() );
}