# class PG::TypeMapInRuby

This class can be used to implement a type map in ruby, typically as a `default_type_map` in a type map chain.

This API is EXPERIMENTAL and could change in the future.

### Public Instance Methods

fit_to_copy_get() click to toggle source

Check that the type map can be used for `PG::Connection#get_copy_data`.

This method is called, when a type map is used for decoding copy data, before the value is casted.

Should return the expected number of columns or 0 if the number of columns is unknown. This number is only used for memory pre-allocation.

    static VALUE pg_tmir_fit_to_copy_get_dummy( VALUE self ){

fit_to_query( params ) click to toggle source

Check that the type map fits to the given user values.

This method is called, when a type map is used for sending a query and for encoding of copy data, before the value is casted.

    static VALUE
    pg_tmir_fit_to_query( VALUE self, VALUE params )
    {
            t_tmir *this = RTYPEDDATA_DATA( self );
            t_typemap *default_tm;

            if( rb_respond_to(self, s_id_fit_to_query) ){
                    rb_funcall( self, s_id_fit_to_query, 1, params );
            }

            /* Ensure that the default type map fits equally. */
            default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
            default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );

            return self;
    }

fit_to_result( result ) click to toggle source

Check that the type map fits to the result.

This method is called, when a type map is assigned to a result. It must return a `PG::TypeMap` object or raise an Exception. This can be `self` or some other type map that fits to the result.

    static VALUE
    pg_tmir_fit_to_result( VALUE self, VALUE result )
    {
            t_tmir *this = RTYPEDDATA_DATA( self );
            t_typemap *default_tm;
            t_typemap *p_new_typemap;
            VALUE sub_typemap;
            VALUE new_typemap;

            if( rb_respond_to(self, s_id_fit_to_result) ){
                    t_typemap *tm;
                    UNUSED(tm);
                    new_typemap = rb_funcall( self, s_id_fit_to_result, 1, result );

                    if ( !rb_obj_is_kind_of(new_typemap, rb_cTypeMap) ) {
                            /* TypedData_Get_Struct() raises "wrong argument type", which is misleading,
                            * so we better raise our own message */
                            rb_raise( rb_eTypeError, "wrong return type from fit_to_result: %s expected kind of PG::TypeMap",
                                            rb_obj_classname( new_typemap ) );
                    }
                    TypedData_Get_Struct(new_typemap, t_typemap, &pg_typemap_type, tm);
            } else {
                    new_typemap = self;
            }

            /* Ensure that the default type map fits equally. */
            default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
            sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );

            if( sub_typemap != this->typemap.default_typemap ){
                    new_typemap = rb_obj_dup( new_typemap );
            }

            p_new_typemap = RTYPEDDATA_DATA(new_typemap);
            p_new_typemap->default_typemap = sub_typemap;
            return new_typemap;
    }

typecast_copy_get( field_str, fieldno, format, encoding ) click to toggle source

Cast a field string received by `PG::Connection#get_copy_data`.

This method implementation uses the `default_type_map` to cast field_str. It can be derived to change this behaviour.

Parameters:

- `field_str` : The String received from the server.

- `fieldno` : The field number from left to right.

- `format` : The format code (0 = text, 1 = binary)

- `encoding` : The encoding of the connection and encoding the returned value should get.

    static VALUE
    pg_tmir_typecast_copy_get( VALUE self, VALUE field_str, VALUE fieldno, VALUE format, VALUE enc )
    {
            t_tmir *this = RTYPEDDATA_DATA( self );
            t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
            int enc_idx = rb_to_encoding_index( enc );

            return default_tm->funcs.typecast_copy_get( default_tm, field_str, NUM2INT(fieldno), NUM2INT(format), enc_idx );
    }

typecast_query_param( param_value, field ) click to toggle source

Cast a field string for transmission to the server.

This method implementation uses the `default_type_map` to cast param_value. It can be derived to change this behaviour.

Parameters:

- `param_value` : The value from the user.

- `field` : The field number from left to right.

    static VALUE
    pg_tmir_typecast_query_param( VALUE self, VALUE param_value, VALUE field )
    {
            t_tmir *this = RTYPEDDATA_DATA( self );
            t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
            t_pg_coder *p_coder = default_tm->funcs.typecast_query_param( default_tm, param_value, NUM2INT(field) );

            return p_coder ? p_coder->coder_obj : Qnil;
    }

typecast_result_value( result, tuple, field ) click to toggle source

Retrieve and cast a field of the given result.

This method implementation uses the `default_type_map` to get the field value. It can be derived to change this behaviour.

Parameters:

- `result` : The `PG::Result` received from the database.

- `tuple` : The row number to retrieve.

- `field` : The column number to retrieve.

Note: Calling any value retrieving methods of `result` will result in an (endless) recursion. Instead super() can be used to retrieve the value using the default_typemap.

    static VALUE
    pg_tmir_typecast_result_value( VALUE self, VALUE result, VALUE tuple, VALUE field )
    {
            t_tmir *this = RTYPEDDATA_DATA( self );
            t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
            return default_tm->funcs.typecast_result_value( default_tm, result, NUM2INT(tuple), NUM2INT(field) );
    }