diff --git a/src/adql/db/FunctionDef.java b/src/adql/db/FunctionDef.java
index 42e29a4edba960df837b06100fed60186fb05f5a..883de81b0ae58808878a1bc9ac601ac654c89ec6 100644
--- a/src/adql/db/FunctionDef.java
+++ b/src/adql/db/FunctionDef.java
@@ -49,7 +49,7 @@ import adql.query.operand.function.UserDefinedFunction;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (ARI)
- * @version 1.4 (07/2015)
+ * @version 1.4 (08/2015)
  * 
  * @since 1.3
  */
@@ -59,7 +59,7 @@ public class FunctionDef implements Comparable<FunctionDef> {
 	/** Rough regular expression for a function return type or a parameter type.
 	 * The exact type is not checked here ; just the type name syntax is tested, not its value.
 	 * This regular expression allows a type to have exactly one parameter (which is generally the length of a character or binary string. */
-	protected final static String typeRegExp = "([a-zA-Z]+[0-9a-zA-Z]*)(\\(\\s*([0-9]+)\\s*\\))?";
+	protected final static String typeRegExp = "([a-zA-Z]+[ 0-9a-zA-Z]*)(\\(\\s*([0-9]+)\\s*\\))?";
 	/** Rough regular expression for a function parameters' list. */
 	protected final static String fctParamsRegExp = "\\s*[^,]+\\s*(,\\s*[^,]+\\s*)*";
 	/** Rough regular expression for a function parameter: a name (see {@link #regularIdentifierRegExp}) and a type (see {@link #typeRegExp}). */
@@ -348,10 +348,12 @@ public class FunctionDef implements Comparable<FunctionDef> {
 	 * <pre>{fctName}([{param1Name} {param1Type}, ...])[ -> {returnType}]</pre>
 	 * 
 	 * <p>
-	 * 	Allowed parameter types and return types should be one the types listed by the UPLOAD section of the TAP recommendation document.
+	 * 	<em>This function must be able to parse functions as defined by TAPRegExt (section 2.3).</em>
+	 * 	Hence, allowed parameter types and return types should be one of the types listed by the UPLOAD section of the TAP recommendation document.
 	 * 	These types are listed in the enumeration object {@link DBType}.
 	 * 	However, other types should be accepted like the common database types...but it should be better to not rely on that
-	 * 	since the conversion of those types to TAP types should not be exactly what is expected.
+	 * 	since the conversion of those types to TAP types should not be exactly what is expected (because depending from the used DBMS);
+	 *  a default interpretation of database types is nevertheless processed by this parser.
 	 * </p>
 	 * 
 	 * @param strDefinition	Serialized function definition to parse.
@@ -426,7 +428,8 @@ public class FunctionDef implements Comparable<FunctionDef> {
 	 * 
 	 * @param datatype	String representation of a datatype.
 	 *                	<i>Note: This string must not contain the length parameter or any other parameter.
-	 *                	These latter should have been separated from the datatype before calling this function.</i>
+	 *                	These latter should have been separated from the datatype before calling this function.
+	 *                	It can however contain space(s) in first, last or intern position.</i>
 	 * @param length	Length of this datatype.
 	 *              	<i>Note: This length will be used only for binary (BINARY and VARBINARY)
 	 *              	and character (CHAR and VARCHAR) types.</i> 
@@ -438,6 +441,9 @@ public class FunctionDef implements Comparable<FunctionDef> {
 		if (datatype == null)
 			return null;
 
+		// Remove leading and trailing spaces and replace each inner serie of spaces by just one space:
+		datatype = datatype.trim().replaceAll(" +", " ");
+
 		try{
 			// Try to find a corresponding DBType item:
 			DBDatatype dbDatatype = DBDatatype.valueOf(datatype.toUpperCase());
@@ -456,31 +462,29 @@ public class FunctionDef implements Comparable<FunctionDef> {
 		}catch(IllegalArgumentException iae){
 			// If there's no corresponding DBType item, try to find a match among the most used DB types:
 			datatype = datatype.toLowerCase();
-			if (datatype.equals("bool") || datatype.equals("boolean") || datatype.equals("short"))
-				return new DBType(DBDatatype.SMALLINT);
-			else if (datatype.equals("int2"))
+			if (datatype.equals("bool") || datatype.equals("boolean") || datatype.equals("short") || datatype.equals("int2") || datatype.equals("smallserial") || datatype.equals("serial2"))
 				return new DBType(DBDatatype.SMALLINT);
-			else if (datatype.equals("int") || datatype.equals("int4"))
+			else if (datatype.equals("int") || datatype.equals("int4") || datatype.equals("serial") || datatype.equals("serial4"))
 				return new DBType(DBDatatype.INTEGER);
-			else if (datatype.equals("long") || datatype.equals("number") || datatype.equals("bigint") || datatype.equals("int8"))
+			else if (datatype.equals("long") || datatype.equals("number") || datatype.equals("int8") || datatype.equals("bigserial") || datatype.equals("bigserial8"))
 				return new DBType(DBDatatype.BIGINT);
 			else if (datatype.equals("float") || datatype.equals("float4"))
 				return new DBType(DBDatatype.REAL);
-			else if (datatype.equals("numeric") || datatype.equals("float8"))
+			else if (datatype.equals("numeric") || datatype.equals("float8") || datatype.equals("double precision"))
 				return new DBType(DBDatatype.DOUBLE);
-			else if (datatype.equals("byte") || datatype.equals("raw"))
+			else if (datatype.equals("bit") || datatype.equals("byte") || datatype.equals("raw"))
 				return new DBType(DBDatatype.BINARY, length);
-			else if (datatype.equals("unsignedByte"))
+			else if (datatype.equals("unsignedByte") || datatype.equals("bit varying") || datatype.equals("varbit"))
 				return new DBType(DBDatatype.VARBINARY, length);
 			else if (datatype.equals("character"))
 				return new DBType(DBDatatype.CHAR, length);
-			else if (datatype.equals("string") || datatype.equals("varchar2"))
+			else if (datatype.equals("string") || datatype.equals("varchar2") || datatype.equals("character varying"))
 				return new DBType(DBDatatype.VARCHAR, length);
 			else if (datatype.equals("bytea"))
 				return new DBType(DBDatatype.BLOB);
 			else if (datatype.equals("text"))
 				return new DBType(DBDatatype.CLOB);
-			else if (datatype.equals("date") || datatype.equals("time"))
+			else if (datatype.equals("date") || datatype.equals("time") || datatype.equals("timetz") || datatype.equals("timestamptz"))
 				return new DBType(DBDatatype.TIMESTAMP);
 			else if (datatype.equals("position"))
 				return new DBType(DBDatatype.POINT);
diff --git a/src/adql/db/exception/UnresolvedFunctionException.java b/src/adql/db/exception/UnresolvedFunctionException.java
index 4551159de43181a7323be4d509d600b1384669e7..4042537893d91c2337c89b8e10ae65529612f247 100644
--- a/src/adql/db/exception/UnresolvedFunctionException.java
+++ b/src/adql/db/exception/UnresolvedFunctionException.java
@@ -27,7 +27,7 @@ import adql.query.operand.function.ADQLFunction;
  * Exception thrown when a function can not be resolved by the library.
  * 
  * @author Gr&eacute;gory Mantelet (ARI)
- * @version 1.4 (06/2015)
+ * @version 1.4 (08/2015)
  * @since 1.3
  */
 public class UnresolvedFunctionException extends ParseException {
@@ -100,7 +100,8 @@ public class UnresolvedFunctionException extends ParseException {
 	 * 
 	 * <p><i>Note 1:
 	 * 	A parameter type can be either "NUMERIC", "STRING" or "GEOMETRY". In order to be the most generic has possible,
-	 * 	no more precision about a type is returned here. If the parameter is none of these type kinds, "???" is returned.
+	 * 	no more precision about a type is returned here. If the parameter is none of these type kinds, "param" suffixed
+	 * 	by the parameter index (e.g. "param1") is returned.
 	 * </i></p>
 	 * 
 	 * <p><i>Note 2:
@@ -118,14 +119,16 @@ public class UnresolvedFunctionException extends ParseException {
 		StringBuffer buf = new StringBuffer(fct.getName().toLowerCase());
 		buf.append('(');
 		for(int i = 0; i < fct.getNbParameters(); i++){
-			if (fct.getParameter(i).isNumeric())
+			if (fct.getParameter(i).isNumeric() && fct.getParameter(i).isString() && fct.getParameter(i).isGeometry())
+				buf.append("param").append(i + 1);
+			else if (fct.getParameter(i).isNumeric())
 				buf.append("NUMERIC");
 			else if (fct.getParameter(i).isString())
 				buf.append("STRING");
 			else if (fct.getParameter(i).isGeometry())
 				buf.append("GEOMETRY");
 			else
-				buf.append("???");
+				buf.append("param").append(i + 1);
 
 			if ((i + 1) < fct.getNbParameters())
 				buf.append(", ");
diff --git a/test/adql/db/TestDBChecker.java b/test/adql/db/TestDBChecker.java
index 36b85b792e4de94f734fafe4b5edf4973fecb2ae..64cc5229768233ba168f280e754cee3539680419 100644
--- a/test/adql/db/TestDBChecker.java
+++ b/test/adql/db/TestDBChecker.java
@@ -155,6 +155,30 @@ public class TestDBChecker {
 			assertEquals("Unresolved function: \"toto('blabla')\"! No UDF has been defined or found with the signature: toto(STRING).", ex.getErrors().next().getMessage());
 		}
 
+		// Test but with at least one column parameter:
+		try{
+			parser.parseQuery("SELECT toto(colS) FROM foo;");
+			fail("This query contains an unknown UDF signature (the fct toto is declared with no parameter): this test should have failed!");
+		}catch(ParseException e){
+			assertTrue(e instanceof UnresolvedIdentifiersException);
+			UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e;
+			assertEquals(1, ex.getNbErrors());
+			assertEquals("Unresolved function: \"toto(colS)\"! No UDF has been defined or found with the signature: toto(STRING).", ex.getErrors().next().getMessage());
+		}
+
+		// Test but with at least one unknown column parameter:
+		try{
+			parser.parseQuery("SELECT toto(whatami) FROM foo;");
+			fail("This query contains an unknown UDF signature (the fct toto is declared with no parameter): this test should have failed!");
+		}catch(ParseException e){
+			assertTrue(e instanceof UnresolvedIdentifiersException);
+			UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e;
+			assertEquals(2, ex.getNbErrors());
+			Iterator<ParseException> errors = ex.getErrors();
+			assertEquals("Unknown column \"whatami\" !", errors.next().getMessage());
+			assertEquals("Unresolved function: \"toto(whatami)\"! No UDF has been defined or found with the signature: toto(param1).", errors.next().getMessage());
+		}
+
 		// Test with a UDF whose the class is specified ; the corresponding object in the ADQL tree must be replace by an instance of this class:
 		udfs = new FunctionDef[]{new FunctionDef("toto", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("txt", new DBType(DBDatatype.VARCHAR))})};
 		udfs[0].setUDFClass(UDFToto.class);
diff --git a/test/adql/db/TestFunctionDef.java b/test/adql/db/TestFunctionDef.java
index 20ae1da3ff4c87bd0b9fc48ad7cad88e7e5b3121..1c8eb4d671e86d0f73483227fd4803390076478f 100644
--- a/test/adql/db/TestFunctionDef.java
+++ b/test/adql/db/TestFunctionDef.java
@@ -135,6 +135,20 @@ public class TestFunctionDef {
 			fail("Wrong type parsing!");
 		}
 
+		// TYPE WITH SPACES AND/OR PARAMETER test:
+		try{
+			assertEquals("foo() -> DOUBLE", FunctionDef.parse("foo() -> double precision").toString());
+			assertEquals("foo(bar DOUBLE)", FunctionDef.parse("foo(bar   DOUBLE  Precision  )").toString());
+			assertEquals("foo() -> VARCHAR", FunctionDef.parse("foo() -> character varying").toString());
+			assertEquals("foo(bar VARBINARY)", FunctionDef.parse("foo(bar bit   varying)").toString());
+			assertEquals("foo(bar VARCHAR(12))", FunctionDef.parse("foo(bar varchar  (12))").toString());
+			assertEquals("foo(bar VARCHAR(12))", FunctionDef.parse("foo(bar character varying (12))").toString());
+			assertEquals("foo() -> DOUBLE", FunctionDef.parse("foo() -> double precision (2)").toString());
+		}catch(Exception ex){
+			ex.printStackTrace(System.err);
+			fail("Wrong type parsing!");
+		}
+
 		// WRONG string definitions:
 		try{
 			FunctionDef.parse("123()");