Content starts here Deconstructing the Inverse Functions Sample
This page last changed on Jul 02, 2008.

edocs Home > BEA AquaLogic Data Services Platform 3.0/3.2 Documentation > ALDSP 3.2 New Features Documentation

Examining the Inverse Functions Sample

This topic describes how to define and configure inverse functions using the sample dataspace and Java function library as an example.

For more information about the inverse functions sample, see Exploring the Inverse Functions Sample.

Topic Map


Using Inverse Functions to Improve Query Performance

Overview

You need to complete the following actions to use inverse functions:

  • Create the underlying Java functions
  • Create physical data services based on the functions
  • Add comparison logic to the data service
  • Configure the inverse functions
  • Create the data service

Creating the Underlying Java Functions

The inverse functions sample includes logic to perform transformations between:

  • first/last names and full names
  • department names and numbers
  • employee IDs and names

The string manipulation logic to manipulate first and last names needed by the inverse function is in the following Java file in the JavaFunctionLib project:

JavaFunctionLib/JavaFuncs/NameLib.java

This file defines three string manipulation functions.

package JavaFuncs;

public class NameLib
{
   public static String fullname(String fn, String ln) {
      return (fn == null || ln == null) ? null : (fn + " " + ln);
   }

   public static String firstname(String name) {
      try {
         int sepidx = name.indexOf(' ');
         if (sepidx < 0) return null;
           return name.substring(0, sepidx);
      }
      catch (Exception e) { return null; }
   }

   public static String lastname(String name) {
      try {
         int sepidx = name.indexOf(' ');
         if (sepidx < 0) return null;
            return name.substring(sepidx+1, name.length());
      }
      catch (Exception e) { return null; }
   }

   public static void main(String[] args) {
      String first = "John";
      String last  = "Doe";
      String full  = "John Doe";
      System.out.println(fullname(first, last));
      System.out.println(firstname(full));
      System.out.println(lastname(full));
      System.out.println(firstname(first));
      System.out.println(lastname(first));
   }
}

Notice that the function fullname() simply concatenates the first and last names. In contrast, the firstnname() and lastname() functions deconstruct the resulting full name using the required space in the full name string as the marker identifying the separation between first and last names. Or, put another way, the fullname() function is the invertible of firstname() and lastname().

Similar functions are available in the DeptLib and EmpIdLib packages supporting transformations between department names and numbers, and employee IDs and names respectively.

Creating the Physical Data Services Based on the Functions

After you have compiled the Java functions, you can create a physical data service from the resulting class file. In the sample, physical data services were created using the NameLib.class, DeptLib.class, and EmpIdLib.class files.

See Create a Physical Data Service from a Java Function for step-by-step instructions for creating a physical data service from a class file.

In the sample, the resulting operations corresponding to the string manipulation logic reside in the NameFunc.ds data service, as illustrated by the following:

NameFunc.ds Data Service

Adding Comparison Logic to the Data Service

As is often the case, some additional programming logic is needed. In the case of the sample, a function, fullnameEQ(), compares names and returns a Boolean value indicating whether the names are identical.

declare function f1:fullnameEQ($full1 as xs:string?, $full2 as xs:string?) as xs:boolean? {
  (f1:firstname($full1)eq f1:firstname($full2)) and (f1:lastname($full1) eq f1:lastname($full2))
};
You can define additional functions for specific conditions, such as "is greater-than" or "is-less-than." Later, when configuring the inverse functions, you can create associations for these conditionals enabling the the XQuery engine to substitute the custom logic for a simple conditional.
Associating Custom Conditional Logic with Functions

Configuring the Inverse Functions

You need to configure the inverse functions to perform the reverse transformation of the data. 

In this particular case, this means that you need to identify an inverse function for each parameter in the fullname() function.

Inverse functions can only be defined when the input and output function parameters are atomic types.

To association the parameters of a function with inverse functions:

  1. Double-click on the data service in Project Explorer. For example, double-click NameFuncs.ds in the sample.
  2. Right-click on the function with which you want to associate inverse functions, and choose Configure Inverse Function. In the sample, right-click the fullname operation and choose Configure Inverse Function.
    Selecting Configure Inverse Function



A dialog appears enabling you to select the inverse functions for each parameter.

  1. Choose the corresponding inverse functions for each parameter using the drop-down lists, and click Next.
    Selecting Configure Inverse Function

  2. Specify the equivalent transforms.



Associating Custom Conditional Logic with Functions


After you have associated inverse functions with the correct parameters, you may want to associate custom conditional logic with the functions. You do this by substituting a custom function for such generic conditions as eq (is equal to) and gt (is greater than). The following table lists conditional operations available for such transformations.

Conditional
Operation
Definition
gt string-greater-than
ne string-not-equal
lt string-less-than
ge
string-greater-than-or-equal-to
eq
string-equal
le string-less-than-or-equal-to

Associating a particular conditional (such as "is greater-than") with a transformational function allows the XQuery engine to substitute the custom logic for a simple conditional. As is always the case with AquaLogic Data Services Platform, the original basis of the function does not matter. It could be created in your data service, or externally in a Java or other routine. In this example the transformational function, fullnameEQ, is in the Java-based physical data service.

Defining the Equivalent Transforms

Create the Data Service

The final step is to build the data service that contains the operations to create, read, update, and delete the data. In the sample dataspace, this data service, Employee.ds, includes operations such as createEmployee, getAll, updateEmployee, and deleteEmployee. The data service also includes operations such as getByDeptName, getByEmpName, and getByEmpNo.

The following shows the overview of the Employee.ds data service.

Employee.ds Data Service

The data service uses XML types associated with the Employee.xsd schema. This schema could have been created through the XQuery Editor, through the ALDSP schema editor, or through a third-party editing tool.

The getAll() operation returns all employee records, as shown in the following listing:

declare function ns1:getAll() as element(ns1:Employee)* {
   for $EMP2 in emp2:EMP2()
   return
      <tns:Employee>
         <EmpNo>{emp1:empnum($EMP2/EmpId)}</EmpNo>
         <EmpName?>{nam:fullname($EMP2/FirstName, $EMP2/LastName)}</EmpName>
         <MgrName?>{fn:data($EMP2/MgrName)}</MgrName>
         <Dept?>{dep:deptname($EMP2/Dept)}</Dept>
      </tns:Employee>
};

Examining the query plan for the getAll() operation, as shown in the following, you can see that predicates are being pushed despite data transformations, because of the use of inverse functions.

Query Plan for the getAll Operation

The case is the same for the other read methods getByDeptName(), getByEmpName(), and getByEmpNo(). Examining the corresponding query plans, you can see that predicates are being pushed regardless of the specific transformations because of the corresponding inverse functions.

The getByEmpName() operation illustrates a typical case where the transformation involves performing a concatenation and the inverse function reverses the operation. In this case, N values are merged into 1 or vice versa. The getByDeptName() and getByEmpNo() operations are both 1:1 examples, transforming between numeric and string values.

Related Topics

Concepts
How Tos
Reference
Document generated by Confluence on Jul 03, 2008 12:12