blob: 0e76c53c398f35406039f09642003c3ec5d520a3 [file] [log] [blame]
/*
* Copyright (c) 2008, 2009, 2011-2013, 2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.internal.db.ddl;
import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.db.ddl.IDBIndex;
import org.eclipse.net4j.db.ddl.IDBIndexField;
import org.eclipse.net4j.db.ddl.IDBSchema;
import org.eclipse.net4j.db.ddl.IDBSchemaElement;
import org.eclipse.net4j.db.ddl.IDBSchemaVisitor;
import org.eclipse.net4j.db.ddl.IDBTable;
import org.eclipse.net4j.db.ddl.SchemaElementNotFoundException;
import org.eclipse.net4j.spi.db.ddl.InternalDBField;
import org.eclipse.net4j.spi.db.ddl.InternalDBIndex;
import org.eclipse.net4j.spi.db.ddl.InternalDBSchema;
import org.eclipse.net4j.spi.db.ddl.InternalDBTable;
import org.eclipse.net4j.util.om.OMPlatform;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class DBIndex extends DBSchemaElement implements InternalDBIndex
{
public static final ThreadLocal<Boolean> FIX_NULLABLE_INDEX_COLUMNS = new InheritableThreadLocal<Boolean>();
public static final ThreadLocal<Set<IDBField>> NULLABLE_INDEX_FIELDS = new InheritableThreadLocal<Set<IDBField>>();
private static final boolean DISABLE_NULLABLE_CHECK = Boolean
.parseBoolean(OMPlatform.INSTANCE.getProperty("org.eclipse.net4j.db.DisableNullableCheck", "true"));
private static final long serialVersionUID = 1L;
private IDBTable table;
private Type type;
private List<IDBIndexField> indexFields = new ArrayList<IDBIndexField>();
public DBIndex(IDBTable table, String name, Type type, IDBField[] fields)
{
super(name);
this.table = table;
this.type = type;
for (int i = 0; i < fields.length; i++)
{
IDBField field = fields[i];
addIndexField(field);
}
}
/**
* Constructor for deserialization.
*/
protected DBIndex()
{
}
@Override
public IDBIndex getWrapper()
{
return (IDBIndex)super.getWrapper();
}
public SchemaElementType getSchemaElementType()
{
return SchemaElementType.INDEX;
}
public IDBSchema getSchema()
{
return table.getSchema();
}
public IDBTable getTable()
{
return table;
}
public IDBTable getParent()
{
return getTable();
}
public Type getType()
{
return type;
}
public void setType(Type type)
{
assertUnlocked();
this.type = type;
}
@Deprecated
public int getPosition()
{
IDBIndex[] indices = table.getIndices();
return Arrays.asList(indices).indexOf(this);
}
public IDBIndexField addIndexField(IDBField field)
{
assertUnlocked();
if (type != Type.NON_UNIQUE && !field.isNotNull())
{
if (!DISABLE_NULLABLE_CHECK && FIX_NULLABLE_INDEX_COLUMNS.get() != Boolean.TRUE)
{
Exception constructionStackTrace = ((InternalDBField)field).getConstructionStackTrace();
throw new DBException(
"Index field is nullable: " + field //$NON-NLS-1$
+ " (to disable this check run with '-Dorg.eclipse.net4j.db.DisableNullableCheck=true')",
constructionStackTrace);
}
Set<IDBField> nullableIndexFields = NULLABLE_INDEX_FIELDS.get();
if (nullableIndexFields == null)
{
nullableIndexFields = new HashSet<IDBField>();
NULLABLE_INDEX_FIELDS.set(nullableIndexFields);
}
nullableIndexFields.add(field);
}
if (field.getTable() != table)
{
throw new DBException("Index field is from different table: " + field); //$NON-NLS-1$
}
String name = field.getName();
if (getIndexField(name) != null)
{
throw new DBException("Index field exists: " + name); //$NON-NLS-1$
}
int position = indexFields.size();
IDBIndexField indexField = new DBIndexField(this, field, position);
indexFields.add(indexField);
resetElements();
return indexField;
}
public IDBIndexField addIndexField(String name) throws SchemaElementNotFoundException
{
IDBField field = table.getFieldSafe(name);
return addIndexField(field);
}
public void removeIndexField(IDBIndexField indexFieldToRemove)
{
assertUnlocked();
boolean found = false;
for (Iterator<IDBIndexField> it = indexFields.iterator(); it.hasNext();)
{
IDBIndexField indexField = it.next();
if (found)
{
((InternalDBField)indexField).setPosition(indexField.getPosition() - 1);
}
else if (indexField == indexFieldToRemove)
{
it.remove();
found = true;
}
}
resetElements();
}
public IDBIndexField getIndexFieldSafe(String name) throws SchemaElementNotFoundException
{
IDBIndexField indexField = getIndexField(name);
if (indexField == null)
{
throw new SchemaElementNotFoundException(this, SchemaElementType.INDEX_FIELD, name);
}
return indexField;
}
public IDBIndexField getIndexField(String name)
{
return findElement(getIndexFields(), name);
}
public IDBIndexField getIndexField(int position)
{
return indexFields.get(position);
}
public IDBField getFieldSafe(String name) throws SchemaElementNotFoundException
{
IDBIndexField indexField = getIndexFieldSafe(name);
return indexField.getField();
}
public IDBField getField(String name)
{
name = name(name);
for (IDBIndexField indexField : indexFields)
{
if (indexField.getName() == name)
{
return indexField.getField();
}
}
return null;
}
public IDBField getField(int position)
{
return indexFields.get(position).getField();
}
public int getFieldCount()
{
return indexFields.size();
}
public IDBIndexField[] getIndexFields()
{
return indexFields.toArray(new IDBIndexField[indexFields.size()]);
}
public IDBField[] getFields()
{
IDBField[] fields = new IDBField[indexFields.size()];
for (int i = 0; i < fields.length; i++)
{
fields[i] = getField(i);
}
return fields;
}
public String getFullName()
{
return getName();
}
public void remove()
{
((InternalDBTable)table).removeIndex(this);
}
@Override
protected void collectElements(List<IDBSchemaElement> elements)
{
elements.addAll(indexFields);
}
@Override
protected void doAccept(IDBSchemaVisitor visitor)
{
visitor.visit(this);
}
@Override
protected void dumpAdditionalProperties(Writer writer) throws IOException
{
writer.append(", type=");
writer.append(String.valueOf(getType()));
}
private void assertUnlocked()
{
((InternalDBSchema)table.getSchema()).assertUnlocked();
}
}