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.