The following table shows a high-level view of how the driver maps Novell® eDirectoryTM objects to database objects.
| eDirectory Object | Database Object |
|---|---|
Tree |
Schema |
Class |
Table/View |
Attribute |
Column |
Association |
Primary Key |
A logical database class is the set of tables or views used to represent an eDirectory class in a database. A logical database class can consist of a single view or one parent table and zero or more child tables. The name of a logical database class is the name of the parent table or view.
In an indirect synchronization model, the driver maps the following:
In the following example, the logical database class emp consists of one parent table emp and one child table phone. Logical class emp is mapped to the eDirectory class User.
CREATE TABLE dirxml.emp
(
empno NUMERIC(8) NOT NULL,
fname VARCHAR(64),
lname VARCHAR(64),
pwdminlen NUMERIC(4),
CONSTRAINT pk_emp_empno PRIMARY KEY(empno)
);
CREATE TABLE dirxml.phone
(
empno NUMERIC(8) NOT NULL,
phone VARCHAR(64) NOT NULL,
CONSTRAINT fk_phone_empno FOREIGN KEY(empno) REFERENCES
emp(empno)
);
<rule name="MappingRule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>emp</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>Given Name</nds-name>
<app-name>fname</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Surname</nds-name>
<app-name>lname</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Password Minimum Length</nds-name>
<app-name>pwdminlen</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Telephone Number</nds-name>
<app-name>phone.phoneno</app-name>
</attr-name>
</attr-name-map>
</rule>
Parent tables are tables with an explicit primary key constraint that contains one or more columns. In a parent table, an explicit primary key constraint is required so that the driver knows which fields to include in an association value.
CREATE TABLE dirxml.emp
(
empno NUMERIC(8) NOT NULL,
...
CONSTRAINT pk_emp_empno PRIMARY KEY(empno)
);
The following table contains sample data for dirxml.emp.
| empno | fname | lname |
|---|---|---|
1 |
John |
Doe |
The resulting association for this row would be:
empno=1,table=emp,schema=dirxml
NOTE: The case of database identifiers in association values is determined dynamically at runtime from database metadata.
Parent table columns can contain only one value. As such, they are ideal for mapping single-valued eDirectory attributes. For example, mapping the single-valued eDirectory attribute Password Minimum Length to the single-valued parent table column pwdminlen.
Parent table columns are implicitly prefixed with the name of the parent table. It is not necessary to explicitly table-prefix parent table columns. For example, emp.fname is equivalent to fname for schema mapping purposes.
<rule name="MappingRule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>emp</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>Given Name</nds-name>
<app-name>fname</app-name>
</attr-name>
</attr-name-map>
</rule>
Large binary and string data types should be typically mapped to parent table columns. In order to map to a child table column, a data type must be comparable in an SQL statements. Large data types usually cannot be compared in SQL statements.
Large binary and string data types can be mapped to child table columns if <remove-value> events on these types are transformed in style sheets into a <remove-all-values> element followed by a series of <add-value> elements, one for each value.
A child table is a table that has a foreign key constraint on its parent table's primary key, linking the two tables together. The columns that comprise the child table's foreign key must have the same name as the columns in the parent table's primary key. This common column name is used by the publisher to identify all rows in the event log table pertaining to a single logical database class.
The following example shows the relationship between parent table emp and child table phone. Note the use of the same column name empno in each table.
CREATE TABLE dirxml.emp
(
empno NUMERIC(8) NOT NULL,
...
CONSTRAINT pk_emp_empno PRIMARY KEY(empno)
);
CREATE TABLE dirxml.phone
(
empno NUMERIC(8) NOT NULL,
phoneno VARCHAR(64) NOT NULL,
CONSTRAINT fk_phone_empno FOREIGN KEY(empno) REFERENCES
emp(empno)
);
The constrained column in a child table identifies the parent table. In the above example, the constrained column in child table phone is empno. The only purpose of this column is to relate tables phone and emp. Because constrained columns do not contain any useful information, they should be omitted from publication triggers and the schema mapping rule.
The unconstrained column is the column of interest. It represents a single, multi-valued attribute. In the above example, the unconstrained column is phoneno. Because unconstrained columns can hold multiple values, they are ideal for mapping multi-valued eDirectory attributes. For example, mapping the multi-valued eDirectory attribute Telephone Number to phone.phoneno.
All columns in a child table should be constrained NOT NULL.
NOTE: Each multi-valued, eDirectory attribute must be mapped to a different child table column.
The following table contains sample data for dirxml.phone.
| empno | phoneno |
|---|---|
1 |
111-1111 |
1 |
222-2222 |
When mapping a multi-valued eDirectory attribute to a child table column, the child column name must be explicitly prefixed with the child table name (for example, phone.phoneno). Otherwise, the driver will implicitly interpret phoneno as emp.phoneno, not phone.phoneno.
<rule name="MappingRule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>emp</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>Telephone Number</nds-name>
<app-name>phone.phoneno</app-name>
</attr-name>
</attr-name-map>
</rule>
Referential containment can be represented in the database through the use of foreign key constraints. Referential attributes are columns within a logical database class that refer to the primary key columns of parent tables of other logical database classes.
Two parent tables can be related through a single parent table column. This column must have a foreign key constraint pointing to the other parent table's primary key. The following example relates a single parent table user to itself.
CREATE TABLE user
(
idu NUMBER(8) NOT NULL,
manager NUMBER(8),
CONSTRAINT pk_user_idu PRIMARY KEY(idu),
CONSTRAINT fk_user_idu FOREIGN KEY(manager)REFERENCES
user(idu)
);
<rule name="Mapping Rule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>user</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>manager</nds-name>
<app-name>manager</app-name>
</attr-name>
</attr-name-map>
</rule>
Single-valued, referential colums must be nullable.
Two parent tables can be related through a common child table. This child table must have a foreign key constraint pointing to each parent table's primary key. The following example relates two parent tables user and group through a common child table member.
CREATE TABLE user
(
idu NUMBER(8) NOT NULL,
lname VARCHAR(64) NOT NULL,
CONSTRAINT pk_user_idu PRIMARY KEY(idu)
);
CREATE TABLE group
(
idg NUMBER(8) NOT NULL,
CONSTRAINT pk_group_idg PRIMARY KEY(idg)
);
CREATE TABLE member
(
idg NUMBER(8) NOT NULL,
idu NUMBER(8) NOT NULL,
CONSTRAINT fk_member_idg FOREIGN KEY(idg) REFERENCES
group(idg),
CONSTRAINT fk_member_idu FOREIGN KEY(idu) REFERENCES
user(idu)
);
<rule name="Mapping Rule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>user</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>Surname</nds-name>
<app-name>lname</app-name>
</attr-name>
<class-name>
<nds-name>Group</nds-name>
<app-name>group</app-name>
</class-name>
<attr-name class-name="Group">
<nds-name>Member</nds-name>
<app-name>member.idu</app-name>
</attr-name>
</attr-name-map>
</rule>
The first constrained column in a child table determines ownership. In the above example, member is considered to be part of class group. member is said to be a proper child of group. The second constrained column in a child table is the multi-valued referential attribute. Both columns must be constrained NOT NULL.
In the following example, the order of the constrained columns has been reversed so member is part of class user. To more accurately reflect the relationship, member has been renamed to member_of.
CREATE TABLE user
(
idu NUMBER(8) NOT NULL,
lname VARCHAR(64) NOT NULL,
CONSTRAINT pk_user_idu PRIMARY KEY(idu)
);
CREATE TABLE group
(
idg NUMBER(8) NOT NULL,
CONSTRAINT pk_group_idg PRIMARY KEY(idg)
);
CREATE TABLE member_of
(
idu NUMBER(8) NOT NULL,
idg NUMBER(8) NOT NULL,
CONSTRAINT fk_member_idg FOREIGN KEY(idg) REFERENCES
group(idg),
CONSTRAINT fk_member_idu FOREIGN KEY(idu) REFERENCES
user(idu)
);
<rule name="Mapping Rule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>user</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>Surname</nds-name>
<app-name>lname</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Group Membership</nds-name>
<app-name>member_of.idg</app-name>
</attr-name>
<class-name>
<nds-name>Group</nds-name>
<app-name>group</app-name>
</class-name>
</attr-name-map>
</rule>
In databases where position is meaningless, order is determined by lexographical comparison.
In general, it is only necessary to synchronize multi-valued, referential attributes as part of one class or the other, not both. If you wanted to synchronize referential attributes for both classes, it would be necessary to construct two child tables, one for each class. For example, if you wanted to synchronize Group Membership and Member, you would need two child tables: member_of and member.
In practice, when synchronizing User and Group objects, we recommend that you synchronize the Group Membership attribute of User instead of the Member attribute of Group. When synchronizing Member, events are generated for unassociated Users added to associated Groups. When synchronizing Group Membership, events are only generated for associated Users added to associated Groups.
In a direct synchronization model, the driver maps the following:
| eDirectory Object | Database Object |
|---|---|
Classes |
Views |
Attributes |
View Columns |
1 Class |
View |
Single-valued attribute |
View Column |
Multi-valued attribute |
View Column |
A view is a logical table. Unlike parent or child tables, they do not physically exist in the database. As such, views cannot have primary key/foreign key constraints. In order to identify to the driver which fields to use when constructing association values, one or more view columns must be prefixed with pk_ (case-insensitive).
NOTE: Views must be constructed in such a way that the pk_ prefixed view columns uniquely identify a single row.
The update capabilities of views vary widely between databases. Most databases allow views to be updated under certain conditions. If views are strictly read-only, then they cannot be used for subscription. Microsoft SQL Server 2000 and Oracle 8i and 9i allow update logic to be defined on views in instead-of-triggers, which allows a view to join multiple tables and still be updateable.
CREATE TABLE dirxml.emp
(
empno NUMERIC(8) NOT NULL UNIQUE,
fname VARCHAR(64),
lname VARCHAR(64),
pwdminlen NUMERIC(4),
phoneno VARCHAR(64)
);
CREATE VIEW dirxml.view_emp
(pk_empno, fname, lname, pwdminlen, phoneno)
AS
SELECT empno, fname, lname, pwdminlen, phoneno FROM dirxml.emp;
<rule name="MappingRule">
<attr-name-map>
<class-name>
<nds-name>User</nds-name>
<app-name>view_emp</app-name>
</class-name>
<attr-name class-name="User">
<nds-name>Given Name</nds-name>
<app-name>fname</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Surname</nds-name>
<app-name>lname</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Password Minimum Length</nds-name>
<app-name>pwdminlen</app-name>
</attr-name>
<attr-name class-name="User">
<nds-name>Telephone Number</nds-name>
<app-name>phoneno</app-name>
</attr-name>
</attr-name-map>
</rule>
When the database is the authoritative source of primary key columns, they should generally be omitted from the publisher and subscriber filters, the schema mapping rule, and publication triggers.
When eDirectory is the authoritative source of primary key columns, they should be included in the subscriber filter and schema mapping rule and omitted from the publisher filter and publication triggers. Also, GUID rather than CN is recommended for use as a primary key. CN is multi-valued and can change. GUID is single-valued and static.
When synchronizing multiple eDirectory classes, it is necessary to synchronize each class to a different parent table or view. Each logical database class must have a unique primary key column name. This common column name is used by the publisher to identify all rows in the event log table pertaining to a single logical database class. For example, logical database classes user and group each have a unique primary key column name.
CREATE TABLE user
(
idu NUMBER(8) NOT NULL,
lname VARCHAR(64) NOT NULL,
CONSTRAINT pk_user_idu PRIMARY KEY(idu)
);
CREATE TABLE group
(
idg NUMBER(8) NOT NULL,
CONSTRAINT pk_group_idg PRIMARY KEY(idg)
);
By default, the driver assumes that all eDirectory attributes mapped to parent table columns or view columns are single-valued. Because the driver is unaware of the eDirectory schema, it has no way of knowing whether an eDirectory attribute is single-valued or multi-valued. Accordingly, multi-valued and single-valued attribute mappings are handled identically.
The driver implements the Most Recently Touched (MRT) algorithm with regard to single-valued parent table or view columns. An MRT algorithm ensures that the most recently added attribute value or most recently deleted attribute value will be stored in the database. The algorithm is adequate if the attribute in question is single-valued, and has some undesirable consequences if the attribute is multi-valued.
When a value is deleted from a multi-valued attribute, the database field it is mapped to will be set to NULL and will remain NULL until another value is added. Several solutions to this undesirable behavior are outlined below.