
schemacrawler.crawl.MetadataResultSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of schemacrawler Show documentation
Show all versions of schemacrawler Show documentation
SchemaCrawler is an open-source Java API that makes working with database metadata as easy as working with plain old Java objects. SchemaCrawler is also a database schema discovery and comprehension, and schema documentation tool. You can search for database schema objects using regular expressions, and output the schema and data in a readable text format. The output is designed to be diff-ed against other database schemas.
/*
*
* SchemaCrawler
* http://sourceforge.net/projects/schemacrawler
* Copyright (c) 2000-2013, Sualeh Fatehi.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
package schemacrawler.crawl;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import sf.util.Utility;
/**
* A wrapper around a JDBC resultset obtained from a database metadata
* call. This allows type-safe methods to obtain boolean, integer and
* string data, while abstracting away the quirks of the JDBC metadata
* API.
*
* @author Sualeh Fatehi
*/
final class MetadataResultSet
implements AutoCloseable
{
private static final Logger LOGGER = Logger.getLogger(MetadataResultSet.class
.getName());
private static final int FETCHSIZE = 20;
private final ResultSet results;
private final List resultSetColumns;
private Set readColumns;
MetadataResultSet(final ResultSet resultSet)
throws SQLException
{
if (resultSet == null)
{
throw new IllegalArgumentException("Cannot use null results");
}
results = resultSet;
try
{
results.setFetchSize(FETCHSIZE);
}
catch (final NullPointerException | SQLException e)
{
LOGGER.log(Level.WARNING, "Could not set fetch size", e);
}
final List resultSetColumns = new ArrayList<>();
try
{
final ResultSetMetaData rsMetaData = resultSet.getMetaData();
for (int i = 0; i < rsMetaData.getColumnCount(); i++)
{
String columnName;
columnName = rsMetaData.getColumnLabel(i + 1);
if (Utility.isBlank(columnName))
{
columnName = rsMetaData.getColumnName(i + 1);
}
resultSetColumns.add(columnName.toUpperCase());
}
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not get columns list");
}
this.resultSetColumns = Collections.unmodifiableList(resultSetColumns);
readColumns = new HashSet<>();
}
/**
* Releases this ResultSet
object's database and JDBC
* resources immediately instead of waiting for this to happen when it
* is automatically closed.
*
* @throws SQLException
* On an exception
*/
@Override
public void close()
throws SQLException
{
results.close();
}
/**
* Gets unread (and therefore unmapped) columns from the database
* metadata resultset, and makes them available as addiiotnal
* attributes.
*
* @return Map of additional attributes to the database object
*/
Map getAttributes()
{
final Map attributes = new HashMap<>();
for (final String columnName: resultSetColumns)
{
if (!readColumns.contains(columnName))
{
try
{
final Object value = results.getObject(columnName);
attributes.put(columnName, value);
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not read value for column "
+ columnName, e);
}
}
}
return attributes;
}
/**
* Checks if the value of a column from the result set evaluates to
* true.
*
* @param columnName
* Column name to check
* @return Whether the string evaluates to true
*/
boolean getBoolean(final String columnName)
{
boolean value = false;
if (useColumn(columnName))
{
try
{
final Object booleanValue = results.getObject(columnName);
final String stringBooleanValue;
if (results.wasNull() || booleanValue == null)
{
stringBooleanValue = null;
}
else
{
stringBooleanValue = String.valueOf(booleanValue);
}
if (!Utility.isBlank(stringBooleanValue))
{
try
{
final int booleanInt = Integer.parseInt(stringBooleanValue);
value = booleanInt != 0;
}
catch (final NumberFormatException e)
{
value = stringBooleanValue.equalsIgnoreCase("YES")
|| Boolean.valueOf(stringBooleanValue).booleanValue();
}
}
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not read boolean value for column "
+ columnName, e);
}
}
return value;
}
/**
* Reads the value of a column from the result set as an enum.
*
* @param columnName
* Column name
* @param defaultValue
* Default enum value to return
* @return Enum value of the column, or the default if not available
*/
> E getEnum(final String columnName, final E defaultValue)
{
final String value = getString(columnName);
E enumValue;
if (value == null || defaultValue == null)
{
enumValue = defaultValue;
}
else
{
try
{
enumValue = (E) Enum.valueOf(defaultValue.getClass(),
value.toLowerCase(Locale.ENGLISH));
}
catch (final Exception e)
{
enumValue = defaultValue;
}
}
return enumValue;
}
/**
* Reads the value of a column from the result set as an integer. If
* the value was null, returns the default.
*
* @param columnName
* Column name
* @param defaultValue
* Default value
* @return Integer value of the column, or the default if not
* available
*/
int getInt(final String columnName, final int defaultValue)
{
int value = defaultValue;
if (useColumn(columnName))
{
try
{
value = results.getInt(columnName);
if (results.wasNull())
{
value = defaultValue;
}
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not read integer value for column "
+ columnName, e);
}
}
return value;
}
/**
* Reads the value of a column from the result set as a long. If the
* value was null, returns the default.
*
* @param columnName
* Column name
* @param defaultValue
* Default value
* @return Long value of the column, or the default if not available
*/
long getLong(final String columnName, final long defaultValue)
{
long value = defaultValue;
if (useColumn(columnName))
{
try
{
value = results.getLong(columnName);
if (results.wasNull())
{
value = defaultValue;
}
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not read long value for column "
+ columnName, e);
}
}
return value;
}
/**
* Reads the value of a column from the result set as a short. If the
* value was null, returns the default.
*
* @param columnName
* Column name
* @param defaultValue
* Default value
* @return Short value of the column, or the default if not available
*/
short getShort(final String columnName, final short defaultValue)
{
short value = defaultValue;
if (useColumn(columnName))
{
try
{
value = results.getShort(columnName);
if (results.wasNull())
{
value = defaultValue;
}
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not read short value for column "
+ columnName, e);
}
}
return value;
}
/**
* Reads the value of a column from the result set as a string.
*
* @param columnName
* Column name
* @return String value of the column, or null if not available
*/
String getString(final String columnName)
{
String value = null;
if (useColumn(columnName))
{
try
{
value = results.getString(columnName);
if (results.wasNull())
{
value = null;
}
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, "Could not read string value for column "
+ columnName, e);
}
}
return value;
}
/**
* Moves the cursor down one row from its current position. A
* ResultSet
cursor is initially positioned before the
* first row; the first call to the method next
makes the
* first row the current row; the second call makes the second row the
* current row, and so on.
*
* @return true
if the new current row is valid;
* false
if there are no more rows
* @throws SQLException
* On a database access error
*/
boolean next()
throws SQLException
{
readColumns = new HashSet<>();
return results.next();
}
private boolean useColumn(final String columnName)
{
final boolean useColumn = columnName != null
&& resultSetColumns.contains(columnName);
if (useColumn)
{
readColumns.add(columnName);
}
return useColumn;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy