| /******************************************************************************* |
| * 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()); |
| } |
| } |