diff --git a/src/adql/parser/feature/FeatureSet.java b/src/adql/parser/feature/FeatureSet.java
index 04b7a61544de50c57fe929e6b692b1ead2477e85..9beafbc0b2abbb50b0182ca4a62919a21efd4c80 100644
--- a/src/adql/parser/feature/FeatureSet.java
+++ b/src/adql/parser/feature/FeatureSet.java
@@ -28,6 +28,7 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 
 import adql.db.FunctionDef;
+import adql.query.constraint.ComparisonOperator;
 import adql.query.operand.function.geometry.AreaFunction;
 import adql.query.operand.function.geometry.BoxFunction;
 import adql.query.operand.function.geometry.CentroidFunction;
@@ -574,9 +575,7 @@ public class FeatureSet implements Iterable<LanguageFeature> {
 	   *                                                                    *
 	   ********************************************************************** */
 
-	/*public static final LanguageFeature ILIKE = new LanguageFeature(FeatureType.ADQL_STRING, "ILIKE"); // TODO ILIKE
-
-	public static final LanguageFeature UNION = new LanguageFeature(FeatureType.ADQL_SETS, "UNION"); // TODO UNION
+	/*public static final LanguageFeature UNION = new LanguageFeature(FeatureType.ADQL_SETS, "UNION"); // TODO UNION
 	public static final LanguageFeature EXCEPT = new LanguageFeature(FeatureType.ADQL_SETS, "EXCEPT"); // TODO EXCEPT
 	public static final LanguageFeature INTERSECT = new LanguageFeature(FeatureType.ADQL_SETS, "INTERSECT");  // TODO INTERSECT
 
@@ -603,7 +602,7 @@ public class FeatureSet implements Iterable<LanguageFeature> {
 	 * <p><i><b>Important note:</b>
 	 * 	All of them must be optional and must have a type.
 	 * </i></p> */
-	static LanguageFeature[] availableFeatures = new LanguageFeature[]{ 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[]{ 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.
diff --git a/src/adql/parser/grammar/adqlGrammar201.jj b/src/adql/parser/grammar/adqlGrammar201.jj
index 5276df35bc098592cb8aac977829611e4e9e0936..778e8a51ff45f402f1e082d13a61d4cafe203f2a 100644
--- a/src/adql/parser/grammar/adqlGrammar201.jj
+++ b/src/adql/parser/grammar/adqlGrammar201.jj
@@ -284,6 +284,7 @@ TOKEN : {
 |	< NULL: "NULL" >       { matchedToken.adqlReserved = true; }
 |	< BETWEEN: "BETWEEN" > { matchedToken.adqlReserved = true; }
 |	< LIKE: "LIKE" >       { matchedToken.adqlReserved = true; }
+|	< ILIKE: "ILIKE" >     { matchedToken.adqlReserved = true; }
 }
 TOKEN : { 
 	< IN: "IN" >         { matchedToken.adqlReserved = matchedToken.isFunctionName = true; }
@@ -1069,6 +1070,14 @@ ADQLConstraint Predicate(): {ADQLQuery q=null; ADQLColumn column=null; ADQLOpera
 		      return comp;
 		    }
 		  )
+		// ilike_predicate
+		| LOOKAHEAD(StringExpression() [<NOT>] <ILIKE>) (strExpr1=StringExpression() [notToken=<NOT>] <ILIKE> strExpr2=StringExpression()
+		    {
+		      Comparison comp = queryFactory.createComparison(strExpr1, (notToken==null)?ComparisonOperator.ILIKE:ComparisonOperator.NOTILIKE, strExpr2);
+		      comp.setPosition(new TextPosition(strExpr1.getPosition(), strExpr2.getPosition()));
+		      return comp;
+		    }
+		  )
 		| (op=ValueExpression()
 			(// comparison_predicate
 			(constraint=ComparisonEnd(op))
diff --git a/src/adql/query/constraint/ComparisonOperator.java b/src/adql/query/constraint/ComparisonOperator.java
index 4dc5c1776309b5dada1a1501fee8ad6782df04c7..02a28144bf8d6156ff680400ddb7490bc0eaa31b 100644
--- a/src/adql/query/constraint/ComparisonOperator.java
+++ b/src/adql/query/constraint/ComparisonOperator.java
@@ -26,12 +26,23 @@ import adql.query.operand.function.SQLFunction;
  * Gathers all comparison operators (numeric or not).
  *
  * @author Gr&eacute;gory Mantelet (CDS)
- * @version 2.0 (07/2019)
+ * @version 2.0 (08/2019)
  *
  * @see Comparison
  */
 public enum ComparisonOperator {
-	EQUAL, NOT_EQUAL, LESS_THAN, LESS_OR_EQUAL, GREATER_THAN, GREATER_OR_EQUAL, LIKE, NOTLIKE;
+	EQUAL,
+	NOT_EQUAL,
+	LESS_THAN,
+	LESS_OR_EQUAL,
+	GREATER_THAN,
+	GREATER_OR_EQUAL,
+	LIKE,
+	/** @since 2.0 */
+	ILIKE,
+	NOTLIKE,
+	/** @since 2.0 */
+	NOTILIKE;
 
 	/** Description of the ADQL Feature based on this type.
 	 * @since 2.0 */
@@ -39,7 +50,10 @@ public enum ComparisonOperator {
 
 	/** @since 2.0 */
 	private ComparisonOperator() {
-		FEATURE = new LanguageFeature(null, this.name(), false);
+		if (name().endsWith("ILIKE"))
+			FEATURE = new LanguageFeature(LanguageFeature.TYPE_ADQL_STRING, "ILIKE", true, "Perform a case-insensitive comparison between its string operands.");
+		else
+			FEATURE = new LanguageFeature(null, this.name(), false);
 	}
 
 	/**
@@ -75,8 +89,12 @@ public enum ComparisonOperator {
 			return GREATER_OR_EQUAL;
 		else if (str.equalsIgnoreCase("LIKE"))
 			return LIKE;
+		else if (str.equalsIgnoreCase("ILIKE"))
+			return ILIKE;
 		else if (str.equalsIgnoreCase("NOT LIKE"))
 			return NOTLIKE;
+		else if (str.equalsIgnoreCase("NOT ILIKE"))
+			return NOTILIKE;
 		else
 			throw new UnsupportedOperationException("Comparison operator unknown: \"" + str + "\" !");
 	}
@@ -97,8 +115,12 @@ public enum ComparisonOperator {
 				return ">=";
 			case LIKE:
 				return "LIKE";
+			case ILIKE:
+				return "ILIKE";
 			case NOTLIKE:
 				return "NOT LIKE";
+			case NOTILIKE:
+				return "NOT ILIKE";
 			default:
 				return "???";
 		}
diff --git a/src/adql/translator/ADQLTranslator.java b/src/adql/translator/ADQLTranslator.java
index 1174f08378a043cc8306ad4938c4972c4734c03d..66d22c6f641cde3d6d397d87e1ec07f6a8b369c7 100644
--- a/src/adql/translator/ADQLTranslator.java
+++ b/src/adql/translator/ADQLTranslator.java
@@ -2,21 +2,21 @@ package adql.translator;
 
 /*
  * 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 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2019 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -65,13 +65,14 @@ 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;
+import adql.query.operand.function.string.LowerFunction;
 
 /**
  * Translates ADQL objects into any language (i.e. SQL).
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS)
- * @version 01/2012
- * 
+ * @version 2.0 (08/2019)
+ *
  * @see PostgreSQLTranslator
  */
 public interface ADQLTranslator {
@@ -143,6 +144,9 @@ public interface ADQLTranslator {
 
 	public String translate(UserDefinedFunction fct) throws TranslationException;
 
+	/** @since 2.0 */
+	public String translate(LowerFunction fct) throws TranslationException;
+
 	/* ***** GEOMETRICAL FUNCTIONS ***** */
 	public String translate(GeometryFunction fct) throws TranslationException;
 
diff --git a/src/adql/translator/JDBCTranslator.java b/src/adql/translator/JDBCTranslator.java
index 0baa58cea6db57f703636f0015cf29b5a955f07e..7cf11859431b251d9ef332a885f1bd33d3aa6a79 100644
--- a/src/adql/translator/JDBCTranslator.java
+++ b/src/adql/translator/JDBCTranslator.java
@@ -77,6 +77,7 @@ 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;
+import adql.query.operand.function.string.LowerFunction;
 
 /**
  * Implementation of {@link ADQLTranslator} which translates ADQL queries in
@@ -89,7 +90,7 @@ import adql.query.operand.function.geometry.RegionFunction;
  * 	{@link MySQLTranslator} and {@link SQLServerTranslator} are doing.
  * </p>
  *
- * <p><i>Note:
+ * <p><i><b>Note:</b>
  * 	Its default implementation of the SQL syntax has been inspired by the
  * 	PostgreSQL one. However, it should work also with other DBMS, although some
  * 	translations might be needed (as it is has been done for PostgreSQL about
@@ -147,8 +148,8 @@ import adql.query.operand.function.geometry.RegionFunction;
  * 	translating differently: LOG, LOG10, RAND and TRUNC.
  * </p>
  *
- * <p><i>Note:
- * 	Geometrical regions and types have not been managed here. They stay abstract
+ * <p><i><b>Note:</b>
+ * 	Geometric regions and types have not been managed here. They stay abstract
  * 	because it is obviously impossible to have a generic translation and
  * 	conversion ; it totally depends from the database system.
  * </i></p>
@@ -162,7 +163,7 @@ import adql.query.operand.function.geometry.RegionFunction;
  * </p>
  *
  * @author Gr&eacute;gory Mantelet (ARI;CDS)
- * @version 1.5 (03/2019)
+ * @version 2.0 (08/2019)
  * @since 1.4
  *
  * @see PostgreSQLTranslator
@@ -203,7 +204,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 * @return	The qualified (with DB catalog name prefix if any, and with double quotes if needed) DB schema name,
 	 *        	or an empty string if there is no schema or no DB name.
 	 */
-	public String getQualifiedSchemaName(final DBTable table){
+	public String getQualifiedSchemaName(final DBTable table) {
 		if (table == null || table.getDBSchemaName() == null)
 			return "";
 
@@ -232,7 +233,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @see #getTableName(DBTable, boolean)
 	 */
-	public String getQualifiedTableName(final DBTable table){
+	public String getQualifiedTableName(final DBTable table) {
 		return getTableName(table, true);
 	}
 
@@ -253,12 +254,12 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @since 2.0
 	 */
-	public String getTableName(final DBTable table, final boolean withSchema){
+	public String getTableName(final DBTable table, final boolean withSchema) {
 		if (table == null)
 			return "";
 
 		StringBuffer buf = new StringBuffer();
-		if (withSchema){
+		if (withSchema) {
 			buf.append(getQualifiedSchemaName(table));
 			if (buf.length() > 0)
 				buf.append('.');
@@ -286,7 +287,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 * @return	The DB column name (with double quotes if needed),
 	 *        	or an empty string if the given column is NULL.
 	 */
-	public String getColumnName(final DBColumn column){
+	public String getColumnName(final DBColumn column) {
 		return (column == null) ? "" : appendIdentifier(new StringBuffer(), column.getDBName(), IdentifierField.COLUMN).toString();
 	}
 
@@ -312,7 +313,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @see #appendIdentifier(StringBuffer, String, boolean)
 	 */
-	public final StringBuffer appendIdentifier(final StringBuffer str, final String id, final IdentifierField field){
+	public final StringBuffer appendIdentifier(final StringBuffer str, final String id, final IdentifierField field) {
 		return appendIdentifier(str, id, isCaseSensitive(field));
 	}
 
@@ -325,7 +326,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @return					The string buffer + identifier.
 	 */
-	public StringBuffer appendIdentifier(final StringBuffer str, final String id, final boolean caseSensitive){
+	public StringBuffer appendIdentifier(final StringBuffer str, final String id, final boolean caseSensitive) {
 		if (caseSensitive && !id.matches("\"[^\"]*\""))
 			return str.append('"').append(id).append('"');
 		else
@@ -334,7 +335,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 
 	@Override
 	@SuppressWarnings({ "unchecked", "rawtypes" })
-	public String translate(ADQLObject obj) throws TranslationException{
+	public String translate(ADQLObject obj) throws TranslationException {
 		if (obj instanceof ADQLQuery)
 			return translate((ADQLQuery)obj);
 		else if (obj instanceof ADQLList)
@@ -356,7 +357,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ADQLQuery query) throws TranslationException{
+	public String translate(ADQLQuery query) throws TranslationException {
 		StringBuffer sql = new StringBuffer(translate(query.getSelect()));
 
 		sql.append("\nFROM ").append(translate(query.getFrom()));
@@ -383,7 +384,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	/* ****** LIST & CLAUSE ****** */
 	/* *************************** */
 	@Override
-	public String translate(ADQLList<? extends ADQLObject> list) throws TranslationException{
+	public String translate(ADQLList<? extends ADQLObject> list) throws TranslationException {
 		if (list instanceof ClauseSelect)
 			return translate((ClauseSelect)list);
 		else if (list instanceof ClauseConstraints)
@@ -412,7 +413,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @see #getDefaultADQLList(ADQLList, boolean)
 	 */
-	protected final String getDefaultADQLList(ADQLList<? extends ADQLObject> list) throws TranslationException{
+	protected final String getDefaultADQLList(ADQLList<? extends ADQLObject> list) throws TranslationException {
 		return getDefaultADQLList(list, true);
 	}
 
@@ -429,7 +430,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @since 1.4
 	 */
-	protected String getDefaultADQLList(ADQLList<? extends ADQLObject> list, final boolean withNamePrefix) throws TranslationException{
+	protected String getDefaultADQLList(ADQLList<? extends ADQLObject> list, final boolean withNamePrefix) throws TranslationException {
 		String sql = (list.getName() == null || !withNamePrefix) ? "" : (list.getName() + " ");
 
 		for(int i = 0; i < list.size(); i++)
@@ -439,13 +440,13 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ClauseSelect clause) throws TranslationException{
+	public String translate(ClauseSelect clause) throws TranslationException {
 		String sql = null;
 
-		for(int i = 0; i < clause.size(); i++){
-			if (i == 0){
+		for(int i = 0; i < clause.size(); i++) {
+			if (i == 0) {
 				sql = clause.getName() + (clause.distinctColumns() ? " DISTINCT" : "");
-			}else
+			} else
 				sql += " " + clause.getSeparator(i);
 
 			sql += " " + translate(clause.get(i));
@@ -455,7 +456,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ClauseConstraints clause) throws TranslationException{
+	public String translate(ClauseConstraints clause) throws TranslationException {
 		if (clause instanceof ConstraintsGroup)
 			return "(" + getDefaultADQLList(clause) + ")";
 		else
@@ -463,18 +464,18 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(SelectItem item) throws TranslationException{
+	public String translate(SelectItem item) throws TranslationException {
 		if (item instanceof SelectAllColumns)
 			return translate((SelectAllColumns)item);
 
 		StringBuffer translation = new StringBuffer(translate(item.getOperand()));
-		if (item.hasAlias()){
+		if (item.hasAlias()) {
 			translation.append(" AS ");
 			if (item.isCaseSensitive())
 				appendIdentifier(translation, item.getAlias(), true);
 			else
 				appendIdentifier(translation, item.getAlias().toLowerCase(), true);
-		}else{
+		} else {
 			translation.append(" AS ");
 			appendIdentifier(translation, item.getName(), true);
 		}
@@ -483,27 +484,27 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(SelectAllColumns item) throws TranslationException{
+	public String translate(SelectAllColumns item) throws TranslationException {
 		// Fetch the full list of columns to display:
 		Iterable<DBColumn> dbCols = null;
-		if (item.getAdqlTable() != null && item.getAdqlTable().getDBLink() != null){
+		if (item.getAdqlTable() != null && item.getAdqlTable().getDBLink() != null) {
 			ADQLTable table = item.getAdqlTable();
 			dbCols = table.getDBLink();
-		}else if (item.getQuery() != null){
-			try{
+		} else if (item.getQuery() != null) {
+			try {
 				dbCols = item.getQuery().getFrom().getDBColumns();
-			}catch(UnresolvedJoinException pe){
+			} catch(UnresolvedJoinException pe) {
 				throw new TranslationException("Due to a join problem, the ADQL to SQL translation can not be completed!", pe);
 			}
 		}
 
 		// Write the DB name of all these columns:
-		if (dbCols != null){
+		if (dbCols != null) {
 			StringBuffer cols = new StringBuffer();
-			for(DBColumn col : dbCols){
+			for(DBColumn col : dbCols) {
 				if (cols.length() > 0)
 					cols.append(',');
-				if (col.getTable() != null){
+				if (col.getTable() != null) {
 					if (col.getTable() instanceof DBTableAlias)
 						cols.append(getTableName(col.getTable(), false)).append('.');
 					else
@@ -513,13 +514,13 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 				cols.append(" AS \"").append(col.getADQLName()).append('\"');
 			}
 			return (cols.length() > 0) ? cols.toString() : item.toADQL();
-		}else{
+		} else {
 			return item.toADQL();
 		}
 	}
 
 	@Override
-	public String translate(ColumnReference ref) throws TranslationException{
+	public String translate(ColumnReference ref) throws TranslationException {
 		if (ref instanceof ADQLOrder)
 			return translate((ADQLOrder)ref);
 		else
@@ -535,17 +536,17 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @throws TranslationException If there is an error during the translation.
 	 */
-	protected String getDefaultColumnReference(ColumnReference ref) throws TranslationException{
-		if (ref.isIndex()){
+	protected String getDefaultColumnReference(ColumnReference ref) throws TranslationException {
+		if (ref.isIndex()) {
 			return "" + ref.getColumnIndex();
-		}else{
-			if (ref.getDBLink() == null){
+		} else {
+			if (ref.getDBLink() == null) {
 				return (ref.isCaseSensitive() ? ("\"" + ref.getColumnName() + "\"") : ref.getColumnName());
-			}else{
+			} else {
 				DBColumn dbCol = ref.getDBLink();
 				StringBuffer colName = new StringBuffer();
 				// Use the table alias if any:
-				if (ref.getAdqlTable() != null && ref.getAdqlTable().hasAlias()){
+				if (ref.getAdqlTable() != null && ref.getAdqlTable().hasAlias()) {
 					if (ref.getAdqlTable().isCaseSensitive(IdentifierField.ALIAS))
 						appendIdentifier(colName, ref.getAdqlTable().getAlias(), true).append('.');
 					else
@@ -563,7 +564,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ADQLOrder order) throws TranslationException{
+	public String translate(ADQLOrder order) throws TranslationException {
 		return getDefaultColumnReference(order) + (order.isDescSorting() ? " DESC" : " ASC");
 	}
 
@@ -571,7 +572,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	/* ****** TABLE & JOIN ****** */
 	/* ************************** */
 	@Override
-	public String translate(FromContent content) throws TranslationException{
+	public String translate(FromContent content) throws TranslationException {
 		if (content instanceof ADQLTable)
 			return translate((ADQLTable)content);
 		else if (content instanceof ADQLJoin)
@@ -581,7 +582,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ADQLTable table) throws TranslationException{
+	public String translate(ADQLTable table) throws TranslationException {
 		StringBuffer sql = new StringBuffer();
 
 		// CASE: SUB-QUERY:
@@ -589,9 +590,9 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 			sql.append('(').append(translate(table.getSubQuery())).append(')');
 
 		// CASE: TABLE REFERENCE:
-		else{
+		else {
 			// Use the corresponding DB table, if known:
-			if (table.getDBLink() != null){
+			if (table.getDBLink() != null) {
 				/* Note: if the table is aliased, the aliased table is wrapped
 				 *       inside a DBTableAlias. So, to get the real table name
 				 *       we should get first the original table thanks to
@@ -607,13 +608,13 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 		}
 
 		// Add the table alias, if any:
-		if (table.hasAlias()){
+		if (table.hasAlias()) {
 			sql.append(" AS ");
 			/* In case where metadata are known, the alias must always be
 			 * written case sensitively in order to ensure a translation
 			 * stability (i.e. all references clearly point toward this alias
 			 * whatever is their character case). */
-			if (table.getDBLink() != null){
+			if (table.getDBLink() != null) {
 				if (table.isCaseSensitive(IdentifierField.ALIAS))
 					appendIdentifier(sql, table.getAlias(), true);
 				else
@@ -628,7 +629,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ADQLJoin join) throws TranslationException{
+	public String translate(ADQLJoin join) throws TranslationException {
 		StringBuffer sql = new StringBuffer(translate(join.getLeftTable()));
 
 		if (join.isNatural())
@@ -636,13 +637,13 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 
 		sql.append(' ').append(join.getJoinType()).append(' ').append(translate(join.getRightTable())).append(' ');
 
-		if (!join.isNatural()){
+		if (!join.isNatural()) {
 			if (join.getJoinCondition() != null)
 				sql.append(translate(join.getJoinCondition()));
-			else if (join.hasJoinedColumns()){
+			else if (join.hasJoinedColumns()) {
 				StringBuffer cols = new StringBuffer();
 				Iterator<ADQLColumn> it = join.getJoinedColumns();
-				while(it.hasNext()){
+				while(it.hasNext()) {
 					ADQLColumn item = it.next();
 					if (cols.length() > 0)
 						cols.append(", ");
@@ -662,7 +663,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	/* ****** OPERAND ****** */
 	/* ********************* */
 	@Override
-	public String translate(ADQLOperand op) throws TranslationException{
+	public String translate(ADQLOperand op) throws TranslationException {
 		if (op instanceof ADQLColumn)
 			return translate((ADQLColumn)op);
 		else if (op instanceof Concatenation)
@@ -684,14 +685,14 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(ADQLColumn column) throws TranslationException{
+	public String translate(ADQLColumn column) throws TranslationException {
 		// Use its DB name if known:
-		if (column.getDBLink() != null){
+		if (column.getDBLink() != null) {
 			DBColumn dbCol = column.getDBLink();
 			StringBuffer colName = new StringBuffer();
 
 			// Use the DBTable if any:
-			if (dbCol.getTable() != null && dbCol.getTable().getDBName() != null){
+			if (dbCol.getTable() != null && dbCol.getTable().getDBName() != null) {
 				/* Note: if the table is aliased, ensure no schema is prefixing
 				 *       this alias thanks to getTableName(..., false). */
 				if (dbCol.getTable() instanceof DBTableAlias)
@@ -714,32 +715,32 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(Concatenation concat) throws TranslationException{
+	public String translate(Concatenation concat) throws TranslationException {
 		return translate((ADQLList<ADQLOperand>)concat);
 	}
 
 	@Override
-	public String translate(NegativeOperand negOp) throws TranslationException{
+	public String translate(NegativeOperand negOp) throws TranslationException {
 		return "-" + translate(negOp.getOperand());
 	}
 
 	@Override
-	public String translate(NumericConstant numConst) throws TranslationException{
+	public String translate(NumericConstant numConst) throws TranslationException {
 		return numConst.getValue();
 	}
 
 	@Override
-	public String translate(StringConstant strConst) throws TranslationException{
+	public String translate(StringConstant strConst) throws TranslationException {
 		return "'" + strConst.getValue().replaceAll("'", "''") + "'";
 	}
 
 	@Override
-	public String translate(WrappedOperand op) throws TranslationException{
+	public String translate(WrappedOperand op) throws TranslationException {
 		return "(" + translate(op.getOperand()) + ")";
 	}
 
 	@Override
-	public String translate(Operation op) throws TranslationException{
+	public String translate(Operation op) throws TranslationException {
 		return translate(op.getLeftOperand()) + op.getOperation().toADQL() + translate(op.getRightOperand());
 	}
 
@@ -747,7 +748,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	/* ****** CONSTRAINT ****** */
 	/* ************************ */
 	@Override
-	public String translate(ADQLConstraint cons) throws TranslationException{
+	public String translate(ADQLConstraint cons) throws TranslationException {
 		if (cons instanceof Comparison)
 			return translate((Comparison)cons);
 		else if (cons instanceof Between)
@@ -765,32 +766,32 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(Comparison comp) throws TranslationException{
+	public String translate(Comparison comp) throws TranslationException {
 		return translate(comp.getLeftOperand()) + " " + comp.getOperator().toADQL() + " " + translate(comp.getRightOperand());
 	}
 
 	@Override
-	public String translate(Between comp) throws TranslationException{
+	public String translate(Between comp) throws TranslationException {
 		return translate(comp.getLeftOperand()) + " " + comp.getName() + " " + translate(comp.getMinOperand()) + " AND " + translate(comp.getMaxOperand());
 	}
 
 	@Override
-	public String translate(Exists exists) throws TranslationException{
+	public String translate(Exists exists) throws TranslationException {
 		return "EXISTS(" + translate(exists.getSubQuery()) + ")";
 	}
 
 	@Override
-	public String translate(In in) throws TranslationException{
+	public String translate(In in) throws TranslationException {
 		return translate(in.getOperand()) + " " + in.getName() + " (" + (in.hasSubQuery() ? translate(in.getSubQuery()) : translate(in.getValuesList())) + ")";
 	}
 
 	@Override
-	public String translate(IsNull isNull) throws TranslationException{
+	public String translate(IsNull isNull) throws TranslationException {
 		return translate(isNull.getColumn()) + " " + isNull.getName();
 	}
 
 	@Override
-	public String translate(NotConstraint notCons) throws TranslationException{
+	public String translate(NotConstraint notCons) throws TranslationException {
 		return "NOT " + translate(notCons.getConstraint());
 	}
 
@@ -798,7 +799,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	/* ****** FUNCTIONS ****** */
 	/* *********************** */
 	@Override
-	public String translate(ADQLFunction fct) throws TranslationException{
+	public String translate(ADQLFunction fct) throws TranslationException {
 		if (fct instanceof GeometryFunction)
 			return translate((GeometryFunction)fct);
 		else if (fct instanceof MathFunction)
@@ -807,6 +808,8 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 			return translate((SQLFunction)fct);
 		else if (fct instanceof UserDefinedFunction)
 			return translate((UserDefinedFunction)fct);
+		else if (fct instanceof LowerFunction)
+			return translate((LowerFunction)fct);
 		else
 			return getDefaultADQLFunction(fct);
 	}
@@ -820,7 +823,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 *
 	 * @throws TranslationException	If there is an error during the translation.
 	 */
-	protected final String getDefaultADQLFunction(ADQLFunction fct) throws TranslationException{
+	protected final String getDefaultADQLFunction(ADQLFunction fct) throws TranslationException {
 		String sql = fct.getName() + "(";
 
 		for(int i = 0; i < fct.getNbParameters(); i++)
@@ -830,7 +833,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(SQLFunction fct) throws TranslationException{
+	public String translate(SQLFunction fct) throws TranslationException {
 		if (fct.getType() == SQLFunctionType.COUNT_ALL)
 			return "COUNT(" + (fct.isDistinct() ? "DISTINCT " : "") + "*)";
 		else
@@ -838,20 +841,25 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(MathFunction fct) throws TranslationException{
+	public String translate(MathFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(UserDefinedFunction fct) throws TranslationException{
+	public String translate(UserDefinedFunction fct) throws TranslationException {
 		return fct.translate(this);
 	}
 
+	@Override
+	public String translate(LowerFunction fct) throws TranslationException {
+		return getDefaultADQLFunction(fct);
+	}
+
 	/* *********************************** */
 	/* ****** GEOMETRICAL FUNCTIONS ****** */
 	/* *********************************** */
 	@Override
-	public String translate(GeometryFunction fct) throws TranslationException{
+	public String translate(GeometryFunction fct) throws TranslationException {
 		if (fct instanceof AreaFunction)
 			return translate((AreaFunction)fct);
 		else if (fct instanceof BoxFunction)
@@ -881,7 +889,7 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	}
 
 	@Override
-	public String translate(GeometryValue<? extends GeometryFunction> geomValue) throws TranslationException{
+	public String translate(GeometryValue<? extends GeometryFunction> geomValue) throws TranslationException {
 		return translate(geomValue.getValue());
 	}
 
diff --git a/src/adql/translator/MySQLTranslator.java b/src/adql/translator/MySQLTranslator.java
index 6d2b3ce465f7e10b6b91633addbec4ce745d413f..28ae9229f4207c041291d16dae6cf689ad7120a9 100644
--- a/src/adql/translator/MySQLTranslator.java
+++ b/src/adql/translator/MySQLTranslator.java
@@ -1,25 +1,5 @@
 package adql.translator;
 
-import adql.db.DBType;
-import adql.db.DBType.DBDatatype;
-import adql.db.STCS.Region;
-import adql.parser.grammar.ParseException;
-import adql.query.IdentifierField;
-import adql.query.operand.ADQLOperand;
-import adql.query.operand.Concatenation;
-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;
-
 /*
  * This file is part of ADQLLibrary.
  *
@@ -40,6 +20,27 @@ import adql.query.operand.function.geometry.RegionFunction;
  *                       UDS/Centre de Données astronomiques de Strasbourg (CDS)
  */
 
+import adql.db.DBType;
+import adql.db.DBType.DBDatatype;
+import adql.db.STCS.Region;
+import adql.parser.grammar.ParseException;
+import adql.query.IdentifierField;
+import adql.query.constraint.Comparison;
+import adql.query.operand.ADQLOperand;
+import adql.query.operand.Concatenation;
+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;
+
 /**
  * Translates all ADQL objects into an SQL interrogation query designed for
  * MySQL.
@@ -51,7 +52,7 @@ import adql.query.operand.function.geometry.RegionFunction;
  * </i></p>
  *
  * @author Gr&eacute;gory Mantelet (ARI;CDS)
- * @version 1.5 (03/2019)
+ * @version 2.0 (08/2019)
  * @since 1.4
  */
 public class MySQLTranslator extends JDBCTranslator {
@@ -77,7 +78,7 @@ public class MySQLTranslator extends JDBCTranslator {
 	 * schema, table and column names will be surrounded by back-quotes in the
 	 * SQL translation.
 	 */
-	public MySQLTranslator(){
+	public MySQLTranslator() {
 		caseSensitivity = 0x0F;
 	}
 
@@ -92,7 +93,7 @@ public class MySQLTranslator extends JDBCTranslator {
 	 *                        	(surrounded by back-quotes),
 	 *                        	<i>false</i> for case insensitivity.
 	 */
-	public MySQLTranslator(final boolean allCaseSensitive){
+	public MySQLTranslator(final boolean allCaseSensitive) {
 		caseSensitivity = allCaseSensitive ? (byte)0x0F : (byte)0x00;
 	}
 
@@ -109,7 +110,7 @@ public class MySQLTranslator extends JDBCTranslator {
 	 * @param column	<i>true</i> to translate column names with back-quotes
 	 *              	(case sensitive in the DBMS), <i>false</i> otherwise.
 	 */
-	public MySQLTranslator(final boolean catalog, final boolean schema, final boolean table, final boolean column){
+	public MySQLTranslator(final boolean catalog, final boolean schema, final boolean table, final boolean column) {
 		caseSensitivity = IdentifierField.CATALOG.setCaseSensitive(caseSensitivity, catalog);
 		caseSensitivity = IdentifierField.SCHEMA.setCaseSensitive(caseSensitivity, schema);
 		caseSensitivity = IdentifierField.TABLE.setCaseSensitive(caseSensitivity, table);
@@ -117,12 +118,12 @@ public class MySQLTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public boolean isCaseSensitive(final IdentifierField field){
+	public boolean isCaseSensitive(final IdentifierField field) {
 		return field == null ? false : field.isCaseSensitive(caseSensitivity);
 	}
 
 	@Override
-	public StringBuffer appendIdentifier(final StringBuffer str, final String id, final boolean caseSensitive){
+	public StringBuffer appendIdentifier(final StringBuffer str, final String id, final boolean caseSensitive) {
 		/* Note: In MySQL the identifier quoting character is a back-quote. */
 		if (caseSensitive && !id.matches("\"[^\"]*\""))
 			return str.append('`').append(id).append('`');
@@ -137,10 +138,21 @@ public class MySQLTranslator extends JDBCTranslator {
 	/* ********************************************************************** */
 
 	@Override
-	public String translate(Concatenation concat) throws TranslationException{
+	public String translate(Comparison comp) throws TranslationException {
+		switch(comp.getOperator()) {
+			case ILIKE:
+			case NOTILIKE:
+				throw new TranslationException("Translation of ILIKE impossible! This is not supported in MySQL.");
+			default:
+				return translate(comp.getLeftOperand()) + " " + comp.getOperator().toADQL() + " " + translate(comp.getRightOperand());
+		}
+	}
+
+	@Override
+	public String translate(Concatenation concat) throws TranslationException {
 		StringBuffer translated = new StringBuffer();
 
-		for(ADQLOperand op : concat){
+		for(ADQLOperand op : concat) {
 			if (translated.length() == 0)
 				translated.append("CONCAT(");
 			else
@@ -159,7 +171,7 @@ public class MySQLTranslator extends JDBCTranslator {
 	/* ********************************************************************** */
 
 	@Override
-	public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params){
+	public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params) {
 		// If no type is provided return VARCHAR:
 		if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0)
 			return null;
@@ -169,10 +181,10 @@ public class MySQLTranslator extends JDBCTranslator {
 
 		// Extract the length parameter (always the first one):
 		int lengthParam = DBType.NO_LENGTH;
-		if (params != null && params.length > 0){
-			try{
+		if (params != null && params.length > 0) {
+			try {
 				lengthParam = Integer.parseInt(params[0]);
-			}catch(NumberFormatException nfe){
+			} catch(NumberFormatException nfe) {
 			}
 		}
 
@@ -218,11 +230,11 @@ public class MySQLTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public String convertTypeToDB(final DBType type){
+	public String convertTypeToDB(final DBType type) {
 		if (type == null)
 			return "VARCHAR(" + DEFAULT_VARIABLE_LENGTH + ")";
 
-		switch(type.type){
+		switch(type.type) {
 
 			case SMALLINT:
 			case INTEGER:
@@ -254,12 +266,12 @@ public class MySQLTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public Region translateGeometryFromDB(final Object jdbcColValue) throws ParseException{
+	public Region translateGeometryFromDB(final Object jdbcColValue) throws ParseException {
 		throw new ParseException("Unsupported geometrical value! The value \"" + jdbcColValue + "\" can not be parsed as a region.");
 	}
 
 	@Override
-	public Object translateGeometryToDB(final Region region) throws ParseException{
+	public Object translateGeometryToDB(final Region region) throws ParseException {
 		throw new ParseException("Geometries can not be uploaded in the database in this implementation!");
 	}
 
@@ -270,62 +282,62 @@ public class MySQLTranslator extends JDBCTranslator {
 	/* ********************************************************************** */
 
 	@Override
-	public String translate(ExtractCoord extractCoord) throws TranslationException{
+	public String translate(ExtractCoord extractCoord) throws TranslationException {
 		return getDefaultADQLFunction(extractCoord);
 	}
 
 	@Override
-	public String translate(ExtractCoordSys extractCoordSys) throws TranslationException{
+	public String translate(ExtractCoordSys extractCoordSys) throws TranslationException {
 		return getDefaultADQLFunction(extractCoordSys);
 	}
 
 	@Override
-	public String translate(AreaFunction areaFunction) throws TranslationException{
+	public String translate(AreaFunction areaFunction) throws TranslationException {
 		return getDefaultADQLFunction(areaFunction);
 	}
 
 	@Override
-	public String translate(CentroidFunction centroidFunction) throws TranslationException{
+	public String translate(CentroidFunction centroidFunction) throws TranslationException {
 		return getDefaultADQLFunction(centroidFunction);
 	}
 
 	@Override
-	public String translate(DistanceFunction fct) throws TranslationException{
+	public String translate(DistanceFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(ContainsFunction fct) throws TranslationException{
+	public String translate(ContainsFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(IntersectsFunction fct) throws TranslationException{
+	public String translate(IntersectsFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(BoxFunction box) throws TranslationException{
+	public String translate(BoxFunction box) throws TranslationException {
 		return getDefaultADQLFunction(box);
 	}
 
 	@Override
-	public String translate(CircleFunction circle) throws TranslationException{
+	public String translate(CircleFunction circle) throws TranslationException {
 		return getDefaultADQLFunction(circle);
 	}
 
 	@Override
-	public String translate(PointFunction point) throws TranslationException{
+	public String translate(PointFunction point) throws TranslationException {
 		return getDefaultADQLFunction(point);
 	}
 
 	@Override
-	public String translate(PolygonFunction polygon) throws TranslationException{
+	public String translate(PolygonFunction polygon) throws TranslationException {
 		return getDefaultADQLFunction(polygon);
 	}
 
 	@Override
-	public String translate(RegionFunction region) throws TranslationException{
+	public String translate(RegionFunction region) throws TranslationException {
 		return getDefaultADQLFunction(region);
 	}
 
diff --git a/src/adql/translator/SQLServerTranslator.java b/src/adql/translator/SQLServerTranslator.java
index 79990dd4eb6f78ccd55d1a7097ab30c0db80894d..3a045b0d41e96fc7caeb25773128dbf00f01fbac 100644
--- a/src/adql/translator/SQLServerTranslator.java
+++ b/src/adql/translator/SQLServerTranslator.java
@@ -33,6 +33,7 @@ import adql.parser.grammar.ParseException;
 import adql.query.ADQLQuery;
 import adql.query.ClauseSelect;
 import adql.query.IdentifierField;
+import adql.query.constraint.Comparison;
 import adql.query.from.ADQLJoin;
 import adql.query.from.ADQLTable;
 import adql.query.from.FromContent;
@@ -77,7 +78,7 @@ import adql.query.operand.function.geometry.RegionFunction;
  * </i></p>
  *
  * @author Gr&eacute;gory Mantelet (ARI;CDS)
- * @version 1.5 (03/2019)
+ * @version 2.0 (08/2019)
  * @since 1.4
  *
  * @see SQLServer_ADQLQueryFactory
@@ -97,7 +98,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 	 * Builds an SQLServerTranslator which always translates in SQL all identifiers (schema, table and column) in a case sensitive manner ;
 	 * in other words, schema, table and column names will be surrounded by double quotes in the SQL translation.
 	 */
-	public SQLServerTranslator(){
+	public SQLServerTranslator() {
 		caseSensitivity = 0x0F;
 	}
 
@@ -107,7 +108,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 	 *
 	 * @param allCaseSensitive	<i>true</i> to translate all identifiers in a case sensitive manner (surrounded by double quotes), <i>false</i> for case insensitivity.
 	 */
-	public SQLServerTranslator(final boolean allCaseSensitive){
+	public SQLServerTranslator(final boolean allCaseSensitive) {
 		caseSensitivity = allCaseSensitive ? (byte)0x0F : (byte)0x00;
 	}
 
@@ -119,7 +120,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 	 * @param table		<i>true</i> to translate table names with double quotes (case sensitive in the DBMS), <i>false</i> otherwise.
 	 * @param column	<i>true</i> to translate column names with double quotes (case sensitive in the DBMS), <i>false</i> otherwise.
 	 */
-	public SQLServerTranslator(final boolean catalog, final boolean schema, final boolean table, final boolean column){
+	public SQLServerTranslator(final boolean catalog, final boolean schema, final boolean table, final boolean column) {
 		caseSensitivity = IdentifierField.CATALOG.setCaseSensitive(caseSensitivity, catalog);
 		caseSensitivity = IdentifierField.SCHEMA.setCaseSensitive(caseSensitivity, schema);
 		caseSensitivity = IdentifierField.TABLE.setCaseSensitive(caseSensitivity, table);
@@ -127,7 +128,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public boolean isCaseSensitive(final IdentifierField field){
+	public boolean isCaseSensitive(final IdentifierField field) {
 		return field == null ? false : field.isCaseSensitive(caseSensitivity);
 	}
 
@@ -139,7 +140,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 	 * @see #translate(ClauseSelect)
 	 */
 	@Override
-	public String translate(ADQLQuery query) throws TranslationException{
+	public String translate(ADQLQuery query) throws TranslationException {
 		StringBuffer sql = new StringBuffer(translate(query.getSelect()));
 
 		sql.append("\nFROM ").append(translate(query.getFrom()));
@@ -160,13 +161,13 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public String translate(ClauseSelect clause) throws TranslationException{
+	public String translate(ClauseSelect clause) throws TranslationException {
 		String sql = null;
 
-		for(int i = 0; i < clause.size(); i++){
-			if (i == 0){
+		for(int i = 0; i < clause.size(); i++) {
+			if (i == 0) {
 				sql = clause.getName() + (clause.distinctColumns() ? " DISTINCT" : "") + (clause.hasLimit() ? " TOP " + clause.getLimit() + " " : "");
-			}else
+			} else
 				sql += " " + clause.getSeparator(i);
 
 			sql += " " + translate(clause.get(i));
@@ -176,10 +177,21 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public String translate(Concatenation concat) throws TranslationException{
+	public String translate(Comparison comp) throws TranslationException {
+		switch(comp.getOperator()) {
+			case ILIKE:
+			case NOTILIKE:
+				throw new TranslationException("Translation of ILIKE impossible! This is not supported in MS-SQL Server.");
+			default:
+				return translate(comp.getLeftOperand()) + " " + comp.getOperator().toADQL() + " " + translate(comp.getRightOperand());
+		}
+	}
+
+	@Override
+	public String translate(Concatenation concat) throws TranslationException {
 		StringBuffer translated = new StringBuffer();
 
-		for(ADQLOperand op : concat){
+		for(ADQLOperand op : concat) {
 			if (translated.length() > 0)
 				translated.append(" + ");
 			translated.append(translate(op));
@@ -189,26 +201,26 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public String translate(final ADQLJoin join) throws TranslationException{
+	public String translate(final ADQLJoin join) throws TranslationException {
 		StringBuffer sql = new StringBuffer(translate(join.getLeftTable()));
 
 		sql.append(' ').append(join.getJoinType()).append(' ').append(translate(join.getRightTable())).append(' ');
 
 		// CASE: NATURAL
-		if (join.isNatural()){
-			try{
+		if (join.isNatural()) {
+			try {
 				StringBuffer buf = new StringBuffer();
 
 				// Find duplicated items between the two lists and translate them as ON conditions:
 				DBColumn rightCol;
 				SearchColumnList leftList = join.getLeftTable().getDBColumns();
 				SearchColumnList rightList = join.getRightTable().getDBColumns();
-				for(DBColumn leftCol : leftList){
+				for(DBColumn leftCol : leftList) {
 					// search for at most one column with the same name in the RIGHT list
 					// and throw an exception is there are several matches:
 					rightCol = ADQLJoin.findAtMostOneColumn(leftCol.getADQLName(), (byte)0, rightList, false);
 					// if there is one...
-					if (rightCol != null){
+					if (rightCol != null) {
 						// ...check there is only one column with this name in the LEFT list,
 						// and throw an exception if it is not the case:
 						ADQLJoin.findExactlyOneColumn(leftCol.getADQLName(), (byte)0, leftList, true);
@@ -222,13 +234,13 @@ public class SQLServerTranslator extends JDBCTranslator {
 				}
 
 				sql.append("ON ").append(buf.toString());
-			}catch(UnresolvedJoinException uje){
+			} catch(UnresolvedJoinException uje) {
 				throw new TranslationException("Impossible to resolve the NATURAL JOIN between " + join.getLeftTable().toADQL() + " and " + join.getRightTable().toADQL() + "!", uje);
 			}
 		}
 		// CASE: USING
-		else if (join.hasJoinedColumns()){
-			try{
+		else if (join.hasJoinedColumns()) {
+			try {
 				StringBuffer buf = new StringBuffer();
 
 				// For each columns of usingList, check there is in each list exactly one matching column, and then, translate it as ON condition:
@@ -237,7 +249,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 				SearchColumnList leftList = join.getLeftTable().getDBColumns();
 				SearchColumnList rightList = join.getRightTable().getDBColumns();
 				Iterator<ADQLColumn> itCols = join.getJoinedColumns();
-				while(itCols.hasNext()){
+				while(itCols.hasNext()) {
 					usingCol = itCols.next();
 					// search for exactly one column with the same name in the LEFT list
 					// and throw an exception if there is none, or if there are several matches:
@@ -253,7 +265,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 				}
 
 				sql.append("ON ").append(buf.toString());
-			}catch(UnresolvedJoinException uje){
+			} catch(UnresolvedJoinException uje) {
 				throw new TranslationException("Impossible to resolve the JOIN USING between " + join.getLeftTable().toADQL() + " and " + join.getRightTable().toADQL() + "!", uje);
 			}
 		}
@@ -278,9 +290,9 @@ public class SQLServerTranslator extends JDBCTranslator {
 	 *
 	 * @return	The generated column.
 	 */
-	protected ADQLColumn generateJoinColumn(final FromContent table, final DBColumn colMeta, final ADQLColumn joinedColumn){
+	protected ADQLColumn generateJoinColumn(final FromContent table, final DBColumn colMeta, final ADQLColumn joinedColumn) {
 		ADQLColumn newCol = (joinedColumn == null ? new ADQLColumn(colMeta.getADQLName()) : new ADQLColumn(joinedColumn));
-		if (table != null){
+		if (table != null) {
 			if (table instanceof ADQLTable)
 				newCol.setAdqlTable((ADQLTable)table);
 			else
@@ -291,68 +303,68 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public String translate(final ExtractCoord extractCoord) throws TranslationException{
+	public String translate(final ExtractCoord extractCoord) throws TranslationException {
 		return getDefaultADQLFunction(extractCoord);
 	}
 
 	@Override
-	public String translate(final ExtractCoordSys extractCoordSys) throws TranslationException{
+	public String translate(final ExtractCoordSys extractCoordSys) throws TranslationException {
 		return getDefaultADQLFunction(extractCoordSys);
 	}
 
 	@Override
-	public String translate(final AreaFunction areaFunction) throws TranslationException{
+	public String translate(final AreaFunction areaFunction) throws TranslationException {
 		return getDefaultADQLFunction(areaFunction);
 	}
 
 	@Override
-	public String translate(final CentroidFunction centroidFunction) throws TranslationException{
+	public String translate(final CentroidFunction centroidFunction) throws TranslationException {
 		return getDefaultADQLFunction(centroidFunction);
 	}
 
 	@Override
-	public String translate(final DistanceFunction fct) throws TranslationException{
+	public String translate(final DistanceFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(final ContainsFunction fct) throws TranslationException{
+	public String translate(final ContainsFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(final IntersectsFunction fct) throws TranslationException{
+	public String translate(final IntersectsFunction fct) throws TranslationException {
 		return getDefaultADQLFunction(fct);
 	}
 
 	@Override
-	public String translate(final PointFunction point) throws TranslationException{
+	public String translate(final PointFunction point) throws TranslationException {
 		return getDefaultADQLFunction(point);
 	}
 
 	@Override
-	public String translate(final CircleFunction circle) throws TranslationException{
+	public String translate(final CircleFunction circle) throws TranslationException {
 		return getDefaultADQLFunction(circle);
 	}
 
 	@Override
-	public String translate(final BoxFunction box) throws TranslationException{
+	public String translate(final BoxFunction box) throws TranslationException {
 		return getDefaultADQLFunction(box);
 	}
 
 	@Override
-	public String translate(final PolygonFunction polygon) throws TranslationException{
+	public String translate(final PolygonFunction polygon) throws TranslationException {
 		return getDefaultADQLFunction(polygon);
 	}
 
 	@Override
-	public String translate(final RegionFunction region) throws TranslationException{
+	public String translate(final RegionFunction region) throws TranslationException {
 		return getDefaultADQLFunction(region);
 	}
 
 	@Override
-	public String translate(MathFunction fct) throws TranslationException{
-		switch(fct.getType()){
+	public String translate(MathFunction fct) throws TranslationException {
+		switch(fct.getType()) {
 			case TRUNCATE:
 				// third argument to round nonzero means do a truncate
 				return "round(convert(float, " + ((fct.getNbParameters() >= 2) ? (translate(fct.getParameter(0)) + ", " + translate(fct.getParameter(1))) : "") + "),1)";
@@ -385,7 +397,7 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params){
+	public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params) {
 		// If no type is provided return VARCHAR:
 		if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0)
 			return null;
@@ -395,10 +407,10 @@ public class SQLServerTranslator extends JDBCTranslator {
 
 		// Extract the length parameter (always the first one):
 		int lengthParam = DBType.NO_LENGTH;
-		if (params != null && params.length > 0){
-			try{
+		if (params != null && params.length > 0) {
+			try {
 				lengthParam = Integer.parseInt(params[0]);
-			}catch(NumberFormatException nfe){
+			} catch(NumberFormatException nfe) {
 			}
 		}
 
@@ -444,11 +456,11 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public String convertTypeToDB(final DBType type){
+	public String convertTypeToDB(final DBType type) {
 		if (type == null)
 			return "varchar";
 
-		switch(type.type){
+		switch(type.type) {
 
 			case SMALLINT:
 			case REAL:
@@ -483,12 +495,12 @@ public class SQLServerTranslator extends JDBCTranslator {
 	}
 
 	@Override
-	public Region translateGeometryFromDB(final Object jdbcColValue) throws ParseException{
+	public Region translateGeometryFromDB(final Object jdbcColValue) throws ParseException {
 		throw new ParseException("Unsupported geometrical value! The value \"" + jdbcColValue + "\" can not be parsed as a region.");
 	}
 
 	@Override
-	public Object translateGeometryToDB(final Region region) throws ParseException{
+	public Object translateGeometryToDB(final Region region) throws ParseException {
 		throw new ParseException("Geometries can not be uploaded in the database in this implementation!");
 	}
 
diff --git a/test/adql/parser/feature/TestFeatureSet.java b/test/adql/parser/feature/TestFeatureSet.java
index fa1d4c4db5ea2fa408b77a6a716a07672214985f..6177a33bc2021740ff0017de71694d91c8359281 100644
--- a/test/adql/parser/feature/TestFeatureSet.java
+++ b/test/adql/parser/feature/TestFeatureSet.java
@@ -14,9 +14,10 @@ import org.junit.Test;
 
 import adql.db.DBType;
 import adql.db.DBType.DBDatatype;
-import adql.parser.grammar.ParseException;
 import adql.db.FunctionDef;
+import adql.parser.grammar.ParseException;
 import adql.query.ColumnReference;
+import adql.query.constraint.ComparisonOperator;
 import adql.query.operand.function.geometry.BoxFunction;
 import adql.query.operand.function.geometry.PolygonFunction;
 import adql.query.operand.function.string.LowerFunction;
@@ -179,6 +180,8 @@ public class TestFeatureSet {
 
 		/* CASE: ok (with a set containing just 1 item)
 		 *       => un-supported + no more set for the feature type! */
+		assertTrue(set.unsupport(ComparisonOperator.ILIKE.getFeatureDescription()));
+		assertEquals(1, set.supportedFeatures.get(LowerFunction.FEATURE.type).size());
 		assertTrue(set.supportedFeatures.containsKey(LowerFunction.FEATURE.type));
 		assertTrue(set.supportedFeatures.get(LowerFunction.FEATURE.type).contains(LowerFunction.FEATURE));
 		assertTrue(set.unsupport(LowerFunction.FEATURE));