void core_sqlsrv_get_field()

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;
    }
}