diff --git a/src/adql/translator/JDBCTranslator.java b/src/adql/translator/JDBCTranslator.java
index 6ea5ae34cf0004bff883ad533d3e344de516f3ff..362e67c9e8843a4c47490a2a3c5c4fd0ea9e85f8 100644
--- a/src/adql/translator/JDBCTranslator.java
+++ b/src/adql/translator/JDBCTranslator.java
@@ -167,7 +167,7 @@ import adql.query.operand.function.geometry.RegionFunction;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (ARI)
- * @version 1.3 (11/2014)
+ * @version 2.0 (02/2015)
  * @since 1.3
  * 
  * @see PostgreSQLTranslator
@@ -232,15 +232,40 @@ public abstract class JDBCTranslator implements ADQLTranslator {
 	 * 
 	 * @return	The qualified (with DB catalog and schema prefix if any, and with double quotes if needed) DB table name,
 	 *        	or an empty string if the given table is NULL or if there is no DB name.
+	 * 
+	 * @see #getTableName(DBTable, boolean)
 	 */
 	public String getQualifiedTableName(final DBTable table){
+		return getTableName(table, true);
+	}
+
+	/**
+	 * <p>Get the DB name of the given table.
+	 * The second parameter lets specify whether the table name must be prefixed by the qualified schema name or not.</p>
+	 * 
+	 * <p><i>Note:
+	 * 	This function will, by default, add double quotes if the table name must be case sensitive in the SQL query.
+	 * 	This information is provided by {@link #isCaseSensitive(IdentifierField)}.
+	 * </i></p>
+	 * 
+	 * @param table			The table whose the DB name is asked.
+	 * @param withSchema	<i>true</i> if the qualified schema name must prefix the table name, <i>false</i> otherwise. 
+	 * 
+	 * @return	The DB table name (prefixed by the qualified schema name if asked, and with double quotes if needed),
+	 *        	or an empty string if the given table is NULL or if there is no DB name.
+	 * 
+	 * @since 2.0
+	 */
+	public String getTableName(final DBTable table, final boolean withSchema){
 		if (table == null)
 			return "";
 
-		StringBuffer buf = new StringBuffer(getQualifiedSchemaName(table));
-		if (buf.length() > 0)
-			buf.append('.');
-
+		StringBuffer buf = new StringBuffer();
+		if (withSchema){
+			buf.append(getQualifiedSchemaName(table));
+			if (buf.length() > 0)
+				buf.append('.');
+		}
 		appendIdentifier(buf, table.getDBName(), IdentifierField.TABLE);
 
 		return buf.toString();
diff --git a/src/tap/data/VOTableIterator.java b/src/tap/data/VOTableIterator.java
index e60d5a84d8a6d433367abc30b64a2cbd59f643d2..f659dccb621bfce0015885ae5af0aec69e43d1cb 100644
--- a/src/tap/data/VOTableIterator.java
+++ b/src/tap/data/VOTableIterator.java
@@ -23,7 +23,7 @@ import adql.db.DBType;
  * <p>{@link #getColType()} will return TAP type based on the type declared in the VOTable metadata part.</p>
  * 
  * @author Gr&eacute;gory Mantelet (ARI)
- * @version 2.0 (12/2014)
+ * @version 2.0 (02/2015)
  * @since 2.0
  */
 public class VOTableIterator implements TableIterator {
@@ -42,7 +42,7 @@ public class VOTableIterator implements TableIterator {
 	 * </p> 
 	 * 
 	 * @author Gr&eacute;gory Mantelet (ARI)
-	 * @version 2.0 (12/2014)
+	 * @version 2.0 (01/2015)
 	 * @since 2.0
 	 */
 	protected static class StreamVOTableSink implements TableSink {
@@ -288,34 +288,6 @@ public class VOTableIterator implements TableIterator {
 			return (value != null) ? value.getValue().toString() : null;
 		}
 
-		/**
-		 * Resolve a VOTable field type by using the datatype, arraysize and xtype strings as specified in a VOTable document.
-		 * 
-		 * @param datatype		Attribute value of VOTable corresponding to the datatype.
-		 * @param arraysize		Attribute value of VOTable corresponding to the arraysize.
-		 * @param xtype			Attribute value of VOTable corresponding to the xtype.
-		 * 
-		 * @return	The resolved VOTable field type, or a CHAR(*) type if the specified type can not be resolved.
-		 * 
-		 * @throws DataReadException	If a field datatype is unknown.
-		 */
-		protected VotType resolveVotType(final String datatype, final String arraysize, final String xtype) throws DataReadException{
-			// If no datatype is specified, return immediately a CHAR(*) type:
-			if (datatype == null || datatype.trim().length() == 0)
-				return new VotType(VotDatatype.CHAR, "*");
-
-			// Identify the specified datatype:
-			VotDatatype votdatatype;
-			try{
-				votdatatype = VotDatatype.valueOf(datatype.toUpperCase());
-			}catch(IllegalArgumentException iae){
-				throw new DataReadException("unknown field datatype: \"" + datatype + "\"");
-			}
-
-			// Build the VOTable type:
-			return new VotType(votdatatype, arraysize, xtype);
-		}
-
 	}
 
 	/** Stream containing the VOTable on which this {@link TableIterator} is iterating. */
@@ -458,4 +430,32 @@ public class VOTableIterator implements TableIterator {
 			throw new IllegalStateException("End of VOTable file already reached!");
 	}
 
+	/**
+	 * Resolve a VOTable field type by using the datatype, arraysize and xtype strings as specified in a VOTable document.
+	 * 
+	 * @param datatype		Attribute value of VOTable corresponding to the datatype.
+	 * @param arraysize		Attribute value of VOTable corresponding to the arraysize.
+	 * @param xtype			Attribute value of VOTable corresponding to the xtype.
+	 * 
+	 * @return	The resolved VOTable field type, or a CHAR(*) type if the specified type can not be resolved.
+	 * 
+	 * @throws DataReadException	If a field datatype is unknown.
+	 */
+	public static VotType resolveVotType(final String datatype, final String arraysize, final String xtype) throws DataReadException{
+		// If no datatype is specified, return immediately a CHAR(*) type:
+		if (datatype == null || datatype.trim().length() == 0)
+			return new VotType(VotDatatype.CHAR, "*");
+
+		// Identify the specified datatype:
+		VotDatatype votdatatype;
+		try{
+			votdatatype = VotDatatype.valueOf(datatype.toUpperCase());
+		}catch(IllegalArgumentException iae){
+			throw new DataReadException("unknown field datatype: \"" + datatype + "\"");
+		}
+
+		// Build the VOTable type:
+		return new VotType(votdatatype, arraysize, xtype);
+	}
+
 }
diff --git a/src/tap/db/JDBCConnection.java b/src/tap/db/JDBCConnection.java
index 8a69226f308e906e6b4462102a78f1068a6607aa..07210e903a0e3d5ebd27db9bb80f9730af73ac71 100644
--- a/src/tap/db/JDBCConnection.java
+++ b/src/tap/db/JDBCConnection.java
@@ -121,7 +121,7 @@ import adql.translator.TranslationException;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (01/2015)
+ * @version 2.0 (02/2015)
  * @since 2.0
  */
 public class JDBCConnection implements DBConnection {
@@ -138,6 +138,9 @@ public class JDBCConnection implements DBConnection {
 	/** DBMS name of Oracle used in the database URL. */
 	protected final static String DBMS_ORACLE = "oracle";
 
+	/** Name of the database column giving the database name of a TAP column, table or schema. */
+	protected final static String DB_NAME_COLUMN = "dbname";
+
 	/** Connection ID (typically, the job ID). It lets identify the DB errors linked to the Job execution in the logs. */
 	protected final String ID;
 
@@ -321,8 +324,10 @@ public class JDBCConnection implements DBConnection {
 		// Build a connection to the specified database:
 		try{
 			Properties p = new Properties();
-			p.setProperty("user", dbUser);
-			p.setProperty("password", dbPassword);
+			if (dbUser != null)
+				p.setProperty("user", dbUser);
+			if (dbPassword != null)
+				p.setProperty("password", dbPassword);
 			Connection con = d.connect(url, p);
 			return con;
 		}catch(SQLException se){
@@ -464,15 +469,7 @@ public class JDBCConnection implements DBConnection {
 		TAPMetadata metadata = new TAPMetadata();
 
 		// Get the definition of the standard TAP_SCHEMA tables:
-		TAPSchema tap_schema = TAPMetadata.getStdSchema();
-
-		// If schemas are not supported by the DBMS connection, the schema must not be translated in the DB:
-		if (!supportsSchema){
-			String namePrefix = getTablePrefix(tap_schema.getADQLName());
-			tap_schema.setDBName(null);
-			for(TAPTable t : tap_schema)
-				t.setDBName(namePrefix + t.getDBName());
-		}
+		TAPSchema tap_schema = TAPMetadata.getStdSchema(supportsSchema);
 
 		// LOAD ALL METADATA FROM THE STANDARD TAP TABLES:
 		Statement stmt = null;
@@ -527,26 +524,29 @@ public class JDBCConnection implements DBConnection {
 	protected void loadSchemas(final TAPTable tableDef, final TAPMetadata metadata, final Statement stmt) throws DBException{
 		ResultSet rs = null;
 		try{
+			// Determine whether the dbName column exists:
+			/* note: if the schema notion is not supported by this DBMS, the column "dbname" is ignored. */
+			boolean hasDBName = supportsSchema && isColumnExisting(tableDef.getDBSchemaName(), tableDef.getDBName(), DB_NAME_COLUMN, connection.getMetaData());
+
 			// Build the SQL query:
 			StringBuffer sqlBuf = new StringBuffer("SELECT ");
 			sqlBuf.append(translator.getColumnName(tableDef.getColumn("schema_name")));
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("description")));
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("utype")));
-			sqlBuf.append(" FROM ").append(translator.getQualifiedTableName(tableDef)).append(';');
+			if (hasDBName)
+				sqlBuf.append(", ").append(DB_NAME_COLUMN);
+			sqlBuf.append(" FROM ").append(translator.getTableName(tableDef, supportsSchema)).append(';');
 
 			// Execute the query:
 			rs = stmt.executeQuery(sqlBuf.toString());
 
 			// Create all schemas:
 			while(rs.next()){
-				String schemaName = rs.getString(1), description = rs.getString(2), utype = rs.getString(3);
+				String schemaName = rs.getString(1), description = rs.getString(2), utype = rs.getString(3), dbName = (hasDBName ? rs.getString(4) : null);
 
 				// create the new schema:
 				TAPSchema newSchema = new TAPSchema(schemaName, nullifyIfNeeded(description), nullifyIfNeeded(utype));
-
-				// If schemas are not supported by the DBMS connection, the schema must not be translated in the DB:
-				if (!supportsSchema)
-					newSchema.setDBName(null);
+				newSchema.setDBName(dbName);
 
 				// add the new schema inside the given metadata:
 				metadata.addSchema(newSchema);
@@ -586,6 +586,9 @@ public class JDBCConnection implements DBConnection {
 	protected List<TAPTable> loadTables(final TAPTable tableDef, final TAPMetadata metadata, final Statement stmt) throws DBException{
 		ResultSet rs = null;
 		try{
+			// Determine whether the dbName column exists:
+			boolean hasDBName = isColumnExisting(tableDef.getDBSchemaName(), tableDef.getDBName(), DB_NAME_COLUMN, connection.getMetaData());
+
 			// Build the SQL query:
 			StringBuffer sqlBuf = new StringBuffer("SELECT ");
 			sqlBuf.append(translator.getColumnName(tableDef.getColumn("schema_name")));
@@ -593,7 +596,9 @@ public class JDBCConnection implements DBConnection {
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("table_type")));
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("description")));
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("utype")));
-			sqlBuf.append(" FROM ").append(translator.getQualifiedTableName(tableDef)).append(';');
+			if (hasDBName)
+				sqlBuf.append(", ").append(DB_NAME_COLUMN);
+			sqlBuf.append(" FROM ").append(translator.getTableName(tableDef, supportsSchema)).append(';');
 
 			// Execute the query:
 			rs = stmt.executeQuery(sqlBuf.toString());
@@ -601,7 +606,7 @@ public class JDBCConnection implements DBConnection {
 			// Create all tables:
 			ArrayList<TAPTable> lstTables = new ArrayList<TAPTable>();
 			while(rs.next()){
-				String schemaName = rs.getString(1), tableName = rs.getString(2), typeStr = rs.getString(3), description = rs.getString(4), utype = rs.getString(5);
+				String schemaName = rs.getString(1), tableName = rs.getString(2), typeStr = rs.getString(3), description = rs.getString(4), utype = rs.getString(5), dbName = (hasDBName ? rs.getString(6) : null);
 
 				// get the schema:
 				TAPSchema schema = metadata.getSchema(schemaName);
@@ -611,6 +616,19 @@ public class JDBCConnection implements DBConnection {
 					throw new DBException("Impossible to find the schema of the table \"" + tableName + "\": \"" + schemaName + "\"!");
 				}
 
+				// If the table name is qualified, check its prefix (it must match to the schema name):
+				int endPrefix = tableName.indexOf('.');
+				if (endPrefix >= 0){
+					if (endPrefix == 0)
+						throw new DBException("Incorrect table name syntax: \"" + tableName + "\"! Missing schema name (before '.').");
+					else if (endPrefix == tableName.length() - 1)
+						throw new DBException("Incorrect table name syntax: \"" + tableName + "\"! Missing table name (after '.').");
+					else if (schemaName == null)
+						throw new DBException("Incorrect schema prefix for the table \"" + tableName.substring(endPrefix + 1) + "\": this table is not in a schema, according to the column \"schema_name\" of TAP_SCHEMA.tables!");
+					else if (!tableName.substring(0, endPrefix).trim().equalsIgnoreCase(schemaName))
+						throw new DBException("Incorrect schema prefix for the table \"" + schemaName + "." + tableName.substring(tableName.indexOf('.') + 1) + "\": " + tableName + "! Mismatch between the schema specified in prefix of the column \"table_name\" and in the column \"schema_name\".");
+				}
+
 				// resolve the table type (if any) ; by default, it will be "table":
 				TableType type = TableType.table;
 				if (typeStr != null){
@@ -621,10 +639,7 @@ public class JDBCConnection implements DBConnection {
 
 				// create the new table:
 				TAPTable newTable = new TAPTable(tableName, type, nullifyIfNeeded(description), nullifyIfNeeded(utype));
-
-				// If schemas are not supported by the DBMS connection, the DB table name must be prefixed by the schema name:
-				if (!supportsSchema)
-					newTable.setDBName(getTablePrefix(schema.getADQLName()) + newTable.getDBName());
+				newTable.setDBName(dbName);
 
 				// add the new table inside its corresponding schema:
 				schema.addTable(newTable);
@@ -658,6 +673,9 @@ public class JDBCConnection implements DBConnection {
 	protected void loadColumns(final TAPTable tableDef, final List<TAPTable> lstTables, final Statement stmt) throws DBException{
 		ResultSet rs = null;
 		try{
+			// Determine whether the dbName column exists:
+			boolean hasDBName = isColumnExisting(tableDef.getDBSchemaName(), tableDef.getDBName(), DB_NAME_COLUMN, connection.getMetaData());
+
 			// Build the SQL query:
 			StringBuffer sqlBuf = new StringBuffer("SELECT ");
 			sqlBuf.append(translator.getColumnName(tableDef.getColumn("table_name")));
@@ -671,14 +689,16 @@ public class JDBCConnection implements DBConnection {
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("principal")));
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("indexed")));
 			sqlBuf.append(", ").append(translator.getColumnName(tableDef.getColumn("std")));
-			sqlBuf.append(" FROM ").append(translator.getQualifiedTableName(tableDef)).append(';');
+			if (hasDBName)
+				sqlBuf.append(", ").append(DB_NAME_COLUMN);
+			sqlBuf.append(" FROM ").append(translator.getTableName(tableDef, supportsSchema)).append(';');
 
 			// Execute the query:
 			rs = stmt.executeQuery(sqlBuf.toString());
 
 			// Create all tables:
 			while(rs.next()){
-				String tableName = rs.getString(1), columnName = rs.getString(2), description = rs.getString(3), unit = rs.getString(4), ucd = rs.getString(5), utype = rs.getString(6), datatype = rs.getString(7);
+				String tableName = rs.getString(1), columnName = rs.getString(2), description = rs.getString(3), unit = rs.getString(4), ucd = rs.getString(5), utype = rs.getString(6), datatype = rs.getString(7), dbName = (hasDBName ? rs.getString(12) : null);
 				int size = rs.getInt(8);
 				boolean principal = toBoolean(rs.getObject(9)), indexed = toBoolean(rs.getObject(10)), std = toBoolean(rs.getObject(11));
 
@@ -710,6 +730,7 @@ public class JDBCConnection implements DBConnection {
 				newColumn.setPrincipal(principal);
 				newColumn.setIndexed(indexed);
 				newColumn.setStd(std);
+				newColumn.setDBName(dbName);
 
 				// add the new column inside its corresponding table:
 				table.addColumn(newColumn);
@@ -747,7 +768,7 @@ public class JDBCConnection implements DBConnection {
 			sqlBuf.append(translator.getColumnName(keyColumnsDef.getColumn("key_id")));
 			sqlBuf.append(", ").append(translator.getColumnName(keyColumnsDef.getColumn("from_column")));
 			sqlBuf.append(", ").append(translator.getColumnName(keyColumnsDef.getColumn("target_column")));
-			sqlBuf.append(" FROM ").append(translator.getQualifiedTableName(keyColumnsDef));
+			sqlBuf.append(" FROM ").append(translator.getTableName(keyColumnsDef, supportsSchema));
 			sqlBuf.append(" WHERE ").append(translator.getColumnName(keyColumnsDef.getColumn("key_id"))).append(" = ?").append(';');
 			keyColumnsStmt = connection.prepareStatement(sqlBuf.toString());
 
@@ -758,7 +779,7 @@ public class JDBCConnection implements DBConnection {
 			sqlBuf.append(", ").append(translator.getColumnName(keysDef.getColumn("target_table")));
 			sqlBuf.append(", ").append(translator.getColumnName(keysDef.getColumn("description")));
 			sqlBuf.append(", ").append(translator.getColumnName(keysDef.getColumn("utype")));
-			sqlBuf.append(" FROM ").append(translator.getQualifiedTableName(keysDef)).append(';');
+			sqlBuf.append(" FROM ").append(translator.getTableName(keysDef, supportsSchema)).append(';');
 
 			// Execute the query:
 			rs = stmt.executeQuery(sqlBuf.toString());
@@ -953,12 +974,7 @@ public class JDBCConnection implements DBConnection {
 		if (tapSchema == null){
 
 			// build a new TAP_SCHEMA definition based on the standard definition:
-			tapSchema = TAPMetadata.getStdSchema();
-
-			/* if the schemas are not supported with this DBMS,
-			 * remove its DB name: */
-			if (!supportsSchema)
-				tapSchema.setDBName(null);
+			tapSchema = TAPMetadata.getStdSchema(supportsSchema);
 
 			// add the new TAP_SCHEMA definition in the given metadata object:
 			metadata.addSchema(tapSchema);
@@ -970,10 +986,8 @@ public class JDBCConnection implements DBConnection {
 
 			// CASE: no custom definition:
 			if (customStdTables[i] == null){
-				/* if the schemas are not supported with this DBMS,
-				 * prefix the DB name with "tap_schema_": */
 				if (!supportsSchema)
-					stdTables[i].setDBName(getTablePrefix(tapSchema.getADQLName()) + stdTables[i].getDBName());
+					stdTables[i].setDBName(STDSchema.TAPSCHEMA.label + "_" + stdTables[i].getADQLName());
 				// add the table to the fetched or built-in schema:
 				tapSchema.addTable(stdTables[i]);
 			}
@@ -1003,7 +1017,7 @@ public class JDBCConnection implements DBConnection {
 		DatabaseMetaData dbMeta = connection.getMetaData();
 
 		// 1. Get the qualified DB schema name:
-		String dbSchemaName = stdTables[0].getDBSchemaName();
+		String dbSchemaName = (supportsSchema ? stdTables[0].getDBSchemaName() : null);
 
 		/* 2. Test whether the schema TAP_SCHEMA exists
 		 *    and if it does not, create it: */
@@ -1080,6 +1094,11 @@ public class JDBCConnection implements DBConnection {
 	 * 	this function will do nothing and will throw an exception.
 	 * </i></p>
 	 * 
+	 * <p><i>Note:
+	 * 	An extra column is added in TAP_SCHEMA.schemas, TAP_SCHEMA.tables and TAP_SCHEMA.columns: {@value #DB_NAME_COLUMN}.
+	 * 	This column is particularly used when getting the TAP metadata from the database to alias some schema, table and/or column names in ADQL. 
+	 * </i></p>
+	 * 
 	 * @param table	Table to create.
 	 * @param stmt	Statement to use in order to interact with the database.
 	 * 
@@ -1095,7 +1114,7 @@ public class JDBCConnection implements DBConnection {
 		StringBuffer sql = new StringBuffer("CREATE TABLE ");
 
 		// a. Write the fully qualified table name:
-		sql.append(translator.getQualifiedTableName(table));
+		sql.append(translator.getTableName(table, supportsSchema));
 
 		// b. List all the columns:
 		sql.append('(');
@@ -1114,6 +1133,10 @@ public class JDBCConnection implements DBConnection {
 				sql.append(',');
 		}
 
+		// b bis. Add the extra dbName column (giving the database name of a schema, table or column): 
+		if ((supportsSchema && table.getADQLName().equalsIgnoreCase(STDTable.SCHEMAS.label)) || table.getADQLName().equalsIgnoreCase(STDTable.TABLES.label) || table.getADQLName().equalsIgnoreCase(STDTable.COLUMNS.label))
+			sql.append(',').append(DB_NAME_COLUMN).append(" VARCHAR");
+
 		// c. Append the primary key definition, if needed:
 		String primaryKey = getPrimaryKeyDef(table.getADQLName());
 		if (primaryKey != null)
@@ -1179,7 +1202,7 @@ public class JDBCConnection implements DBConnection {
 			throw new DBException("Forbidden index creation: " + table + " is not a standard table of TAP_SCHEMA!");
 
 		// Build the fully qualified DB name of the table: 
-		final String dbTableName = translator.getQualifiedTableName(table);
+		final String dbTableName = translator.getTableName(table, supportsSchema);
 
 		// Build the name prefix of all the indexes to create: 
 		final String indexNamePrefix = "INDEX_" + ((table.getADQLSchemaName() != null) ? (table.getADQLSchemaName() + "_") : "") + table.getADQLName() + "_";
@@ -1268,11 +1291,15 @@ public class JDBCConnection implements DBConnection {
 
 		// Build the SQL update query:
 		StringBuffer sql = new StringBuffer("INSERT INTO ");
-		sql.append(translator.getQualifiedTableName(metaTable)).append(" (");
+		sql.append(translator.getTableName(metaTable, supportsSchema)).append(" (");
 		sql.append(translator.getColumnName(metaTable.getColumn("schema_name")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("description")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("utype")));
-		sql.append(") VALUES (?, ?, ?);");
+		if (supportsSchema){
+			sql.append(", ").append(DB_NAME_COLUMN);
+			sql.append(") VALUES (?, ?, ?, ?);");
+		}else
+			sql.append(") VALUES (?, ?, ?);");
 
 		// Prepare the statement:
 		PreparedStatement stmt = null;
@@ -1292,6 +1319,8 @@ public class JDBCConnection implements DBConnection {
 				stmt.setString(1, schema.getADQLName());
 				stmt.setString(2, schema.getDescription());
 				stmt.setString(3, schema.getUtype());
+				if (supportsSchema)
+					stmt.setString(4, (schema.getDBName() == null || schema.getDBName().equals(schema.getADQLName())) ? null : schema.getDBName());
 				executeUpdate(stmt, nbRows);
 			}
 			executeBatchUpdates(stmt, nbRows);
@@ -1323,13 +1352,14 @@ public class JDBCConnection implements DBConnection {
 
 		// Build the SQL update query:
 		StringBuffer sql = new StringBuffer("INSERT INTO ");
-		sql.append(translator.getQualifiedTableName(metaTable)).append(" (");
+		sql.append(translator.getTableName(metaTable, supportsSchema)).append(" (");
 		sql.append(translator.getColumnName(metaTable.getColumn("schema_name")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("table_name")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("table_type")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("description")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("utype")));
-		sql.append(") VALUES (?, ?, ?, ?, ?);");
+		sql.append(", ").append(DB_NAME_COLUMN);
+		sql.append(") VALUES (?, ?, ?, ?, ?, ?);");
 
 		// Prepare the statement:
 		PreparedStatement stmt = null;
@@ -1347,10 +1377,14 @@ public class JDBCConnection implements DBConnection {
 
 				// add the table entry into the DB:
 				stmt.setString(1, table.getADQLSchemaName());
-				stmt.setString(2, table.getADQLName());
+				if (table.isInitiallyQualified())
+					stmt.setString(2, table.getADQLSchemaName() + "." + table.getADQLName());
+				else
+					stmt.setString(2, table.getADQLName());
 				stmt.setString(3, table.getType().toString());
 				stmt.setString(4, table.getDescription());
 				stmt.setString(5, table.getUtype());
+				stmt.setString(6, (table.getDBName() == null || table.getDBName().equals(table.getADQLName())) ? null : table.getDBName());
 				executeUpdate(stmt, nbRows);
 			}
 			executeBatchUpdates(stmt, nbRows);
@@ -1382,7 +1416,7 @@ public class JDBCConnection implements DBConnection {
 
 		// Build the SQL update query:
 		StringBuffer sql = new StringBuffer("INSERT INTO ");
-		sql.append(translator.getQualifiedTableName(metaTable)).append(" (");
+		sql.append(translator.getTableName(metaTable, supportsSchema)).append(" (");
 		sql.append(translator.getColumnName(metaTable.getColumn("table_name")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("column_name")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("description")));
@@ -1394,7 +1428,8 @@ public class JDBCConnection implements DBConnection {
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("principal")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("indexed")));
 		sql.append(", ").append(translator.getColumnName(metaTable.getColumn("std")));
-		sql.append(") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
+		sql.append(", ").append(DB_NAME_COLUMN);
+		sql.append(") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
 
 		// Prepare the statement:
 		PreparedStatement stmt = null;
@@ -1411,7 +1446,10 @@ public class JDBCConnection implements DBConnection {
 				appendAllInto(allKeys, col.getTargets());
 
 				// add the column entry into the DB:
-				stmt.setString(1, col.getTable().getADQLName());
+				if (!(col.getTable() instanceof TAPTable) || ((TAPTable)col.getTable()).isInitiallyQualified())
+					stmt.setString(1, col.getTable().getADQLSchemaName() + "." + col.getTable().getADQLName());
+				else
+					stmt.setString(1, col.getTable().getADQLName());
 				stmt.setString(2, col.getADQLName());
 				stmt.setString(3, col.getDescription());
 				stmt.setString(4, col.getUnit());
@@ -1422,6 +1460,7 @@ public class JDBCConnection implements DBConnection {
 				stmt.setInt(9, col.isPrincipal() ? 1 : 0);
 				stmt.setInt(10, col.isIndexed() ? 1 : 0);
 				stmt.setInt(11, col.isStd() ? 1 : 0);
+				stmt.setString(12, (col.getDBName() == null || col.getDBName().equals(col.getADQLName())) ? null : col.getDBName());
 				executeUpdate(stmt, nbRows);
 			}
 			executeBatchUpdates(stmt, nbRows);
@@ -1450,7 +1489,7 @@ public class JDBCConnection implements DBConnection {
 	private void fillKeys(final TAPTable metaKeys, final TAPTable metaKeyColumns, final Iterator<TAPForeignKey> itKeys) throws SQLException, DBException{
 		// Build the SQL update query for KEYS:
 		StringBuffer sqlKeys = new StringBuffer("INSERT INTO ");
-		sqlKeys.append(translator.getQualifiedTableName(metaKeys)).append(" (");
+		sqlKeys.append(translator.getTableName(metaKeys, supportsSchema)).append(" (");
 		sqlKeys.append(translator.getColumnName(metaKeys.getColumn("key_id")));
 		sqlKeys.append(", ").append(translator.getColumnName(metaKeys.getColumn("from_table")));
 		sqlKeys.append(", ").append(translator.getColumnName(metaKeys.getColumn("target_table")));
@@ -1465,7 +1504,7 @@ public class JDBCConnection implements DBConnection {
 
 			// Build the SQL update query for KEY_COLUMNS:
 			StringBuffer sqlKeyCols = new StringBuffer("INSERT INTO ");
-			sqlKeyCols.append(translator.getQualifiedTableName(metaKeyColumns)).append(" (");
+			sqlKeyCols.append(translator.getTableName(metaKeyColumns, supportsSchema)).append(" (");
 			sqlKeyCols.append(translator.getColumnName(metaKeyColumns.getColumn("key_id")));
 			sqlKeyCols.append(", ").append(translator.getColumnName(metaKeyColumns.getColumn("from_column")));
 			sqlKeyCols.append(", ").append(translator.getColumnName(metaKeyColumns.getColumn("target_column")));
@@ -1482,8 +1521,14 @@ public class JDBCConnection implements DBConnection {
 
 				// add the key entry into KEYS:
 				stmtKeys.setString(1, key.getKeyId());
-				stmtKeys.setString(2, key.getFromTable().getFullName());
-				stmtKeys.setString(3, key.getTargetTable().getFullName());
+				if (key.getFromTable().isInitiallyQualified())
+					stmtKeys.setString(2, key.getFromTable().getADQLSchemaName() + "." + key.getFromTable().getADQLName());
+				else
+					stmtKeys.setString(2, key.getFromTable().getADQLName());
+				if (key.getTargetTable().isInitiallyQualified())
+					stmtKeys.setString(3, key.getTargetTable().getADQLSchemaName() + "." + key.getTargetTable().getADQLName());
+				else
+					stmtKeys.setString(3, key.getTargetTable().getADQLName());
 				stmtKeys.setString(4, key.getDescription());
 				stmtKeys.setString(5, key.getUtype());
 				executeUpdate(stmtKeys, nbKeys);
@@ -1558,7 +1603,7 @@ public class JDBCConnection implements DBConnection {
 			}
 			// 1bis. Ensure the table does not already exist and if it is the case, throw an understandable exception:
 			else if (isTableExisting(tableDef.getDBSchemaName(), tableDef.getDBName(), dbMeta)){
-				DBException de = new DBException("Impossible to create the user uploaded table in the database: " + translator.getQualifiedTableName(tableDef) + "! This table already exists.");
+				DBException de = new DBException("Impossible to create the user uploaded table in the database: " + translator.getTableName(tableDef, supportsSchema) + "! This table already exists.");
 				if (logger != null)
 					logger.logDB(LogLevel.ERROR, this, "ADD_UPLOAD_TABLE", de.getMessage(), de);
 				throw de;
@@ -1567,7 +1612,7 @@ public class JDBCConnection implements DBConnection {
 			// 2. Create the table:
 			// ...build the SQL query:
 			StringBuffer sqlBuf = new StringBuffer("CREATE TABLE ");
-			sqlBuf.append(translator.getQualifiedTableName(tableDef)).append(" (");
+			sqlBuf.append(translator.getTableName(tableDef, supportsSchema)).append(" (");
 			Iterator<TAPColumn> it = tableDef.getColumns();
 			while(it.hasNext()){
 				TAPColumn col = it.next();
@@ -1591,15 +1636,15 @@ public class JDBCConnection implements DBConnection {
 
 			// Log the end:
 			if (logger != null)
-				logger.logDB(LogLevel.INFO, this, "TABLE_CREATED", "Table \"" + tableDef.getADQLName() + "\" (in DB: " + translator.getQualifiedTableName(tableDef) + ") created.", null);
+				logger.logDB(LogLevel.INFO, this, "TABLE_CREATED", "Table \"" + tableDef.getADQLName() + "\" (in DB: " + translator.getTableName(tableDef, supportsSchema) + ") created.", null);
 
 			return true;
 
 		}catch(SQLException se){
 			rollback();
 			if (logger != null)
-				logger.logDB(LogLevel.WARNING, this, "ADD_UPLOAD_TABLE", "Impossible to create the uploaded table: " + translator.getQualifiedTableName(tableDef) + "!", se);
-			throw new DBException("Impossible to create the uploaded table: " + translator.getQualifiedTableName(tableDef) + "!", se);
+				logger.logDB(LogLevel.WARNING, this, "ADD_UPLOAD_TABLE", "Impossible to create the uploaded table: " + translator.getTableName(tableDef, supportsSchema) + "!", se);
+			throw new DBException("Impossible to create the uploaded table: " + translator.getTableName(tableDef, supportsSchema) + "!", se);
 		}catch(DBException de){
 			rollback();
 			throw de;
@@ -1638,7 +1683,7 @@ public class JDBCConnection implements DBConnection {
 		StringBuffer sql = new StringBuffer("INSERT INTO ");
 		StringBuffer varParam = new StringBuffer();
 		// ...table name:
-		sql.append(translator.getQualifiedTableName(metaTable)).append(" (");
+		sql.append(translator.getTableName(metaTable, supportsSchema)).append(" (");
 		// ...list of columns:
 		TAPColumn[] cols = data.getMetadata();
 		for(int c = 0; c < cols.length; c++){
@@ -1744,23 +1789,23 @@ public class JDBCConnection implements DBConnection {
 
 			// Execute the update:
 			stmt = connection.createStatement();
-			int cnt = stmt.executeUpdate("DROP TABLE " + translator.getQualifiedTableName(tableDef) + ";");
+			int cnt = stmt.executeUpdate("DROP TABLE " + translator.getTableName(tableDef, supportsSchema) + ";");
 
 			// Log the end:
 			if (logger != null){
-				if (cnt == 0)
-					logger.logDB(LogLevel.INFO, this, "TABLE_DROPPED", "Table \"" + tableDef.getADQLName() + "\" (in DB: " + translator.getQualifiedTableName(tableDef) + ") dropped.", null);
+				if (cnt >= 0)
+					logger.logDB(LogLevel.INFO, this, "TABLE_DROPPED", "Table \"" + tableDef.getADQLName() + "\" (in DB: " + translator.getTableName(tableDef, supportsSchema) + ") dropped.", null);
 				else
-					logger.logDB(LogLevel.ERROR, this, "TABLE_DROPPED", "Table \"" + tableDef.getADQLName() + "\" (in DB: " + translator.getQualifiedTableName(tableDef) + ") NOT dropped.", null);
+					logger.logDB(LogLevel.ERROR, this, "TABLE_DROPPED", "Table \"" + tableDef.getADQLName() + "\" (in DB: " + translator.getTableName(tableDef, supportsSchema) + ") NOT dropped.", null);
 			}
 
 			// Ensure the update is successful:
-			return (cnt == 0);
+			return (cnt >= 0);
 
 		}catch(SQLException se){
 			if (logger != null)
-				logger.logDB(LogLevel.WARNING, this, "DROP_UPLOAD_TABLE", "Impossible to drop the uploaded table: " + translator.getQualifiedTableName(tableDef) + "!", se);
-			throw new DBException("Impossible to drop the uploaded table: " + translator.getQualifiedTableName(tableDef) + "!", se);
+				logger.logDB(LogLevel.WARNING, this, "DROP_UPLOAD_TABLE", "Impossible to drop the uploaded table: " + translator.getTableName(tableDef, supportsSchema) + "!", se);
+			throw new DBException("Impossible to drop the uploaded table: " + translator.getTableName(tableDef, supportsSchema) + "!", se);
 		}finally{
 			close(stmt);
 		}
@@ -1792,10 +1837,11 @@ public class JDBCConnection implements DBConnection {
 		if (tableDef.getSchema() == null || !tableDef.getSchema().getADQLName().equals(STDSchema.UPLOADSCHEMA.label))
 			throw new DBException("Missing upload schema! An uploaded table must be inside a schema whose the ADQL name is strictly equals to \"" + STDSchema.UPLOADSCHEMA.label + "\" (but the DB name may be different).");
 
-		// If schemas are not supported, prefix the table name and set to NULL the DB schema name:
-		if (!supportsSchema && tableDef.getDBSchemaName() != null){
-			tableDef.setDBName(getTablePrefix(tableDef.getDBSchemaName()) + tableDef.getDBName());
-			tableDef.getSchema().setDBName(null);
+		if (!supportsSchema){
+			if (tableDef.getADQLSchemaName() != null && tableDef.getADQLSchemaName().trim().length() > 0 && !tableDef.getDBName().startsWith(tableDef.getADQLSchemaName() + "_"))
+				tableDef.setDBName(tableDef.getADQLSchemaName() + "_" + tableDef.getDBName());
+			if (tableDef.getSchema() != null)
+				tableDef.getSchema().setDBName(null);
 		}
 	}
 
@@ -2156,7 +2202,7 @@ public class JDBCConnection implements DBConnection {
 
 	/**
 	 * Return NULL if the given column value is an empty string (or it just contains space characters) or NULL.
-	 * Otherwise the given given is returned as provided.
+	 * Otherwise the given string is returned as provided.
 	 * 
 	 * @param dbValue	Value to nullify if needed.
 	 * 
@@ -2226,7 +2272,7 @@ public class JDBCConnection implements DBConnection {
 	 * @throws SQLException	If any error occurs while interrogating the database about existing schema.
 	 */
 	protected boolean isSchemaExisting(String schemaName, final DatabaseMetaData dbMeta) throws SQLException{
-		if (schemaName == null || schemaName.length() == 0)
+		if (!supportsSchema || schemaName == null || schemaName.length() == 0)
 			return true;
 
 		// Determine the case sensitivity to use for the equality test:
@@ -2282,9 +2328,6 @@ public class JDBCConnection implements DBConnection {
 
 		ResultSet rs = null;
 		try{
-			// Prefix the table name by the schema name if needed (if schemas are not supported by this connection):
-			if (!supportsSchema)
-				tableName = getTablePrefix(schemaName) + tableName;
 
 			// List all matching tables:
 			if (supportsSchema){
@@ -2321,6 +2364,103 @@ public class JDBCConnection implements DBConnection {
 	}
 
 	/**
+	 * <p>Tell whether the specified column exists in the specified table of the database.
+	 * 	To do so, it is using the given {@link DatabaseMetaData} object to query the database and list all existing columns.</p>
+	 * 
+	 * <p><i><b>Important note:</b>
+	 * 	If schemas are not supported by this connection but a schema name is even though provided in parameter,
+	 * 	the table name will be prefixed by the schema name using {@link #getTablePrefix(String)}.
+	 * 	The research will then be done with NULL as schema name and this prefixed table name.
+	 * </i></p>
+	 * 
+	 * <p><i>Note:
+	 * 	Test on the schema name is done considering the case sensitivity indicated by the translator
+	 * 	(see {@link ADQLTranslator#isCaseSensitive(IdentifierField)}).
+	 * </i></p>
+	 * 
+	 * <p><i>Note:
+	 * 	This function is used by {@link #loadSchemas(TAPTable, TAPMetadata, Statement)}, {@link #loadTables(TAPTable, TAPMetadata, Statement)}
+	 * 	and {@link #loadColumns(TAPTable, List, Statement)}.
+	 * </i></p>
+	 * 
+	 * @param schemaName	DB name of the table schema. <i>MAY BE NULL</i>
+	 * @param tableName		DB name of the table containing the column to search. <i>MAY BE NULL</i>
+	 * @param columnName	DB name of the column to search.
+	 * @param dbMeta		Metadata about the database, and mainly the list of all existing tables.
+	 * 
+	 * @return	<i>true</i> if the specified column exists, <i>false</i> otherwise.
+	 * 
+	 * @throws SQLException	If any error occurs while interrogating the database about existing columns.
+	 */
+	protected boolean isColumnExisting(String schemaName, String tableName, String columnName, final DatabaseMetaData dbMeta) throws DBException, SQLException{
+		if (columnName == null || columnName.length() == 0)
+			return true;
+
+		// Determine the case sensitivity to use for the equality test:
+		boolean schemaCaseSensitive = translator.isCaseSensitive(IdentifierField.SCHEMA);
+		boolean tableCaseSensitive = translator.isCaseSensitive(IdentifierField.TABLE);
+		boolean columnCaseSensitive = translator.isCaseSensitive(IdentifierField.COLUMN);
+
+		ResultSet rsT = null, rsC = null;
+		try{
+			/* Note:
+			 * 
+			 *     The DatabaseMetaData.getColumns(....) function does not work properly
+			 * with the SQLite driver: when all parameters are set to null, meaning all columns of the database
+			 * must be returned, absolutely no rows are selected.
+			 * 
+			 *     The solution proposed here, is to first search all (matching) tables, and then for each table get
+			 * all its columns and find the matching one(s).
+			 */
+
+			// List all matching tables:
+			if (supportsSchema){
+				String schemaPattern = schemaCaseSensitive ? schemaName : null;
+				String tablePattern = tableCaseSensitive ? tableName : null;
+				rsT = dbMeta.getTables(null, schemaPattern, tablePattern, null);
+			}else{
+				String tablePattern = tableCaseSensitive ? tableName : null;
+				rsT = dbMeta.getTables(null, null, tablePattern, null);
+			}
+
+			// For each matching table:
+			int cnt = 0;
+			String columnPattern = columnCaseSensitive ? columnName : null;
+			while(rsT.next()){
+				String rsSchema = nullifyIfNeeded(rsT.getString(2));
+				String rsTable = rsT.getString(3);
+				// test the schema name:
+				if (!supportsSchema || schemaName == null || equals(rsSchema, schemaName, schemaCaseSensitive)){
+					// test the table name:
+					if ((tableName == null || equals(rsTable, tableName, tableCaseSensitive))){
+						// list its columns:
+						rsC = dbMeta.getColumns(null, rsSchema, rsTable, columnPattern);
+						// count all matching columns:
+						while(rsC.next()){
+							String rsColumn = rsC.getString(4);
+							if (equals(rsColumn, columnName, columnCaseSensitive))
+								cnt++;
+						}
+						close(rsC);
+					}
+				}
+			}
+
+			if (cnt > 1){
+				if (logger != null)
+					logger.logDB(LogLevel.ERROR, this, "COLUMN_EXIST", "More than one column match to these criteria (schema=" + schemaName + " (case sensitive?" + schemaCaseSensitive + ") && table=" + tableName + " (case sensitive?" + tableCaseSensitive + ") && column=" + columnName + " (case sensitive?" + columnCaseSensitive + "))!", null);
+				throw new DBException("More than one column match to these criteria (schema=" + schemaName + " (case sensitive?" + schemaCaseSensitive + ") && table=" + tableName + " (case sensitive?" + tableCaseSensitive + ") && column=" + columnName + " (case sensitive?" + columnCaseSensitive + "))!");
+			}
+
+			return cnt == 1;
+
+		}finally{
+			close(rsT);
+			close(rsC);
+		}
+	}
+
+	/*
 	 * <p>Build a table prefix with the given schema name.</p>
 	 * 
 	 * <p>By default, this function returns: schemaName + "_".</p>
@@ -2339,13 +2479,13 @@ public class JDBCConnection implements DBConnection {
 	 * @param schemaName	(DB) Schema name.
 	 * 
 	 * @return	The corresponding table prefix, or "" if the given schema name is an empty string or NULL.
-	 */
+	 *
 	protected String getTablePrefix(final String schemaName){
 		if (schemaName != null && schemaName.trim().length() > 0)
 			return schemaName + "_";
 		else
 			return "";
-	}
+	}*/
 
 	/**
 	 * Tell whether the specified table (using its DB name only) is a standard one or not.
diff --git a/src/tap/formatter/VOTableFormat.java b/src/tap/formatter/VOTableFormat.java
index 2a4d1ae575b764466a18097d93cf31a59cb3e64d..07c80e121bd31278e7512344fc682cc73461b70b 100644
--- a/src/tap/formatter/VOTableFormat.java
+++ b/src/tap/formatter/VOTableFormat.java
@@ -569,11 +569,11 @@ public class VOTableFormat implements OutputFormat {
 				return isScalar ? Boolean.class : boolean[].class;
 			case DOUBLE:
 				return isScalar ? Double.class : double[].class;
-			case DOUBLE_COMPLEX:
+			case DOUBLECOMPLEX:
 				return double[].class;
 			case FLOAT:
 				return isScalar ? Float.class : float[].class;
-			case FLOAT_COMPLEX:
+			case FLOATCOMPLEX:
 				return float[].class;
 			case INT:
 				return isScalar ? Integer.class : int[].class;
@@ -581,10 +581,10 @@ public class VOTableFormat implements OutputFormat {
 				return isScalar ? Long.class : long[].class;
 			case SHORT:
 				return isScalar ? Short.class : short[].class;
-			case UNSIGNED_BYTE:
+			case UNSIGNEDBYTE:
 				return isScalar ? Short.class : short[].class;
 			case CHAR:
-			case UNICODE_CHAR:
+			case UNICODECHAR:
 			default: /* If the type is not know (theoretically, never happens), return char[*] by default. */
 				return isScalar ? Character.class : String.class;
 		}
diff --git a/src/tap/log/TAPLog.java b/src/tap/log/TAPLog.java
index 2e9118f783bbb2ac933aeef0ec162d7529af62df..a332080de1400636015ce657bef61b5ec2cb2e49 100644
--- a/src/tap/log/TAPLog.java
+++ b/src/tap/log/TAPLog.java
@@ -46,6 +46,7 @@ public interface TAPLog extends UWSLog {
 	 * 	<li>CLEAN_TAP_SCHEMA</li>
 	 * 	<li>CREATE_TAP_SCHEMA</li>
 	 * 	<li>TABLE_EXIST</li>
+	 * 	<li>COLUMN_EXIST</li>
 	 * 	<li>EXEC_UPDATE</li>
 	 * 	<li>ADD_UPLOAD_TABLE</li>
 	 * 	<li>DROP_UPLOAD_TABLE</li>
diff --git a/src/tap/metadata/TAPColumn.java b/src/tap/metadata/TAPColumn.java
index 13cb81a25ce9d59dc184c3a7c9737a2ea5cc58a1..a8eaa618cd71dc92d015a437a90ebe4eb6086b61 100644
--- a/src/tap/metadata/TAPColumn.java
+++ b/src/tap/metadata/TAPColumn.java
@@ -67,7 +67,7 @@ import adql.db.DBType.DBDatatype;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (09/2014)
+ * @version 2.0 (02/2015)
  */
 public class TAPColumn implements DBColumn {
 
@@ -112,6 +112,11 @@ public class TAPColumn implements DBColumn {
 	 * <i>Note: Standard TAP column field ; FALSE by default.</i> */
 	private boolean indexed = false;
 
+	/** Flag indicating whether this column can be set to NULL in the database.
+	 * <i>Note: Standard TAP column field ; FALSE by default.</i>
+	 * @since 2.0 */
+	private boolean nullable = false;
+
 	/** Flag indicating whether this column is defined by a standard.
 	 * <i>Note: Standard TAP column field ; FALSE by default.</i> */
 	private boolean std = false;
@@ -480,6 +485,7 @@ public class TAPColumn implements DBColumn {
 	 * 
 	 * @return	Its datatype. <i>CAN'T be NULL</i>
 	 */
+	@Override
 	public final DBType getDatatype(){
 		return datatype;
 	}
@@ -534,6 +540,28 @@ public class TAPColumn implements DBColumn {
 		this.indexed = indexed;
 	}
 
+	/**
+	 * Tell whether this column is nullable.
+	 * 
+	 * @return	<i>true</i> if this column is nullable, <i>false</i> otherwise.
+	 * 
+	 * @since 2.0
+	 */
+	public final boolean isNullable(){
+		return nullable;
+	}
+
+	/**
+	 * Set whether this column is nullable or not.
+	 * 
+	 * @param  nullable	<i>true</i> if this column is nullable, <i>false</i> otherwise.
+	 * 
+	 * @since 2.0
+	 */
+	public final void setNullable(boolean nullable){
+		this.nullable = nullable;
+	}
+
 	/**
 	 * Tell whether this column is defined by a standard.
 	 * 
diff --git a/src/tap/metadata/TAPMetadata.java b/src/tap/metadata/TAPMetadata.java
index 76907843db3686640ab95949fce5c8f143cd7df7..08f329d3d45ba88a1d4018bc99982a5c6180fda4 100644
--- a/src/tap/metadata/TAPMetadata.java
+++ b/src/tap/metadata/TAPMetadata.java
@@ -23,8 +23,8 @@ package tap.metadata;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
@@ -62,7 +62,7 @@ import adql.db.DBType.DBDatatype;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (10/2014)
+ * @version 2.0 (02/2015)
  */
 public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResource {
 
@@ -100,7 +100,7 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 	 * </i></p> 
 	 */
 	public TAPMetadata(){
-		schemas = new HashMap<String,TAPSchema>();
+		schemas = new LinkedHashMap<String,TAPSchema>();
 	}
 
 	/**
@@ -456,7 +456,21 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 		response.setContentType("application/xml");
 
 		PrintWriter writer = response.getWriter();
+		write(writer);
 
+		return false;
+	}
+
+	/**
+	 * Format in XML this whole metadata set and write it in the given writer.
+	 * 
+	 * @param writer	Stream in which the XML representation of this metadata must be written.
+	 * 
+	 * @throws IOException	If there is any error while writing the XML in the given writer.
+	 * 
+	 * @since 2.0
+	 */
+	public void write(final PrintWriter writer) throws IOException{
 		writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
 
 		/* TODO The XSD schema for VOSITables should be fixed soon! This schema should be changed here before the library is released!
@@ -470,8 +484,6 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 		writer.println("</vosi:tableset>");
 
 		writer.flush();
-
-		return false;
 	}
 
 	/**
@@ -481,6 +493,7 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 	 * <pre>
 	 * &lt;schema&gt;
 	 * 	&lt;name&gt;...&lt;/name&gt;
+	 * 	&lt;title&gt;...&lt;/title&gt;
 	 * 	&lt;description&gt;...&lt;/description&gt;
 	 * 	&lt;utype&gt;...&lt;/utype&gt;
 	 * 		// call #writeTable(TAPTable, PrintWriter) for each table
@@ -503,6 +516,7 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 		writer.println("\t<schema>");
 
 		writeAtt(prefix, "name", s.getADQLName(), false, writer);
+		writeAtt(prefix, "title", s.getTitle(), true, writer);
 		writeAtt(prefix, "description", s.getDescription(), true, writer);
 		writeAtt(prefix, "utype", s.getUtype(), true, writer);
 
@@ -519,6 +533,7 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 	 * <pre>
 	 * &lt;table type="..."&gt;
 	 * 	&lt;name&gt;...&lt;/name&gt;
+	 * 	&lt;title&gt;...&lt;/title&gt;
 	 * 	&lt;description&gt;...&lt;/description&gt;
 	 * 	&lt;utype&gt;...&lt;/utype&gt;
 	 * 		// call #writeColumn(TAPColumn, PrintWriter) for each column
@@ -539,10 +554,17 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 		final String prefix = "\t\t\t";
 
 		writer.print("\t\t<table");
-		writer.print(VOSerializer.formatAttribute("type", t.getType().toString()));
+		if (t.getType() != null){
+			if (t.getType() != TableType.table)
+				writer.print(VOSerializer.formatAttribute("type", t.getType().toString()));
+		}
 		writer.println(">");
 
-		writeAtt(prefix, "name", t.getADQLName(), false, writer);
+		if (t.isInitiallyQualified())
+			writeAtt(prefix, "name", t.getADQLSchemaName() + "." + t.getADQLName(), false, writer);
+		else
+			writeAtt(prefix, "name", t.getADQLName(), false, writer);
+		writeAtt(prefix, "title", t.getTitle(), true, writer);
 		writeAtt(prefix, "description", t.getDescription(), true, writer);
 		writeAtt(prefix, "utype", t.getUtype(), true, writer);
 
@@ -586,9 +608,10 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 	private void writeColumn(TAPColumn c, PrintWriter writer) throws IOException{
 		final String prefix = "\t\t\t\t";
 
-		writer.print("\t\t\t<column std=\"");
-		writer.print(c.isStd());
-		writer.println("\">");
+		writer.print("\t\t\t<column");
+		if (c.isStd())
+			writer.print(" std=\"true\"");
+		writer.println(">");
 
 		writeAtt(prefix, "name", c.getADQLName(), false, writer);
 		writeAtt(prefix, "description", c.getDescription(), true, writer);
@@ -613,6 +636,8 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 			writeAtt(prefix, "flag", "indexed", true, writer);
 		if (c.isPrincipal())
 			writeAtt(prefix, "flag", "primary", true, writer);
+		if (c.isNullable())
+			writeAtt(prefix, "flag", "nullable", true, writer);
 
 		writer.println("\t\t\t</column>");
 	}
@@ -696,6 +721,8 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 	 * 	This function create the {@link TAPSchema} and all its {@link TAPTable}s objects on the fly.
 	 * </p>
 	 * 
+	 * @param isSchemaSupported	<i>false</i> if the DB name must be prefixed by "TAP_SCHEMA_", <i>true</i> otherwise.
+	 * 
 	 * @return	The whole TAP_SCHEMA definition.
 	 * 
 	 * @see STDSchema#TAPSCHEMA
@@ -704,10 +731,14 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour
 	 * 
 	 * @since 2.0
 	 */
-	public static final TAPSchema getStdSchema(){
+	public static final TAPSchema getStdSchema(final boolean isSchemaSupported){
 		TAPSchema tap_schema = new TAPSchema(STDSchema.TAPSCHEMA.toString(), "Set of tables listing and describing the schemas, tables and columns published in this TAP service.", null);
+		if (!isSchemaSupported)
+			tap_schema.setDBName(null);
 		for(STDTable t : STDTable.values()){
 			TAPTable table = getStdTable(t);
+			if (!isSchemaSupported)
+				table.setDBName(STDSchema.TAPSCHEMA.label + "_" + table.getADQLName());
 			tap_schema.addTable(table);
 		}
 		return tap_schema;
diff --git a/src/tap/metadata/TAPSchema.java b/src/tap/metadata/TAPSchema.java
index 984d08753af6851d6777c8a68813723ac6068704..c43b44ec35ddd945ea04675cb64ff9ddbfdbcf3a 100644
--- a/src/tap/metadata/TAPSchema.java
+++ b/src/tap/metadata/TAPSchema.java
@@ -21,8 +21,8 @@ package tap.metadata;
  */
 
 import java.awt.List;
-import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import tap.metadata.TAPTable.TableType;
@@ -44,7 +44,7 @@ import tap.metadata.TAPTable.TableType;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (08/2014)
+ * @version 2.0 (02/2015)
  */
 public class TAPSchema implements Iterable<TAPTable> {
 
@@ -55,6 +55,11 @@ public class TAPSchema implements Iterable<TAPTable> {
 	 * <i>Note: It MAY be NULL. By default, it is the ADQL name.</i> */
 	private String dbName = null;
 
+	/** Descriptive, human-interpretable name of the schema.
+	 * <i>Note: Standard TAP schema field ; MAY be NULL.</i>
+	 * @since 2.0 */
+	private String title = null;
+
 	/** Description of this schema.
 	 * <i>Note: Standard TAP schema field ; MAY be NULL.</i> */
 	private String description = null;
@@ -92,7 +97,7 @@ public class TAPSchema implements Iterable<TAPTable> {
 		int indPrefix = schemaName.lastIndexOf('.');
 		adqlName = (indPrefix >= 0) ? schemaName.substring(indPrefix + 1).trim() : schemaName.trim();
 		dbName = adqlName;
-		tables = new HashMap<String,TAPTable>();
+		tables = new LinkedHashMap<String,TAPTable>();
 	}
 
 	/**
@@ -178,6 +183,28 @@ public class TAPSchema implements Iterable<TAPTable> {
 		dbName = name;
 	}
 
+	/**
+	 * Get the title of this schema.
+	 * 
+	 * @return	Its title. <i>MAY be NULL</i>
+	 * 
+	 * @since 2.0
+	 */
+	public final String getTitle(){
+		return title;
+	}
+
+	/**
+	 * Set the title of this schema.
+	 * 
+	 * @param title	Its new title. <i>MAY be NULL</i>
+	 * 
+	 * @since 2.0
+	 */
+	public final void setTitle(final String title){
+		this.title = title;
+	}
+
 	/**
 	 * Get the description of this schema.
 	 * 
diff --git a/src/tap/metadata/TAPTable.java b/src/tap/metadata/TAPTable.java
index 9f001f323b24bc37c9eec525e3bcee1784ffe74f..f3030d0aea914e9b6340d2fec5407db949a5cf21 100644
--- a/src/tap/metadata/TAPTable.java
+++ b/src/tap/metadata/TAPTable.java
@@ -50,7 +50,7 @@ import adql.db.DBType;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (08/2014)
+ * @version 2.0 (02/2015)
  */
 public class TAPTable implements DBTable {
 
@@ -70,6 +70,11 @@ public class TAPTable implements DBTable {
 	/** Name that this table MUST have in ADQL queries. */
 	private final String adqlName;
 
+	/** <p>Indicate whether the ADQL name has been given at creation with a schema prefix or not.</p>
+	 * <p><i>Note: This information is used only when writing TAP_SCHEMA.tables or when writing the output of the resource /tables.</i></p>
+	 * @since 2.0 */
+	private boolean isInitiallyQualified;
+
 	/** Name that this table have in the database.
 	 * <i>Note: It CAN'T be NULL. By default, it is the ADQL name.</i> */
 	private String dbName = null;
@@ -84,6 +89,11 @@ public class TAPTable implements DBTable {
 	 * <i>Note: Standard TAP table field ; CAN NOT be NULL ; by default, it is "table".</i> */
 	private TableType type = TableType.table;
 
+	/** Descriptive, human-interpretable name of the table.
+	 * <i>Note: Standard TAP table field ; MAY be NULL.</i>
+	 * @since 2.0 */
+	private String title = null;
+
 	/** Description of this table.
 	 * <i>Note: Standard TAP table field ; MAY be NULL.</i> */
 	private String description = null;
@@ -125,6 +135,7 @@ public class TAPTable implements DBTable {
 			throw new NullPointerException("Missing table name !");
 		int indPrefix = tableName.lastIndexOf('.');
 		adqlName = (indPrefix >= 0) ? tableName.substring(indPrefix + 1).trim() : tableName.trim();
+		isInitiallyQualified = (indPrefix >= 0);
 		dbName = adqlName;
 		columns = new LinkedHashMap<String,TAPColumn>();
 		foreignKeys = new ArrayList<TAPForeignKey>();
@@ -217,6 +228,38 @@ public class TAPTable implements DBTable {
 		return adqlName;
 	}
 
+	/**
+	 * <p>Tells whether the ADQL name of this table must be qualified in the "table_name" column of TAP_SCHEMA.tables
+	 * and in the /schema/table/name field of the resource /tables.</p>
+	 * 
+	 * <p><i>Note: this value is set automatically by the constructor: "true" if the table name was qualified,
+	 * "false" otherwise. It can be changed with the function {@link #setInitiallyQualifed(boolean)}, BUT by doing so
+	 * you may generate a mismatch between the table name of TAP_SCHEMA.tables and the one of /tables.</i></p>
+	 * 
+	 * @return	<i>true</i> if the table name must be qualified in TAP_SCHEMA.tables and in /tables, <i>false</i> otherwise.
+	 * 
+	 * @since 2.0
+	 */
+	public final boolean isInitiallyQualified(){
+		return isInitiallyQualified;
+	}
+
+	/**
+	 * <p>Let specifying whether the table name must be qualified in TAP_SCHEMA.tables and in the resource /tables.</p>
+	 * 
+	 * <p><b>WARNING: Calling this function may generate a mismatch between the table name of TAP_SCHEMA.tables and
+	 * the one of the resource /tables. So, be sure to change this flag before setting the content of TAP_SCHEMA.tables
+	 * using {@link tap.db.JDBCConnection#setTAPSchema(TAPMetadata)}.</b></p>
+	 * 
+	 * @param mustBeQualified	<i>true</i> if the table name in TAP_SCHEMA.tables and in the resource /tables must be qualified by the schema name,
+	 *                       	<i>false</i> otherwise.
+	 * 
+	 * @since 2.0
+	 */
+	public final void setInitiallyQualifed(final boolean mustBeQualified){
+		isInitiallyQualified = mustBeQualified;
+	}
+
 	@Override
 	public final String getDBName(){
 		return dbName;
@@ -233,7 +276,8 @@ public class TAPTable implements DBTable {
 	 */
 	public final void setDBName(String name){
 		name = (name != null) ? name.trim() : name;
-		dbName = (name == null || name.length() == 0) ? adqlName : name;
+		if (name != null && name.length() > 0)
+			dbName = name;
 	}
 
 	@Override
@@ -309,6 +353,28 @@ public class TAPTable implements DBTable {
 			this.type = type;
 	}
 
+	/**
+	 * Get the title of this table.
+	 * 
+	 * @return	Its title. <i>MAY be NULL</i>
+	 * 
+	 * @since 2.0
+	 */
+	public final String getTitle(){
+		return title;
+	}
+
+	/**
+	 * Set the title of this table.
+	 * 
+	 * @param title	Its new title. <i>MAY be NULL</i>
+	 * 
+	 * @since 2.0
+	 */
+	public final void setTitle(final String title){
+		this.title = title;
+	}
+
 	/**
 	 * Get the description of this table.
 	 * 
diff --git a/src/tap/metadata/VotType.java b/src/tap/metadata/VotType.java
index 35f8babfd4e5863b573ef993d29c876975dbf742..3f27046f0f3b228cff38d61485bf2ea666a83dfd 100644
--- a/src/tap/metadata/VotType.java
+++ b/src/tap/metadata/VotType.java
@@ -20,10 +20,10 @@ package tap.metadata;
  *                       Astronomisches Rechen Institut (ARI)
  */
 
-import adql.db.DBType;
-import adql.db.DBType.DBDatatype;
 import tap.TAPException;
 import uk.ac.starlink.votable.VOSerializer;
+import adql.db.DBType;
+import adql.db.DBType.DBDatatype;
 
 /**
  * <p>Describes a full VOTable type. Thus it includes the following field attributes:</p>
@@ -34,18 +34,18 @@ import uk.ac.starlink.votable.VOSerializer;
  * </ul>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (07/2014)
+ * @version 2.0 (02/2015)
  */
 public final class VotType {
 	/**
 	 * All possible values for a VOTable datatype (i.e. boolean, short, char, ...).
 	 * 
 	 * @author Gr&eacute;gory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de
-	 * @version 2.0 (07/2014)
+	 * @version 2.0 (01/2015)
 	 * @since 2.0
 	 */
 	public static enum VotDatatype{
-		BOOLEAN("boolean"), BIT("bit"), UNSIGNED_BYTE("unsignedByte"), SHORT("short"), INT("int"), LONG("long"), CHAR("char"), UNICODE_CHAR("unicodeChar"), FLOAT("float"), DOUBLE("double"), FLOAT_COMPLEX("floatComplex"), DOUBLE_COMPLEX("doubleComplex");
+		BOOLEAN("boolean"), BIT("bit"), UNSIGNEDBYTE("unsignedByte"), SHORT("short"), INT("int"), LONG("long"), CHAR("char"), UNICODECHAR("unicodeChar"), FLOAT("float"), DOUBLE("double"), FLOATCOMPLEX("floatComplex"), DOUBLECOMPLEX("doubleComplex");
 
 		private final String strExpr;
 
@@ -164,7 +164,7 @@ public final class VotType {
 				break;
 
 			case BINARY:
-				this.datatype = VotDatatype.UNSIGNED_BYTE;
+				this.datatype = VotDatatype.UNSIGNEDBYTE;
 				this.arraysize = Integer.toString(tapType.length > 0 ? tapType.length : 1);
 				this.xtype = null;
 				break;
@@ -173,13 +173,13 @@ public final class VotType {
 				/* TODO HOW TO MANAGE VALUES WHICH WHERE ORIGINALLY NUMERIC ARRAYS ?
 				 * (cf the IVOA document TAP#Upload: votable numeric arrays should be converted into VARBINARY...no more array information and particularly the datatype)
 				 */
-				this.datatype = VotDatatype.UNSIGNED_BYTE;
+				this.datatype = VotDatatype.UNSIGNEDBYTE;
 				this.arraysize = (tapType.length > 0 ? tapType.length + "*" : "*");
 				this.xtype = null;
 				break;
 
 			case BLOB:
-				this.datatype = VotDatatype.UNSIGNED_BYTE;
+				this.datatype = VotDatatype.UNSIGNEDBYTE;
 				this.arraysize = "*";
 				this.xtype = VotType.XTYPE_BLOB;
 				break;
@@ -282,7 +282,7 @@ public final class VotType {
 				return convertNumericType(DBDatatype.DOUBLE);
 
 				/* BINARY TYPES */
-			case UNSIGNED_BYTE:
+			case UNSIGNEDBYTE:
 				// BLOB exception:
 				if (xtype != null && xtype.equalsIgnoreCase(XTYPE_BLOB))
 					return new DBType(DBDatatype.BLOB);
diff --git a/test/tap/db/JDBCConnectionTest.java b/test/tap/db/JDBCConnectionTest.java
index bd43211f3588f1efc4d473db3a4e6413f9aa2a2d..b018612580c7cc793a546908fd15d0515f62846f 100644
--- a/test/tap/db/JDBCConnectionTest.java
+++ b/test/tap/db/JDBCConnectionTest.java
@@ -98,7 +98,7 @@ public class JDBCConnectionTest {
 			TAPMetadata meta = createCustomSchema();
 			TAPTable customColumns = meta.getTable(STDSchema.TAPSCHEMA.toString(), STDTable.COLUMNS.toString());
 			TAPTable[] tapTables = conn.mergeTAPSchemaDefs(meta);
-			TAPSchema stdSchema = TAPMetadata.getStdSchema();
+			TAPSchema stdSchema = TAPMetadata.getStdSchema(conn.supportsSchema);
 			assertEquals(5, tapTables.length);
 			assertTrue(equals(tapTables[0], stdSchema.getTable(STDTable.SCHEMAS.label)));
 			assertEquals(customColumns.getSchema(), tapTables[0].getSchema());
@@ -340,22 +340,22 @@ public class JDBCConnectionTest {
 				// Prepare the test:
 				createTAPSchema(conn);
 				// Test the existence of all TAP_SCHEMA tables:
-				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.SCHEMAS.label, dbMeta));
-				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.TABLES.label, dbMeta));
-				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.COLUMNS.label, dbMeta));
-				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.KEYS.label, dbMeta));
-				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.KEY_COLUMNS.label, dbMeta));
+				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.SCHEMAS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.SCHEMAS.label), dbMeta));
+				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.TABLES.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.TABLES.label), dbMeta));
+				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.COLUMNS.label), dbMeta));
+				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEYS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEYS.label), dbMeta));
+				assertTrue(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEY_COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEY_COLUMNS.label), dbMeta));
 				// Test the non-existence of any other table:
 				assertFalse(conn.isTableExisting(null, "foo", dbMeta));
 
 				// Prepare the test:
 				dropSchema(STDSchema.TAPSCHEMA.label, conn);
 				// Test the non-existence of all TAP_SCHEMA tables:
-				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.SCHEMAS.label, dbMeta));
-				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.TABLES.label, dbMeta));
-				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.COLUMNS.label, dbMeta));
-				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.KEYS.label, dbMeta));
-				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, STDTable.KEY_COLUMNS.label, dbMeta));
+				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.SCHEMAS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.SCHEMAS.label), dbMeta));
+				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.TABLES.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.TABLES.label), dbMeta));
+				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.COLUMNS.label), dbMeta));
+				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEYS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEYS.label), dbMeta));
+				assertFalse(conn.isTableExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEY_COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEY_COLUMNS.label), dbMeta));
 			}catch(Exception ex){
 				ex.printStackTrace(System.err);
 				fail("{" + conn.getID() + "} Testing the existence of a table should not throw an error!");
@@ -363,6 +363,43 @@ public class JDBCConnectionTest {
 		}
 	}
 
+	@Test
+	public void testIsColumnExisting(){
+		// There should be no difference between a POSTGRESQL connection and a SQLITE one!
+		JDBCConnection[] connections = new JDBCConnection[]{pgJDBCConnection,sensPgJDBCConnection,sqliteJDBCConnection,sensSqliteJDBCConnection};
+		int i = -1;
+		for(JDBCConnection conn : connections){
+			i++;
+			try{
+				// Get the database metadata:
+				DatabaseMetaData dbMeta = conn.connection.getMetaData();
+
+				// Prepare the test:
+				createTAPSchema(conn);
+				// Test the existence of one column for all TAP_SCHEMA tables:
+				assertTrue(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.SCHEMAS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.SCHEMAS.label), "schema_name", dbMeta));
+				assertTrue(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.TABLES.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.TABLES.label), "table_name", dbMeta));
+				assertTrue(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.COLUMNS.label), "column_name", dbMeta));
+				assertTrue(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEYS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEYS.label), "key_id", dbMeta));
+				assertTrue(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEY_COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEY_COLUMNS.label), "key_id", dbMeta));
+				// Test the non-existence of any column:
+				assertFalse(conn.isColumnExisting(null, null, "foo", dbMeta));
+
+				// Prepare the test:
+				dropSchema(STDSchema.TAPSCHEMA.label, conn);
+				// Test the non-existence of the same column for all TAP_SCHEMA tables:
+				assertFalse(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.SCHEMAS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.SCHEMAS.label), "schema_name", dbMeta));
+				assertFalse(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.TABLES.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.TABLES.label), "table_name", dbMeta));
+				assertFalse(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.COLUMNS.label), "column_name", dbMeta));
+				assertFalse(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEYS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEYS.label), "key_id", dbMeta));
+				assertFalse(conn.isColumnExisting(STDSchema.TAPSCHEMA.label, (conn.supportsSchema ? STDTable.KEY_COLUMNS.label : STDSchema.TAPSCHEMA.label + "_" + STDTable.KEY_COLUMNS.label), "key_id", dbMeta));
+			}catch(Exception ex){
+				ex.printStackTrace(System.err);
+				fail("{" + conn.getID() + "} Testing the existence of a column should not throw an error!");
+			}
+		}
+	}
+
 	@Test
 	public void testAddUploadedTable(){
 		// There should be no difference between a POSTGRESQL connection and a SQLITE one!
@@ -427,7 +464,7 @@ public class JDBCConnectionTest {
 					assertFalse(conn.addUploadedTable(tableDef, it));
 				}catch(Exception ex){
 					if (ex instanceof DBException)
-						assertEquals("Impossible to create the user uploaded table in the database: " + conn.translator.getQualifiedTableName(tableDef) + "! This table already exists.", ex.getMessage());
+						assertEquals("Impossible to create the user uploaded table in the database: " + conn.translator.getTableName(tableDef, conn.supportsSchema) + "! This table already exists.", ex.getMessage());
 					else{
 						ex.printStackTrace(System.err);
 						fail("{" + conn.ID + "} DBException was the expected exception!");
@@ -480,24 +517,25 @@ public class JDBCConnectionTest {
 
 	@Test
 	public void testExecuteQuery(){
-		TAPSchema schema = TAPMetadata.getStdSchema();
-		ArrayList<DBTable> tables = new ArrayList<DBTable>(schema.getNbTables());
-		for(TAPTable t : schema)
-			tables.add(t);
-
-		ADQLParser parser = new ADQLParser(new DBChecker(tables));
-		parser.setDebug(false);
-
 		// There should be no difference between a POSTGRESQL connection and a SQLITE one!
 		JDBCConnection[] connections = new JDBCConnection[]{pgJDBCConnection,sensPgJDBCConnection,sqliteJDBCConnection,sensSqliteJDBCConnection};
 		for(JDBCConnection conn : connections){
-			if (conn.ID.equalsIgnoreCase("SQLITE")){
+
+			TAPSchema schema = TAPMetadata.getStdSchema(conn.supportsSchema);
+			ArrayList<DBTable> tables = new ArrayList<DBTable>(schema.getNbTables());
+			for(TAPTable t : schema)
+				tables.add(t);
+
+			ADQLParser parser = new ADQLParser(new DBChecker(tables));
+			parser.setDebug(false);
+
+			/*if (conn.ID.equalsIgnoreCase("SQLITE")){
 				for(DBTable t : tables){
 					TAPTable tapT = (TAPTable)t;
 					tapT.getSchema().setDBName(null);
 					tapT.setDBName(tapT.getSchema().getADQLName() + "_" + tapT.getDBName());
 				}
-			}
+			}*/
 
 			TableIterator result = null;
 			try{
@@ -571,6 +609,33 @@ public class JDBCConnectionTest {
 		JDBCConnectionTest.dropSchema(STDSchema.TAPSCHEMA.label, conn);
 	}
 
+	/**
+	 * <p>Build a table prefix with the given schema name.</p>
+	 * 
+	 * <p>By default, this function returns: schemaName + "_".</p>
+	 * 
+	 * <p><b>CAUTION:
+	 * 	This function is used only when schemas are not supported by the DBMS connection.
+	 * 	It aims to propose an alternative of the schema notion by prefixing the table name by the schema name.
+	 * </b></p>
+	 * 
+	 * <p><i>Note:
+	 * 	If the given schema is NULL or is an empty string, an empty string will be returned.
+	 * 	Thus, no prefix will be set....which is very useful when the table name has already been prefixed
+	 * 	(in such case, the DB name of its schema has theoretically set to NULL).
+	 * </i></p>
+	 * 
+	 * @param schemaName	(DB) Schema name.
+	 * 
+	 * @return	The corresponding table prefix, or "" if the given schema name is an empty string or NULL.
+	 */
+	protected static String getTablePrefix(final String schemaName){
+		if (schemaName != null && schemaName.trim().length() > 0)
+			return schemaName + "_";
+		else
+			return "";
+	}
+
 	private static void dropSchema(final String schemaName, final JDBCConnection conn){
 		Statement stmt = null;
 		ResultSet rs = null;
@@ -582,7 +647,7 @@ public class JDBCConnectionTest {
 				stmt.executeUpdate("DROP SCHEMA IF EXISTS " + formatIdentifier(schemaName, caseSensitive) + " CASCADE;");
 			else{
 				startTransaction(conn);
-				final String tablePrefix = conn.getTablePrefix(schemaName);
+				final String tablePrefix = getTablePrefix(schemaName);
 				final int prefixLen = tablePrefix.length();
 				if (prefixLen <= 0)
 					return;
@@ -621,20 +686,13 @@ public class JDBCConnectionTest {
 			if (conn.supportsSchema)
 				stmt.executeUpdate("DROP TABLE IF EXISTS " + formatIdentifier(schemaName, sCaseSensitive) + "." + formatIdentifier(tableName, tCaseSensitive) + ";");
 			else{
-				final String tablePrefix = conn.getTablePrefix(schemaName);
-				final int prefixLen = tablePrefix.length();
 				rs = conn.connection.getMetaData().getTables(null, null, null, null);
 				String tableToDrop = null;
 				while(rs.next()){
 					String table = rs.getString(3);
-					if (prefixLen <= 0 && equals(tableName, table, tCaseSensitive)){
+					if (equals(tableName, table, tCaseSensitive)){
 						tableToDrop = table;
 						break;
-					}else if (prefixLen > 0 && table.length() > prefixLen){
-						if (equals(schemaName, table.substring(0, prefixLen - 1), sCaseSensitive) && equals(tableName, table.substring(prefixLen + 1), tCaseSensitive)){
-							tableToDrop = table;
-							break;
-						}
 					}
 				}
 				close(rs);
@@ -680,10 +738,10 @@ public class JDBCConnectionTest {
 			final boolean sCaseSensitive = conn.translator.isCaseSensitive(IdentifierField.SCHEMA);
 			final boolean tCaseSensitive = conn.translator.isCaseSensitive(IdentifierField.TABLE);
 			String tablePrefix = formatIdentifier(schemaName, sCaseSensitive);
-			if (tablePrefix == null)
+			if (!conn.supportsSchema || tablePrefix == null)
 				tablePrefix = "";
 			else
-				tablePrefix += (conn.supportsSchema ? "." : "_");
+				tablePrefix += ".";
 			stmt = conn.connection.createStatement();
 			stmt.executeUpdate("CREATE TABLE " + tablePrefix + formatIdentifier(tableName, tCaseSensitive) + " (ID integer);");
 		}catch(Exception ex){
@@ -695,9 +753,10 @@ public class JDBCConnectionTest {
 		}
 	}
 
-	private static void createTAPSchema(final JDBCConnection conn){
+	private static TAPMetadata createTAPSchema(final JDBCConnection conn){
 		dropSchema(STDSchema.TAPSCHEMA.label, conn);
 
+		TAPMetadata metadata = new TAPMetadata();
 		Statement stmt = null;
 		try{
 			final boolean sCaseSensitive = conn.translator.isCaseSensitive(IdentifierField.SCHEMA);
@@ -708,7 +767,7 @@ public class JDBCConnectionTest {
 					tableNames[i] = formatIdentifier(STDSchema.TAPSCHEMA.label, sCaseSensitive) + "." + formatIdentifier(tableNames[i], tCaseSensitive);
 			}else{
 				for(int i = 0; i < tableNames.length; i++)
-					tableNames[i] = formatIdentifier(conn.getTablePrefix(STDSchema.TAPSCHEMA.label) + tableNames[i], tCaseSensitive);
+					tableNames[i] = formatIdentifier(getTablePrefix(STDSchema.TAPSCHEMA.label) + tableNames[i], tCaseSensitive);
 			}
 
 			startTransaction(conn);
@@ -718,13 +777,13 @@ public class JDBCConnectionTest {
 			if (conn.supportsSchema)
 				stmt.executeUpdate("CREATE SCHEMA " + formatIdentifier(STDSchema.TAPSCHEMA.label, sCaseSensitive) + ";");
 
-			stmt.executeUpdate("CREATE TABLE " + tableNames[0] + "(\"schema_name\" VARCHAR,\"description\" VARCHAR,\"utype\" VARCHAR, PRIMARY KEY(\"schema_name\"));");
+			stmt.executeUpdate("CREATE TABLE " + tableNames[0] + "(\"schema_name\" VARCHAR,\"description\" VARCHAR,\"utype\" VARCHAR,\"dbname\" VARCHAR, PRIMARY KEY(\"schema_name\"));");
 			stmt.executeUpdate("DELETE FROM " + tableNames[0] + ";");
 
-			stmt.executeUpdate("CREATE TABLE " + tableNames[1] + "(\"schema_name\" VARCHAR,\"table_name\" VARCHAR,\"table_type\" VARCHAR,\"description\" VARCHAR,\"utype\" VARCHAR, PRIMARY KEY(\"schema_name\", \"table_name\"));");
+			stmt.executeUpdate("CREATE TABLE " + tableNames[1] + "(\"schema_name\" VARCHAR,\"table_name\" VARCHAR,\"table_type\" VARCHAR,\"description\" VARCHAR,\"utype\" VARCHAR,\"dbname\" VARCHAR, PRIMARY KEY(\"schema_name\", \"table_name\"));");
 			stmt.executeUpdate("DELETE FROM " + tableNames[1] + ";");
 
-			stmt.executeUpdate("CREATE TABLE " + tableNames[2] + "(\"table_name\" VARCHAR,\"column_name\" VARCHAR,\"description\" VARCHAR,\"unit\" VARCHAR,\"ucd\" VARCHAR,\"utype\" VARCHAR,\"datatype\" VARCHAR,\"size\" INTEGER,\"principal\" INTEGER,\"indexed\" INTEGER,\"std\" INTEGER, PRIMARY KEY(\"table_name\", \"column_name\"));");
+			stmt.executeUpdate("CREATE TABLE " + tableNames[2] + "(\"table_name\" VARCHAR,\"column_name\" VARCHAR,\"description\" VARCHAR,\"unit\" VARCHAR,\"ucd\" VARCHAR,\"utype\" VARCHAR,\"datatype\" VARCHAR,\"size\" INTEGER,\"principal\" INTEGER,\"indexed\" INTEGER,\"std\" INTEGER,\"dbname\" VARCHAR, PRIMARY KEY(\"table_name\", \"column_name\"));");
 			stmt.executeUpdate("DELETE FROM " + tableNames[2] + ";");
 
 			stmt.executeUpdate("CREATE TABLE " + tableNames[3] + "(\"key_id\" VARCHAR,\"from_table\" VARCHAR,\"target_table\" VARCHAR,\"description\" VARCHAR,\"utype\" VARCHAR, PRIMARY KEY(\"key_id\"));");
@@ -733,19 +792,24 @@ public class JDBCConnectionTest {
 			stmt.executeUpdate("CREATE TABLE " + tableNames[4] + "(\"key_id\" VARCHAR,\"from_column\" VARCHAR,\"target_column\" VARCHAR, PRIMARY KEY(\"key_id\"));");
 			stmt.executeUpdate("DELETE FROM " + tableNames[4] + ";");
 
-			TAPMetadata metadata = new TAPMetadata();
-			metadata.addSchema(TAPMetadata.getStdSchema());
+			/*if (!conn.supportsSchema){
+				TAPSchema stdSchema = TAPMetadata.getStdSchema();
+				for(TAPTable t : stdSchema)
+					t.setDBName(getTablePrefix(STDSchema.TAPSCHEMA.label) + t.getADQLName());
+				metadata.addSchema(stdSchema);
+			}else*/
+			metadata.addSchema(TAPMetadata.getStdSchema(conn.supportsSchema));
 
 			ArrayList<TAPTable> lstTables = new ArrayList<TAPTable>();
 			for(TAPSchema schema : metadata){
-				stmt.executeUpdate("INSERT INTO " + tableNames[0] + " VALUES('" + schema.getADQLName() + "','" + schema.getDescription() + "','" + schema.getUtype() + "')");
+				stmt.executeUpdate("INSERT INTO " + tableNames[0] + " VALUES('" + schema.getADQLName() + "','" + schema.getDescription() + "','" + schema.getUtype() + "','" + schema.getDBName() + "')");
 				for(TAPTable t : schema)
 					lstTables.add(t);
 			}
 
 			ArrayList<DBColumn> lstCols = new ArrayList<DBColumn>();
 			for(TAPTable table : lstTables){
-				stmt.executeUpdate("INSERT INTO " + tableNames[1] + " VALUES('" + table.getADQLSchemaName() + "','" + table.getADQLName() + "','" + table.getType() + "','" + table.getDescription() + "','" + table.getUtype() + "')");
+				stmt.executeUpdate("INSERT INTO " + tableNames[1] + " VALUES('" + table.getADQLSchemaName() + "','" + table.getADQLName() + "','" + table.getType() + "','" + table.getDescription() + "','" + table.getUtype() + "','" + table.getDBName() + "')");
 				for(DBColumn c : table)
 					lstCols.add(c);
 
@@ -754,7 +818,7 @@ public class JDBCConnectionTest {
 
 			for(DBColumn c : lstCols){
 				TAPColumn col = (TAPColumn)c;
-				stmt.executeUpdate("INSERT INTO " + tableNames[2] + " VALUES('" + col.getTable().getADQLName() + "','" + col.getADQLName() + "','" + col.getDescription() + "','" + col.getUnit() + "','" + col.getUcd() + "','" + col.getUtype() + "','" + col.getDatatype().type + "'," + col.getDatatype().length + "," + (col.isPrincipal() ? 1 : 0) + "," + (col.isIndexed() ? 1 : 0) + "," + (col.isStd() ? 1 : 0) + ")");
+				stmt.executeUpdate("INSERT INTO " + tableNames[2] + " VALUES('" + col.getTable().getADQLName() + "','" + col.getADQLName() + "','" + col.getDescription() + "','" + col.getUnit() + "','" + col.getUcd() + "','" + col.getUtype() + "','" + col.getDatatype().type + "'," + col.getDatatype().length + "," + (col.isPrincipal() ? 1 : 0) + "," + (col.isIndexed() ? 1 : 0) + "," + (col.isStd() ? 1 : 0) + ",'" + col.getDBName() + "')");
 			}
 
 			commit(conn);
@@ -766,6 +830,8 @@ public class JDBCConnectionTest {
 		}finally{
 			close(stmt);
 		}
+
+		return metadata;
 	}
 
 	private static void startTransaction(final JDBCConnection conn){
@@ -956,10 +1022,10 @@ public class JDBCConnectionTest {
 			TAPSchema tapSchema = meta.getSchema(STDSchema.TAPSCHEMA.toString());
 
 			String schemaPrefix = formatIdentifier(tapSchema.getDBName(), conn.translator.isCaseSensitive(IdentifierField.SCHEMA));
-			if (schemaPrefix == null)
+			if (!conn.supportsSchema || schemaPrefix == null)
 				schemaPrefix = "";
 			else
-				schemaPrefix += (conn.supportsSchema ? "." : "_");
+				schemaPrefix += ".";
 
 			boolean tCaseSensitive = conn.translator.isCaseSensitive(IdentifierField.TABLE);
 			TAPTable tapTable = tapSchema.getTable(STDTable.SCHEMAS.toString());
diff --git a/test/tap/db/TestTAPDb.db b/test/tap/db/TestTAPDb.db
index d722315944c5da861381aede0e50b8951ae85fb2..c36006ea9746e081c41096322c5a83eae4b678d4 100644
Binary files a/test/tap/db/TestTAPDb.db and b/test/tap/db/TestTAPDb.db differ