in source/shared/core_stmt.cpp [805:907]
void core_sqlsrv_get_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_phptype sqlsrv_php_type_in, _In_ bool prefer_string,
_Outref_result_bytebuffer_maybenull_(*field_len) void*& field_value, _Inout_ SQLLEN* field_len, _In_ bool cache_field,
_Out_ SQLSRV_PHPTYPE *sqlsrv_php_type_out)
{
try {
// close the stream to release the resource
close_active_stream(stmt);
// if the field has been retrieved before, return the previous result
field_cache* cached = NULL;
if (NULL != ( cached = static_cast<field_cache*>( zend_hash_index_find_ptr( Z_ARRVAL( stmt->field_cache ), static_cast<zend_ulong>( field_index ))))) {
// the field value is NULL
if( cached->value == NULL ) {
field_value = NULL;
*field_len = 0;
if( sqlsrv_php_type_out ) { *sqlsrv_php_type_out = SQLSRV_PHPTYPE_NULL; }
}
else {
field_value = sqlsrv_malloc( cached->len, sizeof( char ), 1 );
memcpy_s( field_value, ( cached->len * sizeof( char )), cached->value, cached->len );
if( cached->type.typeinfo.type == SQLSRV_PHPTYPE_STRING) {
// prevent the 'string not null terminated' warning
reinterpret_cast<char*>( field_value )[cached->len] = '\0';
}
*field_len = cached->len;
if( sqlsrv_php_type_out) { *sqlsrv_php_type_out = static_cast<SQLSRV_PHPTYPE>(cached->type.typeinfo.type); }
}
return;
}
sqlsrv_phptype sqlsrv_php_type = sqlsrv_php_type_in;
// Make sure that the statement was executed and not just prepared.
CHECK_CUSTOM_ERROR( !stmt->executed, stmt, SQLSRV_ERROR_STATEMENT_NOT_EXECUTED ) {
throw core::CoreException();
}
// if the field is to be cached, and this field is being retrieved out of order, cache prior fields so they
// may also be retrieved.
if( cache_field && (field_index - stmt->last_field_index ) >= 2 ) {
sqlsrv_phptype invalid;
invalid.typeinfo.type = SQLSRV_PHPTYPE_INVALID;
for( int i = stmt->last_field_index + 1; i < field_index; ++i ) {
SQLSRV_ASSERT( reinterpret_cast<field_cache*>( zend_hash_index_find_ptr( Z_ARRVAL( stmt->field_cache ), i )) == NULL, "Field already cached." );
core_sqlsrv_get_field( stmt, i, invalid, prefer_string, field_value, field_len, cache_field, sqlsrv_php_type_out );
// delete the value returned since we only want it cached, not the actual value
if( field_value ) {
efree( field_value );
field_value = NULL;
*field_len = 0;
}
}
}
// If the php type was not specified set the php type to be the default type.
if (sqlsrv_php_type.typeinfo.type == SQLSRV_PHPTYPE_INVALID) {
SQLSRV_ASSERT(stmt->current_meta_data.size() > field_index, "core_sqlsrv_get_field - meta data vector not in sync" );
// Get the corresponding php type from the sql type and then save the result for later
if (stmt->current_meta_data[field_index]->sqlsrv_php_type.typeinfo.type == SQLSRV_PHPTYPE_INVALID) {
SQLLEN sql_field_type = 0;
SQLLEN sql_field_len = 0;
sql_field_type = stmt->current_meta_data[field_index]->field_type;
if (stmt->current_meta_data[field_index]->field_precision > 0) {
sql_field_len = stmt->current_meta_data[field_index]->field_precision;
}
else {
sql_field_len = stmt->current_meta_data[field_index]->field_size;
}
sqlsrv_php_type = stmt->sql_type_to_php_type(static_cast<SQLINTEGER>(sql_field_type), static_cast<SQLUINTEGER>(sql_field_len), prefer_string);
stmt->current_meta_data[field_index]->sqlsrv_php_type = sqlsrv_php_type;
}
else {
// use the previously saved php type
sqlsrv_php_type = stmt->current_meta_data[field_index]->sqlsrv_php_type;
}
}
// Verify that we have an acceptable type to convert.
CHECK_CUSTOM_ERROR(!is_valid_sqlsrv_phptype(sqlsrv_php_type), stmt, SQLSRV_ERROR_INVALID_TYPE) {
throw core::CoreException();
}
if( sqlsrv_php_type_out != NULL )
*sqlsrv_php_type_out = static_cast<SQLSRV_PHPTYPE>( sqlsrv_php_type.typeinfo.type );
// Retrieve the data
core_get_field_common( stmt, field_index, sqlsrv_php_type, field_value, field_len );
// if the user wants us to cache the field, we'll do it
if( cache_field ) {
field_cache cache( field_value, *field_len, sqlsrv_php_type );
core::sqlsrv_zend_hash_index_update_mem( *stmt, Z_ARRVAL( stmt->field_cache ), field_index, &cache, sizeof(field_cache) );
}
}
catch( core::CoreException& e ) {
throw e;
}
}