DMO Index¶
The DMO index provides a list of all tables (permanent and temporary) which will be registered with Hibernate at server startup. Also, it is used as a persistent container to save additional info which can not be specified in the associated .hbm.xml
file of a certain DMO file or other 4GL features which can not be determined from the table metadata or from the DMO configuration file. The DMO index is stored in an XML file named dmo/dmo_index.xml
. It is stored in the root package of the converted Java code.
While the 4GL code is still maintained, this file should not be edited by hand, as the file gets generated on each conversion (assuming that the schema generation step is included). Instead, there are two different ways to add a new table: either edit the main database schema file and add the new table definition directly in 4GL style or the new DMO can be written directly in Java. When writing it directly in Java, DMO registration and other DMO-related information must be added to a special merge file. More details about this special merge file and about how the schema changes can be handled while the 4GL code is still maintained can be found in the Managing Data Model Object (DMO) Changes section of the Integrating Hand-Written Java chapter of the FWD Developer Guide book.
This file contains the DMO list, grouped per each schema. For permanent tables, the schema name is the same as the name of the .df
file which holds the 4GL schema. The list of temporary tables is always kept under the _temp
schema, which is a reserved name in FWD. The following table explains the structure of the DMO index file. Later, each element will be described in more detail.
Element name | Description | Attributes |
||||
---|---|---|---|---|---|---|
dmo-index | The root element. | package - this package name followed by the schema name will determine the package where DMO source files are generated. |
||||
schema+ | An element of this type will be emitted for each permanent schema. An element with the _temp name will emitted if there are any temporary tables. |
impl - the package name (relative to the package specified at the dmo-index element) where the DMO implementation class and .hbm.xml file are generated.name - the schema name |
||||
class+ | This element is used to register in the DMO index file the DMO interface associated with each converted table. On FWD server startup, all the DMOs registered here will be registered with Hibernate. | interface - the DMO interface name |
||||
case-sensitive* | Used to store all the character and case-sensitive DMO properties. | name - the DMO property name |
||||
encoded* | Used to store all the character and base64-encoded DMO properties. | name - the DMO property name |
||||
foreign* | Used to store the foreign | interface - the foreign DMO interface name |
||||
property+ | The DMO property names which appear in the foreign relation. | name - the foreign DMO property name |
||||
unique* | Store data about each unique constraint. | N/A |
||||
component+ | The DMO property names which appear in the unique constraint. | name - the DMO property name |
||||
index* | Used for temporary tables only. Store information about the index DDL. | name - the index nameunique - when true , it marks an unique index |
||||
column+ | Store data about each indexed column. | ignore-case – when false , it marks a case-sensitive columnname - the table column name |
Table 1. The structure of the DMO index file.
The root element of the DMO index file is named dmo-index
and has as a single attribute the root package name of all DMOs, which is built from the root package name of the converted Java code followed by the dmo
package name. So, if the root package name is com.foo.bar
, this will result in the following header of the dmo_index.xml file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!--Data Model Object classes managed with Hibernate--><!DOCTYPE dmo-index SYSTEM "dmo-index-1.0.dtd"> <dmo-index package="com.foo.bar.dmo">
The root element will have as children schema
elements with the DMO list belonging to that schema. The first schema
elements will always be for the permanent tables, while the schema
element for the temporary tables will be emitted last.
As there are differences on what data the DMO index file stores for the permanent and temporary schema, each element will be treated in two sections - for permanent tables and for temporary tables.
DMO Index for Permanent Tables¶
Each permanent schema is stored in a separate .df
file. When converting the schema from i.e simple.df
file, this will result in a schema
element which will have as attributes the schema name (which is simple
) and the package where the DMO implementation classes reside, built from the schema name and the impl
suffix (resulting in the simple.impl
package name). This package name is relative to the root DMO package name specified at the dmo-index
root node. Following is the resulted element in the DMO index file:
<schema impl="simple.impl" name="simple">
This element has as children a list of class
elements where each element has as single attribute, the name of the DMO interface associated with a converted table. If the table name is book
and it belongs to the simple
schema, this will result in the following class
element under the simple
schema element:
<class interface="Book">
This means an interface named Book
exists in the package built from the root package name defined at the dmo-index
element and the schema name, resulting in the com.foo.bar.dmo.simple
package name. Also, the DMO implementation class (named BookImpl
) and the .hbm.xml
file (named BookImpl.hbm.xml
) will reside under the package built from the root package name defined at the dmo-index
element and the package name defined at the schema
element, resulting in the com.foo.bar.dmo.simple.impl
package name.
For each DMO, the middle conversion process will gather data from the .df
schema file, the schema hints or by analyzing the 4GL code. The .df
schema file provides data about case sensitive columns and unique indexes; the schema hints file is used to identify base64-encoded character columns and the 4GL code will be used to determine the foreign side of a primary-foreign key relation in a natural join.
Case Sensitive Columns¶
In 4GL, by default all character columns are case insensitive. If a certain column needs to be marked as case sensitive, this is done by specifying the CASE-SENSITIVE
attribute at the column definition within the 4GL schema file. This will result in adding a case-sensitive
child element under the class
element generated for this table's DMO. For more information about what changes the case (in)sensitive column imply in the converted code, please see the CASE-SENSITIVE
entry of the table in the Database Schema Elements chapter of Part 3 - Schema conversion of this book.
Unique Indexes¶
Some of the index data must be stored in the DMO index file, as some index behavior can only be implemented inside the FWD runtime (for example, how unique constraints cause flushing of newly created records). Thus, the conversion process gathers data about all unique constraints and saves them as unique
child elements under the class
element.
The following example shows how the unique indexes defined for the book
table are saved in the DMO index file:
ADD TABLE "Book" AREA "Schema Area" DESCRIPTION "Test table with variety of indexes" DUMP-NAME "book" ... ADD INDEX "book-id" ON "Book" AREA "Schema Area" UNIQUE PRIMARY INDEX-FIELD "book-id" ASCENDING ADD INDEX "isbn" ON "Book" AREA "Schema Area" UNIQUE INDEX-FIELD "isbn" ASCENDING
If the .df
schema file has the above two indexes defined for the book
table, this will result in the following elements added to the Book
class
element.
<class interface="Book"> <unique> <component name="isbn"/> </unique> <unique> <component name="bookId"/> </unique> </class>
The order of the unique
elements under the class
element it's not important. For each unique index, its columns are specified using component
elements; each component
element will have as an mandatory attribute the DMO property name which maps the table column name (i.e. the column's converted Java name). Note that in this case, the order of the component
elements is important and they will always be emitted in the same order as the table columns appear in the index definition.
Base64 Encoded Columns¶
Currently, P2j provides only conversion support for character columns which need to be base64-encoded for storage and decrypted upon retrieval. To mark a certain character column as encoded
, the schema hints file must be modified; assuming the schema name is simple
, there will be a data/namespace/simple.schema.hints
file which will contain an entry similar to the following entry, to mark the comments
column for table book
as being base64-encoded:
<hints> <schema> ... <table name="book"> <field name="comments" encoded="true"/> </table> ... </schema> </hints>
For more information about the structure of the schema hints file, please see the chapter on Conversion Hints in the FWD Conversion Handbook.
When the above hint exist for a certain column, the DMO index file will be added an encoded
element as child of the class
node; this element will have as single mandatory attribute the converted Java name of the encoded column. For the above example, the encoded
element of the class
node in DMO index file will look like this:
<class interface="Book"> ... <encoded name="comments"/> </class>
where comments
is the column's converted Java name.
Foreign Relations¶
In 4GL, there is no concept of formal foreign keys between tables, and only natural joins (i.e., joins between tables identified by the 4GL construct <BUFFER-A> OF <BUFFER-B>
within a record phrase) can be used. When a natural join is encountered, the 4GL runtime determines the common fields between the two tables and, from those, it chooses the fields which are part of an unique constraint in one of the tables.
In FWD, this relationship is determined at conversion time rather than at runtime. The DMO index file is used to hold metadata about the columns which are part of the foreign key relation. This data is determined at conversion time by analyzing the queries and the involved tables. Once it has determined that a natural join is involved, the FWD conversion will collect the data about the foreign table and the referenced columns and it will store them using a foreign
element under the class
element for the child table. If the 4GL queries are not enough to determine the foreign table of the relation (i.e. an one-to-one relation where both tables have an unique index on the common fields), file-level hints can be used to hard code the table and columns which are part of the foreign relation. For more information about how to use the hints file, please see the chapter on Conversion Hints in the FWD Conversion Handbook.
As an example, lets assume that a book can have one or more authors and a certain author may write one or more books. To simulate this many-to-many relation we will use another table (named book-author
) which will have a one-to-many relation to the book
table and a one-to-many relation to the author
table. If we want to display all the authors of this book, a construct like the following can be used:
... for each book where book.book-title = 'FWD Conversion Reference', book-author of book, author of book-author: display author. End. ...
In this example, the book
table has an unique index on the book-id
field and the author
table has an unique index on the author-id
field. The book-author
table contains only the book-id
and author-id
fields. During conversion, FWD will identify the natural joins and will translate them into an one-to-many relation between the book-author
and the book
table (on the book-id
field) and another one-to-many relation between the book-author
table and the author
table (on the author-id
field). This will result on the following foreign
elements emitted under the class
element for the BookAuthor
DMO:
<class interface="BookAuthor"> <foreign interface="Book"> <property name="bookId"/> </foreign> <foreign interface="Author"> <property name="authorId"/> </foreign> </class>
Each foreign
element will have as children property
elements, with the name of the foreign columns. With this information provided, FWD will be able to identify correctly the foreign side of the relation, when the natural joins are executed.
Indexes¶
For permanent tables, no indexes will be emitted into the DMO index file. On server startup, FWD will automatically collect the table indexes from the table metadata.
DMO Index for Temporary Tables¶
For all temporary tables defined using the DEFINE TEMP-TABLE
or DEFINE WORK-TABLE
statements, during conversion the DMO sources will be generated under the com.foo.bar.dmo._temp
package. In the DMO index file, all DMOs will have a class
element emitted under the schema
element with the _temp
name. For a temporary table defined as in:
def temp-table tt-book field book-title as char field comments as char field copies as integer.
if the tt-book
will be converted to the DMO with the TempRecord1
name, the schema element in DMO index file will look like this:
<schema impl="_temp.impl" name="_temp"> <class interface="TempRecord1" /> </schema>
Note that a schema
element with the _temp
name will be emitted only if there is at least a temporary table defined in the converted programs.
The data collected for the temporary tables is the same as the data collected for the permanent tables. But, as there is no .df
schema file where the temporary tables are defined, all the data will be collected from the temporary table definition as it appears in the DEFINE TEMP-TABLE
statement.
Case Sensitive Columns¶
If a certain character field is specified the case-sensitive
attribute, then a case-sensitive
element with the name of that field will be emitted. If the temporary table is defined as:
def temp-table tt-book field book-title as char case-sensitive field comments as char field copies as integer.
the following element emitted under the class
node is shows how the generated DMO index file will save the case-sensitive
element:
... <case-sensitive name=”bookTitle” /> ...
Unique Indexes¶
For the temporary tables, the unique constraint information saved in the DMO index file is determined in the same way as for the permanent tables: all unique indexes are identified and the unique constraint is saved in the unique
element, under the class
element for the temporary DMO. If the unique index is defined for the temporary table as in:
def temp-table tt-book field book-title as char case-sensitive field comments as char field copies as integer index idx-book is unique book-title asc.
this is how the generated DMO index file will save the case-sensitive
element:
... <unique> <component name=”bookTitle” /> </unique> ...
Base64 Encoded Columns¶
A temporary table's column is marked as being base64-encoded in the same way as a column belonging to a permanent table is marked: the column must be registered in a hints file, so that on conversion FWD will be aware of the special usage of this column. In this case, as temporary tables are created by the 4GL program where the DEFINE TEMP-TABLE
statement exists, the file which must be modified is the schema hints file associated with this program. If the program's name is test.p
, then the associated schema hints file is named test.p.schema.hints
and resides in the same location as the test.p
program. In our case, where we only need to mark a certain column as base64 encoded, the hits file looks similar as the one for the permanent table.
Assuming we want to mark the comments field of the tt-book
table as being base64 encoded, the hints file would look like this:
<hints> <schema> ... <table name="tt-book"> <field name="comments" encoded="true"/> </table> ... </schema> </hints>
For more information about the structure of the schema hints file, please see the chapter on Conversion Hints in the FWD Conversion Handbook.
When the above hint exist for a certain column, the DMO index file will be added an encoded
element as child of the class
node; this element will have as single mandatory attribute the converted Java name of the encoded column. For the above example, the encoded
element of the class
node in DMO index file will look like this:
... <encoded name="comments"/> ...
where comments
is the column's converted Java name.
Foreign Relations¶
As with the permanent tables, when a natural join between two temporary tables is involved, FWD needs to determine the foreign side of the relation. The conversion logic and the output result is the same as for permanent tables: for each child table of a foreign key relation, foreign
elements will be emitted under its class
element. See the Foreign Relations sections in the DMO Index for Permanent Tables for details.
Indexes¶
As the DDL for the temporary tables can not be kept in the Hibernate configuration files, the indexes defined for the temporary tables are collected during conversion and saved in the DMO index file. At runtime, after the temporary table is created, FWD will generate the DDL for the the indexes stored in the DMO index file and create them in the temporary database.
The information stored for each index is about the index direction, if it's an unique index or not and its columns. Also, for each column, its case-sensitive state will be stored.
If the tt-book
table has the following indexes defined:
def temp-table tt-book field book-title as char case-sensitive field comments as char field copies as integer index idx-book-title is unique book-title asc index idx-copies copies desc book-title asc.
this will result in the following index
elements, emitted under the class
node for this table's DMO:
... <index name="idx__tt1_idx_book_title" unique="true"> <column ignore-case="false" name="book_title"/> </index> <index name="idx__tt1_idx_copies"> <column name="copies"/> <column name="book_title"/> </index> ...
The index name will always start with the idx__
prefix followed by the converted temporary table name (tt1
in this case) and the converted 4GL index name (idx_book_title
). For unique indexes, the unique
attribute at the index
element will be set to true
. Each index will have as children column
elements; the order of these elements is important, as it determines the order of the indexed columns.
For each column
element, the mandatory name
attribute will contain the table's column name as specified in the .hbm.xml
file for this table's DMO. If the column is case-sensitive, then the ignore-case
attribute will be emitted and set to false
.
© 2004-2017 Golden Code Development Corporation. ALL RIGHTS RESERVED.