All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.curs.celesta.score.Index Maven / Gradle / Ivy

The newest version!
package ru.curs.celesta.score;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

/**
 * Table index. Celesta permits only creation of simple indices without
 * UNIQUE restriction.
 */
public class Index extends GrainElement implements HasColumns {

    private static final Logger LOGGER = LoggerFactory.getLogger(Index.class);

    private static final String INDEX_CREATION_ERROR = "Error while creating index '%s': column '%s' in table '%s' is ";
    private final BasicTable table;
    private final NamedElementHolder> columns = new NamedElementHolder<>() {
        @Override
        protected String getErrorMsg(String name) {
            return String.format("Column '%s' is defined more than once in index '%s'", name, getName());
        }
    };

    Index(GrainPart grainPart, String tableName, String name) throws ParseException {
        super(grainPart, name);
        if (tableName == null) {
            throw new IllegalArgumentException();
        }
        table = getGrain().getElement(tableName, BasicTable.class);
        getGrain().addIndex(this);
        table.addIndex(this);
    }

    public Index(BasicTable t, String name, String[] columns) throws ParseException {
        this(t.getGrainPart(), t.getName(), name);
        for (String n : columns) {
            addColumn(n);
        }
        finalizeIndex();
    }

    /**
     * Returns table of the index.
     *
     * @return
     */
    public BasicTable getTable() {
        return table;
    }

    /**
     * Adds a column to the index.
     *
     * @param columnName  column name (such column should exist in the table)
     * @throws ParseException  in case if the column is not found, or is already
     *                         available in the index, or is of type IMAGE
     */
    void addColumn(String columnName) throws ParseException {
        if (columnName == null) {
            throw new IllegalArgumentException();
        }
        Column c = table.getColumns().get(columnName);
        if (c == null) {
            throw new ParseException(
                    String.format(INDEX_CREATION_ERROR + "not defined.", getName(), columnName, table.getName()));
        }
        if (c instanceof BinaryColumn) {
            throw new ParseException(String.format(
                    INDEX_CREATION_ERROR + "of long binary type and therefore cannot be a part of an index.", getName(),
                    columnName, table.getName()));
        }
        if (c instanceof StringColumn && ((StringColumn) c).isMax()) {
            throw new ParseException(
                    String.format(INDEX_CREATION_ERROR + "of TEXT type and therefore cannot be a part of an index.",
                            getName(), columnName, table.getName()));
        }

        if (c.isNullable()) {
            LOGGER.warn(
                    "WARNING for index '{}': column '{}' in table '{}' is nullable and this can affect performance.",
                    getName(), columnName, table.getName());
        }

        columns.addElement(c);
    }

    /**
     * Finalizes the index.
     *
     * @throws ParseException  in case if there's already an index on the table
     *                         that duplicates the set of fields of this index.
     */
    void finalizeIndex() throws ParseException {
        if (Arrays.equals(
                getColumns().entrySet().toArray(),
                table.getPrimaryKey().entrySet().toArray()
        )) {
            throw new ParseException(
                    String.format("Can't add index %s to table %s.%s. "
                                  + "Primary key with same columns and order already exists.",
                            getName(), table.getGrain().getName(), table.getName())
            );
        }
        // Finding indices duplicated by fields content
        for (Index ind : getGrain().getIndices().values()) {
            if (ind == this) {
                continue;
            }
            if (ind.table != table) {
                continue;
            }
            if (ind.columns.size() != columns.size()) {
                continue;
            }
            Iterator> i = ind.columns.iterator();
            boolean coincide = true;
            for (Column c : columns) {
                if (c != i.next()) {
                    coincide = false;
                    break;
                }
            }
            if (coincide) {
                throw new ParseException(
                        String.format("Error while creating index '%s': it is duplicate of index '%s' for table '%s'",
                                getName(), ind.getName(), table.getName()));
            }
        }
    }

    /**
     * Returns columns of the index.
     *
     * @return
     */
    public Map> getColumns() {
        return columns.getElements();
    }

    /**
     * Deletes the index.
     *
     * @throws ParseException  when trying to change the system grain
     */
    public void delete() throws ParseException {
        getGrain().removeIndex(this);
    }

    @Override
    public int getColumnIndex(String name) {
        return columns.getIndex(name);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy