Commit f496d64e authored by gmantele's avatar gmantele
Browse files

[TAP] Complete the bug fix a0e5c56f for MySQL in JDBCConnection

Now, JDBCConnection is fully capable to test the existence of schemas, tables
and columns of a MySQL database. Thanks to @zonia3000 for solving this issue.
parent a0e5c56f
Loading
Loading
Loading
Loading
+110 −22
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ package tap.db;
 * You should have received a copy of the GNU Lesser General Public License
 * along with TAPLibrary.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
 * Copyright 2012-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
 *                       Astronomisches Rechen Institut (ARI)
 */

@@ -181,7 +181,7 @@ import uws.service.log.UWSLog.LogLevel;
 * </i></p>
 *
 * @author Gr&eacute;gory Mantelet (CDS;ARI)
 * @version 2.1 (08/2017)
 * @version 2.1 (01/2018)
 * @since 2.0
 */
public class JDBCConnection implements DBConnection {
@@ -3090,6 +3090,95 @@ public class JDBCConnection implements DBConnection {
		return null;
	}

	/**
	 * Get the index of the column returning the schema name in the ResultSet
	 * returned by {@link DatabaseMetaData#getTables(String, String, String, String[])}.
	 *
	 * <p>
	 * 	The index returned by this function may be different from one DBMS from
	 * 	another depending on how it deals with schemas. For instance, in MySQL
	 * 	database, schemas are interpreted as catalogs (so the index would be 2
	 * 	instead of 1).
	 * </p>
	 *
	 * @return	Index of the column providing the table's schema name.
	 *
	 * @since 2.1
	 */
	protected int getTableSchemaIndexInMetadata(){
		return dbms.equalsIgnoreCase(DBMS_MYSQL) ? 1 : 2;
	}

	/**
	 * Get all schemas available in the database.
	 *
	 * @param dbMeta	Metadata of the database to investigate.
	 *
	 * @return	Metadata about all available schemas.
	 *
	 * @throws SQLException	If any error occurs while querying the database
	 *                     	metadata.
	 *
	 * @since 2.1
	 */
	protected ResultSet getDBMetaSchemas(final DatabaseMetaData dbMeta) throws SQLException{
		return (dbms.equalsIgnoreCase(DBMS_MYSQL) ? dbMeta.getCatalogs() : dbMeta.getSchemas());
	}

	/**
	 * Get all tables matching the given table name pattern and being inside
	 * the specified schema(s).
	 *
	 * @param dbMeta		Metadata of the database to investigate.
	 * @param schemaPattern	Pattern matching the schema(s) name containing the
	 *                     	target tables.
	 *                     	<i>If NULL, the table will be searched in all
	 *                     	schemas.</i>
	 * @param tablePattern	Pattern matching the name of the tables to list.
	 *
	 * @return	Metadata about all matching tables.
	 *
	 * @throws SQLException	If any error occurs while querying the database
	 *                     	metadata.
	 *
	 * @since 2.1
	 */
	protected ResultSet getDBMetaTables(final DatabaseMetaData dbMeta, final String schemaPattern, final String tablePattern) throws SQLException{
		if (dbms.equalsIgnoreCase(DBMS_MYSQL))
			return dbMeta.getTables(schemaPattern, null, tablePattern, null);
		else
			return dbMeta.getTables(null, schemaPattern, tablePattern, null);
	}

	/**
	 * Get all columns matching the given column name pattern and being inside
	 * the specified table(s) and schema(s).
	 *
	 * @param dbMeta		Metadata of the database to investigate.
	 * @param schemaPattern	Pattern matching the schema(s) name containing the
	 *                     	target columns.
	 *                     	<i>If NULL, the columns will be searched in all
	 *                     	schemas.</i>
	 * @param tablePattern	Pattern matching the table(s) name containing the
	 *                     	target columns.
	 *                     	<i>If NULL, the columns will be searched in all
	 *                     	tables.</i>
	 * @param columnPattern	Pattern matching the name of the columns to list.
	 *
	 * @return	Metadata about all matching columns.
	 *
	 * @throws SQLException	If any error occurs while querying the database
	 *                     	metadata.
	 *
	 * @since 2.1
	 */
	protected ResultSet getDBMetaColumns(final DatabaseMetaData dbMeta, final String schemaPattern, final String tablePattern, final String columnPattern) throws SQLException{
		if (dbms.equalsIgnoreCase(DBMS_MYSQL))
			return dbMeta.getColumns(schemaPattern, null, tablePattern, columnPattern);
		else
			return dbMeta.getColumns(null, schemaPattern, tablePattern, columnPattern);
	}

	/**
	 * <p>Tell whether the specified schema exists in the database.
	 * 	To do so, it is using the given {@link DatabaseMetaData} object to query the database and list all existing schemas.</p>
@@ -3115,7 +3204,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 (DBMS_MYSQL.equals(dbms) || !supportsSchema || schemaName == null || schemaName.length() == 0)
		if (!supportsSchema || schemaName == null || schemaName.length() == 0)
			return true;

		// Determine the case sensitivity to use for the equality test:
@@ -3124,7 +3213,7 @@ public class JDBCConnection implements DBConnection {
		ResultSet rs = null;
		try{
			// List all schemas available and stop when a schema name matches ignoring the case:
			rs = dbMeta.getSchemas();
			rs = getDBMetaSchemas(dbMeta);
			boolean hasSchema = false;
			while(!hasSchema && rs.next()){
				hasSchema = equals(rs.getString(1), schemaName, caseSensitive);
@@ -3177,16 +3266,16 @@ public class JDBCConnection implements DBConnection {
			if (supportsSchema){
				String schemaPattern = schemaCaseSensitive ? schemaName : null;
				String tablePattern = tableCaseSensitive ? tableName : null;
				rs = dbMeta.getTables(null, schemaPattern, tablePattern, null);
				rs = getDBMetaTables(dbMeta, schemaPattern, tablePattern);
			}else{
				String tablePattern = tableCaseSensitive ? tableName : null;
				rs = dbMeta.getTables(null, null, tablePattern, null);
				rs = getDBMetaTables(dbMeta, null, tablePattern);
			}

			// Stop on the first table which match completely (schema name + table name in function of their respective case sensitivity):
			int cnt = 0;
			while(rs.next()){
				String rsSchema = nullifyIfNeeded(rs.getString(2));
				String rsSchema = nullifyIfNeeded(rs.getString(getTableSchemaIndexInMetadata()));
				String rsTable = rs.getString(3);
				if (!supportsSchema || schemaName == null || equals(rsSchema, schemaName, schemaCaseSensitive)){
					if (equals(rsTable, tableName, tableCaseSensitive))
@@ -3261,25 +3350,24 @@ public class JDBCConnection implements DBConnection {
			if (supportsSchema){
				String schemaPattern = schemaCaseSensitive ? schemaName : null;
				String tablePattern = tableCaseSensitive ? tableName : null;
				rsT = dbMeta.getTables(null, schemaPattern, tablePattern, null);
				rsT = getDBMetaTables(dbMeta, schemaPattern, tablePattern);
			}else{
				String tablePattern = tableCaseSensitive ? tableName : null;
				rsT = dbMeta.getTables(null, null, tablePattern, null);
				rsT = getDBMetaTables(dbMeta, null, tablePattern);
			}

			// For each matching table:
			int cnt = 0;
			String columnPattern = columnCaseSensitive ? columnName : null;
			while(rsT.next()){
                                int rsTSchemaIndex = dbms.equalsIgnoreCase(DBMS_MYSQL) ? 1 : 2;
				String rsSchema = nullifyIfNeeded(rsT.getString(rsTSchemaIndex));
				String rsSchema = nullifyIfNeeded(rsT.getString(getTableSchemaIndexInMetadata()));
				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);
						rsC = getDBMetaColumns(dbMeta, rsSchema, rsTable, columnPattern);
						// count all matching columns:
						while(rsC.next()){
							String rsColumn = rsC.getString(4);