Commit 73630130 authored by gmantele's avatar gmantele
Browse files

[ADQL] Fix return type of some math. functions for MS-SQLServer.

In MS-SQLServer, the following functions return a value of the same
type as the given argument:
  - abs
  - ceiling
  - degrees
  - floor
  - radians
  - round.

Since ADQL requires that these functions return a DOUBLE
(i.e. a float in MS-SQLServer), it must be ensured that the given
argument is a float.

This commit partially fixes the Pull Request #16
parent a382b251
Loading
Loading
Loading
Loading
+51 −16
Original line number Diff line number Diff line
@@ -16,12 +16,21 @@ package adql.translator;
 * 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 2016 - Astronomisches Rechen Institut (ARI)
 * Copyright 2016-2017 - Astronomisches Rechen Institut (ARI)
 */

import adql.db.*;
import java.util.ArrayList;
import java.util.Iterator;

import adql.db.DBChecker;
import adql.db.DBColumn;
import adql.db.DBTable;
import adql.db.DBType;
import adql.db.DBType.DBDatatype;
import adql.db.DefaultDBColumn;
import adql.db.DefaultDBTable;
import adql.db.STCS.Region;
import adql.db.SearchColumnList;
import adql.db.exception.UnresolvedJoinException;
import adql.parser.ADQLParser;
import adql.parser.ParseException;
@@ -32,10 +41,18 @@ import adql.query.IdentifierField;
import adql.query.from.ADQLJoin;
import adql.query.operand.ADQLColumn;
import adql.query.operand.function.MathFunction;
import adql.query.operand.function.geometry.*;

import java.util.ArrayList;
import java.util.Iterator;
import adql.query.operand.function.geometry.AreaFunction;
import adql.query.operand.function.geometry.BoxFunction;
import adql.query.operand.function.geometry.CentroidFunction;
import adql.query.operand.function.geometry.CircleFunction;
import adql.query.operand.function.geometry.ContainsFunction;
import adql.query.operand.function.geometry.DistanceFunction;
import adql.query.operand.function.geometry.ExtractCoord;
import adql.query.operand.function.geometry.ExtractCoordSys;
import adql.query.operand.function.geometry.IntersectsFunction;
import adql.query.operand.function.geometry.PointFunction;
import adql.query.operand.function.geometry.PolygonFunction;
import adql.query.operand.function.geometry.RegionFunction;

/**
 * <p>MS SQL Server translator.</p>
@@ -59,7 +76,7 @@ import java.util.Iterator;
 * </i></p>
 * 
 * @author Gr&eacute;gory Mantelet (ARI)
 * @version 1.4 (03/2016)
 * @version 1.4 (09/2017)
 * @since 1.4
 * 
 * @see SQLServer_ADQLQueryFactory
@@ -137,9 +154,12 @@ public class SQLServerTranslator extends JDBCTranslator {
		return field == null ? false : field.isCaseSensitive(caseSensitivity);
	}

	/* For SQL Server, translate(ADQLQuery) must be overridden for TOP/LIMIT handling.
	 * We must not add "LIMIT" at the end of the query, it must go in select.
	 * @see adql.translator.ADQLTranslator#translate(adql.query.ADQLQuery)
	/**
	 * For SQL Server, {@link #translate(ClauseSelect)} must be overridden for
	 * TOP/LIMIT handling. We must not add the LIMIT at the end of the query, it
	 * must go in the SELECT.
	 * 
	 * @see #translate(ClauseSelect)
	 */
	@Override
	public String translate(ADQLQuery query) throws TranslationException{
@@ -162,10 +182,6 @@ public class SQLServerTranslator extends JDBCTranslator {
		return sql.toString();
	}

	/* For SQL Server, translate(ClauseSelect) must be overridden for TOP/LIMIT handling.
	 * We must not add "LIMIT" at the end of the query, it must go in select.
	 * @see adql.translator.ADQLTranslator#translate(adql.query.ClauseSelect)
	 */
	@Override
	public String translate(ClauseSelect clause) throws TranslationException{
		String sql = null;
@@ -323,11 +339,30 @@ public class SQLServerTranslator extends JDBCTranslator {
		switch(fct.getType()){
			case TRUNCATE:
				// third argument to round nonzero means do a truncate
				return "round(" + ((fct.getNbParameters() >= 2) ? (translate(fct.getParameter(0)) + ", " + translate(fct.getParameter(1))) : "") + ",1)";
				return "round(convert(float, " + ((fct.getNbParameters() >= 2) ? (translate(fct.getParameter(0)) + ", " + translate(fct.getParameter(1))) : "") + "),1)";
			case MOD:
				return ((fct.getNbParameters() >= 2) ? (translate(fct.getParameter(0)) + "% " + translate(fct.getParameter(1))) : "");
				return ((fct.getNbParameters() >= 2) ? ("convert(float, " + translate(fct.getParameter(0)) + ") % convert(float, " + translate(fct.getParameter(1)) + ")") : "");
			case ATAN2:
				return "ATN2(" + translate(fct.getParameter(0)) + ", " + translate(fct.getParameter(1)) + ")";

			/* In MS-SQLServer, the following functions returns a value of the
			 * same type as the given argument. However, ADQL requires that an
			 * SQLServer float (so a double in ADQL) is returned. So, in order
			 * to follow the ADQL standard, the given parameter must be
			 * converted into a float: */
			case ABS:
				return "abs(convert(float, " + translate(fct.getParameter(0)) + "))";
			case CEILING:
				return "ceiling(convert(float, " + translate(fct.getParameter(0)) + "))";
			case DEGREES:
				return "degrees(convert(float, " + translate(fct.getParameter(0)) + "))";
			case FLOOR:
				return "floor(convert(float, " + translate(fct.getParameter(0)) + "))";
			case RADIANS:
				return "radians(convert(float, " + translate(fct.getParameter(0)) + "))";
			case ROUND:
				return "round(convert(float, " + translate(fct.getParameter(0)) + ")" + ", " + translate(fct.getParameter(1)) + ")";

			default:
				return getDefaultADQLFunction(fct);
		}