| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| // Dies Koper - avoid generating constraints on platforms that do not support constraint generation |
| // Dies Koper - add support for creating indices on tables |
| // 09/09/2011-2.3.1 Guy Pelletier |
| // - 356197: Add new VPD type to MultitenantType |
| // 09/14/2011-2.3.1 Guy Pelletier |
| // - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU |
| // 12/07/2012-2.5 Guy Pelletier |
| // - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support) |
| // 02/04/2013-2.5 Guy Pelletier |
| // - 389090: JPA 2.1 DDL Generation Support |
| package org.eclipse.persistence.tools.schemaframework; |
| |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| import org.eclipse.persistence.exceptions.DatabaseException; |
| import org.eclipse.persistence.exceptions.EclipseLinkException; |
| import org.eclipse.persistence.exceptions.ValidationException; |
| import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor; |
| import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; |
| import org.eclipse.persistence.internal.helper.DatabaseField; |
| import org.eclipse.persistence.internal.helper.DatabaseTable; |
| import org.eclipse.persistence.internal.helper.Helper; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.queries.SQLCall; |
| |
| /** |
| * <p> |
| * <b>Purpose</b>: Allow a generic way of creating tables on the different platforms. |
| * </p> |
| */ |
| public class TableDefinition extends DatabaseObjectDefinition { |
| protected List<FieldDefinition> fields; //FieldDefinitions |
| protected Map<String, ForeignKeyConstraint> foreignKeyMap; //key is the name of ForeignKeyConstraint |
| protected List<UniqueKeyConstraint> uniqueKeys; |
| protected List<IndexDefinition> indexes; |
| protected String creationPrefix; |
| protected String creationSuffix; |
| private boolean createSQLFiles; |
| private boolean createVPDCalls; |
| private String tenantFieldName; |
| //holds onto the name and delimiting info. |
| protected DatabaseTable table; |
| protected boolean hasUserDefinedForeignKeyConstraints; |
| |
| public TableDefinition() { |
| createVPDCalls = false; |
| hasUserDefinedForeignKeyConstraints = false; |
| this.fields = new ArrayList<>(); |
| this.indexes = new ArrayList<>(); |
| this.foreignKeyMap = new HashMap<>(); |
| this.uniqueKeys = new ArrayList<>(); |
| this.creationPrefix = "CREATE TABLE "; |
| this.creationSuffix = ""; |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table, default sizes are used. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addField(String fieldName, Class<?> type) { |
| this.addField(new FieldDefinition(fieldName, type)); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addField(String fieldName, Class<?> type, int fieldSize) { |
| this.addField(new FieldDefinition(fieldName, type, fieldSize)); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addField(String fieldName, Class<?> type, int fieldSize, int fieldSubSize) { |
| this.addField(new FieldDefinition(fieldName, type, fieldSize, fieldSubSize)); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the type to a nested type. |
| * @param typeName is the name of the nested type. |
| */ |
| public void addField(String fieldName, String typeName) { |
| addField(new FieldDefinition(fieldName, typeName)); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table. |
| */ |
| public void addField(FieldDefinition field) { |
| getFields().add(field); |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the SQL alter table to add the field to the table. |
| */ |
| public void addFieldOnDatabase(final AbstractSession session, FieldDefinition field){ |
| session.priviledgedExecuteNonSelectingCall( |
| new SQLCall( buildAddFieldWriter(session, field, new StringWriter()).toString() ) ); |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the alter table statement to add a field to the table. |
| */ |
| public Writer buildAddFieldWriter(AbstractSession session, FieldDefinition field, Writer writer) throws ValidationException { |
| try { |
| writer.write("ALTER TABLE " + getFullName() + " "); |
| session.getPlatform().writeAddColumnClause(writer, session, this, field); |
| writer.write(" "); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| return writer; |
| } |
| |
| /** |
| * PUBLIC: |
| * Add a foreign key constraint to the table. |
| * If there is a same name foreign key constraint already, nothing will happen. |
| */ |
| public void addForeignKeyConstraint(String name, String sourceField, String targetField, String targetTable) { |
| ForeignKeyConstraint foreignKey = new ForeignKeyConstraint(name, sourceField, targetField, targetTable); |
| addForeignKeyConstraint(foreignKey); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add a unique key constraint to the table. |
| */ |
| public void addUniqueKeyConstraint(String name, String sourceField) { |
| UniqueKeyConstraint uniqueKey = new UniqueKeyConstraint(name, sourceField); |
| addUniqueKeyConstraint(uniqueKey); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add a unique key constraint to the table. |
| */ |
| public void addUniqueKeyConstraint(String name, String[] sourceFields) { |
| UniqueKeyConstraint uniqueKey = new UniqueKeyConstraint(name, sourceFields); |
| addUniqueKeyConstraint(uniqueKey); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add a foreign key constraint to the table. |
| * If there is a same name foreign key constraint already, nothing will happen. |
| */ |
| public void addForeignKeyConstraint(ForeignKeyConstraint foreignKey) { |
| if (! hasUserDefinedForeignKeyConstraints) { |
| if (!foreignKeyMap.containsKey(foreignKey.getName())) { |
| foreignKeyMap.put(foreignKey.getName(), foreignKey); |
| } |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Add a unique key constraint to the table. |
| */ |
| public void addUniqueKeyConstraint(UniqueKeyConstraint uniqueKey) { |
| getUniqueKeys().add(uniqueKey); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add an index to the table. |
| */ |
| public void addIndex(IndexDefinition index) { |
| getIndexes().add(index); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table, default sizes are used. |
| * Identity fields are used on Sybase for native sequencing, |
| * The field must be of number type and cannot have a subsize. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addIdentityField(String fieldName, Class<?> type) { |
| FieldDefinition fieldDef = new FieldDefinition(fieldName, type); |
| fieldDef.setIsIdentity(true); |
| fieldDef.setIsPrimaryKey(true); |
| addField(fieldDef); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table, default sizes are used. |
| * Identity fields are used on Sybase for native sequencing, |
| * The field must be of number type and cannot have a subsize. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addIdentityField(String fieldName, Class<?> type, int fieldSize) { |
| FieldDefinition fieldDef = new FieldDefinition(fieldName, type, fieldSize); |
| fieldDef.setIsIdentity(true); |
| fieldDef.setIsPrimaryKey(true); |
| addField(fieldDef); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table, default sizes are used. |
| * This field is set as part of the primary key. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addPrimaryKeyField(String fieldName, Class<?> type) { |
| FieldDefinition fieldDef = new FieldDefinition(fieldName, type); |
| fieldDef.setIsPrimaryKey(true); |
| addField(fieldDef); |
| } |
| |
| /** |
| * PUBLIC: |
| * Add the field to the table, default sizes are used. |
| * This field is set as part of the primary key. |
| * @param type is the Java class type corresponding to the database type. |
| */ |
| public void addPrimaryKeyField(String fieldName, Class<?> type, int fieldSize) { |
| FieldDefinition fieldDef = new FieldDefinition(fieldName, type, fieldSize); |
| fieldDef.setIsPrimaryKey(true); |
| addField(fieldDef); |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the alter table statement to add the constraints. |
| * This is done separately from the create because of dependencies. |
| */ |
| public Writer buildConstraintCreationWriter(AbstractSession session, ForeignKeyConstraint foreignKey, Writer writer) throws ValidationException { |
| try { |
| writer.write("ALTER TABLE " + getFullName()); |
| writer.write(" ADD CONSTRAINT "); |
| if (!session.getPlatform().shouldPrintConstraintNameAfter()) { |
| writer.write(foreignKey.getName() + " "); |
| } |
| foreignKey.appendDBString(writer, session); |
| if (session.getPlatform().shouldPrintConstraintNameAfter()) { |
| writer.write(" CONSTRAINT " + foreignKey.getName()); |
| } |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the alter table statement to drop the constraints. |
| * This is done separately to allow constraints to be dropped before the tables. |
| */ |
| public Writer buildConstraintDeletionWriter(AbstractSession session, ForeignKeyConstraint foreignKey, Writer writer) throws ValidationException { |
| try { |
| writer.write("ALTER TABLE " + getFullName()); |
| writer.write(session.getPlatform().getConstraintDeletionString() + foreignKey.getName()); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the alter table statement to add the constraints. |
| * This is done separately from the create because of dependencies. |
| */ |
| public Writer buildUniqueConstraintCreationWriter(AbstractSession session, UniqueKeyConstraint uniqueKey, Writer writer) throws ValidationException { |
| try { |
| writer.write("ALTER TABLE " + getFullName()); |
| writer.write(" ADD CONSTRAINT "); |
| if (!session.getPlatform().shouldPrintConstraintNameAfter()) { |
| writer.write(uniqueKey.getName() + " "); |
| } |
| uniqueKey.appendDBString(writer, session); |
| if (session.getPlatform().shouldPrintConstraintNameAfter()) { |
| writer.write(" CONSTRAINT " + uniqueKey.getName()); |
| } |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the alter table statement to drop the constraints. |
| * This is done separately to allow constraints to be dropped before the tables. |
| */ |
| public Writer buildUniqueConstraintDeletionWriter(AbstractSession session, UniqueKeyConstraint uniqueKey, Writer writer) throws ValidationException { |
| try { |
| writer.write("ALTER TABLE " + getFullName()); |
| writer.write(session.getPlatform().getUniqueConstraintDeletionString() + uniqueKey.getName()); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the index creation statement. |
| */ |
| public IndexDefinition buildIndex(AbstractSession session, String key, List<String> columnNames, boolean isUniqueSetOnField) { |
| String indexName = buildIndexName(getName(), key, session.getPlatform().getIndexNamePrefix(isUniqueSetOnField), session.getPlatform().getMaxIndexNameSize(), session.getPlatform()); |
| IndexDefinition index = new IndexDefinition(); |
| index.setName(indexName); |
| index.setTargetTable(getFullName()); |
| index.getFields().addAll(columnNames); |
| return index; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the index drop statement. |
| */ |
| public Writer buildIndexDeletionWriter(AbstractSession session, String key, Writer writer, boolean isUniqueSetOnField) { |
| String indexName = buildIndexName(getName(), key, session.getPlatform().getIndexNamePrefix(isUniqueSetOnField), |
| session.getPlatform().getMaxIndexNameSize(), session.getPlatform()); |
| IndexDefinition index = new IndexDefinition(); |
| index.setName(indexName); |
| index.setTargetTable(getFullName()); |
| index.buildDeletionWriter(session, writer); |
| return writer; |
| } |
| |
| |
| /** |
| * INTERNAL: |
| * Return the beginning of the sql create statement - the part before the name. |
| * Unless temp table is created should be "CREATE TABLE " |
| */ |
| public String getCreationPrefix() { |
| return creationPrefix; |
| } |
| |
| /** |
| * INTERNAL: |
| * Set the beginning of the sql create statement - the part before the name. |
| * Use to create temp. table. |
| */ |
| public void setCreationPrefix(String creationPrefix) { |
| this.creationPrefix = creationPrefix; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the end of the sql create statement - the part after the field list. |
| * Unless temp table is created should be empty. |
| */ |
| public String getCreationSuffix() { |
| return creationSuffix; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the schema associated with this table. |
| */ |
| @Override |
| public String getDatabaseSchema() { |
| return getTable().getTableQualifier(); |
| } |
| |
| /** |
| * INTERNAL: |
| * Set the end of the sql create statement - the part after the field list. |
| */ |
| public void setCreationSuffix(String creationSuffix) { |
| this.creationSuffix = creationSuffix; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the create table statement. |
| */ |
| @Override |
| public Writer buildCreationWriter(AbstractSession session, Writer writer) throws ValidationException { |
| try { |
| writer.write(getCreationPrefix() + getFullName() + " ("); |
| for (Iterator<FieldDefinition> itetrator = getFields().iterator(); itetrator.hasNext();) { |
| FieldDefinition field = itetrator.next(); |
| field.appendDBString(writer, session, this); |
| if (itetrator.hasNext()) { |
| writer.write(", "); |
| } |
| } |
| List<String> keyFields = getPrimaryKeyFieldNames(); |
| if ((!keyFields.isEmpty()) && session.getPlatform().supportsPrimaryKeyConstraint()) { |
| writer.write(", "); |
| if (session.getPlatform().requiresNamedPrimaryKeyConstraints()) { |
| writer.write("CONSTRAINT " + getFullName() + "_PK "); |
| } |
| writer.write("PRIMARY KEY ("); |
| for (Iterator<String> iterator = keyFields.iterator(); iterator.hasNext();) { |
| writer.write(iterator.next()); |
| if (iterator.hasNext()) { |
| writer.write(", "); |
| } |
| } |
| writer.write(")"); |
| } |
| if (session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) { |
| for (UniqueKeyConstraint constraint : getUniqueKeys()) { |
| writer.write(", "); |
| constraint.appendDBString(writer, session); |
| } |
| } |
| writer.write(")"); |
| //let the platform write out the CreationSuffix and the platform's default tableCreationSuffix |
| session.getPlatform().writeTableCreationSuffix(writer, getCreationSuffix()); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the drop table statement. |
| */ |
| @Override |
| public Writer buildDeletionWriter(AbstractSession session, Writer writer) throws ValidationException { |
| try { |
| writer.write("DROP TABLE " + getFullName() + session.getPlatform().getDropCascadeString()); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public Writer buildVPDCreationPolicyWriter(AbstractSession session, Writer writer) { |
| try { |
| writer.write(session.getPlatform().getVPDCreationPolicyString(getName(), session)); |
| return writer; |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public Writer buildVPDCreationFunctionWriter(AbstractSession session, Writer writer) { |
| try { |
| writer.write(session.getPlatform().getVPDCreationFunctionString(getName(), tenantFieldName)); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Build the create schema DDL. |
| */ |
| protected Writer buildDatabaseSchemaCreationWriter(AbstractSession session, Writer writer, Set<String> createdDatabaseSchemas) { |
| try { |
| writer.write(session.getPlatform().getCreateDatabaseSchemaString(getDatabaseSchema())); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| |
| // Tag that we created a schema (to avoid creating it again) |
| createdDatabaseSchemas.add(getDatabaseSchema()); |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Build the drop schema DDL. |
| */ |
| protected Writer buildDatabaseSchemaDeletionWriter(AbstractSession session, Writer writer) { |
| try { |
| writer.write(session.getPlatform().getDropDatabaseSchemaString(getDatabaseSchema())); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| @Override |
| public Writer buildVPDDeletionWriter(AbstractSession session, Writer writer) { |
| try { |
| writer.write(session.getPlatform().getVPDDeletionString(getName(), session)); |
| } catch (IOException ioException) { |
| throw ValidationException.fileError(ioException); |
| } |
| |
| return writer; |
| } |
| |
| /** |
| * INTERNAL: |
| * Build the foreign key constraints. |
| */ |
| protected void buildFieldTypes(AbstractSession session) { |
| // The ForeignKeyConstraint object is the newer way of doing things. |
| // We support FieldDefinition.getForeignKeyFieldName() due to backwards compatibility |
| // by converting it. To allow mixing both ways, we just add converted one to foreignKeys list. |
| for (FieldDefinition field : getFields()) { |
| if (field.getForeignKeyFieldName() != null) { |
| addForeignKeyConstraint(buildForeignKeyConstraint(field, session.getPlatform())); |
| } |
| } |
| } |
| |
| /** |
| * Build a foreign key constraint using FieldDefinition.getForeignKeyFieldName(). |
| */ |
| protected ForeignKeyConstraint buildForeignKeyConstraint(FieldDefinition field, DatabasePlatform platform) { |
| List<String> sourceFields = new Vector<>(); |
| List<String> targetFields = new Vector<>(); |
| ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(); |
| DatabaseField tempTargetField = new DatabaseField(field.getForeignKeyFieldName()); |
| DatabaseField tempSourceField = new DatabaseField(field.getName()); |
| |
| sourceFields.add(tempSourceField.getName()); |
| targetFields.add(tempTargetField.getName()); |
| |
| fkConstraint.setSourceFields(sourceFields); |
| fkConstraint.setTargetFields(targetFields); |
| fkConstraint.setTargetTable(tempTargetField.getTable().getQualifiedNameDelimited(platform)); |
| String tempName = buildForeignKeyConstraintName(this.getName(), tempSourceField.getName(), platform.getMaxForeignKeyNameSize(), platform); |
| |
| fkConstraint.setName(tempName); |
| return fkConstraint; |
| } |
| |
| /** |
| * Build a foreign key constraint. |
| */ |
| protected ForeignKeyConstraint buildForeignKeyConstraint(List<String> fkFieldNames, List<String> pkFieldNames, TableDefinition targetTable, DatabasePlatform platform) { |
| assert fkFieldNames.size() > 0 && fkFieldNames.size() == pkFieldNames.size(); |
| |
| ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(); |
| for(int i=0; i<fkFieldNames.size(); i++) { |
| fkConstraint.getSourceFields().add(fkFieldNames.get(i)); |
| fkConstraint.getTargetFields().add(pkFieldNames.get(i)); |
| } |
| |
| fkConstraint.setTargetTable(targetTable.getFullName()); |
| String fkFieldName = fkFieldNames.get(0); |
| String name = buildForeignKeyConstraintName(this.getName(), fkFieldName, platform.getMaxForeignKeyNameSize(), platform); |
| |
| fkConstraint.setName(name); |
| return fkConstraint; |
| } |
| |
| /** |
| * Return foreign key constraint name built from the table and field name with the specified maximum length. To |
| * make the name short enough we |
| * 1. Drop the "FK_" prefix. |
| * 2. Drop the underscore characters if any. |
| * 3. Drop the vowels from the table and field name. |
| * 4. Truncate the table name to zero length if necessary. |
| */ |
| protected String buildForeignKeyConstraintName(String tableName, String fieldName, int maximumNameLength, DatabasePlatform platform) { |
| String startDelimiter = ""; |
| String endDelimiter = ""; |
| boolean useDelimiters = !platform.getStartDelimiter().equals("") && (tableName.startsWith(platform.getStartDelimiter()) || fieldName.startsWith(platform.getStartDelimiter())); |
| // we will only delimit our generated constraints if either of the names that composes them is already delimited |
| if (useDelimiters){ |
| startDelimiter = platform.getStartDelimiter(); |
| endDelimiter = platform.getEndDelimiter(); |
| } |
| String adjustedTableName = tableName; |
| if(adjustedTableName.indexOf(' ') != -1 || adjustedTableName.indexOf('\"') != -1 || adjustedTableName.indexOf('`') != -1) { |
| //if table name has spaces and/or is quoted, remove this from the constraint name. |
| StringBuilder buff = new StringBuilder(); |
| for(int i = 0; i < tableName.length(); i++) { |
| char c = tableName.charAt(i); |
| if(c != ' ' && c != '\"' && c != '`') { |
| buff.append(c); |
| } |
| } |
| adjustedTableName = buff.toString(); |
| } |
| StringBuilder buff = new StringBuilder(); |
| for(int i = 0; i < fieldName.length(); i++) { |
| char c = fieldName.charAt(i); |
| if(c != ' ' && c != '\"' && c != '`') { |
| buff.append(c); |
| } |
| } |
| String adjustedFieldName = buff.toString(); |
| String foreignKeyName = startDelimiter + "FK_" + adjustedTableName + "_" + adjustedFieldName + endDelimiter; |
| if (foreignKeyName.length() > maximumNameLength) { |
| // First Remove the "FK_" prefix. |
| foreignKeyName = startDelimiter + adjustedTableName + "_" + adjustedFieldName + endDelimiter; |
| if (foreignKeyName.length() > maximumNameLength) { |
| // Still too long: remove the underscore characters |
| foreignKeyName = startDelimiter + Helper.removeAllButAlphaNumericToFit(adjustedTableName + adjustedFieldName, maximumNameLength) + endDelimiter; |
| if (foreignKeyName.length() > maximumNameLength) { |
| // Still too long: remove vowels from the table name and field name. |
| String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(adjustedTableName, 0); |
| String onlyAlphaNumericFieldName = Helper.removeAllButAlphaNumericToFit(adjustedFieldName, 0); |
| foreignKeyName = startDelimiter + Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, onlyAlphaNumericFieldName, maximumNameLength) + endDelimiter; |
| if (foreignKeyName.length() > maximumNameLength) { |
| // Still too long: remove vowels from the table name and field name and truncate the table name. |
| String shortenedFieldName = Helper.removeVowels(onlyAlphaNumericFieldName); |
| String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName); |
| int delimiterLength = startDelimiter.length() + endDelimiter.length(); |
| if (shortenedFieldName.length() + delimiterLength >= maximumNameLength) { |
| foreignKeyName = startDelimiter + Helper.truncate(shortenedFieldName, maximumNameLength - delimiterLength) + endDelimiter; |
| } else { |
| foreignKeyName = startDelimiter + Helper.truncate(shortenedTableName, maximumNameLength - shortenedFieldName.length() - delimiterLength) + shortenedFieldName + endDelimiter; |
| } |
| } |
| } |
| } |
| } |
| return foreignKeyName; |
| } |
| |
| protected UniqueKeyConstraint buildUniqueKeyConstraint(String name, List<String> fieldNames, int serialNumber, DatabasePlatform platform) { |
| assert fieldNames.size() > 0; |
| |
| UniqueKeyConstraint unqConstraint = new UniqueKeyConstraint(); |
| |
| for (String fieldName : fieldNames) { |
| unqConstraint.addSourceField(fieldName); |
| } |
| |
| // If the name was not provided, default one, otherwise use the name provided. |
| if (name == null || name.equals("")) { |
| unqConstraint.setName(buildUniqueKeyConstraintName(getName(), serialNumber, platform.getMaxUniqueKeyNameSize())); |
| } else { |
| // Hack if off if it exceeds the max size. |
| if (name.length() > platform.getMaxUniqueKeyNameSize()) { |
| unqConstraint.setName(name.substring(0, platform.getMaxUniqueKeyNameSize() - 1)); |
| } else { |
| unqConstraint.setName(name); |
| } |
| } |
| |
| return unqConstraint; |
| } |
| |
| /** |
| * Return unique key constraint name built from the table name and sequence |
| * number with the specified maximum length. To make the name short enough we |
| * 1. Drop the "UNQ_" prefix. |
| * 2. Drop the underscore characters if any. |
| * 3. Drop the vowels from the table name. |
| * 4. Truncate the table name to zero length if necessary. |
| */ |
| protected String buildUniqueKeyConstraintName(String tableName, int serialNumber, int maximumNameLength) { |
| String uniqueKeyName = "UNQ_" + tableName + "_" + serialNumber; |
| if (uniqueKeyName.length() > maximumNameLength) { |
| // First Remove the "UNQ_" prefix. |
| uniqueKeyName = tableName + serialNumber; |
| if (uniqueKeyName.length() > maximumNameLength) { |
| // Still too long: remove the underscore characters |
| uniqueKeyName = Helper.removeAllButAlphaNumericToFit(tableName + serialNumber, maximumNameLength); |
| if (uniqueKeyName.length() > maximumNameLength) { |
| // Still too long: remove vowels from the table name |
| String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(tableName, 0); |
| String serialName = String.valueOf(serialNumber); |
| uniqueKeyName = Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, serialName, maximumNameLength); |
| if (uniqueKeyName.length() > maximumNameLength) { |
| // Still too long: remove vowels from the table name and truncate the table name. |
| String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName); |
| uniqueKeyName = Helper.truncate(shortenedTableName, maximumNameLength - serialName.length()) + serialName; |
| } |
| } |
| } |
| } |
| return uniqueKeyName; |
| } |
| |
| /** |
| * Return key constraint name built from the table and key name with the |
| * specified maximum length and index prefix. If indexPrefix is null, |
| * "IX_" is used for prefix. To make the name short enough we: |
| * |
| * <pre> |
| * 1. Drop the prefix. |
| * 2. Drop the underscore characters if any. |
| * 3. Drop the vowels from the table and key name. |
| * 4. Truncate the table name to zero length if necessary. |
| * </pre> |
| */ |
| protected String buildIndexName(String tableName, String key, String indexPrefix, int maximumNameLength, DatabasePlatform platform) { |
| String startDelimiter = ""; |
| String endDelimiter = ""; |
| boolean useDelimiters = !platform.getStartDelimiter().equals("") && (tableName.startsWith(platform.getStartDelimiter()) || key.startsWith(platform.getStartDelimiter())); |
| // we will only delimit our generated indices if either of the names that composes them is already delimited |
| if (useDelimiters){ |
| startDelimiter = platform.getStartDelimiter(); |
| endDelimiter = platform.getEndDelimiter(); |
| } |
| String adjustedTableName = tableName; |
| if(adjustedTableName.indexOf(' ') != -1 || adjustedTableName.indexOf('\"') != -1 || adjustedTableName.indexOf('`') != -1) { |
| //if table name has spaces and/or is quoted, remove this from the constraint name. |
| StringBuilder buff = new StringBuilder(); |
| for(int i = 0; i < tableName.length(); i++) { |
| char c = tableName.charAt(i); |
| if(c != ' ' && c != '\"' && c != '`') { |
| buff.append(c); |
| } |
| } |
| adjustedTableName = buff.toString(); |
| } |
| StringBuilder buff = new StringBuilder(); |
| for(int i = 0; i < key.length(); i++) { |
| char c = key.charAt(i); |
| if(c != ' ' && c != '\"' && c != '`') { |
| buff.append(c); |
| } |
| } |
| String adjustedFieldName = buff.toString(); |
| if (indexPrefix == null) { |
| indexPrefix = "IX_"; |
| } |
| String indexName = startDelimiter + indexPrefix + adjustedTableName + "_" + adjustedFieldName + endDelimiter; |
| if (indexName.length() > maximumNameLength) { |
| // First Remove the prefix. |
| indexName = startDelimiter + adjustedTableName + "_" + adjustedFieldName + endDelimiter; |
| if (indexName.length() > maximumNameLength) { |
| // Still too long: remove the underscore characters |
| indexName = startDelimiter + Helper.removeAllButAlphaNumericToFit(adjustedTableName + adjustedFieldName, maximumNameLength) + endDelimiter; |
| if (indexName.length() > maximumNameLength) { |
| // Still too long: remove vowels from the table name and field name. |
| String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(adjustedTableName, 0); |
| String onlyAlphaNumericFieldName = Helper.removeAllButAlphaNumericToFit(adjustedFieldName, 0); |
| indexName = startDelimiter + Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, onlyAlphaNumericFieldName, maximumNameLength) + endDelimiter; |
| if (indexName.length() > maximumNameLength) { |
| // Still too long: remove vowels from the table name and field name and truncate the table name. |
| String shortenedFieldName = Helper.removeVowels(onlyAlphaNumericFieldName); |
| String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName); |
| int delimiterLength = startDelimiter.length() + endDelimiter.length(); |
| if (shortenedFieldName.length() + delimiterLength >= maximumNameLength) { |
| indexName = startDelimiter + Helper.truncate(shortenedFieldName, maximumNameLength - delimiterLength) + endDelimiter; |
| } else { |
| indexName = startDelimiter + Helper.truncate(shortenedTableName, maximumNameLength - shortenedFieldName.length() - delimiterLength) + shortenedFieldName + endDelimiter; |
| } |
| } |
| } |
| } |
| } |
| return indexName; |
| } |
| |
| /** |
| * PUBLIC: |
| * Performs a deep copy of this table definition. |
| */ |
| @Override |
| public Object clone() { |
| TableDefinition clone = (TableDefinition)super.clone(); |
| if (fields != null) { |
| clone.setFields(new ArrayList<>(fields.size())); |
| for (FieldDefinition fieldDef : getFields()) { |
| clone.addField((FieldDefinition)fieldDef.clone()); |
| } |
| } |
| if (foreignKeyMap != null) { |
| clone.setForeignKeyMap(new HashMap<>(this.foreignKeyMap)); |
| } |
| if (uniqueKeys != null) { |
| clone.setUniqueKeys(new ArrayList<>(this.uniqueKeys)); |
| } |
| return clone; |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the SQL alter table constraint creation string. |
| */ |
| public void createConstraints(AbstractSession session, Writer schemaWriter) throws EclipseLinkException { |
| createUniqueConstraints(session, schemaWriter); |
| createForeignConstraints(session, schemaWriter); |
| } |
| |
| void createUniqueConstraints(final AbstractSession session, final Writer schemaWriter) throws ValidationException { |
| if (schemaWriter == null) { |
| createUniqueConstraintsOnDatabase(session); |
| return; |
| } |
| |
| if ((!session.getPlatform().supportsUniqueKeyConstraints()) |
| || getUniqueKeys().isEmpty() |
| || session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) { |
| return; |
| } |
| for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) { |
| buildUniqueConstraintCreationWriter(session, uniqueKey, schemaWriter); |
| writeLineSeperator(session, schemaWriter); |
| } |
| } |
| |
| void createForeignConstraints(final AbstractSession session, final Writer schemaWriter) throws ValidationException { |
| if (schemaWriter == null) { |
| createForeignConstraintsOnDatabase(session); |
| return; |
| } |
| |
| if (session.getPlatform().supportsForeignKeyConstraints()) { |
| for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) { |
| if (! foreignKey.disableForeignKey()) { |
| buildConstraintCreationWriter(session, foreignKey, schemaWriter); |
| writeLineSeperator(session, schemaWriter); |
| } |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the SQL alter table constraint creation string. |
| */ |
| public void createConstraintsOnDatabase(AbstractSession session) throws EclipseLinkException { |
| createUniqueConstraintsOnDatabase(session); |
| createForeignConstraintsOnDatabase(session); |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to create the database schema for this object. |
| */ |
| @Override |
| public void createDatabaseSchema(AbstractSession session, Writer writer, Set<String> createdDatabaseSchemas) throws EclipseLinkException { |
| buildDatabaseSchemaCreationWriter(session, writer, createdDatabaseSchemas); |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to create the database schema for this object. |
| */ |
| @Override |
| public void createDatabaseSchemaOnDatabase(AbstractSession session, Set<String> createdDatabaseSchemas) throws EclipseLinkException { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildDatabaseSchemaCreationWriter(session, new StringWriter(), createdDatabaseSchemas).toString())); |
| } |
| |
| void createUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException { |
| if ((!session.getPlatform().supportsUniqueKeyConstraints()) |
| || getUniqueKeys().isEmpty() |
| || session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) { |
| return; |
| } |
| |
| for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) { |
| session.priviledgedExecuteNonSelectingCall(new org.eclipse.persistence.queries.SQLCall(buildUniqueConstraintCreationWriter(session, uniqueKey, new StringWriter()).toString())); |
| } |
| } |
| |
| void createForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException { |
| if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeyMap().isEmpty()) { |
| return; |
| } |
| |
| for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) { |
| if (! foreignKey.disableForeignKey()) { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildConstraintCreationWriter(session, foreignKey, new StringWriter()).toString())); |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL:<br> |
| * Write the SQL create index string to create index if |
| * passed a writer, else delegate to a method that executes the string on |
| * the database. |
| * |
| * @throws ValidationException wraps any IOException from the writer |
| */ |
| public void createIndexes(AbstractSession session, Writer writer) { |
| if (!session.getPlatform().supportsIndexes()) { |
| return; |
| } |
| // Primary key |
| if (session.getPlatform().shouldCreateIndicesForPrimaryKeys()) { |
| List<String> primKeyList = getPrimaryKeyFieldNames(); |
| if (!primKeyList.isEmpty()) { |
| IndexDefinition index = buildIndex(session, primKeyList.get(0), primKeyList, false); |
| if (writer == null) { |
| index.createOnDatabase(session); |
| } else { |
| index.buildCreationWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| // Unique keys |
| if (session.getPlatform().shouldCreateIndicesOnUniqueKeys()) { |
| // indices for columns in unique key constraint declarations |
| for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) { |
| IndexDefinition index = buildIndex(session, uniqueKey.getName(), uniqueKey.getSourceFields(), false); |
| if (writer == null) { |
| index.createOnDatabase(session); |
| } else { |
| index.buildCreationWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| |
| // indices for columns with unique=true declarations |
| for (FieldDefinition field : getFields()) { |
| if (field.isUnique()) { |
| List<String> columnAsList = new ArrayList<>(); |
| columnAsList.add(field.getName()); |
| IndexDefinition index = buildIndex(session, field.getName(), columnAsList, true); |
| if (writer == null) { |
| index.createOnDatabase(session); |
| } else { |
| index.buildCreationWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| } |
| // Foreign keys |
| if (session.getPlatform().shouldCreateIndicesOnForeignKeys()) { |
| // indices for columns in foreign key constraint declarations |
| for (ForeignKeyConstraint foreignKey : getForeignKeys()) { |
| if (!foreignKey.isDisableForeignKey()) { |
| // Do not re-index pk. |
| boolean alreadyIndexed = false; |
| List<String> primaryKeys = getPrimaryKeyFieldNames(); |
| if ((primaryKeys.size() == foreignKey.getSourceFields().size()) |
| && primaryKeys.containsAll(foreignKey.getSourceFields())) { |
| alreadyIndexed = true; |
| } |
| // Also check unique fields. |
| if (foreignKey.getSourceFields().size() == 1) { |
| FieldDefinition field = getField(foreignKey.getSourceFields().get(0)); |
| if ((field != null) && field.isUnique()) { |
| alreadyIndexed = true; |
| } |
| } |
| for (UniqueKeyConstraint uniqueConstraint : getUniqueKeys()) { |
| if ((uniqueConstraint.getSourceFields().size() == foreignKey.getSourceFields().size()) |
| && uniqueConstraint.getSourceFields().containsAll(foreignKey.getSourceFields())) { |
| alreadyIndexed = true; |
| } |
| } |
| if (!alreadyIndexed) { |
| IndexDefinition index = buildIndex(session, foreignKey.getName(), foreignKey.getSourceFields(), false); |
| if (writer == null) { |
| try { |
| index.createOnDatabase(session); |
| } catch (Exception failed) { |
| //ignore |
| } |
| } else { |
| index.buildCreationWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| } |
| } |
| // Indexes |
| for (IndexDefinition index : getIndexes()) { |
| if (writer == null) { |
| index.createOnDatabase(session); |
| } else { |
| index.buildCreationWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| |
| public void writeLineSeperator(AbstractSession session, Writer writer) { |
| try { |
| if (this.createSQLFiles) { |
| writer.write(session.getPlatform().getStoredProcedureTerminationToken()); |
| } |
| writer.write("\n"); |
| } catch (IOException exception) { |
| throw ValidationException.fileError(exception); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the delete SQL string. |
| */ |
| public String deletionStringFor(DatabaseAccessor accessor) { |
| return "DROP TABLE " + this.getName(); |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to drop the database schema for this object. |
| */ |
| @Override |
| public void dropDatabaseSchema(AbstractSession session, Writer writer) throws EclipseLinkException { |
| buildDatabaseSchemaDeletionWriter(session, writer); |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the DDL to drop the database schema for this object. |
| */ |
| @Override |
| public void dropDatabaseSchemaOnDatabase(AbstractSession session) throws EclipseLinkException { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildDatabaseSchemaDeletionWriter(session, new StringWriter()).toString())); |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the SQL alter table constraint creation string. |
| */ |
| public void dropConstraints(AbstractSession session, Writer schemaWriter) throws EclipseLinkException { |
| if (schemaWriter == null) { |
| dropConstraintsOnDatabase(session); |
| } else { |
| if (session.getPlatform().supportsForeignKeyConstraints()){ |
| for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) { |
| buildConstraintDeletionWriter(session, foreignKey, schemaWriter); |
| writeLineSeperator(session, schemaWriter); |
| } |
| } |
| if (session.getPlatform().supportsUniqueKeyConstraints() |
| && (!session.getPlatform().requiresUniqueConstraintCreationOnTableCreate())) { |
| for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) { |
| buildUniqueConstraintDeletionWriter(session, uniqueKey, schemaWriter); |
| writeLineSeperator(session, schemaWriter); |
| } |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Execute the SQL alter table constraint creation string. Exceptions are caught and masked so that all |
| * the foreign keys are dropped (even if they don't exist). |
| */ |
| public void dropConstraintsOnDatabase(AbstractSession session) throws EclipseLinkException { |
| dropForeignConstraintsOnDatabase(session); |
| dropUniqueConstraintsOnDatabase(session); |
| } |
| |
| private void dropUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException { |
| if ((!session.getPlatform().supportsUniqueKeyConstraints()) |
| || getUniqueKeys().isEmpty() |
| || session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) { |
| return; |
| } |
| |
| for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) { |
| try { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildUniqueConstraintDeletionWriter(session, uniqueKey, new StringWriter()).toString())); |
| } catch (DatabaseException ex) {/* ignore */ |
| } |
| } |
| } |
| |
| private void dropForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException { |
| if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeyMap().isEmpty()) { |
| return; |
| } |
| |
| for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) { |
| try { |
| session.priviledgedExecuteNonSelectingCall(new SQLCall(buildConstraintDeletionWriter(session, foreignKey, new StringWriter()).toString())); |
| } catch (DatabaseException ex) {/* ignore */ |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL:<br> |
| * Write the SQL drop index string to drop indexes if passed a writer, |
| * else delegate to a method that executes the string on the database. |
| * @throws ValidationException wraps any IOException from the writer |
| */ |
| public void dropIndexes(AbstractSession session, Writer writer) { |
| if (!session.getPlatform().supportsIndexes()) { |
| return; |
| } |
| // Primary key |
| if (session.getPlatform().shouldCreateIndicesForPrimaryKeys()) { |
| List<String> primKeyList = getPrimaryKeyFieldNames(); |
| if (!primKeyList.isEmpty()) { |
| IndexDefinition index = buildIndex(session, primKeyList.get(0), primKeyList, false); |
| if (writer == null) { |
| try { |
| index.dropFromDatabase(session); |
| } catch (Exception notThere) { |
| //ignore |
| } |
| } else { |
| index.buildDeletionWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| // Unique keys |
| if (session.getPlatform().shouldCreateIndicesOnUniqueKeys()) { |
| // indices for columns in unique key constraint declarations |
| for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) { |
| IndexDefinition index = buildIndex(session, uniqueKey.getName(), uniqueKey.getSourceFields(), false); |
| if (writer == null) { |
| try { |
| index.dropFromDatabase(session); |
| } catch (Exception notThere) { |
| //ignore |
| } |
| } else { |
| index.buildDeletionWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| |
| // indices for columns with unique=true declarations |
| for (FieldDefinition field : getFields()) { |
| if (field.isUnique()) { |
| List<String> columnAsList = new ArrayList<>(); |
| columnAsList.add(field.getName()); |
| IndexDefinition index = buildIndex(session, field.getName(), columnAsList, true); |
| if (writer == null) { |
| try { |
| index.dropFromDatabase(session); |
| } catch (Exception notThere) { |
| //ignore |
| } |
| } else { |
| index.buildDeletionWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| } |
| // Foreign keys |
| if (session.getPlatform().shouldCreateIndicesOnForeignKeys()) { |
| // indices for columns in foreign key constraint declarations |
| for (ForeignKeyConstraint foreignKey : getForeignKeys()) { |
| if (!foreignKey.isDisableForeignKey()) { |
| // Do not re-index pk. |
| boolean alreadyIndexed = false; |
| List<String> primaryKeys = getPrimaryKeyFieldNames(); |
| if ((primaryKeys.size() == foreignKey.getSourceFields().size()) |
| && primaryKeys.containsAll(foreignKey.getSourceFields())) { |
| alreadyIndexed = true; |
| } |
| // Also check unique fields. |
| if (foreignKey.getSourceFields().size() == 1) { |
| FieldDefinition field = getField(foreignKey.getSourceFields().get(0)); |
| if ((field != null) && field.isUnique()) { |
| alreadyIndexed = true; |
| } |
| } |
| for (UniqueKeyConstraint uniqueConstraint : getUniqueKeys()) { |
| if ((uniqueConstraint.getSourceFields().size() == foreignKey.getSourceFields().size()) |
| && uniqueConstraint.getSourceFields().containsAll(foreignKey.getSourceFields())) { |
| alreadyIndexed = true; |
| } |
| } |
| if (!alreadyIndexed) { |
| IndexDefinition index = buildIndex(session, foreignKey.getName(), foreignKey.getSourceFields(), false); |
| if (writer == null) { |
| try { |
| index.dropFromDatabase(session); |
| } catch (Exception notThere) { |
| //ignore |
| } |
| } else { |
| index.buildDeletionWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| } |
| } |
| // Indexes |
| for (IndexDefinition index : getIndexes()) { |
| if (writer == null) { |
| try { |
| index.dropFromDatabase(session); |
| } catch (Exception notThere) { |
| //ignore |
| } |
| } else { |
| index.buildDeletionWriter(session, writer); |
| writeLineSeperator(session, writer); |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| public Map<String, ForeignKeyConstraint> getForeignKeyMap() { |
| return foreignKeyMap; |
| } |
| |
| /** |
| * INTERNAL: |
| */ |
| public void setForeignKeyMap(Map<String, ForeignKeyConstraint> foreignKeyMap) { |
| this.foreignKeyMap = foreignKeyMap; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the field the corresponds to the name. |
| */ |
| public FieldDefinition getField(String fieldName) { |
| for (FieldDefinition field : getFields()) { |
| if (field.getName().equals(fieldName)) { |
| return field; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public List<FieldDefinition> getFields() { |
| return fields; |
| } |
| |
| /** |
| * PUBLIC: |
| * Returns the ForeignKeyConstraint list. |
| */ |
| public Collection<ForeignKeyConstraint> getForeignKeys() { |
| return this.foreignKeyMap.values(); |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public List<UniqueKeyConstraint> getUniqueKeys() { |
| return uniqueKeys; |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public void setIndexes(List<IndexDefinition> indexes) { |
| this.indexes = indexes; |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public void setCreateVPDCalls(boolean createVPDCalls, String tenantFieldName) { |
| this.createVPDCalls = createVPDCalls; |
| this.tenantFieldName = tenantFieldName; |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public List<IndexDefinition> getIndexes() { |
| return indexes; |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public List<String> getPrimaryKeyFieldNames() { |
| List<String> keyNames = new ArrayList<>(); |
| |
| for (FieldDefinition field : getFields()) { |
| if (field.isPrimaryKey()) { |
| keyNames.add(field.getName()); |
| } |
| } |
| return keyNames; |
| } |
| |
| |
| /** |
| * Execute any statements required after the creation of the object |
| */ |
| @Override |
| public void postCreateObject(AbstractSession session, Writer createSchemaWriter, boolean createSQLFiles){ |
| // create indices on table's primary and unique keys (if required) |
| setCreateSQLFiles(createSQLFiles); |
| createIndexes(session, createSchemaWriter); |
| } |
| |
| /** |
| * Execute any statements required before the deletion of the object |
| */ |
| @Override |
| public void preDropObject(AbstractSession session, Writer dropSchemaWriter, boolean createSQLFiles) { |
| // drop indices on table's primary and unique keys (if required) |
| setCreateSQLFiles(createSQLFiles); |
| dropIndexes(session, dropSchemaWriter); |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public void setFields(List<FieldDefinition> fields) { |
| this.fields = fields; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the ForeignKeyConstraint list. |
| * If the list contains the same name foreign key constraints, only the first one of that name will be added. |
| */ |
| public void setForeignKeys(List<ForeignKeyConstraint> foreignKeys) { |
| this.foreignKeyMap.clear(); |
| if (foreignKeys != null) { |
| for( ForeignKeyConstraint foreignKey : foreignKeys) { |
| this.foreignKeyMap.put(foreignKey.getName(), foreignKey); |
| } |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public void setUniqueKeys(List<UniqueKeyConstraint> uniqueKeys) { |
| this.uniqueKeys = uniqueKeys; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the foreign key constraints for this table. |
| */ |
| public void setUserDefinedForeignKeyConstraints(Map<String, ForeignKeyConstraint> foreignKeyConstraints) { |
| foreignKeyMap = foreignKeyConstraints; |
| hasUserDefinedForeignKeyConstraints = true; |
| } |
| |
| /** |
| * If this table has a schema (and catalog specified) make sure it is |
| * created. |
| */ |
| @Override |
| public boolean shouldCreateDatabaseSchema(Set<String> createdDatabaseSchemas) { |
| return hasDatabaseSchema() && ! createdDatabaseSchemas.contains(getDatabaseSchema()); |
| } |
| |
| /** |
| * INTERNAL: |
| * Subclasses who care should override this method. |
| */ |
| @Override |
| public boolean shouldCreateVPDCalls(AbstractSession session) { |
| if (createVPDCalls) { |
| if (! session.getPlatform().supportsVPD()) { |
| throw ValidationException.vpdNotSupported(session.getPlatform().getClass().getName()); |
| } |
| } |
| |
| return createVPDCalls; |
| } |
| |
| /** |
| * PUBLIC: |
| */ |
| public void setCreateSQLFiles(boolean genFlag) { |
| this.createSQLFiles = genFlag; |
| } |
| |
| public DatabaseTable getTable() { |
| return table; |
| } |
| |
| public void setTable(DatabaseTable table) { |
| this.table = table; |
| } |
| } |