# Virtual methods for recordsets

This section explains how to write virtual methods for the GdaDataSelect subclasses implementations, which should be done when implementing a database provider.

That data model implementation simplifies the implementation of provider's recordsets by having them implement only a few virtual methods.

The data model represents each row as a separate GdaRow object, and virtual methods to retrieve rows have to return new (and correctly initialized) objects of that class. The referencing of these new objects is left up to the implementation which:

- can use the gda_data_select_take_row () method for on row object created which transfers the ownership of the GdaRow object to the data model (this is the easiest and the fastest as once created, the rows are available for further usage, but will consume more memory with each row read from the model).

- can keep the references to these objects to the subclass implementation which will consume less memory but will make it necessary to create a new row object each time a row is read which is slower

- can do a mix of the two solutions above: monitor the memory usage for the data model to enable to "cache" some rows and discard some when memory is needed

Note that the methods mentioned in the 1st and 3rd items should be reserved for random data access mode, and that cursor based access mode should implement the method mentioned in th 2nd item.

## fetch_nb_rows()

This method is called when the user calls gda_data_model_get_n_rows ().

Its implementation is mandatory if the data model supports random access.

Note about the the data model's number of rows: it may not be known until the cursor has reached the last row of the recordset, but once known, the number of rows can be stored in the advertized_nrows's member of the GdaDataSelect object.

## fetch_random()

This method is called when the user calls gda_data_model_get_value_at (), and is used only when the data access mode for the data model is random (that is not cursor based) (i.e. when data access is cursor based, this method will not be called).

Its implementation is mandatory if the data model supports random access.

Also it is safe to assume that when called, the prow parameter will not be NULL, and that *prow is actually NULL.

## store_all()

This method is called when the user sets the "store-all-rows" to TRUE or calls gda_data_select_prepare_for_offline. It has the effect of forcing the creation of a GdaRow object for each row of the data model (thus increasing the memory consumption but reducing further access times). It is available only when the data access mode for the data model is random (that is not cursor based). When random data access is not supported, this method will not be called.

Its implementation is optional.

## fetch_next()

This method is called when data access is cursor based and a data model iterator is moved one position forward. The rownum is an indication of what the row number will be once the next row has been fetched (it can safely be discarded if that information is not necessary).

This method is not used when data is accessed in a random way. Also it is safe to assume that when called, the prow parameter will not be NULL, and that *prow is actually NULL.

Its implementation is mandatory if the data model supports forward cursor access.

## fetch_prev()

This method is called when data access is cursor based and a data model iterator is moved one position backward. The rownum is an indication of what the row number will be once the previous row has been fetched (it can safely be discarded if that information is not necessary). Implementing this method is not necessary if the data model does not support moving iterators backward.

This method is not used when data is accessed in a random way. Also it is safe to assume that when called, the prow parameter will not be NULL, and that *prow is actually NULL.

Its implementation is mandatory if the data model supports backward cursor access.

## fetch_at()

This method can be implemented (but it is not required) when data access is cursor based and there is a shorter way of getting to a specific row than having to call the fetch_next() or fetch_prev() methods several times.

Its implementation is mandatory if the data model supports forward or backward cursor access.