More convenient multi-column indexing! From Charlie.

This commit is contained in:
Par Winzell
2009-10-15 16:21:14 +00:00
parent 27b7790275
commit 8f25455481
2 changed files with 48 additions and 19 deletions
@@ -32,15 +32,21 @@ import java.lang.annotation.Target;
@Retention(value=RetentionPolicy.RUNTIME)
public @interface Index
{
/** Defines the name of the index. If this is defined, a static method must be defined on the
* record that provides the index configuration. The method must match one of the following
* two signatures:
/**
* Defines the name of the index.<p>
*
* If this annotation is on a field, an index is created for all fields annotated with this
* name in the order of the fields in the class.<p>
*
* If this is defined, a static method must be defined on the record that provides the index
* configuration. The method must match one of the following two signatures:
* <pre>
* public static ColumnExp[] indexName ()
* public static List<Tuple<SQLExpression, OrderBy.Order>> indexName ()
* public static List&lt;Tuple&lt;SQLExpression, OrderBy.Order>> indexName ()
* </pre>
* The first form will result in a simple multicolum index being created with the supplied
* columns. The second will create a function index using the supplied SQLExpressions.
* The first form will result in a simple multicolum index being created
* with the supplied columns. The second will create a function index using the supplied
* SQLExpressions.
*/
String name () default "";
@@ -23,6 +23,9 @@ package com.samskivert.depot.impl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
@@ -30,10 +33,9 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -44,6 +46,7 @@ import com.samskivert.util.Tuple;
import com.samskivert.jdbc.ColumnDefinition;
import com.samskivert.jdbc.DatabaseLiaison;
import com.samskivert.depot.DatabaseException;
import com.samskivert.depot.Key;
import com.samskivert.depot.PersistenceContext;
@@ -60,11 +63,10 @@ import com.samskivert.depot.annotation.Index;
import com.samskivert.depot.annotation.TableGenerator;
import com.samskivert.depot.annotation.Transient;
import com.samskivert.depot.annotation.UniqueConstraint;
import com.samskivert.depot.clause.OrderBy.Order;
import com.samskivert.depot.clause.QueryClause;
import com.samskivert.depot.clause.OrderBy.Order;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.expression.SQLExpression;
import com.samskivert.depot.impl.clause.CreateIndexClause;
import static com.samskivert.depot.Log.log;
@@ -112,8 +114,12 @@ public class DepotMarshaller<T extends PersistentRecord>
boolean seenIdentityGenerator = false;
// introspect on the class and create marshallers for persistent fields
// introspect on the class and create marshallers and indices for persistent fields
List<ColumnExp> fields = Lists.newArrayList();
ListMultimap<String, Tuple<SQLExpression, Order>> namedFieldIndices =
ArrayListMultimap.create();
ListMultimap<String, Tuple<SQLExpression, Order>> uniqueNamedFieldIndices =
ArrayListMultimap.create();
for (Field field : _pClass.getFields()) {
int mods = field.getModifiers();
@@ -136,7 +142,8 @@ public class DepotMarshaller<T extends PersistentRecord>
FieldMarshaller<?> fm = FieldMarshaller.createMarshaller(field);
_fields.put(field.getName(), fm);
fields.add(new ColumnExp(_pClass, field.getName()));
ColumnExp fieldColumn = new ColumnExp(_pClass, field.getName());
fields.add(fieldColumn);
// check to see if this is our primary key
if (field.getAnnotation(Id.class) != null) {
@@ -197,19 +204,35 @@ public class DepotMarshaller<T extends PersistentRecord>
// check whether this field is indexed
Index index = field.getAnnotation(Index.class);
if (index != null) {
String ixName = index.name().equals("") ? field.getName() + "Index" : index.name();
_indexes.add(buildIndex(ixName, index.unique(),
new ColumnExp(_pClass, field.getName())));
String name = index.name().equals("") ? field.getName() + "Index" : index.name();
Tuple<SQLExpression, Order> entry =
new Tuple<SQLExpression, Order>(fieldColumn, Order.ASC);
if (index.unique()) {
Preconditions.checkArgument(!namedFieldIndices.containsKey(index.name()),
"All @Index for a particular name must be unique or non-unique");
uniqueNamedFieldIndices.put(name, entry);
} else {
Preconditions.checkArgument(
!uniqueNamedFieldIndices.containsKey(index.name()),
"All @Index for a particular name must be unique or non-unique");
namedFieldIndices.put(name, entry);
}
}
// if this column is marked as unique, that also means we create an index
Column column = field.getAnnotation(Column.class);
if (column != null && column.unique()) {
_indexes.add(buildIndex(field.getName() + "Index", true,
new ColumnExp(_pClass, field.getName())));
_indexes.add(buildIndex(field.getName() + "Index", true, fieldColumn));
}
}
for (String indexName : namedFieldIndices.keySet()) {
_indexes.add(buildIndex(indexName, false, namedFieldIndices.get(indexName)));
}
for (String indexName : uniqueNamedFieldIndices.keySet()) {
_indexes.add(buildIndex(indexName, true, uniqueNamedFieldIndices.get(indexName)));
}
// if we did not find a schema version field, freak out (but not for computed records, for
// whom there is no table)
if (_tableName != null && _schemaVersion <= 0) {