Skip to content
Snippets Groups Projects
Commit bccfe162 authored by Grégory Mantelet's avatar Grégory Mantelet
Browse files

[ADQL] Support the function IN_UNIT(...). (just for parsing....no translation

done because the function must also be available in the database)
parent 0bad1f8b
No related branches found
No related tags found
No related merge requests found
...@@ -64,6 +64,7 @@ import adql.query.operand.function.MathFunction; ...@@ -64,6 +64,7 @@ import adql.query.operand.function.MathFunction;
import adql.query.operand.function.MathFunctionType; import adql.query.operand.function.MathFunctionType;
import adql.query.operand.function.SQLFunction; import adql.query.operand.function.SQLFunction;
import adql.query.operand.function.SQLFunctionType; import adql.query.operand.function.SQLFunctionType;
import adql.query.operand.function.UnitConversionFunction;
import adql.query.operand.function.UserDefinedFunction; import adql.query.operand.function.UserDefinedFunction;
import adql.query.operand.function.geometry.AreaFunction; import adql.query.operand.function.geometry.AreaFunction;
import adql.query.operand.function.geometry.BoxFunction; import adql.query.operand.function.geometry.BoxFunction;
...@@ -317,6 +318,11 @@ public class ADQLQueryFactory { ...@@ -317,6 +318,11 @@ public class ADQLQueryFactory {
return new MathFunction(type, param1, param2); return new MathFunction(type, param1, param2);
} }
/** @since 2.0 */
public UnitConversionFunction createUnitConversionFunction(final ADQLOperand value, final ADQLOperand targetUnit) throws Exception {
return new UnitConversionFunction(value, targetUnit);
}
/** /**
* Creates the user defined functions called as the given name and with * Creates the user defined functions called as the given name and with
* the given parameters. * the given parameters.
......
...@@ -32,6 +32,7 @@ import adql.query.ClauseOffset; ...@@ -32,6 +32,7 @@ import adql.query.ClauseOffset;
import adql.query.constraint.ComparisonOperator; import adql.query.constraint.ComparisonOperator;
import adql.query.operand.BitNotOperand; import adql.query.operand.BitNotOperand;
import adql.query.operand.OperationType; import adql.query.operand.OperationType;
import adql.query.operand.function.UnitConversionFunction;
import adql.query.operand.function.geometry.AreaFunction; import adql.query.operand.function.geometry.AreaFunction;
import adql.query.operand.function.geometry.BoxFunction; import adql.query.operand.function.geometry.BoxFunction;
import adql.query.operand.function.geometry.CentroidFunction; import adql.query.operand.function.geometry.CentroidFunction;
...@@ -584,9 +585,7 @@ public class FeatureSet implements Iterable<LanguageFeature> { ...@@ -584,9 +585,7 @@ public class FeatureSet implements Iterable<LanguageFeature> {
public static final LanguageFeature WITH = new LanguageFeature(FeatureType.ADQL_COMMON_TABLE, "WITH"); // TODO WITH public static final LanguageFeature WITH = new LanguageFeature(FeatureType.ADQL_COMMON_TABLE, "WITH"); // TODO WITH
public static final LanguageFeature CAST = new LanguageFeature(FeatureType.ADQL_TYPE, "CAST"); // TODO CAST public static final LanguageFeature CAST = new LanguageFeature(FeatureType.ADQL_TYPE, "CAST"); // TODO CAST*/
public static final LanguageFeature IN_UNIT = new LanguageFeature(FeatureType.ADQL_UNIT, "IN_UNIT"); // TODO IN_UNIT*/
/** All standard features available. /** All standard features available.
* <p> * <p>
...@@ -598,7 +597,7 @@ public class FeatureSet implements Iterable<LanguageFeature> { ...@@ -598,7 +597,7 @@ public class FeatureSet implements Iterable<LanguageFeature> {
* <p><i><b>Important note:</b> * <p><i><b>Important note:</b>
* All of them must be optional and must have a type. * All of them must be optional and must have a type.
* </i></p> */ * </i></p> */
static LanguageFeature[] availableFeatures = new LanguageFeature[]{ BitNotOperand.FEATURE, OperationType.BIT_AND.getFeatureDescription(), OperationType.BIT_OR.getFeatureDescription(), OperationType.BIT_XOR.getFeatureDescription(), ClauseOffset.FEATURE, ComparisonOperator.ILIKE.getFeatureDescription(), LowerFunction.FEATURE, AreaFunction.FEATURE, BoxFunction.FEATURE, CentroidFunction.FEATURE, CircleFunction.FEATURE, ContainsFunction.FEATURE, ExtractCoord.FEATURE_COORD1, ExtractCoord.FEATURE_COORD2, ExtractCoordSys.FEATURE, DistanceFunction.FEATURE, IntersectsFunction.FEATURE, PointFunction.FEATURE, PolygonFunction.FEATURE, RegionFunction.FEATURE }; static LanguageFeature[] availableFeatures = new LanguageFeature[]{ UnitConversionFunction.FEATURE, BitNotOperand.FEATURE, OperationType.BIT_AND.getFeatureDescription(), OperationType.BIT_OR.getFeatureDescription(), OperationType.BIT_XOR.getFeatureDescription(), ClauseOffset.FEATURE, ComparisonOperator.ILIKE.getFeatureDescription(), LowerFunction.FEATURE, AreaFunction.FEATURE, BoxFunction.FEATURE, CentroidFunction.FEATURE, CircleFunction.FEATURE, ContainsFunction.FEATURE, ExtractCoord.FEATURE_COORD1, ExtractCoord.FEATURE_COORD2, ExtractCoordSys.FEATURE, DistanceFunction.FEATURE, IntersectsFunction.FEATURE, PointFunction.FEATURE, PolygonFunction.FEATURE, RegionFunction.FEATURE };
/** /**
* List all available language features. * List all available language features.
......
...@@ -387,6 +387,13 @@ TOKEN : { ...@@ -387,6 +387,13 @@ TOKEN : {
| < TAN: "TAN" > { matchedToken.adqlReserved = matchedToken.isFunctionName = true; } | < TAN: "TAN" > { matchedToken.adqlReserved = matchedToken.isFunctionName = true; }
} }
/* ******************** */
/* Conversion functions */
/* ******************** */
TOKEN : {
< IN_UNIT: "IN_UNIT" > { matchedToken.adqlReserved = matchedToken.isFunctionName = true; }
}
/* ******* */ /* ******* */
/* Comment */ /* Comment */
/* ******* */ /* ******* */
...@@ -1493,10 +1500,24 @@ ADQLFunction NumericFunction(): {ADQLFunction fct;} { ...@@ -1493,10 +1500,24 @@ ADQLFunction NumericFunction(): {ADQLFunction fct;} {
(fct=MathFunction() (fct=MathFunction()
| fct=TrigFunction() | fct=TrigFunction()
| fct=GeometryFunction() | fct=GeometryFunction()
| fct=UnitConversionFunction()
| fct=UserDefinedFunction() { ((UserDefinedFunction)fct).setExpectedType('N'); }) | fct=UserDefinedFunction() { ((UserDefinedFunction)fct).setExpectedType('N'); })
{return fct;} {return fct;}
} }
UnitConversionFunction UnitConversionFunction() : { Token start, end; ADQLOperand value, destUnit; } {
start=<IN_UNIT> <LEFT_PAR> value=NumericExpression() <COMMA> destUnit=StringExpression() end=<RIGHT_PAR>
{
try {
UnitConversionFunction fct = queryFactory.createUnitConversionFunction(value, destUnit);
fct.setPosition(new TextPosition(start, end));
return fct;
}catch(Exception ex) {
throw generateParseException(ex);
}
}
}
MathFunction MathFunction(): {Token fct=null, end; ADQLOperand param1=null, param2=null; NumericConstant integerValue = null;} { MathFunction MathFunction(): {Token fct=null, end; ADQLOperand param1=null, param2=null; NumericConstant integerValue = null;} {
try{ try{
((fct=<ABS> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>) ((fct=<ABS> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
......
package adql.query.operand.function;
/*
* This file is part of ADQLLibrary.
*
* ADQLLibrary is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ADQLLibrary is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2019 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import adql.parser.feature.LanguageFeature;
import adql.query.ADQLObject;
import adql.query.operand.ADQLOperand;
/**
* It represents the IN_UNIT function of ADQL.
*
* <p>This function converts the given value into the given VO-Unit.</p>
*
* <p>
* This function should report an error if the specified unit is not valid or
* if the conversion is not possible.
* </p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 2.0 (08/2019)
* @since 2.0
*/
public class UnitConversionFunction extends ADQLFunction {
/** Description of this ADQL Feature. */
public static final LanguageFeature FEATURE = new LanguageFeature(LanguageFeature.TYPE_ADQL_UNIT, "IN_UNIT", true, "Convert the given value (1st argument) into the given VO-Unit (2nd argument).");
/** Constant name of this function. */
protected final String FCT_NAME = "IN_UNIT";
/** The value to convert. */
protected ADQLOperand value;
/** The VO-Unit into which the value must be converted. */
protected ADQLOperand targetUnit;
/**
* Create the object representation of the ADQL function IN_UNIT.
*
* @param value The value to convert.
* @param targetUnit The VO-Unit into which the value must be converted.
*
* @throws NullPointerException If one of the given operands is NULL.
* @throws IllegalArgumentException If the 1st operand is not a numeric,
* or if the 2nd is not a string.
*/
public UnitConversionFunction(final ADQLOperand value, final ADQLOperand targetUnit) throws NullPointerException, IllegalArgumentException {
setValue(value);
setTargetUnit(targetUnit);
}
/**
* Get the numeric operand to convert into a different unit.
*
* @return The value to convert.
*/
public final ADQLOperand getValue() {
return value;
}
/**
* Set the numeric operand to convert into a different unit.
*
* @param value The value to convert.
*
* @throws NullPointerException If the given operand is NULL.
* @throws IllegalArgumentException If the given operand is not a numeric.
*/
public final void setValue(final ADQLOperand value) throws NullPointerException, IllegalArgumentException {
if (value == null)
throw new NullPointerException("The 1st argument of the ADQL function " + FCT_NAME + " (i.e. the value to convert) must be non-NULL!");
if (!value.isNumeric())
throw new IllegalArgumentException("The 1st argument of the ADQL function " + FCT_NAME + " (i.e. the value to convert) must be a numeric!");
this.value = value;
}
/**
* Get the VO-Unit into which the value must be converted.
*
* @return The target unit.
*/
public final ADQLOperand getTargetUnit() {
return targetUnit;
}
/**
* Set the VO-Unit into which the value must be converted.
*
* @param targetUnit The target unit.
*
* @throws NullPointerException If the given operand is NULL.
* @throws IllegalArgumentException If the given operand is not a string.
*/
public final void setTargetUnit(final ADQLOperand targetUnit) throws NullPointerException, IllegalArgumentException {
if (targetUnit == null)
throw new NullPointerException("The 2nd argument of the ADQL function " + FCT_NAME + " (i.e. target unit) must be non-NULL!");
if (!targetUnit.isString())
throw new IllegalArgumentException("The 2nd argument of the ADQL function " + FCT_NAME + " (i.e. target unit) must be of type VARCHAR (i.e. a string)!");
this.targetUnit = targetUnit;
}
@Override
public final boolean isNumeric() {
return true;
}
@Override
public final boolean isString() {
return false;
}
@Override
public final boolean isGeometry() {
return false;
}
@Override
public String getName() {
return FCT_NAME;
}
@Override
public LanguageFeature getFeatureDescription() {
return FEATURE;
}
@Override
public ADQLObject getCopy() throws Exception {
return new UnitConversionFunction((ADQLOperand)value.getCopy(), (ADQLOperand)targetUnit.getCopy());
}
@Override
public int getNbParameters() {
return 2;
}
@Override
public ADQLOperand[] getParameters() {
return new ADQLOperand[]{ value, targetUnit };
}
@Override
public ADQLOperand getParameter(int index) throws ArrayIndexOutOfBoundsException {
if (index < 0 || index >= getNbParameters())
throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + FCT_NAME + "\" (nb required params = " + getNbParameters() + ")!");
switch(index) {
case 0:
return value;
case 1:
return targetUnit;
default:
return null;
}
}
@Override
public ADQLOperand setParameter(int index, ADQLOperand replacer) throws ArrayIndexOutOfBoundsException, NullPointerException, Exception {
if (index < 0 || index >= getNbParameters())
throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + FCT_NAME + "\" (nb required params = " + getNbParameters() + ")!");
else if (replacer == null)
throw new NullPointerException("Impossible to remove any parameter from the " + FCT_NAME + " function! All parameters are required!");
else {
ADQLOperand replaced = null;
switch(index) {
case 0:
replaced = value;
setValue(replacer);
setPosition(null);
break;
case 1:
replaced = targetUnit;
setTargetUnit(replacer);
setPosition(null);
break;
}
return replaced;
}
}
}
...@@ -64,15 +64,16 @@ public class LowerFunction extends ADQLFunction { ...@@ -64,15 +64,16 @@ public class LowerFunction extends ADQLFunction {
* Builds a LOWER function with its parameter. * Builds a LOWER function with its parameter.
* *
* @param param Parameter of LOWER. * @param param Parameter of LOWER.
* @throws NullPointerException If the given operand is NULL *
* or if it's not a string parameter. * @throws NullPointerException If the given operand is NULL.
* @throws IllegalArgumentException If the operand is not a string parameter.
*/ */
public LowerFunction(final ADQLOperand strParam) { public LowerFunction(final ADQLOperand strParam) throws NullPointerException, IllegalArgumentException {
if (strParam == null) if (strParam == null)
throw new NullPointerException("The function " + FCT_NAME + " must have one non-NULL parameter!"); throw new NullPointerException("The function " + FCT_NAME + " must have one non-NULL parameter!");
if (!strParam.isString()) if (!strParam.isString())
throw new NullPointerException("The ADQL function " + FCT_NAME + " must have one parameter of type VARCHAR (i.e. a String)!"); throw new IllegalArgumentException("The ADQL function " + FCT_NAME + " must have one parameter of type VARCHAR (i.e. a String)!");
this.strParam = strParam; this.strParam = strParam;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment