GdaMetaStruct

## GdaMetaStruct GdaMetaStruct — In memory representation of some database objects |

## Synopsis

                        GdaMetaStruct;
    enum                GdaMetaStructFeature;
    enum                GdaMetaStructError;
    enum                GdaMetaDbObjectType;
                        GdaMetaDbObject;
    #define             GDA_META_DB_OBJECT                  (x)
    #define             GDA_META_TABLE                      (dbobj)
    #define             GDA_META_VIEW                       (dbobj)
                        GdaMetaTable;
                        GdaMetaView;
                        GdaMetaTableColumn;
    #define             GDA_META_TABLE_COLUMN               (x)
    const GValue *      gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol,
                                                             const gchar *attribute);
    void                gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol,
                                                             const gchar *attribute,
                                                             const GValue *value,
                                                             GDestroyNotify destroy);
    #define             gda_meta_table_column_set_attribute_static(column,attribute,value)
    void                gda_meta_table_column_foreach_attribute
                                                            (GdaMetaTableColumn *tcol,
                                                             GdaAttributesManagerFunc func,
                                                             gpointer data);
                        GdaMetaTableForeignKey;
    #define             GDA_META_TABLE_FOREIGN_KEY          (x)
    #define             GDA_META_STRUCT_ERROR
    GdaMetaStruct *     gda_meta_struct_new                 (GdaMetaStore *store,
                                                             GdaMetaStructFeature features);
    GdaMetaDbObject *   gda_meta_struct_complement          (GdaMetaStruct *mstruct,
                                                             GdaMetaDbObjectType type,
                                                             const GValue *catalog,
                                                             const GValue *schema,
                                                             const GValue *name,
                                                             GError **error);
    gboolean            gda_meta_struct_complement_schema   (GdaMetaStruct *mstruct,
                                                             const GValue *catalog,
                                                             const GValue *schema,
                                                             GError **error);
    gboolean            gda_meta_struct_complement_default  (GdaMetaStruct *mstruct,
                                                             GError **error);
    gboolean            gda_meta_struct_complement_all      (GdaMetaStruct *mstruct,
                                                             GError **error);
    gboolean            gda_meta_struct_complement_depend   (GdaMetaStruct *mstruct,
                                                             GdaMetaDbObject *dbo,
                                                             GError **error);
    enum                GdaMetaSortType;
    gboolean            gda_meta_struct_sort_db_objects     (GdaMetaStruct *mstruct,
                                                             GdaMetaSortType sort_type,
                                                             GError **error);
    GSList *            gda_meta_struct_get_all_db_objects  (GdaMetaStruct *mstruct);
    GdaMetaDbObject *   gda_meta_struct_get_db_object       (GdaMetaStruct *mstruct,
                                                             const GValue *catalog,
                                                             const GValue *schema,
                                                             const GValue *name);
    GdaMetaTableColumn * gda_meta_struct_get_table_column   (GdaMetaStruct *mstruct,
                                                             GdaMetaTable *table,
                                                             const GValue *col_name);
    enum                GdaMetaGraphInfo;
    gchar *             gda_meta_struct_dump_as_graph       (GdaMetaStruct *mstruct,
                                                             GdaMetaGraphInfo info,
                                                             GError **error);

## Object Hierarchy

      GObject
       +----GdaMetaStruct

## Properties

      "features"                 guint                 : Read / Write / Construct Only
      "meta-store"               GdaMetaStore*         : Read / Write / Construct Only

## Description

The GdaMetaStruct object reads data from a GdaMetaStore object and creates an easy to use in memory representation for some database objects. For example one can easily analyse the columns of a table (or its foreign keys) using a GdaMetaStruct.

When created, the new GdaMetaStruct object is empty (it does not have any information about any database object). Information about database objects is computed upon request using the `gda_meta_struct_complement()` method. Information about individual database objects is represented by GdaMetaDbObject structures, which can be obtained using `gda_meta_struct_get_db_object()` or `gda_meta_struct_get_all_db_objects()`.

Note that the GdaMetaDbObject structures may change or may be removed or replaced by others, so it not advised to keep pointers to these structures: pointers to these structures should be considered valid as long as `gda_meta_struct_complement()` and other similar functions have not been called.

In the following code sample, one prints the columns names and types of a table:

    GdaMetaStruct *mstruct;
    GdaMetaDbObject *dbo;
    GValue *catalog, *schema, *name;
    /* Define name (and optionnally catalog and schema) */
    [...]
    mstruct = gda_meta_struct_new ();
    gda_meta_struct_complement (mstruct, store, GDA_META_DB_TABLE, catalog, schema, name, NULL);
    dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
    if (!dbo)
            g_print ("Table not found\n");
    else {
            GSList *list;
            for (list = GDA_META_TABLE (dbo)->columns; list; list = list->next) {
                    GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
                    g_print ("COLUMN: %s (%s)\n", tcol->column_name, tcol->column_type);
            }
    }
    gda_meta_struct_free (mstruct);

If now the database object type is not known, one can use the following code:

    GdaMetaStruct *mstruct;
    GdaMetaDbObject *dbo;
    GValue *catalog, *schema, *name;
    /* Define name (and optionnally catalog and schema) */
    [...]
    mstruct = gda_meta_struct_new ();
    gda_meta_struct_complement (mstruct, store, GDA_META_DB_UNKNOWN, catalog, schema, name, NULL);
    dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
    if (!dbo)
            g_print ("Object not found\n");
    else {
            if ((dbo->obj_type == GDA_META_DB_TABLE) || (dbo->obj_type == GDA_META_DB_VIEW)) {
                    if (dbo->obj_type == GDA_META_DB_TABLE)
                            g_print ("Is a table\n");
                    else if (dbo->obj_type == GDA_META_DB_VIEW) {
                            g_print ("Is a view, definition is:\n");
                            g_print ("%s\n", GDA_META_VIEW (dbo)->view_def);
                    }
                    GSList *list;
                    for (list = GDA_META_TABLE (dbo)->columns; list; list = list->next) {
                            GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
                            g_print ("COLUMN: %s (%s)\n", tcol->column_name, tcol->column_type);
                    }
            }
            else
                    g_print ("Not a table or a view\n");
    }
    gda_meta_struct_free (mstruct);

## Details

### GdaMetaStruct

    typedef struct _GdaMetaStruct GdaMetaStruct;

### enum GdaMetaStructFeature

    typedef enum {
    	GDA_META_STRUCT_FEATURE_NONE              = 0,
    	GDA_META_STRUCT_FEATURE_FOREIGN_KEYS      = 1 << 0,
    	GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES = 1 << 1,

    	GDA_META_STRUCT_FEATURE_ALL               = GDA_META_STRUCT_FEATURE_FOREIGN_KEYS |
    	                                            GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES
    } GdaMetaStructFeature;

Controls which features are computed about database objects.

`GDA_META_STRUCT_FEATURE_NONE` | database objects only have their own attributes
`GDA_META_STRUCT_FEATURE_FOREIGN_KEYS` | foreign keys are computed for tables
`GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES` | for views, the tables they use are also computed
`GDA_META_STRUCT_FEATURE_ALL` | all the features are computed

### enum GdaMetaStructError

    typedef enum {
    	GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
            GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR,
            GDA_META_STRUCT_INCOHERENCE_ERROR
    } GdaMetaStructError;

### enum GdaMetaDbObjectType

    typedef enum {
    	GDA_META_DB_UNKNOWN,
    	GDA_META_DB_TABLE,
    	GDA_META_DB_VIEW
    } GdaMetaDbObjectType;

Type of database object represented by a GdaMetaDbObject structure

`GDA_META_DB_UNKNOWN` | unknown type, we only know the object exists
`GDA_META_DB_TABLE` | the object is a table
`GDA_META_DB_VIEW` | the object is a view

### GdaMetaDbObject

    typedef struct {
    	union {
    		GdaMetaTable    meta_table;
    		GdaMetaView     meta_view;
    	}                       extra;
    	GdaMetaDbObjectType     obj_type;
    	gboolean                outdated;
    	gchar                  *obj_catalog;
    	gchar                  *obj_schema;
    	gchar                  *obj_name;
    	gchar                  *obj_short_name;
    	gchar                  *obj_full_name;
    	gchar                  *obj_owner;

    	GSList                 *depend_list; /* list of GdaMetaDbObject pointers on which this object depends */
    } GdaMetaDbObject;

Struture to hold information about each database object (tables, views, ...), its contents must not be modified.

Note: `obj_catalog`, `obj_schema`, `obj_name`, `obj_short_name` and `obj_full_name` are case sensitive: one must use `gda_sql_identifier_quote()` to know if is it is necessary to surround by double quotes before using in an SQL statement

Struture to hold information about each database object (tables, views, triggers, ...)

Note: `obj_catalog`, `obj_schema`, `obj_name`, `obj_short_name` and `obj_full_name` are case sensitive: one must call `gda_sql_identifier_needs_quotes()` to know if is it is necessary to surround by double quotes before using in an SQL statement

GdaMetaDbObjectType `obj_type`; | the type of object (table, view)
gboolean `outdated`; |
gchar *`obj_catalog`; | the catalog the object is in
gchar *`obj_schema`; | the schema the object is in
gchar *`obj_name`; | the object's name
gchar *`obj_short_name`; | the shortest way to name the object
gchar *`obj_full_name`; | the full name of the object (in the <schema>.<nameagt; notation
gchar *`obj_owner`; | object's owner
GSList *`depend_list`; | list of GdaMetaDbObject pointers on which this object depends (through foreign keys or tables used for views)

### GDA_META_DB_OBJECT()

    #define GDA_META_DB_OBJECT(x) ((GdaMetaDbObject*)(x))

`x` : |

### GDA_META_TABLE()

    #define GDA_META_TABLE(dbobj) (&((dbobj)->extra.meta_table))

`dbobj` : |

### GDA_META_VIEW()

    #define GDA_META_VIEW(dbobj) (&((dbobj)->extra.meta_view))

`dbobj` : |

### GdaMetaTable

    typedef struct {
    	GSList       *columns;

    	/* PK fields index */
    	gint         *pk_cols_array;
    	gint          pk_cols_nb;

    	/* Foreign keys */
    	GSList       *reverse_fk_list; /* list of GdaMetaTableForeignKey where @depend_on == this GdaMetaDbObject */
    	GSList       *fk_list; /* list of GdaMetaTableForeignKey where @meta_table == this GdaMetaDbObject */
    } GdaMetaTable;

This structure specifies a GdaMetaDbObject to represent a table's specific attributes, its contents must not be modified.

GSList *`columns`; | list of GdaMetaTableColumn structures, one for each column in the table
gint *`pk_cols_array`; | index of the columns part of the primary key for the table (WARNING: columns numbering here start at 0)
gint `pk_cols_nb`; | size of the `pk_cols_array` array
GSList *`reverse_fk_list`; | list of GdaMetaTableForeignKey where the referenced table is this table
GSList *`fk_list`; | list of GdaMetaTableForeignKey for this table

### GdaMetaView

    typedef struct {
    	GdaMetaTable  table;
    	gchar        *view_def;
    	gboolean      is_updatable;
    } GdaMetaView;

This structure specifies a GdaMetaDbObject to represent a view's specific attributes, its contents must not be modified.

GdaMetaTable `table`; | a view is also a table as it has columns
gchar *`view_def`; | views' definition
gboolean `is_updatable`; | tells if the view's contents can be updated

### GdaMetaTableColumn

    typedef struct {
    	gchar        *column_name;
    	gchar        *column_type;
    	GType         gtype;
    	gboolean      pkey;
    	gboolean      nullok;
    	gchar        *default_value;
    } GdaMetaTableColumn;

This structure represents a table of view's column, its contents must not be modified.

gchar *`column_name`; | the column's name
gchar *`column_type`; | the column's DBMS's type
GType `gtype`; | the detected column's GType
gboolean `pkey`; | tells if the column is part of a primary key
gboolean `nullok`; | tells if the column can be `NULL`
gchar *`default_value`; | the column's default value

### GDA_META_TABLE_COLUMN()

    #define GDA_META_TABLE_COLUMN(x) ((GdaMetaTableColumn*)(x))

`x` : |

### gda_meta_table_column_get_attribute ()

    const GValue *      gda_meta_table_column_get_attribute (GdaMetaTableColumn *tcol,
                                                             const gchar *attribute);

Get the value associated to a named attribute.

Attributes can have any name, but Libgda proposes some default names, see this section.

`tcol` : | a GdaMetaTableColumn
`attribute` : | attribute name as a string
Returns : | a read-only GValue, or `NULL` if not attribute named `attribute` has been set for `column`

### gda_meta_table_column_set_attribute ()

    void                gda_meta_table_column_set_attribute (GdaMetaTableColumn *tcol,
                                                             const gchar *attribute,
                                                             const GValue *value,
                                                             GDestroyNotify destroy);

Set the value associated to a named attribute.

Attributes can have any name, but Libgda proposes some default names, see this section. If there is already an attribute named `attribute` set, then its value is replaced with the new `value`, except if `value` is `NULL`, in which case the attribute is removed.

Warning: `attribute` is not copied, if it needs to be freed when not used anymore, then `destroy` should point to the functions which will free it (typically `g_free()`). If `attribute` does not need to be freed, then `destroy` can be `NULL`.

`tcol` : | a GdaMetaTableColumn
`attribute` : | attribute name as a static string
`value` : | a GValue, or `NULL`
`destroy` : | function called when `attribute` has to be freed, or `NULL`

### gda_meta_table_column_set_attribute_static()

    #define gda_meta_table_column_set_attribute_static(column,attribute,value) gda_meta_table_column_set_attribute((column),(attribute),(value),NULL)

This function is similar to `gda_meta_table_column_set_attribute()` but for static strings

`column` : | a GdaMetaTableColumn
`attribute` : | attribute's name
`value` : | a GValue, or `NULL`

### gda_meta_table_column_foreach_attribute ()

    void                gda_meta_table_column_foreach_attribute
                                                            (GdaMetaTableColumn *tcol,
                                                             GdaAttributesManagerFunc func,
                                                             gpointer data);

Calls `func` for each attribute set to tcol

`tcol` : | a GdaMetaTableColumn
`func` : | a GdaAttributesManagerFunc function
`data` : | user data to be passed as last argument of `func` each time it is called

### GdaMetaTableForeignKey

    typedef struct {
    	GdaMetaDbObject  *meta_table;
    	GdaMetaDbObject  *depend_on;

    	gint              cols_nb;
    	gint             *fk_cols_array; /* FK fields index */
    	gchar           **fk_names_array; /* FK fields names */
    	gint             *ref_pk_cols_array; /* Ref PK fields index */
    	gchar           **ref_pk_names_array; /* Ref PK fields names */
    } GdaMetaTableForeignKey;

This structure represents a foreign key constraint, its contents must not be modified.

GdaMetaDbObject *`meta_table`; | the GdaMetaDbObject for which this structure represents a foreign key
GdaMetaDbObject *`depend_on`; | the GdaMetaDbObject which is referenced by the foreign key
gint `cols_nb`; | the size of the `fk_cols_array`, `fk_names_array`, `ref_pk_cols_array` and `ref_pk_names_array` arrays
gint *`fk_cols_array`; | the columns' indexes in `meta_table` which participate in the constraint (WARNING: columns numbering here start at 1)
gchar **`fk_names_array`; | the columns' names in `meta_table` which participate in the constraint
gint *`ref_pk_cols_array`; | the columns' indexes in `depend_on` which participate in the constraint (WARNING: columns numbering here start at 1)
gchar **`ref_pk_names_array`; | the columns' names in `depend_on` which participate in the constraint

### GDA_META_TABLE_FOREIGN_KEY()

    #define GDA_META_TABLE_FOREIGN_KEY(x) ((GdaMetaTableForeignKey*)(x))

`x` : |

### GDA_META_STRUCT_ERROR

    #define GDA_META_STRUCT_ERROR gda_meta_struct_error_quark ()

### gda_meta_struct_new ()

    GdaMetaStruct *     gda_meta_struct_new                 (GdaMetaStore *store,
                                                             GdaMetaStructFeature features);

Creates a new GdaMetaStruct object. The `features` specifies the extra features which will also be computed: the more features, the more time it takes to run. Features such as table's columns, each column's attributes, etc are not optional and will always be computed.

`store` : | a GdaMetaStore from which the new GdaMetaStruct object will fetch information
`features` : | the kind of extra information the new GdaMetaStruct object will compute
Returns : | the newly created GdaMetaStruct object

### gda_meta_struct_complement ()

    GdaMetaDbObject *   gda_meta_struct_complement          (GdaMetaStruct *mstruct,
                                                             GdaMetaDbObjectType type,
                                                             const GValue *catalog,
                                                             const GValue *schema,
                                                             const GValue *name,
                                                             GError **error);

Creates a new GdaMetaDbObject structure in `mstruct` to represent the database object (of type `type`) which can be uniquely identified as `catalog`.`schema`.`name`.

If `catalog` is not `NULL`, then `schema` should not be `NULL`.

If both `catalog` and `schema` are `NULL`, then the database object will be the one which is "visible" by default (that is which can be accessed only by its short `name` name).

If `catalog` is `NULL` and `schema` is not `NULL`, then the database object will be the one which can be accessed by its `schema`.`name` name.

Important note: `catalog`, `schema` and `name` will be used using the following convention:

- be surrounded by double quotes for a case sensitive search

- otherwise for case insensitive search

For more information, see the meta data section about SQL identifiers.

`mstruct` : | a GdaMetaStruct object
`type` : | the type of object to add (which can be GDA_META_DB_UNKNOWN)
`catalog` : | the catalog the object belongs to (as a G_TYPE_STRING GValue), or `NULL`
`schema` : | the schema the object belongs to (as a G_TYPE_STRING GValue), or `NULL`
`name` : | the object's name (as a G_TYPE_STRING GValue), not `NULL`
`error` : | a place to store errors, or `NULL`
Returns : | the GdaMetaDbObject corresponding to the database object if no error occurred, or `NULL`

### gda_meta_struct_complement_schema ()

    gboolean            gda_meta_struct_complement_schema   (GdaMetaStruct *mstruct,
                                                             const GValue *catalog,
                                                             const GValue *schema,
                                                             GError **error);

This method is similar to `gda_meta_struct_complement()` but creates GdaMetaDbObject for all the database object which are in the `schema` schema (and in the `catalog` catalog). If `catalog` is `NULL`, then any catalog will be used, and if `schema` is `NULL` then any schema will be used (if `schema` is `NULL` then catalog must also be `NULL`).

Please refer to `gda_meta_struct_complement()` form more information.

`mstruct` : | a GdaMetaStruct object
`catalog` : | name of a catalog, or `NULL`
`schema` : | name of a schema, or `NULL`
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_meta_struct_complement_default ()

    gboolean            gda_meta_struct_complement_default  (GdaMetaStruct *mstruct,
                                                             GError **error);

This method is similar to `gda_meta_struct_complement()` and `gda_meta_struct_complement_all()` but creates GdaMetaDbObject for all the database object which are useable using only their short name (that is which do not need to be prefixed by the schema in which they are to be used).

Please refer to `gda_meta_struct_complement()` form more information.

`mstruct` : | a GdaMetaStruct object
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_meta_struct_complement_all ()

    gboolean            gda_meta_struct_complement_all      (GdaMetaStruct *mstruct,
                                                             GError **error);

This method is similar to `gda_meta_struct_complement()` and `gda_meta_struct_complement_default()` but creates GdaMetaDbObject for all the database object.

Please refer to `gda_meta_struct_complement()` form more information.

`mstruct` : | a GdaMetaStruct object
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_meta_struct_complement_depend ()

    gboolean            gda_meta_struct_complement_depend   (GdaMetaStruct *mstruct,
                                                             GdaMetaDbObject *dbo,
                                                             GError **error);

This method is similar to `gda_meta_struct_complement()` but creates GdaMetaDbObject for all the dependencies of `dbo`.

Please refer to `gda_meta_struct_complement()` form more information.

`mstruct` : | a GdaMetaStruct object
`dbo` : | a GdaMetaDbObject part of `mstruct`
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### enum GdaMetaSortType

    typedef enum {
    	GDA_META_SORT_ALHAPETICAL,
    	GDA_META_SORT_DEPENDENCIES
    } GdaMetaSortType;

`GDA_META_SORT_ALHAPETICAL` | sort by alphabetical order on the schema name and on the object name
`GDA_META_SORT_DEPENDENCIES` | sort such as that for any given GdaMetaDbObject in the list, all its dependencies are _before_ it in the list

### gda_meta_struct_sort_db_objects ()

    gboolean            gda_meta_struct_sort_db_objects     (GdaMetaStruct *mstruct,
                                                             GdaMetaSortType sort_type,
                                                             GError **error);

Reorders the list of database objects within `mstruct` in a way specified by `sort_type`.

`mstruct` : | a GdaMetaStruct object
`sort_type` : | the kind of sorting requested
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_meta_struct_get_all_db_objects ()

    GSList *            gda_meta_struct_get_all_db_objects  (GdaMetaStruct *mstruct);

Get a list of all the GdaMetaDbObject structures representing database objects in `mstruct`. Note that no GdaMetaDbObject structure must not be modified.

`mstruct` : | a GdaMetaStruct object
Returns : | a new GSList list of pointers to GdaMetaDbObject structures which must be destroyed after usage using `g_slist_free()`. The individual GdaMetaDbObject must not be modified.

### gda_meta_struct_get_db_object ()

    GdaMetaDbObject *   gda_meta_struct_get_db_object       (GdaMetaStruct *mstruct,
                                                             const GValue *catalog,
                                                             const GValue *schema,
                                                             const GValue *name);

Tries to locate the GdaMetaDbObject structure representing the database object named after `catalog`, `schema` and `name`.

If one or both of `catalog` and `schema` are `NULL`, and more than one database object matches the name, then the return value is also `NULL`.

`mstruct` : | a GdaMetaStruct object
`catalog` : | the catalog the object belongs to (as a G_TYPE_STRING GValue), or `NULL`
`schema` : | the schema the object belongs to (as a G_TYPE_STRING GValue), or `NULL`
`name` : | the object's name (as a G_TYPE_STRING GValue), not `NULL`
Returns : | the GdaMetaDbObject or `NULL` if not found

### gda_meta_struct_get_table_column ()

    GdaMetaTableColumn * gda_meta_struct_get_table_column   (GdaMetaStruct *mstruct,
                                                             GdaMetaTable *table,
                                                             const GValue *col_name);

Tries to find the GdaMetaTableColumn representing the column named `col_name` in `table`.

`mstruct` : | a GdaMetaStruct object
`table` : | the GdaMetaTable structure to find the column for
`col_name` : | the name of the column to find (as a G_TYPE_STRING GValue)
Returns : | the GdaMetaTableColumn or `NULL` if not found

### enum GdaMetaGraphInfo

    typedef enum {
    	GDA_META_GRAPH_COLUMNS = 1 << 0
    } GdaMetaGraphInfo;

### gda_meta_struct_dump_as_graph ()

    gchar *             gda_meta_struct_dump_as_graph       (GdaMetaStruct *mstruct,
                                                             GdaMetaGraphInfo info,
                                                             GError **error);

Creates a new graph (in the GraphViz syntax) representation of `mstruct`.

`mstruct` : | a GdaMetaStruct object
`info` : | informs what kind of information to show in the resulting graph
`error` : | a place to store errors, or `NULL`
Returns : | a new string, or `NULL` if an error occurred.

## Property Details

### The `"features"` property

      "features"                 guint                 : Read / Write / Construct Only

Allowed values: <= G_MAXINT

Default value: 3

### The `"meta-store"` property

      "meta-store"               GdaMetaStore*         : Read / Write / Construct Only

GdaMetaStore object to fetch information from.