gmantele / vollt

Java libraries implementing the IVOA protocol: ADQL, UWS and TAP
http://cdsportal.u-strasbg.fr/taptuto/
29 stars 28 forks source link

Easier SQL translation of UDF #115

Closed gmantele closed 4 years ago

gmantele commented 5 years ago

In the TAP configuration file allow a simple inline SQL translation for a declared UDF.

For instance, lets assume the UDF my_adql_udf(INT, DOUBLE, DOUBLE) -> LONG. Its declaration in the TAP configuration file would be:

udfs = [
        my_adql_udf(INT, DOUBLE, DOUBLE) -> LONG,
        ,
        "This function does something".
       ]

If no SQL function named my_adql_udf exists, the way to translate it into SQL is required. In the current status of TAP-Lib, a class extending adq.query.operand.functionUserDefinedFunction should be written in order to specify the appropriate SQL translation with the function translate(ADQLTranslator). So, the corresponding TAP configuration line would be:

udfs = [
        my_adql_udf(INT, DOUBLE, DOUBLE) -> LONG,
        {aPackage.MyAdqlUdf},
        "This function does something".
       ]

And here would be the class for the SQL translation:

package aPackage;

public class MyAdqlUdf extends UserDefinedFunction {
    protected NumericConstant firstParam;
    protected NumericConstant secondParam;
    protected NumericConstant thirdParam;

    public MyAdqlUdf(final ADQLOperand[] params) throws Exception {
        // TODO Check parameters number and their resp. type
    }

    public final boolean isNumeric() { return true; }
    public final boolean isString() { return false; }
    public final boolean isGeometry() { return false; }

    public ADQLObject getCopy() throws Exception {
        ADQLOperand[] params = new ADQLOperand[]{ firstParam.getCopy(), secondParam.getCopy(), thirdParam.getCopy() };
        return new MyAdqlUdf(params);
    }

    public final String getName() { return "my_adql_udf"; }

    public final int getNbParameters() { return 3; }

    public final ADQLOperand[] getParameters() {
        return new ADQLOperand[]{ firstParam, secondParam, thirdParam };
    }

    public final ADQLOperand getParameter(int index) throws ArrayIndexOutOfBoundsException {
        // TODO Check the index and if correct return the corresponding parameter
    }

    public ADQLOperand setParameter(int index, ADQLOperand replacer) throws ArrayIndexOutOfBoundsException, NullPointerException, Exception {
        // TODO Check the index and operand's type and then, set the corresponding parameter
    }

    public String translate(final ADQLTranslator caller) throws TranslationException {
        return "my_SQL_udf("+caller.translate(firstParam)+", another_fct("+caller.translate(secondParam)+","+caller.translate(thirdParam)+"))";
    }
}

So, though the SQL translation is really simple, writing an entire Java class is quite time-consuming and force a compilation step in addition of having some knowledge about the ADQL-Lib's API.

In order to simplify such UDF declaration, it is proposed to write the SQL translation directly in the TAP configuration file. This inline SQL translation would be in place of the class specification. Then, it would be something like:

udfs = [
        my_adql_udf(INT, DOUBLE, DOUBLE) -> LONG,
        "my_SQL_udf($1, another_fct($2,$3))",
        "This function does something".
       ]