blob: 88b88c3d32b590ec0bfbe3779e809d0e1f5d5005 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.db.relational.spi.jdbc;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey;
import org.eclipse.persistence.tools.db.relational.spi.ExternalTable;
import org.eclipse.persistence.tools.utility.ObjectTools;
/**
* see comment about defensive programming at JDBCExternalDatabase
*
* @version 2.6
*/
final class JDBCExternalTable implements ExternalTable {
private final JDBCExternalTableDescription tableDescription;
private final JDBCExternalColumn[] columns;
private final ExternalForeignKey[] foreignKeys;
private static final JDBCExternalForeignKey[] EMPTY_FOREIGN_KEYS = new JDBCExternalForeignKey[0];
// ********** constructor/initialization **********
/**
*
*/
JDBCExternalTable(JDBCExternalTableDescription tableDescription) throws SQLException {
super();
this.tableDescription = tableDescription;
this.columns = this.buildColumns();
this.markPrimaryKeyColumns();
this.foreignKeys = this.buildForeignKeys();
}
/**
* query the database for the table's columns
* @see java.sql.DatabaseMetaData#getColumns(String, String, String, String)
*/
private JDBCExternalColumn[] buildColumns() throws SQLException {
Collection<JDBCExternalColumn> cols = new ArrayList<JDBCExternalColumn>();
ResultSet resultSet = this.metaData().getColumns(
this.tableDescription.getCatalogName(),
this.tableDescription.getSchemaName(),
this.tableDescription.getName(),
null
);
while (resultSet.next()) {
cols.add(new JDBCExternalColumn(resultSet));
}
resultSet.close();
return cols.toArray(new JDBCExternalColumn[cols.size()]);
}
private void markPrimaryKeyColumns() {
Collection<String> pkColNames = this.primaryKeyColumnNames();
for (int i = this.columns.length; i-- > 0; ) {
JDBCExternalColumn column = this.columns[i];
column.setPrimaryKey(pkColNames.contains(column.getName()));
}
}
/**
* defensive wrapper
*/
private Collection<String> primaryKeyColumnNames() {
try {
return this.primaryKeyColumnNames2();
} catch (SQLException ex) {
// defensive - this is not fatal if unsupported by driver
}
return Collections.emptySet();
}
/**
* Returns the names of the table's primary key columns
* @see java.sql.DatabaseMetaData#getPrimaryKeys(String, String, String)
*/
private Collection<String> primaryKeyColumnNames2() throws SQLException {
Collection<String> names = new HashSet<String>();
ResultSet resultSet = this.metaData().getPrimaryKeys(
this.tableDescription.getCatalogName(),
this.tableDescription.getSchemaName(),
this.tableDescription.getName()
);
while (resultSet.next()) {
// * Returns fixed-length strings
names.add(resultSet.getString(4).trim()); // COLUMN_NAME
}
resultSet.close();
return names;
}
/**
* defensive wrapper
*/
private JDBCExternalForeignKey[] buildForeignKeys() {
try {
return this.buildForeignKeys2();
} catch (SQLException ex) {
// defensive - this is not fatal if unsupported by driver
}
return EMPTY_FOREIGN_KEYS;
}
/**
* query the database for the table's foreign keys
* @see java.sql.DatabaseMetaData#getImportedKeys(String, String, String)
*/
private JDBCExternalForeignKey[] buildForeignKeys2() throws SQLException {
Collection<JDBCExternalForeignKey> fKeys = new ArrayList<JDBCExternalForeignKey>();
ResultSet resultSet = this.metaData().getImportedKeys(
this.tableDescription.getCatalogName(),
this.tableDescription.getSchemaName(),
this.tableDescription.getName()
);
while (resultSet.next()) {
String fKeyName = resultSet.getString(12).trim(); // FK_NAME
JDBCExternalForeignKey fKey = this.foreignKeyNamed(fKeyName, fKeys);
if (fKey == null) {
fKey = new JDBCExternalForeignKey(this, fKeyName, resultSet);
fKeys.add(fKey);
}
fKey.addColumnPair(resultSet);
}
resultSet.close();
return fKeys.toArray(new JDBCExternalForeignKey[fKeys.size()]);
}
/**
* search the specified collection of foreign keys for the foreign
* key with the specified name; assume(?) that foreign keys with
* the same name have the same target table
*/
private JDBCExternalForeignKey foreignKeyNamed(String fKeyName, Collection<JDBCExternalForeignKey> fKeys) {
for (JDBCExternalForeignKey fKey : fKeys) {
if (fKey.getName().equals(fKeyName)) {
return fKey;
}
}
return null;
}
// ********** ExternalTable implementation **********
/**
* {@inheritDoc}
*/
@Override
public ExternalColumn[] getColumns() {
return this.columns;
}
/**
* {@inheritDoc}
*/
@Override
public ExternalForeignKey[] getForeignKeys() {
return this.foreignKeys;
}
// ********** queries **********
private DatabaseMetaData metaData() {
return this.tableDescription.metaData();
}
JDBCExternalDatabase database() {
return this.tableDescription.getDatabase();
}
JDBCExternalColumn columnNamed(String columnName) {
for (int i = this.columns.length; i-- > 0; ) {
JDBCExternalColumn column = this.columns[i];
if (column.getName().equals(columnName)) {
return column;
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return ObjectTools.toString(this, this.tableDescription.getQualifiedName());
}
}