Sample Custom Scalar Function

The information on this page has been superseded as of BBj 19.10. See SQL - Custom Functions for current information.


The following is the Java source code for the SUBSTRING scalar function. To implement a custom scalar function, follow the pattern in this sample:

 

package com.basis.sql.sqlengine2.scalarfunction;
import com.basis.sql.sqlengine2.value.FunctionConnectionInformation;
import com.basis.sql.sqlengine2.value.SQLValue;
import com.basis.sql.sqlengine2.value.FixedSQLValue;
import com.basis.sql.sqlengine2.value.ScalarFunctionSQLValue;
import com.basis.sql.sqlengine2.value.TypeInfo;

import java.sql.Types;
import java.sql.SQLException;

import java.util.List;

/**
 * Representing a scalar function (SUBSTRING).
 *
 * @author Christopher Hardekopf
 */
public class SUBSTRING extends ScalarFunctionSQLValue
{
    /**
     * Defines the parameter options available for this function. Each element in the array
     * consists of an array of parameter types. If a parameter supports more than one
     * possible type, the types are OR'd together. Available types are ANY_TYPE,
     * CHARACTER_TYPE, NUMERIC_TYPE, DATETIME_TYPE, and BINARY_TYPE.
     */
    private static final int [][]USAGE =
    { { CHARACTER_TYPE|BINARY_TYPE, NUMERIC_TYPE } ,
      { CHARACTER_TYPE|BINARY_TYPE, NUMERIC_TYPE, NUMERIC_TYPE } };

    // Contains the length of the value returned.
    private int m_length;

    /**
     * Constructor
     *
     * @param p_args The list of arguments passed into the method by the SQL parser. See getFixedValue()
     *               for how to access these values.
     * @param p_info Various pieces of info related to the SQL connection. See the m_info variable to access it.
     *
     * @throws SQLException If there is a problem.
     */
    public SUBSTRING (List<SQLValue> p_args, FunctionConnectionInformation p_info)
        throws SQLException
    {
        super(p_args,p_info,USAGE);

        if (isTypeKnown())
        {
            m_length = -1;
            if (getArgumentCount() > 2)
            {
                SQLValue arg3 = getArgument(2);
                if (arg3 instanceof FixedSQLValue)
                {
                    m_length = arg3.getInt();
                }
            }

            TypeInfo arg = getArgument(0);
            if (m_length < 0)
            {
                m_length = arg.getMaxLength();
            }
            setType(Types.VARCHAR);
        }
    }

    /**
     * Method to to get a FixedSQLValue for the _current_
     * value.
     */
    @Override
    public FixedSQLValue getFixedValue ()
        throws SQLException
    {
        // Each getArgument() call returns the SQLValue for the specified zero-indexed argument.
        FixedSQLValue arg = getArgument(0).getFixedValue();
        if (arg.isNull())
        {
            return arg;
        }

        try
        {
            FixedSQLValue arg2 = getArgument(1).getFixedValue();
            if (arg2.isNull())
            {
                return arg2;
            }
            try
            {
        String value1 = arg.getBinaryString(m_info.getCharset());
        int value2 = arg2.getInt() - 1;
        int value3 = value1.length();

                if (getArgumentCount() == 3)
                {
                    FixedSQLValue arg3 = getArgument(2).getFixedValue();
                    if (arg3.isNull())
                    {
                        return arg3;
                    }
                    try
                    {
                        value3 = arg3.getInt();
                    }
                    finally
                    {
                        arg3.clear();
                    }
                }

        if (value2 < 0)
        {
            value2 = 0;
        }
        if (value2 > value1.length())
        {
            value2 = value1.length();
        }
        if (value2 + value3 >= value1.length())
        {
                    value3 = value1.length() - value2;
                    if (value3 < 0)
                    {
                        value3 = 0;
                    }
        }

                return FixedSQLValue.getInstance(value1.substring(value2,(value2+value3)),true, getLocale(), m_info);
            }
            finally
            {
                arg2.clear();
            }
        }
        finally
        {
            arg.clear();
        }
    }

    // Additional functions to be overloaded.

    @Override
    public int getNativeMaxLength ()
        throws SQLException
    {
        return m_length;
    }

    /**
     * Is this function memoizable meaning sortable?
     */
    @Override
    protected boolean memoizable ()
    {
        return true;
    }
}