Working with LDAP Tables
The driver includes table schemas for many standard LDAP objects. You can easily extend the included table schemas to edit column behavior or you can write your own from scratch.
Table schemas are defined in .rsd files, which are simple configuration files. This section will walk through different parts of the schema, adding several columns to the Person table as an example.
You can find the Person.rsd file in the db subfolder in the installation folder of the CData ODBC Driver for LDAP.
Connecting to Custom Tables
To use custom schemas, set the Location property to the folder containing the schema files.
Defining a New Table
It is important to define a new table with the same name as the object class that the table will represent. This will allow the driver to search for only the desired object class when querying the LDAP server. The file name defines the table name.
Defining Table Columns and Inputs
Columns are defined in the rsb:info block, a shown below. The attr tags in the schema represent the columns of the table. These should match the attributes that make up the desired object class.There are a few columns that every table should include, regardless of the object class:
<rsb:script xmlns:rsb="http://www.rssbus.com/ns/rsbscript/2">
<rsb:info title="Person" description="Create, update, delete, and query person entries in Active Directory.">
<!-- Required Columns -->
<attr name="Id" xs:type="string" readonly="true" key="true" />
<attr name="DN" xs:type="string" readonly="true" required="false" other:ldaptype="OID" />
<attr name="RDN" xs:type="string" readonly="true" required="false" other:ldaptype="Directory String" />
<attr name="BaseDN" xs:type="string" readonly="true" required="false" other:ldaptype="OID" />
Note: The title attribute of the rsb:info block must match the name of the .rsd file.
Customizing Column Behavior
Each column requires at least name and xs:type attributes. Additionally, you will need to specify dataFormat to decide how data is returned from the table. For example:
<!-- Person Required Attributes -->
<attr name="ObjectClass" other:dataFormat="splitDataByRow" xs:type="string" readonly="false" required="false" other:ldaptype="OID" />
<attr name="SN" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="CN" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<!-- Person Optional Attributes -->
<attr name="UserPassword" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Binary" />
<attr name="TelephoneNumber" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="SeeAlso" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="DN" />
<attr name="Description_1" other:dataFormat="splitDataByCol" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="Description_2" other:dataFormat="splitDataByCol" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="Description_3" other:dataFormat="splitDataByCol" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
The other:dataFormat attribute has three options:
-
delimitedData: Return multiple LDAP attribute values as delimited strings, separated by the delimiter character defined in the Table Settings section of the .rsd file, detailed later.
This is the default format in which to retrieve data and the delimiter defaults to a semicolon.
- splitDataByRow: Push multiple LDAP attribute values for the same DN as separate rows. All other columns will be pushed consistently, and the index in Id will be incremented. Note: Pushing multiple columns like this will exponentially grow the result set, potentially causing performance issues.
- splitDataByCol: Push multiple LDAP attribute values for the same DN with an appended index on the column name. You need to define multiple columns and append an "_n" to the end; for example, ObjectClass_1, ObjectClass_2, and ObjectClass_3. In this example, if there are more than 3 values, the remaining values will not be visible in the table, unless more columns are added.
Example: Splitting the ObjectClass Attribute
The code below can be used to split the different values of the ObjectClass attributes into their own rows and Description attributes into their own columns. Notice the column definition now includes multiple columns for the Description attribute. Also note the other:dataFormat attribute for the attr.
...
<attr name="ObjectClass" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="OID" />
<attr name="SN" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="CN" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="UserPassword" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Binary" />
<attr name="TelephoneNumber" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="SeeAlso" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="DN" />
<attr name="Description_1" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="Description_2" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
<attr name="Description_3" other:dataFormat="delimitedData" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" />
</rsb:info>
<!-- Table Settings -->
<rsb:set attr="delimiter" value=";"/>
...
An example result will look like:
Id | DN | ObjectClass | SN | CN | UserPassword | TelephoneNumber | SeeAlso | Description_1 | Description_2 | Description_3 |
1|CN=User1,DC=Test | CN=User1,DC=Test | Top | TestSN | User1 | 555-5555 | A;B;C | Desc1 | Desc2 | Desc3 | |
2|CN=User1,DC=Test | CN=User1,DC=Test | User | TestSN | User1 | 555-5555 | A;B;C | Desc1 | Desc2 | Desc3 |
Specifying Column Encoding
In addition to data format on inputs, encoding can also be specified. Currently, returning data with UTF8 encoding or BASE64 encoding is supported. In order to retrieve data with a specified encoding, the other:encoding field must be specified for the desired attribute to be encoded. If no encoding is specified, UTF8 is the default.
An example of specifying encoding for an attribute:
...
<attr name="ObjectClass" other:dataFormat="delimitedData" other:encoding="UTF8" xs:type="string" readonly="false" required="false" other:ldaptype="OID" desc="The object class of the entry."/>
<attr name="SN" other:dataFormat="delimitedData" other:encoding="BASE64" xs:type="string" readonly="false" required="false" other:ldaptype="Directory String" desc="The surname of the person."/>
...
Modifying Filter Behavior
Optionally, there are two attributes that can be used to control how filtering is handled when using the driver with SupportEnhancedSQL. The other:ldaptype attribute can be used to set the LDAP syntax of a field. This is used to determine the comparison operators that are supported server-side on a per-field basis. For example, if a field is marked as the type 'DN' and a query filtering for a substring (i.e., CONTAINS), which is not supported server-side, the driver will instead process this part of the filter entirely client-side. The supported type names are found in section 4.3.2 of RFC 2252. If you are unsure of the type or just want to disable server-side filtering for a given column entirely, the other:filterable attribute is also available. Setting this to false for the field will prevent this from ever being sent to the server in a filter, overriding the other:ldaptype attribute entirely.
Configuring Table Settings
In addition to the attributes and inputs, you will need to specify the delimiter.
The delimiter specifies the character that will be used for delimited data. Delimited data will be returned for any attribute that appears multiple times for a single object (unless otherwise specified in other:dataFormat).
For example, the code below will concatenate multiple values of an attribute using the ';' character.
...
</rsb:info>
<!-- Table Settings -->
<rsb:set attr="delimiter" value=";"/>
...
Defining Supported Operations
Operation definitions will remain exactly the same for all newly created tables: Simply copy and paste these from an existing table, as needed.
<!-- Operation definitions -->
<rsb:script method="GET">
<rsb:set attr="action" value="Get" />
<rsb:call op="ldapadoLDAP" >
<rsb:push />
</rsb:call>
</rsb:script>
<rsb:script method="POST">
<rsb:set attr="action" value="Post" />
<rsb:call op="ldapadoLDAP" >
<rsb:push item="toout"/>
</rsb:call>
</rsb:script>
<rsb:script method="MERGE">
<rsb:set attr="action" value="Merge" />
<rsb:call op="ldapadoLDAP" >
<rsb:push />
</rsb:call>
</rsb:script>
<rsb:script method="DELETE">
<rsb:set attr="action" value="Delete" />
<rsb:call op="ldapadoLDAP" >
<rsb:push />
</rsb:call>
</rsb:script>