/* * Copyright 2007 - 2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sf.jailer.datamodel; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import net.sf.jailer.configuration.Configuration; import net.sf.jailer.util.Quoting; /** * Primary-key of a {@link Table}. * * @author Ralf Wisser */ public class PrimaryKey { /** * The primary-key columns. */ private final List<Column> columns; /** * Constructor. * * @param primaryKeyColumns the primary-key columns */ PrimaryKey(List<Column> columns) { this.columns = columns; } /** * Gets the primary-key columns. * * @return the primary-key columns */ public List<Column> getColumns() { return columns; } /** * Matches the columns with the columns of <code>primaryKey</code> * s.t. each column of <code>primaryKey</code> is assigned to a * column of this PK with same type. * * @param primaryKey to match * @return a match of all columns of <code>primaryKey</code> */ public Map<Column, Column> match(PrimaryKey primaryKey) { if (Configuration.getInstance().getDoMinimizeUPK()) { Set<Integer> assignedUPKColumns = new HashSet<Integer>(); Map<Column, Column> match = new HashMap<Column, Column>(); for (Column column: getColumns()) { for (int i = 0; i < primaryKey.getColumns().size(); ++i) { if (assignedUPKColumns.contains(i)) { continue; } Column otherColumn = primaryKey.getColumns().get(i); if (isAssignable(column, otherColumn)) { match.put(column, otherColumn); assignedUPKColumns.add(i); break; } } } return match; } else { Map<Column, Column> match = new HashMap<Column, Column>(); int i = 0; for (Column column: getColumns()) { Column otherColumn = primaryKey.getColumns().get(i); if (isAssignable(column, otherColumn)) { match.put(column, otherColumn); ++i; if (i >= primaryKey.columns.size()) { break; } } } return match; } } public static boolean isAssignable(Column uPKColumn, Column entityColumn) { if (!uPKColumn.type.equals(entityColumn.type)) { return false; } if (uPKColumn.length == 0 && entityColumn.length != 0) { return false; } if (uPKColumn.length != 0 && entityColumn.length == 0) { return false; } if (uPKColumn.length < entityColumn.length) { return false; } if (uPKColumn.precision < 0 && entityColumn.precision >= 0) { return false; } if (uPKColumn.precision >= 0 && entityColumn.precision < 0) { return false; } if (uPKColumn.precision < entityColumn.precision) { return false; } return true; } /** * Creates a comma-separated list of column names. * * @param columnPrefix an optional prefix for each PK-column */ public String columnList(String prefix) { return columnList(prefix, null); } /** * Creates a comma-separated list of column names. * * @param columnPrefix an optional prefix for each PK-column */ public String columnList(String prefix, Quoting quoting) { String list = ""; for (Column column: getColumns()) { if (list.length() > 0) { list += ", "; } if (prefix != null) { list += prefix; } list += quoting != null? quoting.requote(column.name) : column.name; } return list; } /** * Returns the primary key in SQL syntax. * * @param columnPrefix an optional prefix for each PK-column */ public String toSQL(String columnPrefix) { return toSQL(columnPrefix, true); } /** * Returns the primary key in SQL syntax. * * @param columnPrefix an optional prefix for each PK-column */ public String toSQL(String columnPrefix, boolean withContraints) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < columns.size(); ++i) { if (i > 0) { sb.append(", "); } sb.append(columns.get(i).toSQL(columnPrefix) + (withContraints? " NOT NULL" : "")); } return sb.toString(); } /** * Returns the primary key in SQL syntax. * * @param columnPrefix an optional prefix for each PK-column * @param typeReplacement column types replacements */ public String toSQL(String columnPrefix, String contraint, Map<String, String> typeReplacement) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < columns.size(); ++i) { if (i > 0) { sb.append(", "); } sb.append(columns.get(i).toSQL(columnPrefix, typeReplacement) + " " + contraint); } return sb.toString(); } /** * Returns a string representation of the primary key. */ public String toString() { return toSQL(null); } public static boolean isIncreasable(Column uPKColumn, Column column) { if(!uPKColumn.type.equals(column.type)) { return false; } if((uPKColumn.precision < 0) && (column.precision >=0) ) { return false; } if((uPKColumn.precision >=0) && (column.precision < 0)) { return false; } if(uPKColumn.length == 0 && column.length > 0) { return false; } if(uPKColumn.length < column.length) { return true; } if(uPKColumn.precision < column.precision) { return true; } // never should get THIS far ! return false; } }