Extensions : RDBMS SQL Methods Support

Plugin

DataNucleus is developed as a plugin-driven framework and one of the components that is pluggable is the support for JDOQL/JPQL methods in the RDBMS query mechanism. DataNucleus provides support for the majority of SQL methods that you are ever likely to need but is structured so that you could add on support for your own easily enough

The following sections describe how to create your own SQL Method plugin for DataNucleus.

Interface

Any SQL Method plugin will need to implement org.datanucleus.store.rdbms.sql.method.SQLMethod Javadoc. So you need to implement the following interface

import org.datanucleus.store.rdbms.sql.method;

public interface SQLMethod
{
    /**
     * Return the expression for this SQL function.
     * @param expr The expression that it is invoked on
     * @param args Arguments passed in
     * @return The SQL expression using the SQL function
     */
    public SQLExpression getExpression(SQLExpression expr, List args);
}

Implementation

So there is only one method to provide in your implementation. The arguments to this are

  • The expression on which the method is invoked. So if you have {string}.myMethod(args) then the first argument will be a StringExpression. If the method is a static function then this argument is null
  • The args are the arguments passed in to the method call. They will be SQLExpression/SQLLiteral

So if we wanted to support {String}.length() as an example, so we define our class as

package mydomain;

import java.util.List;
import java.util.ArrayList;

import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.store.rdbms.sql.expression.NumericExpression;
import org.datanucleus.store.rdbms.sql.expression.SQLExpression;
import org.datanucleus.store.rdbms.sql.expression.StringExpression;

public class MyStringLengthMethod extends AbstractSQLMethod
{
    public SQLExpression getExpression(SQLExpression expr, List args)
    {
        if (expr instanceof StringExpression)
        {
            ArrayList funcArgs = new ArrayList();
            funcArgs.add(expr);
            return new NumericExpression("CHAR_LENGTH", funcArgs);
        }
        else
        {
            throw new NucleusException(Localiser.msg("060001", "length", expr));
        }
    }
}

So in this implementation when the user includes {string}.length() this is translated into the SQL _CHARLENGTH({string}) which will certainly work on some RDBMS. Obviously you could use this extension mechanism to support a different underlying SQL function.

Plugin Specification

So we now have our custom SQL method and we just need to make this into a DataNucleus plugin. To do this you simply add a file plugin.xml to your JAR at the root. The file plugin.xml should look like this

<?xml version="1.0"?>
<plugin id="mydomain" name="DataNucleus plug-ins" provider-name="My Company">
    <extension point="org.datanucleus.store.rdbms.sql_method">
        <sql-method class="java.lang.String" method="length" datastore="h2"
            evaluator="mydomain.MyStringLengthMethod"/>
    </extension>
</plugin>

If implementing support for a method that is static (e.g JDOHelper.getObjectId()) omit the class argument from the plugin.xml entry, and put the method as JDOHelper.getObjectId Note that you also require a MANIFEST.MF file as per the Extensions Guide.

So we defined calls to a method length for the type java.lang.String for the datastore h2 to use our evaluator. Simple! Whenever this method is encountered in a query from then on for the H2 database it will use our method evaluator.