The Farrago DBMS platform makes all of this possible via its SQL/MED extensibility feature. This document describes how to make use of the MDR plugin.
After you have installed Farrago, make sure you're able to execute simple queries via iSQL-Viewer.
create server mof_repository
foreign data wrapper sys_mdr
options(
"org.netbeans.mdr.persistence.Dir" 'unitsql/ddl/mdr',
extent_name 'MOF',
schema_name 'MODEL'
);
Explanation:
mof_repository is the name we will give the repository in
Farrago. It will appear as a top-level catalog name.
sys_mdr is the name of the foreign data wrapper used to
access MDR. Farrago allows you to define and plug in your own, but this
isn't necessary here because the system already provides one for MDR.
"org.netbeans.mdr.persistence.Dir" tells MDR the
directory in which to find the btree storage. This option name has to
be quoted (with double-quotes as an identifier) in order for its case
to be preserved correctly. Any properties understood by MDR can be
passed in this way (allowing you to choose a storage representation
other than btree, for example). The path is relative to the working
directory; depending on where you ran iSQL-Viewer from, you may have
to modify it accordingly. Using an absolute path is usually the best
approach. Note that option values are always single-quoted (as string
literals, not identifiers like option names).
extent_name tells MDR what extent name to look for
in the repository
schema_name is bit of a hack. Normally, in a repository
with a nested package structure, the root_package_name
option would be specified instead, and all child packages of the root
package would appear as schemas. However, the MOF repository has no
nested packages at all, so in such cases the schema_name option should
be specified to make the namespace conform to the standard catalog.schema.table
convention. Choosing an upper-case name will allow you to avoid quoting
it later.
select * from mof_repository.model."Class";
NOTE: object names from MDR (like "Class") are case
sensitive and have to be quoted when they aren't upper-case to begin
with. The reason mof_repository and model
don't have to be quoted is that they were defined by Farrago DDL, not
MDR.
The results should look something like this:
|
Now we know the column names, so we can issue a more meaningful query,
like finding the names of all abstract classes. Since the
isAbstract column has type BOOLEAN, we can use it
directly in the WHERE clause.
select "name" from mof_repository.model."Class" where "isAbstract";
Expected results:
|
container and mofId columns. These are
MOFID values, which are essentially object identifiers. The
mofId attribute represents the ID for the object
represented by the row in question (so in the above example, they are
ID's for Class instances). The association between
Namespace and ModelElement gives rise to the
container column in the Class result set; it's
really a foreign key referencing the mofId column of the
Namespace result set. MDR takes care of the object-oriented
aspects, so we can query for Package instances, which are
a subset of all Namespace instances:
select "name","mofId" from mof_repository.model."Package";
Expected results:
|
Notice that the mofId for the row with
name=Model is the same as the container ID
for all of the classes in the first result set. So this means all MOF
classes are defined in the Model package. You can use a
join to navigate the association; try the query below:
select
n."name" as container_name,
e."name" as element_name
from
mof_repository.model."Package" n
inner join
mof_repository.model."ModelElement" e
on n."mofId" = e."container";
Some other result set details:
mofId column, there is an additional
meta-column mofClassName associated with every table.
When you query a leaf-level class in an object hierarchy, this value
will always be the same (the name of the class you queried). However,
when you query a non-leaf class (e.g. select
"name","mofClassName" from mof_repository.model."Namespace"),
the mofClassName column can be used to determine the actual
leaf type of each object returned.
create schema mof_schema;
create foreign table mof_schema.exceptions(
name varchar(20),
annotation varchar(1),
container char(54),
"SCOPE" varchar(20),
visibility varchar(20),
exception_id char(54),
unused_name varchar(20))
server mof_repository
options (class_name 'Exception');
Explanation:
mof_schema under the default
LOCALDB catalog. This schema will contain our imported metadata. This
imported metadata will remain available even if the repository becomes
unavailable.
scope column whose
name happens to be a SQL reserved word. And the datatypes are more
reasonable than the defaults (e.g. we know that the MOFID's for this
repository are fixed-length 54-character strings).
exceptions is never seen by the repository
at all. Instead, we explicitly tell the repository the desired
class_name via the options clause at the end.
select name,visibility
from mof_schema.exceptions;
|
create view mof_schema.exception_visibility as
select name,visibility
from mof_schema.exceptions;
The same view could instead be defined directly against the repository
metadata:
create view mof_schema.exception_visibility as
select "name" as name,"visibility" as visibility
from mof_repository.model."Exception";
Note that in this second view definition, the column types would be
based on the repository metadata rather than on the overriding types
specified when the table definition was imported.
create server command. For example, if you are using
JDBC storage, you might specify something like:
options(
"org.netbeans.mdr.storagemodel.StorageFactoryClassName" = 'org.netbeans.mdr.persistence.jdbcimpl.JdbcStorageFactory',
"MDRStorageProperty.org.netbeans.mdr.persistence.jdbcimpl.driverClassName" = 'org.hsqldb.jdbcDriver',
"MDRStorageProperty.org.netbeans.mdr.persistence.jdbcimpl.url" = 'jdbc:hsqldb:/home/hsqldb/stored_repos'
)
schema_name option as in the MOF example.
Otherwise, you'll need to specify the root_package_name
option instead. All packages under this root package will appear as
schemas under your repository catalog. If your package nesting structure
has a depth greater than 2, you'll probably have to choose multiple roots
and issue multiple create server statements accordingly.