Database structure

Libgda imposes its own structure (based on objects such as tables and views which name starts with an underscore '_') for the meta data database associated to a GdaMetaStore object, but a user can also add its own tables or other database objects. The following diagram shows the tables defined by Libgda for its internal needs:

Dictionary's tables and views initially defined by Libgda

Data types

Data types (as reported for example for table's columns) can be one of the following kinds:

  • Builtin data types offered by the database engine such as integers, varchar, etc. Those data types are all listed in the "_builtin_data_types" table.

  • Database domains: domains are data types with optional constraints (restrictions on the allowed set of values). A domain refers to the base data type from which it is defined (that base data type can also be an array). Those data types are all listed in the "_domains" table.

  • User defined data types (which are not part of the SQL standard but featured by some databases such as PostgreSQL) are simple or composed data types based on existing data types (which may also be arrays). Those data types are all listed in the "_udt" table.

  • Arrays of any of the previous data types (one or more dimensions). Arrays are not per-se data types, but rather refer to an existing data type. Arrays are described in the "_element_types" table.

Note that the data types which are built in, domains or user defined are all also listed in the "_all_types" view as a convenience.

The impact of that data types' hierarchy is that every time a data type is referenced (from a table's column definition for example), there will be two attributes for the data type: one named data_type which, if not NULL, refers to a data type listed in the "_all_types" view (thus a built in, domain or user defined data type), and one named array_spec which, if not NULL, refers to an array, listed in the "_element_types" table. Any of these attributes can be NULL, but they should never be both NULL at the same time.

Single dimension arrays will have the data_type attribute referencing a data type in the "_all_types" view (and the array_spec attribute set to NULL), whereas multi dimension arrays will have the data_type attribute set to NULL and the array_spec attribute referencing another tow in the "_element_types" table.

The following diagram illustrates the data types representation and how they are referred from table's columns, domains, and other database objects which refer to a data type:

Dictioanry's tables and views initially defined by Libgda

SQL identifiers

Please refer to the SQL identifiers and abstraction section for an overview of how SQL identifiers are handled thoughout Libgda

Considering that each database has its own internal way of representing case insensitive SQL identifiers (for instance PostgreSQL represents them in lower case whereas Oracle represents them in upper case and MySQL represents them in upper or lower case depending on the platform and the configuration), Libgda has chosen by convention to represent case insensitive SQL identifiers in lower case and case sensitive SQL identifiers enclosed between double quotes when storing meta data in GdaMetaStore.

This convention has been made necessary to avoid confusion. To illustrate the problem, let's consider a table named mytable. Without this convention, if that table was in a PostgreSQL database, then the meta data would report it as mytable, and if it was in an ORACLE, it would report it as MYTABLE. Now, a programmer which wants to compare the schemas of the PostgreSQL and Oracle databases has to know that the PostgreSQL's mytable and Oracle's MYTABLE represent in fact the same table which means he needs to know how each database internally stores SQL identifiers, which is not a good choice because it makes the application less portable between database engines. Better let each database provider do the job. Note that things can even get more confusing if MySQL is used because then one needs to figure out on which platform the MySQL server is running and how it's configured, a task which makes an application even less portable.

To keep the same example, to build some SQL using the SQL identifier as reported by the meta data (mytable for PostgreSQL and MYTABLE for Oracle), one has either to determine if the SQL identifier needs to be quoted or not (which limits the application's portability), or systematically enquote the SQL identifier which is not something Libgda can impose to application developpers.

Short and full names

Database objects will have two associated names, the short name and the long name, the difference being the same as machine in a local network being called either by its machine name such as "moon" or by its fully qualified domain name such as "moon.my.network", but applied to databases and schemas. The full name corresponding to the <database>.<schema>.<object_name> or <schema>.<object_name>, and the short name corresponding to the <object_name>.

Short name and full name differ when the schema being accessed is not the schema containing the named database object, in which case the full name must be used. Some database specific features may also alter the differences between the short name and the sull name such as the "search_path" variable for PostgreSQL (which is to a unix PATH variable but for schemas).

Declared foreign keys

Foreign key constraints are used to constraint the contents of one or more columns of a table to the columns of another table. They are also use to help understand the database structure and withing UI programs to present relevant choices.

Libgda reports existing foreign key constraints in its meta data.

There are however some situations where the database developper does not whish to use foreign keys to actually implement the constraint, but the relation between the tables still exists. Libgda allows one to declare foreign keys, an operation which does not alter the database's schema, but add information to the database's meta data, specifically into the "__declared_fk" table. For more information, see the gda_meta_store_declare_foreign_key() and gda_meta_store_undeclare_foreign_key methods.

Individual table description

This section individually describes each table.

_attributes table

Table to store (key,value) pairs (keys starting with '_' are reserved)

The following table describes the columns:

Column name Type Key Can be NULL description
att_name string Yes No  
att_value string   No  

_information_schema_catalog_name table

Name of the current database (current catalog), has only one row

The following table describes the columns:

Column name Type Key Can be NULL description
catalog_name string Yes No  

_schemata table

List of schemas

The following table describes the columns:

Column name Type Key Can be NULL description
catalog_name string Yes No Name of the catalog that contains the schema
schema_name string Yes No  
schema_owner string   Yes Name of the schema
schema_internal boolean   No Tells if the schema is specific to the database implementation (and usually can't be modified)
schema_default boolean   Yes Tells if the schema is used by default when creating a new table without schema name

  • (catalog_name) references _information_schema_catalog_name(catalog_name)

_builtin_data_types table

List of built-in data types such as varchar, int, ...

The following table describes the columns:

Column name Type Key Can be NULL description
short_type_name string   No Short name of the data type
full_type_name string Yes No Full name of the data type
gtype string   Yes  
comments string   Yes  
synonyms string   Yes  
internal boolean   No Tells if the data type is reserved for the database implementation and should not be used in applications

_udt table

User defined data types

The following table describes the columns:

Column name Type Key Can be NULL description
udt_catalog string Yes No Name of the catalog that contains the data type
udt_schema string Yes No Name of the schema that contains the data type
udt_name string Yes No Name of the data type
udt_gtype string   Yes GType associated to the data type
udt_comments string   Yes  
udt_short_name string   No  
udt_full_name string   No  
udt_internal boolean   No Tells if the data type is reserved for the database implementation and should not be used in applications
udt_owner string   Yes  

  • (udt_catalog, udt_schema) references _schemata(catalog_name, schema_name)

_udt_columns table

List of components for a user defined data type for composed data types (such as a complex number data type which has real and imaginary parts)

The following table describes the columns:

Column name Type Key Can be NULL description
udt_catalog string Yes No Name of the catalog that contains the user defined data type for which the column is
udt_schema string Yes No Name of the schema that contains the user defined data type for which the column is
udt_name string Yes No Name of the user defined data type for which the column is
udt_column string Yes No Name of the column (part)
ordinal_position gint   No Column position, starts at 1
data_type string   Yes Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)
array_spec string   Yes Array description if the column is an array
character_maximum_length gint   Yes  
character_octet_length gint   Yes  
numeric_precision gint   Yes  
numeric_scale gint   Yes  
datetime_precision gint   Yes  
character_set_catalog string   Yes  
character_set_schema string   Yes  
character_set_name string   Yes  
collation_catalog string   Yes  
collation_schema string   Yes  
collation_name string   Yes  

  • (udt_catalog, udt_schema, udt_name) references _udt(udt_catalog, udt_schema, udt_name)

  • (array_spec) references _element_types(specific_name)

_enums table

List of possible enumeration labels for enumerations

The following table describes the columns:

Column name Type Key Can be NULL description
udt_catalog string Yes No Name of the catalog that contains the ENUM user defined data type
udt_schema string Yes No Name of the schema that contains the ENUM user defined data type
udt_name string Yes No Name of the ENUM user defined data type
label string Yes No  
ordinal_position gint   No Position, starts at 1

  • (udt_catalog, udt_schema, udt_name) references _udt(udt_catalog, udt_schema, udt_name)

_element_types table

Array specific attributes for array data types

The following table describes the columns:

Column name Type Key Can be NULL description
specific_name string Yes No No specific meaning, used as a primary key, and for joining
object_catalog string   No Name of the catalog that contains the object that uses the array being described
object_schema string   No Name of the schema that contains the object that uses the array being described
object_name string   No Name of the object that uses the array being described
object_type string   No The type of the object that uses the array being described TABLE_COL, DOMAIN, UDT_COL, ROUTINE_COL, ROUTINE_PAR
data_type string   Yes Base data type of the array (if the base data type is an array, then 'array_spec' is set, and this may be NULL)
array_spec string   Yes Array description if the base data type is an array
min_cardinality gint   Yes  
max_cardinality gint   Yes  

_domains table

List of domains

The following table describes the columns:

Column name Type Key Can be NULL description
domain_catalog string Yes No Name of catalog that contains the domain
domain_schema string Yes No Name of schema that contains the domain
domain_name string Yes No Name of the domain
data_type string   Yes Data type of the domain (if the domain is an array, then 'array_spec' is set, and this may be NULL)
array_spec string   Yes Array description if the domain is an array
domain_gtype string   No  
character_maximum_length gint   Yes  
character_octet_length gint   Yes  
collation_catalog string   Yes Name of catalog that contains the associated collation
collation_schema string   Yes Name of schema that contains the associated collation
collation_name string   Yes Name of the associated collation
character_set_catalog string   Yes Name of catalog that contains the associated character set
character_set_schema string   Yes Name of schema that contains the associated character set
character_set_name string   Yes Name of the associated character set
numeric_precision gint   Yes  
numeric_scale gint   Yes  
domain_default string   Yes  
domain_comments string   Yes  
domain_short_name string   No  
domain_full_name string   No  
domain_internal boolean   No  
domain_owner string   Yes  

  • (domain_catalog, domain_schema) references _schemata(catalog_name, schema_name)

  • (array_spec) references _element_types(specific_name)

_tables table

List of tables (tables, views or other objects which can contain data)

The following table describes the columns:

Column name Type Key Can be NULL description
table_catalog string Yes No Name of catalog that contains the table
table_schema string Yes No Name of schema that contains the table
table_name string Yes No Name of the table
table_type string   No Type of table: BASE TABLE, VIEW, LOCAL TEMPORARY, SYSTEM TABLE, GLOBAL TEMPORARY, ALIAS or SYNONYM
is_insertable_into boolean   Yes Tells if the table's contents can be modified
table_comments string   Yes  
table_short_name string   No  
table_full_name string   No  
table_owner string   Yes  

  • (table_catalog, table_schema) references _schemata(catalog_name, schema_name)

_views table

List of views and their specific information

The following table describes the columns:

Column name Type Key Can be NULL description
table_catalog string Yes No Name of catalog that contains the view
table_schema string Yes No Name of schema that contains the view
table_name string Yes No Name of the view
view_definition string   Yes View as SQL
check_option string   Yes CASCADE if the statement used to create the view included the WITH CHECK OPTION; otherwise, NONE
is_updatable boolean   Yes Tells if the view's contents can be modified

  • (table_catalog, table_schema, table_name) references _tables(table_catalog, table_schema, table_name)

_collations table

List of collations methods

The following table describes the columns:

Column name Type Key Can be NULL description
collation_catalog string Yes No  
collation_schema string Yes No  
collation_name string Yes No  
collation_comments string   Yes  
collation_short_name string   No  
collation_full_name string   No  

  • (collation_catalog, collation_schema) references _schemata(catalog_name, schema_name)

_character_sets table

List of character sets

The following table describes the columns:

Column name Type Key Can be NULL description
character_set_catalog string Yes No  
character_set_schema string Yes No  
character_set_name string Yes No  
default_collate_catalog string   Yes  
default_collate_schema string   Yes  
default_collate_name string   Yes  
character_set_comments string   Yes  
character_set_short_name string   No  
character_set_full_name string   No  

  • (character_set_catalog, character_set_schema) references _schemata(catalog_name, schema_name)

  • (default_collate_catalog, default_collate_schema, default_collate_name) references _collations(collation_catalog, collation_schema, collation_name)

_routines table

List of functions and stored procedures (note: the primary jey for that table is composed of (specific_catalog, specific_schema, specific_name))

The following table describes the columns:

Column name Type Key Can be NULL description
specific_catalog string Yes No Specific name of catalog that contains the routine
specific_schema string Yes No Specific name of schema that contains the routine
specific_name string Yes No Specific name of the routine (may be mangled for polymorphic routines)
routine_catalog string   Yes Name of catalog that contains the routine (may be NULL)
routine_schema string   Yes Name of schema that contains the routine (may be NULL)
routine_name string   No Name of the routine
routine_type string   Yes FUNCTION, PROCEDURE, AGGREGATE
return_type string   Yes Data type returned by the routine (may be NULL if routine does not return any value)
returns_set boolean   No True if routine returns a set (i.e., multiple values of the specified data type or if data type may vary)
nb_args gint   No Number of arguments (-1 for variable number of arguments)
routine_body string   Yes If the routine is an SQL function, then SQL, else EXTERNAL
routine_definition string   Yes The source text of the routine
external_name string   Yes If the routine is an external function, then the external name (link symbol) of the function
external_language string   Yes The language the routine is written in
parameter_style string   Yes Parameter style (GENERAL, JAVA, SQL, GENERAL WITH NULLS)
is_deterministic boolean   Yes Tells if the routine returns the same results given the same arguments forever
sql_data_access string   Yes Whether the routine contains SQL and whether it reads or modifies data (NONE, CONTAINS, READS, MODIFIES)
is_null_call boolean   Yes Tells if the routine will be called if any one of its arguments is NULL
routine_comments string   Yes  
routine_short_name string   No  
routine_full_name string   No  
routine_owner string   Yes  

  • (specific_catalog, specific_schema) references _schemata(catalog_name, schema_name)

_triggers table

List of triggers

The following table describes the columns:

Column name Type Key Can be NULL description
trigger_catalog string Yes No  
trigger_schema string Yes No  
trigger_name string Yes No  
event_manipulation string Yes No Event that fires the trigger (INSERT, UPDATE, or DELETE)
event_object_catalog string Yes No Name of the database that contains the table that the trigger is defined on
event_object_schema string Yes No Name of the schema that contains the table that the trigger is defined on
event_object_table string Yes No Name of the table that the trigger is defined on
action_statement string   Yes Statement that is executed by the trigger
action_orientation string   No Identifies whether the trigger fires once for each processed row or once for each statement (ROW or STATEMENT)
condition_timing string   No Time at which the trigger fires (BEFORE or AFTER)
trigger_comments string   Yes  
trigger_short_name string   No  
trigger_full_name string   No  

  • (trigger_catalog, trigger_schema) references _schemata(catalog_name, schema_name)

  • (event_object_catalog, event_object_schema, event_object_table) references _tables(table_catalog, table_schema, table_name)

_columns table

List of columns composing tables

The following table describes the columns:

Column name Type Key Can be NULL description
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
column_name string Yes No  
ordinal_position gint   No Column position, starts at 1
column_default string   Yes  
is_nullable boolean   No  
data_type string   Yes Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)
array_spec string   Yes Array description if the column is an array
gtype string   No  
character_maximum_length gint   Yes  
character_octet_length gint   Yes  
numeric_precision gint   Yes If data_type identifies a numeric type, this column contains the precision of the type for this column (the number of significant digits)
numeric_scale gint   Yes If data_type identifies an exact numeric type, this column contains the scale of the type for this column (the number of significant digits to the right of the decimal point)
datetime_precision gint   Yes  
character_set_catalog string   Yes  
character_set_schema string   Yes  
character_set_name string   Yes  
collation_catalog string   Yes  
collation_schema string   Yes  
collation_name string   Yes  
extra string   Yes CSV string with: AUTO_INCREMENT
is_updatable boolean   Yes  
column_comments string   Yes  

  • (table_catalog, table_schema, table_name) references _tables(table_catalog, table_schema, table_name)

  • (character_set_catalog, character_set_schema, character_set_name) references _character_sets(character_set_catalog, character_set_schema, character_set_name)

  • (collation_catalog, collation_schema, collation_name) references _collations(collation_catalog, collation_schema, collation_name)

  • (array_spec) references _element_types(specific_name)

_table_constraints table

List of constraints applied to tables (Check, primary or foreign key, or unique constraints)

The following table describes the columns:

Column name Type Key Can be NULL description
constraint_catalog string   Yes Name of the catalog that contains the constraint
constraint_schema string   Yes Name of the schema that contains the constraint
constraint_name string Yes No  
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
constraint_type string   No CHECK, FOREIGN KEY, PRIMARY KEY or UNIQUE
check_clause string   Yes The check expression if the constraint is a check constraint, NULL otherwise
is_deferrable boolean   Yes  
initially_deferred boolean   Yes  

  • (table_catalog, table_schema, table_name) references _tables(table_catalog, table_schema, table_name)

_referential_constraints table

List of foreign key constraints, along with some specific attributes

The following table describes the columns:

Column name Type Key Can be NULL description
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
constraint_name string Yes No  
ref_table_catalog string   No  
ref_table_schema string   No  
ref_table_name string   No  
ref_constraint_name string   No  
match_option string   Yes FULL, PARTIAL or NONE
update_rule string   Yes CASCADE, SET NULL, SET DEFAULT, RESTRICT, NO ACTION or NONE
delete_rule string   Yes CASCADE, SET NULL, SET DEFAULT, RESTRICT, NO ACTION or NONE

  • (table_catalog, table_schema, table_name, constraint_name) references _table_constraints(table_catalog, table_schema, table_name, constraint_name)

  • (ref_table_catalog, ref_table_schema, ref_table_name, ref_constraint_name) references _table_constraints(table_catalog, table_schema, table_name, constraint_name)

_key_column_usage table

List of primary key constraints and the name of the tables' columns involved

The following table describes the columns:

Column name Type Key Can be NULL description
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
constraint_name string Yes No  
column_name string Yes No  
ordinal_position gint Yes No Ordinal position of the column within the constraint key (count starts at 1)

  • (table_catalog, table_schema, table_name, constraint_name) references _table_constraints(table_catalog, table_schema, table_name, constraint_name)

  • (table_catalog, table_schema, table_name, column_name) references _columns(table_catalog, table_schema, table_name, column_name)

__declared_fk table

List of foreign key constraints, declared in Libgda and unknown to the database

The following table describes the columns:

Column name Type Key Can be NULL description
constraint_name string Yes No  
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
column_name string Yes No  
ref_table_catalog string Yes No  
ref_table_schema string Yes No  
ref_table_name string Yes No  
ref_column_name string Yes No  
ts timestamp   Yes  
descr string   Yes  

_check_column_usage table

List of check constraints and the name of the tables' columns involved

The following table describes the columns:

Column name Type Key Can be NULL description
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
constraint_name string Yes No  
column_name string Yes No  

  • (table_catalog, table_schema, table_name, constraint_name) references _table_constraints(table_catalog, table_schema, table_name, constraint_name)

  • (table_catalog, table_schema, table_name, column_name) references _columns(table_catalog, table_schema, table_name, column_name)

_view_column_usage table

List of the tables' columns involved in a view

The following table describes the columns:

Column name Type Key Can be NULL description
view_catalog string Yes No  
view_schema string Yes No  
view_name string Yes No  
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
column_name string Yes No  

  • (view_catalog, view_schema, view_name) references _views(table_catalog, table_schema, table_name)

  • (table_catalog, table_schema, table_name, column_name) references _columns(table_catalog, table_schema, table_name, column_name)

_domain_constraints table

List of constraints applicable to domains

The following table describes the columns:

Column name Type Key Can be NULL description
constraint_catalog string   Yes Name of the catalog that contains the constraint
constraint_schema string   Yes Name of the schema that contains the constraint
constraint_name string Yes No  
domain_catalog string Yes No  
domain_schema string Yes No  
domain_name string Yes No  
check_clause string   Yes  
is_deferrable boolean   Yes  
initially_deferred boolean   Yes  

  • (domain_catalog, domain_schema, domain_name) references _domains(domain_catalog, domain_schema, domain_name)

  • (constraint_catalog, constraint_schema) references _schemata(catalog_name, schema_name)

_parameters table

List of routines' (functions and stored procedures) parameters (may not contain data for some routines which accept any type of parameter)

The following table describes the columns:

Column name Type Key Can be NULL description
specific_catalog string Yes No  
specific_schema string Yes No  
specific_name string Yes No  
ordinal_position gint Yes No  
parameter_mode string   No  
parameter_name string   Yes  
data_type string   Yes Data type of the parameter (if the parameter is an array, then 'array_spec' is set, and this may be NULL; can also be NULL if any type of parameter is accepted)
array_spec string   Yes Array description if the parameter is an array

  • (specific_catalog, specific_schema, specific_name) references _routines(specific_catalog, specific_schema, specific_name)

  • (array_spec) references _element_types(specific_name)

_routine_columns table

List of routines' (functions and stored procedures) returned values' parts (columns) for routines returning composed values

The following table describes the columns:

Column name Type Key Can be NULL description
specific_catalog string Yes No  
specific_schema string Yes No  
specific_name string Yes No  
column_name string Yes No  
ordinal_position gint Yes Yes  
data_type string   Yes Data type of the column (if the column is an array, then 'array_spec' is set, and this may be NULL)
array_spec string   Yes Array description if the column is an array

  • (specific_catalog, specific_schema, specific_name) references _routines(specific_catalog, specific_schema, specific_name)

  • (array_spec) references _element_types(specific_name)

_table_indexes table

List of tables' indexes which do not relate to primary keys

The following table describes the columns:

Column name Type Key Can be NULL description
index_catalog string   Yes Name of the catalog that contains the index
index_schema string   Yes Name of the schema that contains the index
index_name string Yes No  
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
is_unique boolean   Yes  
index_def string   Yes Index definition
index_type string   Yes Database specific type of index such as BTREE, ...
extra string   Yes CSV string with: ASCENDING, ...
index_owner string   Yes  
index_comments string   Yes  

  • (table_catalog, table_schema, table_name) references _tables(table_catalog, table_schema, table_name)

_index_column_usage table

List of the tables' columns involved in an index listed in the _table_indexes table

The following table describes the columns:

Column name Type Key Can be NULL description
index_catalog string   Yes  
index_schema string   Yes  
index_name string Yes No  
table_catalog string Yes No  
table_schema string Yes No  
table_name string Yes No  
column_name string Yes Yes  
column_expr string Yes Yes  
ordinal_position gint   No Column position in the index, starts at 1

  • (index_name, table_catalog, table_schema, table_name) references _table_indexes(index_name, table_catalog, table_schema, table_name)

_all_types view

List of all the data types

Definition is:

SELECT short_type_name AS short_type_name, gtype, full_type_name AS full_type_name, comments, internal AS internal, synonyms,
       NULL AS domain_catalog, NULL AS domain_schema, NULL AS domain_name,
       NULL AS udt_catalog, NULL AS udt_schema, NULL AS udt_name
       FROM _builtin_data_types
UNION
SELECT udt_short_name, udt_gtype, udt_full_name, udt_comments, udt_internal, NULL,
       NULL, NULL, NULL, udt_catalog, udt_schema, udt_name FROM _udt
UNION
SELECT domain_short_name, domain_gtype, domain_full_name, domain_comments, domain_internal, NULL,
       domain_catalog, domain_schema, domain_name , NULL, NULL, NULL FROM _domains

_detailed_fk view

For each foreign key constraint, lists all the tables' columns involved and the constraint name

Definition is:

SELECT rc.table_catalog as fk_table_catalog, rc.table_schema as fk_table_schema, rc.table_name as fk_table_name, kc1.column_name as fk_column,
      rc.ref_table_catalog as ref_table_catalog, rc.ref_table_schema as ref_table_schema, rc.ref_table_name as ref_table_name, kc2.column_name as ref_column,
      rc.constraint_name as fk_constraint_name, kc1.ordinal_position as ordinal_position
      FROM _referential_constraints rc 
      INNER JOIN _key_column_usage kc2 ON (rc.ref_table_catalog=kc2.table_catalog AND rc.ref_table_schema=kc2.table_schema AND rc.ref_table_name=kc2.table_name AND rc.ref_constraint_name=kc2.constraint_name) 
      INNER JOIN _key_column_usage kc1 ON (rc.table_catalog=kc1.table_catalog AND rc.table_schema=kc1.table_schema AND rc.table_name=kc1.table_name AND rc.constraint_name=kc1.constraint_name) 
      WHERE kc1.ordinal_position = kc2.ordinal_position 
      ORDER BY rc.table_catalog, rc.table_schema, rc.table_name, kc1.ordinal_position