The GdaServerProviderMeta structure defines all the methods which database providers must implement for the meta data extraction feature to work. Each method is used internally by the GdaConnection object when one calls the gda_connection_update_meta_store() method (where the connection object itself computes the list and order of methods to call). Each method must update the contents of one table in the connection's associated metadata (in its associated GdaMetaStore object), each has the same "base" arguments and some have extra arguments further specifying what needs to be updated.
For each table to update, there are two methods, which differ in their name only by the fact that one is starting with an underscore '_'. The method starting with an underscore must update the whole contents of the meta data table, and the other one must accept some more parameters to refine what gets updated. There are exception to this rule (such as the "tables_views()" method which must update both the "_tables" and "_views" tables, or the for the tables which have no foreign key (no dependency) to any other table).
Also, by convetion, the arguments can't be NULL unless the argument name has the "_n" suffix. For example
the signature of the "tables_views()" method has the following signature (as defined in the
gda-server-provider.h
file)
gboolean (*tables_views) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n);
which means that the table_catalog
and table_schema
arguments can't be NULL, whereas the table_name
can be NULL (and in this case the
"tables_views()" method must update the "_tables" and
"_views" tables regarding all the tables which
are in the specified catalog and schema.
Make sure you read the information about the meta data's database structure in the Database structure, and specifically the data types section and the SQL identifiers section.
As mentioned in the SQL identifiers section, any SQL identifier in the meta store is represented either:
between double quotes if the SQL identifier is case sensitive
all in lower case if the SQL identifier is not case sensitive
For database engines which internally store case insensitive SQL identifiers in lower case (such as PostgreSQL), the meta data reported by the database engine can be used almost AS IS, but for database engines which internally store case insensitive SQL identifiers in upper case (such as Oracle), the upper case needs to be converted to lower case. Also case sensitive SQL identifiers also need to be double quoted.
To minimize the work required to implement a database provider, Libgda allows the database provider to specifiy how case insensitive SQL identifiers are represented using gda_meta_store_set_identifiers_style() and the GdaMetaStore object will perform the work itself (the default being GDA_SQL_IDENTIFIERS_LOWER_CASE in GdaSqlIdentifierStyle.
Also note that the extra arguments for each virtual method listed below, when they are present and when they represent an SQL identifier, will be represented:
for case insensitive SQL identifiers: using all lower or all upper case (depending on the setting set using gda_meta_store_set_identifiers_style()
for case sensitive SQL identifiers: without the double quotes, but possibily with mixed or not lower and upper characters
Every database engine reserves some keywords for its own usage or because they are part of the SQL language. Reserved keywords can be used as SQL identifiers if they are put between double quotes.
As Each database engine has its own set of reserved keywords, the database provider has to tell the GdaMetaStore object what its keywords are, which is done using gda_meta_store_set_reserved_keywords_func() and passing a function which determines if a specific string is a reserved keyword. The usage of this function is similar to the usage of the gda_meta_store_set_identifiers_style() mentioned above.
Writing a function which tests if a string is a reserved keyword is a non complicated but error
prone and not optimized, in the same way as writing a parser/lexer directly, so Libgda has a tool
which generates a static hash table from a list of reserved keywords, which is in the
keywords.list
(several keywords can appear on the same line, separated by spaces or commas
but the last line must remain empty).
gboolean (*_info) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
This method must update the contents of the "_information_schema_catalog_name" table, which must contain exactly one row describing the catalog name for the connection.
gboolean (*_btypes) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
This method must update the contents of the "_builtin_data_types" table which lists all the database's built in data types. There is no specific parameter.
gboolean (*_schemata) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **); gboolean (*schemata) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *catalog_name, const GValue *schema_name_n);
This method must update the contents of the "_schemata" table, which lists all the schemas (namespaces).
gboolean (*_tables_views) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **); gboolean (*tables_views) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n);
This method must update the contents of the "_tables" and "_views" tables which list all the tables and views.
gboolean (*_columns) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **); gboolean (*columns) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *table_catalog, const GValue *table_schema, const GValue *table_name);
This method must update the contents of the "_columns" table which lists all the columns of all the tables and views.
gboolean (*_constraints_tab) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **); gboolean (*constraints_tab) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, const GValue *constraint_name_n);
This method must update the contents of the "_table_constraints" table which lists all the constraints (primary key, foreign key, unique or check constraints) for each table.
gboolean (*_constraints_ref) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **); gboolean (*constraints_ref) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, const GValue *constraint_name);
This method must update the contents of the "_referential_constraints" table which lists all the referential constraints (which are also listed in the "_table_constraints" table).
gboolean (*_key_columns) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **); gboolean (*key_columns) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, const GValue *constraint_name);
This method must update the contents of the "_key_column_usage" table which lists all the columns involved in each table constraint (as listed in the "_table_constraints" table).