#include "PreparedResultSet.h" #include "ResultBind.h" #include "DataType.h" #include #include #include #include #include #include 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() ); }