Great big revampage: no more strings anywhere. It's all ColumnExps all the way
down (well, all the way to the public API anyway). Revamped index creation while I was in there because that was one of the big string users. Now you just put @Index on the field you want indexed, and if you want a multi-column index you do things with a magical static method just like we do for complex (function) indices. @UniqueConstraint may still go away since it's basically exactly the same thing as @Index(unique=true), so it's kind of pointless to support both.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
<project name="library-dependencies">
|
<project name="library-dependencies">
|
||||||
<fileset dir="${libs.dir}" id="depot.libs">
|
<fileset dir="${libs.dir}" id="depot.libs">
|
||||||
<include name="ant.jar"/>
|
<include name="ant.jar"/>
|
||||||
|
<include name="commons-collections.jar"/>
|
||||||
<include name="ehcache.jar"/>
|
<include name="ehcache.jar"/>
|
||||||
<include name="google-collect.jar"/>
|
<include name="google-collect.jar"/>
|
||||||
<include name="junit4.jar"/>
|
<include name="junit4.jar"/>
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import com.samskivert.depot.clause.InsertClause;
|
|||||||
import com.samskivert.depot.clause.QueryClause;
|
import com.samskivert.depot.clause.QueryClause;
|
||||||
import com.samskivert.depot.clause.UpdateClause;
|
import com.samskivert.depot.clause.UpdateClause;
|
||||||
import com.samskivert.depot.clause.WhereClause;
|
import com.samskivert.depot.clause.WhereClause;
|
||||||
|
import com.samskivert.depot.expression.ColumnExp;
|
||||||
import com.samskivert.depot.expression.SQLExpression;
|
import com.samskivert.depot.expression.SQLExpression;
|
||||||
import com.samskivert.depot.expression.ValueExp;
|
import com.samskivert.depot.expression.ValueExp;
|
||||||
import com.samskivert.depot.impl.DepotMarshaller;
|
import com.samskivert.depot.impl.DepotMarshaller;
|
||||||
@@ -55,8 +56,8 @@ import com.samskivert.depot.impl.DepotTypes;
|
|||||||
import com.samskivert.depot.impl.FindAllKeysQuery;
|
import com.samskivert.depot.impl.FindAllKeysQuery;
|
||||||
import com.samskivert.depot.impl.FindAllQuery;
|
import com.samskivert.depot.impl.FindAllQuery;
|
||||||
import com.samskivert.depot.impl.FindOneQuery;
|
import com.samskivert.depot.impl.FindOneQuery;
|
||||||
import com.samskivert.depot.impl.Modifier;
|
|
||||||
import com.samskivert.depot.impl.Modifier.*;
|
import com.samskivert.depot.impl.Modifier.*;
|
||||||
|
import com.samskivert.depot.impl.Modifier;
|
||||||
import com.samskivert.depot.impl.SQLBuilder;
|
import com.samskivert.depot.impl.SQLBuilder;
|
||||||
|
|
||||||
import static com.samskivert.depot.Log.log;
|
import static com.samskivert.depot.Log.log;
|
||||||
@@ -208,7 +209,7 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> T load (Class<T> type, String ix, Comparable<?> val,
|
protected <T extends PersistentRecord> T load (Class<T> type, ColumnExp ix, Comparable<?> val,
|
||||||
QueryClause... clauses)
|
QueryClause... clauses)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
@@ -221,8 +222,8 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> T load (Class<T> type, String ix1, Comparable<?> val1,
|
protected <T extends PersistentRecord> T load (Class<T> type, ColumnExp ix1, Comparable<?> val1,
|
||||||
String ix2, Comparable<?> val2,
|
ColumnExp ix2, Comparable<?> val2,
|
||||||
QueryClause... clauses)
|
QueryClause... clauses)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
@@ -235,8 +236,8 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> T load (Class<T> type, String ix1, Comparable<?> val1,
|
protected <T extends PersistentRecord> T load (Class<T> type, ColumnExp ix1, Comparable<?> val1,
|
||||||
String ix2, Comparable<?> val2, String ix3,
|
ColumnExp ix2, Comparable<?> val2, ColumnExp ix3,
|
||||||
Comparable<?> val3, QueryClause... clauses)
|
Comparable<?> val3, QueryClause... clauses)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
@@ -448,7 +449,7 @@ public abstract class DepotRepository
|
|||||||
updateKey(marsh.getPrimaryKey(_result, false));
|
updateKey(marsh.getPrimaryKey(_result, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.newQuery(new InsertClause<T>(pClass, _result, identityFields));
|
builder.newQuery(new InsertClause(pClass, _result, identityFields));
|
||||||
|
|
||||||
PreparedStatement stmt = builder.prepare(conn);
|
PreparedStatement stmt = builder.prepare(conn);
|
||||||
try {
|
try {
|
||||||
@@ -515,7 +516,7 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int update (T record, final String... modifiedFields)
|
protected <T extends PersistentRecord> int update (T record, final ColumnExp... modifiedFields)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
@SuppressWarnings("unchecked") Class<T> pClass = (Class<T>) record.getClass();
|
@SuppressWarnings("unchecked") Class<T> pClass = (Class<T>) record.getClass();
|
||||||
@@ -527,7 +528,8 @@ public abstract class DepotRepository
|
|||||||
throw new IllegalArgumentException("Can't update record with null primary key.");
|
throw new IllegalArgumentException("Can't update record with null primary key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateClause<T> update = new UpdateClause<T>(pClass, key, modifiedFields, record);
|
UpdateClause<T> update = new UpdateClause<T>(
|
||||||
|
pClass, key, ColumnExp.toNames(modifiedFields), record);
|
||||||
final SQLBuilder builder = _ctx.getSQLBuilder(DepotTypes.getDepotTypes(_ctx, update));
|
final SQLBuilder builder = _ctx.getSQLBuilder(DepotTypes.getDepotTypes(_ctx, update));
|
||||||
builder.newQuery(update);
|
builder.newQuery(update);
|
||||||
|
|
||||||
@@ -551,7 +553,7 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @param type the type of the persistent object to be modified.
|
* @param type the type of the persistent object to be modified.
|
||||||
* @param primaryKey the primary key to match in the update.
|
* @param primaryKey the primary key to match in the update.
|
||||||
* @param updates an mapping from the names of the fields/columns ti the values to be assigned.
|
* @param updates an mapping from the columns to the values to be assigned.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
*
|
*
|
||||||
@@ -560,12 +562,12 @@ public abstract class DepotRepository
|
|||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updatePartial (
|
protected <T extends PersistentRecord> int updatePartial (
|
||||||
Class<T> type, Comparable<?> primaryKey, Map<String,Object> updates)
|
Class<T> type, Comparable<?> primaryKey, Map<ColumnExp,Object> updates)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
Object[] fieldsValues = new Object[updates.size()*2];
|
Object[] fieldsValues = new Object[updates.size()*2];
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (Map.Entry<String,Object> entry : updates.entrySet()) {
|
for (Map.Entry<ColumnExp,Object> entry : updates.entrySet()) {
|
||||||
fieldsValues[idx++] = entry.getKey();
|
fieldsValues[idx++] = entry.getKey();
|
||||||
fieldsValues[idx++] = entry.getValue();
|
fieldsValues[idx++] = entry.getValue();
|
||||||
}
|
}
|
||||||
@@ -577,7 +579,7 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @param type the type of the persistent object to be modified.
|
* @param type the type of the persistent object to be modified.
|
||||||
* @param primaryKey the primary key to match in the update.
|
* @param primaryKey the primary key to match in the update.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues an array containing the columns (as ColumnExp) and the values to be
|
||||||
* assigned, in key, value, key, value, etc. order.
|
* assigned, in key, value, key, value, etc. order.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
@@ -598,7 +600,7 @@ public abstract class DepotRepository
|
|||||||
* primary key.
|
* primary key.
|
||||||
*
|
*
|
||||||
* @param type the type of the persistent object to be modified.
|
* @param type the type of the persistent object to be modified.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues an array containing the columns (as ColumnExp) and the values to be
|
||||||
* assigned, in key, value, key, value, etc. order.
|
* assigned, in key, value, key, value, etc. order.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
@@ -608,7 +610,7 @@ public abstract class DepotRepository
|
|||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updatePartial (
|
protected <T extends PersistentRecord> int updatePartial (
|
||||||
Class<T> type, String ix1, Comparable<?> val1, String ix2, Comparable<?> val2,
|
Class<T> type, ColumnExp ix1, Comparable<?> val1, ColumnExp ix2, Comparable<?> val2,
|
||||||
Object... fieldsValues)
|
Object... fieldsValues)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
@@ -620,7 +622,7 @@ public abstract class DepotRepository
|
|||||||
* primary key.
|
* primary key.
|
||||||
*
|
*
|
||||||
* @param type the type of the persistent object to be modified.
|
* @param type the type of the persistent object to be modified.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues an array containing the columns (as ColumnExp) and the values to be
|
||||||
* assigned, in key, value, key, value, etc. order.
|
* assigned, in key, value, key, value, etc. order.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
@@ -630,8 +632,8 @@ public abstract class DepotRepository
|
|||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updatePartial (
|
protected <T extends PersistentRecord> int updatePartial (
|
||||||
Class<T> type, String ix1, Comparable<?> val1, String ix2, Comparable<?> val2,
|
Class<T> type, ColumnExp ix1, Comparable<?> val1, ColumnExp ix2, Comparable<?> val2,
|
||||||
String ix3, Comparable<?> val3, Object... fieldsValues)
|
ColumnExp ix3, Comparable<?> val3, Object... fieldsValues)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
return updatePartial(new Key<T>(type, ix1, val1, ix2, val2, ix3, val3), fieldsValues);
|
return updatePartial(new Key<T>(type, ix1, val1, ix2, val2, ix3, val3), fieldsValues);
|
||||||
@@ -641,7 +643,7 @@ public abstract class DepotRepository
|
|||||||
* Updates the specified columns for all persistent objects matching the supplied key.
|
* Updates the specified columns for all persistent objects matching the supplied key.
|
||||||
*
|
*
|
||||||
* @param key the key for the persistent objects to be modified.
|
* @param key the key for the persistent objects to be modified.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues an array containing the columns (as ColumnExp) and the values to be
|
||||||
* assigned, in key, value, key, value, etc. order.
|
* assigned, in key, value, key, value, etc. order.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
@@ -666,7 +668,7 @@ public abstract class DepotRepository
|
|||||||
* @param key the key to match in the update.
|
* @param key the key to match in the update.
|
||||||
* @param invalidator a cache invalidator that will be run prior to the update to flush the
|
* @param invalidator a cache invalidator that will be run prior to the update to flush the
|
||||||
* relevant persistent objects from the cache, or null if no invalidation is needed.
|
* relevant persistent objects from the cache, or null if no invalidation is needed.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues an array containing the columns (as ColumnExp) and the values to be
|
||||||
* assigned, in key, value, key, value, etc. order.
|
* assigned, in key, value, key, value, etc. order.
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
@@ -688,7 +690,7 @@ public abstract class DepotRepository
|
|||||||
final String[] fields = new String[fieldsValues.length/2];
|
final String[] fields = new String[fieldsValues.length/2];
|
||||||
final SQLExpression[] values = new SQLExpression[fields.length];
|
final SQLExpression[] values = new SQLExpression[fields.length];
|
||||||
for (int ii = 0, idx = 0; ii < fields.length; ii++) {
|
for (int ii = 0, idx = 0; ii < fields.length; ii++) {
|
||||||
fields[ii] = (String)fieldsValues[idx++];
|
fields[ii] = ((ColumnExp)fieldsValues[idx++]).name;
|
||||||
values[ii] = new ValueExp(fieldsValues[idx++]);
|
values[ii] = new ValueExp(fieldsValues[idx++]);
|
||||||
}
|
}
|
||||||
UpdateClause<T> update = new UpdateClause<T>(type, key, fields, values);
|
UpdateClause<T> update = new UpdateClause<T>(type, key, fields, values);
|
||||||
@@ -720,8 +722,7 @@ public abstract class DepotRepository
|
|||||||
*
|
*
|
||||||
* @param type the type of the persistent object to be modified.
|
* @param type the type of the persistent object to be modified.
|
||||||
* @param primaryKey the key to match in the update.
|
* @param primaryKey the key to match in the update.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues a map containing the columns and the values to be assigned.
|
||||||
* assigned, in key, literal value, key, literal value, etc. order.
|
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
*
|
*
|
||||||
@@ -730,7 +731,7 @@ public abstract class DepotRepository
|
|||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updateLiteral (
|
protected <T extends PersistentRecord> int updateLiteral (
|
||||||
Class<T> type, Comparable<?> primaryKey, Map<String, SQLExpression> fieldsValues)
|
Class<T> type, Comparable<?> primaryKey, Map<ColumnExp, SQLExpression> fieldsValues)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
Key<T> key = _ctx.getMarshaller(type).makePrimaryKey(primaryKey);
|
Key<T> key = _ctx.getMarshaller(type).makePrimaryKey(primaryKey);
|
||||||
@@ -748,8 +749,7 @@ public abstract class DepotRepository
|
|||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param type the type of the persistent object to be modified.
|
* @param type the type of the persistent object to be modified.
|
||||||
* @param fieldsValues an array containing the names of the fields/columns and the values to be
|
* @param fieldsValues a map containing the columns and the values to be assigned.
|
||||||
* assigned, in key, literal value, key, literal value, etc. order.
|
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by this action.
|
* @return the number of rows modified by this action.
|
||||||
*
|
*
|
||||||
@@ -758,8 +758,8 @@ public abstract class DepotRepository
|
|||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updateLiteral (
|
protected <T extends PersistentRecord> int updateLiteral (
|
||||||
Class<T> type, String ix1, Comparable<?> val1, String ix2, Comparable<?> val2,
|
Class<T> type, ColumnExp ix1, Comparable<?> val1, ColumnExp ix2, Comparable<?> val2,
|
||||||
Map<String, SQLExpression> fieldsValues)
|
Map<ColumnExp, SQLExpression> fieldsValues)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
Key<T> key = new Key<T>(type, ix1, val1, ix2, val2);
|
Key<T> key = new Key<T>(type, ix1, val1, ix2, val2);
|
||||||
@@ -787,8 +787,8 @@ public abstract class DepotRepository
|
|||||||
* @throws DatabaseException if any problem is encountered communicating with the database.
|
* @throws DatabaseException if any problem is encountered communicating with the database.
|
||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updateLiteral (
|
protected <T extends PersistentRecord> int updateLiteral (
|
||||||
Class<T> type, String ix1, Comparable<?> val1, String ix2, Comparable<?> val2,
|
Class<T> type, ColumnExp ix1, Comparable<?> val1, ColumnExp ix2, Comparable<?> val2,
|
||||||
String ix3, Comparable<?> val3, Map<String, SQLExpression> fieldsValues)
|
ColumnExp ix3, Comparable<?> val3, Map<ColumnExp, SQLExpression> fieldsValues)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
Key<T> key = new Key<T>(type, ix1, val1, ix2, val2, ix3, val3);
|
Key<T> key = new Key<T>(type, ix1, val1, ix2, val2, ix3, val3);
|
||||||
@@ -818,7 +818,7 @@ public abstract class DepotRepository
|
|||||||
*/
|
*/
|
||||||
protected <T extends PersistentRecord> int updateLiteral (
|
protected <T extends PersistentRecord> int updateLiteral (
|
||||||
Class<T> type, final WhereClause key, CacheInvalidator invalidator,
|
Class<T> type, final WhereClause key, CacheInvalidator invalidator,
|
||||||
Map<String, SQLExpression> fieldsValues)
|
Map<ColumnExp, SQLExpression> fieldsValues)
|
||||||
throws DatabaseException
|
throws DatabaseException
|
||||||
{
|
{
|
||||||
requireNotComputed(type, "updateLiteral");
|
requireNotComputed(type, "updateLiteral");
|
||||||
@@ -832,8 +832,8 @@ public abstract class DepotRepository
|
|||||||
final String[] fields = new String[fieldsValues.size()];
|
final String[] fields = new String[fieldsValues.size()];
|
||||||
final SQLExpression[] values = new SQLExpression[fields.length];
|
final SQLExpression[] values = new SQLExpression[fields.length];
|
||||||
int ii = 0;
|
int ii = 0;
|
||||||
for (Map.Entry<String, SQLExpression> entry : fieldsValues.entrySet()) {
|
for (Map.Entry<ColumnExp, SQLExpression> entry : fieldsValues.entrySet()) {
|
||||||
fields[ii] = entry.getKey();
|
fields[ii] = entry.getKey().name;
|
||||||
values[ii] = entry.getValue();
|
values[ii] = entry.getValue();
|
||||||
ii ++;
|
ii ++;
|
||||||
}
|
}
|
||||||
@@ -907,7 +907,7 @@ public abstract class DepotRepository
|
|||||||
updateKey(marsh.getPrimaryKey(_result, false));
|
updateKey(marsh.getPrimaryKey(_result, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.newQuery(new InsertClause<T>(pClass, _result, identityFields));
|
builder.newQuery(new InsertClause(pClass, _result, identityFields));
|
||||||
|
|
||||||
stmt = builder.prepare(conn);
|
stmt = builder.prepare(conn);
|
||||||
int mods = stmt.executeUpdate();
|
int mods = stmt.executeUpdate();
|
||||||
@@ -1012,7 +1012,7 @@ public abstract class DepotRepository
|
|||||||
}
|
}
|
||||||
where.validateQueryType(type); // and another
|
where.validateQueryType(type); // and another
|
||||||
|
|
||||||
DeleteClause<T> delete = new DeleteClause<T>(type, where);
|
DeleteClause delete = new DeleteClause(type, where);
|
||||||
final SQLBuilder builder = _ctx.getSQLBuilder(DepotTypes.getDepotTypes(_ctx, delete));
|
final SQLBuilder builder = _ctx.getSQLBuilder(DepotTypes.getDepotTypes(_ctx, delete));
|
||||||
builder.newQuery(delete);
|
builder.newQuery(delete);
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.util.Map;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import com.samskivert.depot.clause.WhereClause;
|
import com.samskivert.depot.clause.WhereClause;
|
||||||
|
import com.samskivert.depot.expression.ColumnExp;
|
||||||
import com.samskivert.depot.expression.SQLExpression;
|
import com.samskivert.depot.expression.SQLExpression;
|
||||||
import com.samskivert.depot.impl.DepotMarshaller;
|
import com.samskivert.depot.impl.DepotMarshaller;
|
||||||
import com.samskivert.depot.impl.DepotUtil;
|
import com.samskivert.depot.impl.DepotUtil;
|
||||||
@@ -71,33 +72,42 @@ public class Key<T extends PersistentRecord> extends WhereClause
|
|||||||
/**
|
/**
|
||||||
* Constructs a new single-column {@code Key} with the given value.
|
* Constructs a new single-column {@code Key} with the given value.
|
||||||
*/
|
*/
|
||||||
public Key (Class<T> pClass, String ix, Comparable<?> val)
|
public Key (Class<T> pClass, ColumnExp ix, Comparable<?> val)
|
||||||
{
|
{
|
||||||
this(pClass, new String[] { ix }, new Comparable[] { val });
|
this(pClass, new ColumnExp[] { ix }, new Comparable[] { val });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new two-column {@code Key} with the given values.
|
* Constructs a new two-column {@code Key} with the given values.
|
||||||
*/
|
*/
|
||||||
public Key (Class<T> pClass, String ix1, Comparable<?> val1,
|
public Key (Class<T> pClass, ColumnExp ix1, Comparable<?> val1,
|
||||||
String ix2, Comparable<?> val2)
|
ColumnExp ix2, Comparable<?> val2)
|
||||||
{
|
{
|
||||||
this(pClass, new String[] { ix1, ix2 }, new Comparable[] { val1, val2 });
|
this(pClass, new ColumnExp[] { ix1, ix2 }, new Comparable[] { val1, val2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new three-column {@code Key} with the given values.
|
* Constructs a new three-column {@code Key} with the given values.
|
||||||
*/
|
*/
|
||||||
public Key (Class<T> pClass, String ix1, Comparable<?> val1,
|
public Key (Class<T> pClass, ColumnExp ix1, Comparable<?> val1,
|
||||||
String ix2, Comparable<?> val2, String ix3, Comparable<?> val3)
|
ColumnExp ix2, Comparable<?> val2, ColumnExp ix3, Comparable<?> val3)
|
||||||
{
|
{
|
||||||
this(pClass, new String[] { ix1, ix2, ix3 }, new Comparable[] { val1, val2, val3 });
|
this(pClass, new ColumnExp[] { ix1, ix2, ix3 }, new Comparable[] { val1, val2, val3 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMP: legacy foo bar!
|
||||||
|
*/
|
||||||
|
public Key (Class<T> pClass, String[] fields, Comparable<?>[] values)
|
||||||
|
{
|
||||||
|
_pClass = pClass;
|
||||||
|
_values = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new multi-column {@code Key} with the given values.
|
* Constructs a new multi-column {@code Key} with the given values.
|
||||||
*/
|
*/
|
||||||
public Key (Class<T> pClass, String[] fields, Comparable<?>[] values)
|
public Key (Class<T> pClass, ColumnExp[] fields, Comparable<?>[] values)
|
||||||
{
|
{
|
||||||
if (fields.length != values.length) {
|
if (fields.length != values.length) {
|
||||||
throw new IllegalArgumentException("Field and Value arrays must be of equal length.");
|
throw new IllegalArgumentException("Field and Value arrays must be of equal length.");
|
||||||
@@ -109,7 +119,7 @@ public class Key<T extends PersistentRecord> extends WhereClause
|
|||||||
// build a local map of field name -> field value
|
// build a local map of field name -> field value
|
||||||
Map<String, Comparable<?>> map = Maps.newHashMap();
|
Map<String, Comparable<?>> map = Maps.newHashMap();
|
||||||
for (int i = 0; i < fields.length; i ++) {
|
for (int i = 0; i < fields.length; i ++) {
|
||||||
map.put(fields[i], values[i]);
|
map.put(fields[i].name, values[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// look up the cached primary key fields for this object
|
// look up the cached primary key fields for this object
|
||||||
@@ -138,9 +148,10 @@ public class Key<T extends PersistentRecord> extends WhereClause
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to create a key when you know you have the canonical values array.
|
* Used to create a key when you know you have the canonical values array. Don't call this
|
||||||
|
* unless you know what you're doing!
|
||||||
*/
|
*/
|
||||||
protected Key (Class<T> pClass, Comparable<?>[] values)
|
public Key (Class<T> pClass, Comparable<?>[] values)
|
||||||
{
|
{
|
||||||
_pClass = pClass;
|
_pClass = pClass;
|
||||||
_values = values;
|
_values = values;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.google.common.base.Function;
|
|||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.samskivert.depot.clause.WhereClause;
|
import com.samskivert.depot.clause.WhereClause;
|
||||||
|
import com.samskivert.depot.expression.ColumnExp;
|
||||||
import com.samskivert.depot.expression.LiteralExp;
|
import com.samskivert.depot.expression.LiteralExp;
|
||||||
import com.samskivert.depot.expression.SQLExpression;
|
import com.samskivert.depot.expression.SQLExpression;
|
||||||
import com.samskivert.depot.impl.DepotUtil;
|
import com.samskivert.depot.impl.DepotUtil;
|
||||||
@@ -171,7 +172,8 @@ public abstract class KeySet<T extends PersistentRecord> extends WhereClause
|
|||||||
// from WhereClause
|
// from WhereClause
|
||||||
public SQLExpression getWhereExpression () {
|
public SQLExpression getWhereExpression () {
|
||||||
// Single-column keys result in the compact IN(keyVal1, keyVal2, ...)
|
// Single-column keys result in the compact IN(keyVal1, keyVal2, ...)
|
||||||
return new Conditionals.In(_pClass, DepotUtil.getKeyFields(_pClass)[0], _keys);
|
ColumnExp column = new ColumnExp(_pClass, DepotUtil.getKeyFields(_pClass)[0]);
|
||||||
|
return new Conditionals.In(column, _keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
// from Iterable<Key<T>>
|
// from Iterable<Key<T>>
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ package com.samskivert.depot;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.samskivert.depot.expression.ColumnExp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base class for all persistent records used in Depot. Persistent records must be cloneable
|
* The base class for all persistent records used in Depot. Persistent records must be cloneable
|
||||||
* and serializable; this class is used to enforce those requirements.
|
* and serializable; this class is used to enforce those requirements.
|
||||||
@@ -29,6 +31,10 @@ import java.io.Serializable;
|
|||||||
public class PersistentRecord
|
public class PersistentRecord
|
||||||
implements Cloneable, Serializable
|
implements Cloneable, Serializable
|
||||||
{
|
{
|
||||||
|
// AUTO-GENERATED: FIELDS START
|
||||||
|
public static final Class<PersistentRecord> _R = PersistentRecord.class;
|
||||||
|
// AUTO-GENERATED: FIELDS END
|
||||||
|
|
||||||
@Override // from Object
|
@Override // from Object
|
||||||
public PersistentRecord clone ()
|
public PersistentRecord clone ()
|
||||||
{
|
{
|
||||||
@@ -38,4 +44,13 @@ public class PersistentRecord
|
|||||||
throw new RuntimeException(cnse); // this should never happen
|
throw new RuntimeException(cnse); // this should never happen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a column expression for this class with the specified field name. Used by the
|
||||||
|
* autogenerated column expression constants.
|
||||||
|
*/
|
||||||
|
protected static ColumnExp colexp (Class<? extends PersistentRecord> clazz, String fieldName)
|
||||||
|
{
|
||||||
|
return new ColumnExp(clazz, fieldName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.samskivert.jdbc.ColumnDefinition;
|
import com.samskivert.jdbc.ColumnDefinition;
|
||||||
import com.samskivert.jdbc.DatabaseLiaison;
|
import com.samskivert.jdbc.DatabaseLiaison;
|
||||||
|
|
||||||
import com.samskivert.depot.annotation.Column;
|
import com.samskivert.depot.annotation.Column;
|
||||||
|
import com.samskivert.depot.expression.ColumnExp;
|
||||||
import com.samskivert.depot.impl.FieldMarshaller;
|
import com.samskivert.depot.impl.FieldMarshaller;
|
||||||
import com.samskivert.depot.impl.Modifier;
|
import com.samskivert.depot.impl.Modifier;
|
||||||
|
|
||||||
@@ -74,10 +76,10 @@ public abstract class SchemaMigration extends Modifier
|
|||||||
*/
|
*/
|
||||||
public static class Rename extends SchemaMigration
|
public static class Rename extends SchemaMigration
|
||||||
{
|
{
|
||||||
public Rename (int targetVersion, String oldColumnName, String newColumnName) {
|
public Rename (int targetVersion, String oldColumnName, ColumnExp newColumn) {
|
||||||
super(targetVersion);
|
super(targetVersion);
|
||||||
_oldColumnName = oldColumnName;
|
_oldColumnName = oldColumnName;
|
||||||
_newColumnName = newColumnName;
|
_newColumnName = newColumn.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean runBeforeDefault () {
|
@Override public boolean runBeforeDefault () {
|
||||||
@@ -132,9 +134,9 @@ public abstract class SchemaMigration extends Modifier
|
|||||||
*/
|
*/
|
||||||
public static class Retype extends SchemaMigration
|
public static class Retype extends SchemaMigration
|
||||||
{
|
{
|
||||||
public Retype (int targetVersion, String fieldName) {
|
public Retype (int targetVersion, ColumnExp column) {
|
||||||
super(targetVersion);
|
super(targetVersion);
|
||||||
_fieldName = fieldName;
|
_fieldName = column.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean runBeforeDefault () {
|
@Override public boolean runBeforeDefault () {
|
||||||
@@ -170,9 +172,9 @@ public abstract class SchemaMigration extends Modifier
|
|||||||
*/
|
*/
|
||||||
public static class Add extends SchemaMigration
|
public static class Add extends SchemaMigration
|
||||||
{
|
{
|
||||||
public Add (int targetVersion, String fieldName, String defaultValue) {
|
public Add (int targetVersion, ColumnExp column, String defaultValue) {
|
||||||
super(targetVersion);
|
super(targetVersion);
|
||||||
_fieldName = fieldName;
|
_fieldName = column.name;
|
||||||
_defaultValue = defaultValue;
|
_defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
package com.samskivert.depot.annotation;
|
package com.samskivert.depot.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
@@ -27,23 +28,22 @@ import java.lang.annotation.Target;
|
|||||||
/**
|
/**
|
||||||
* Defines an index on an entity table.
|
* Defines an index on an entity table.
|
||||||
*/
|
*/
|
||||||
@Target(value={})
|
@Target(value=ElementType.FIELD)
|
||||||
@Retention(value=RetentionPolicy.RUNTIME)
|
@Retention(value=RetentionPolicy.RUNTIME)
|
||||||
public @interface Index
|
public @interface Index
|
||||||
{
|
{
|
||||||
/** Defines the name of the index. */
|
/** Defines the name of the index. If this is defined, a static method must be defined on the
|
||||||
String name ();
|
* 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 ()
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
String name () default "";
|
||||||
|
|
||||||
/** Does this index enforce a uniqueness constraint? */
|
/** Does this index enforce a uniqueness constraint? */
|
||||||
boolean unique () default false;
|
boolean unique () default false;
|
||||||
|
|
||||||
/** Defines the fields on which the index operates. */
|
|
||||||
String[] fields () default {};
|
|
||||||
|
|
||||||
/** Whether or not this is a complex index. If true, a static method
|
|
||||||
* must be defined on the record that declares this index of the signature:
|
|
||||||
* <pre>public static List<Tuple<SQLExpression, OrderBy.Order>> indexNameExpression ()</pre>
|
|
||||||
* which should return the index's defining expressions and whether each one is ascending
|
|
||||||
* or descending. */
|
|
||||||
boolean complex () default false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,15 +25,16 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This annotation is used to specify that a unique constraint is to be included in the
|
* Used to specify a uniqueness constraint on a set of columns. If you want a single column to be
|
||||||
* generated DDL for a table.
|
* unique, simply use {@link Column#unique}.
|
||||||
*/
|
*/
|
||||||
@Target(value={})
|
@Target(value={})
|
||||||
@Retention(value=RetentionPolicy.RUNTIME)
|
@Retention(value=RetentionPolicy.RUNTIME)
|
||||||
public @interface UniqueConstraint
|
public @interface UniqueConstraint
|
||||||
{
|
{
|
||||||
/**
|
/** The name of the index that will be created to enforce this constraint. */
|
||||||
* An array of the field names that make up the constraint
|
String name ();
|
||||||
*/
|
|
||||||
public String[] fieldNames () default {};
|
/** An array of the field names that make up the constraint */
|
||||||
|
String[] fields ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,17 +32,15 @@ import com.samskivert.util.Tuple;
|
|||||||
/**
|
/**
|
||||||
* Represents an CREATE INDEX instruction to the database.
|
* Represents an CREATE INDEX instruction to the database.
|
||||||
*/
|
*/
|
||||||
public class CreateIndexClause<T extends PersistentRecord>
|
public class CreateIndexClause
|
||||||
implements QueryClause
|
implements QueryClause
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Create a new {@link CreateIndexClause} clause. The name must be unique within the
|
* Create a new {@link CreateIndexClause} clause. The name must be unique within the relevant
|
||||||
* relevant database.
|
* database.
|
||||||
*/
|
*/
|
||||||
public CreateIndexClause (
|
public CreateIndexClause (Class<? extends PersistentRecord> pClass, String name, boolean unique,
|
||||||
Class<? extends PersistentRecord> pClass, String name, boolean unique,
|
|
||||||
List<Tuple<SQLExpression, Order>> fields)
|
List<Tuple<SQLExpression, Order>> fields)
|
||||||
|
|
||||||
{
|
{
|
||||||
_pClass = pClass;
|
_pClass = pClass;
|
||||||
_name = name;
|
_name = name;
|
||||||
@@ -83,9 +81,7 @@ public class CreateIndexClause<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Class<? extends PersistentRecord> _pClass;
|
protected Class<? extends PersistentRecord> _pClass;
|
||||||
|
|
||||||
protected String _name;
|
protected String _name;
|
||||||
|
|
||||||
protected boolean _unique;
|
protected boolean _unique;
|
||||||
|
|
||||||
/** The components of the index, e.g. columns or functions of columns. */
|
/** The components of the index, e.g. columns or functions of columns. */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import com.samskivert.depot.impl.ExpressionVisitor;
|
|||||||
/**
|
/**
|
||||||
* Builds actual SQL given a main persistent type and some {@link QueryClause} objects.
|
* Builds actual SQL given a main persistent type and some {@link QueryClause} objects.
|
||||||
*/
|
*/
|
||||||
public class DeleteClause<T extends PersistentRecord> implements QueryClause
|
public class DeleteClause implements QueryClause
|
||||||
{
|
{
|
||||||
public DeleteClause (Class<? extends PersistentRecord> pClass, WhereClause where)
|
public DeleteClause (Class<? extends PersistentRecord> pClass, WhereClause where)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,6 +55,12 @@ public class FieldDefinition implements QueryClause
|
|||||||
_definition = override;
|
_definition = override;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FieldDefinition (ColumnExp field, SQLExpression override)
|
||||||
|
{
|
||||||
|
_field = field.name;
|
||||||
|
_definition = override;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The field we're defining. The Query object uses this for indexing.
|
* The field we're defining. The Query object uses this for indexing.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ import com.samskivert.depot.impl.ExpressionVisitor;
|
|||||||
/**
|
/**
|
||||||
* Builds actual SQL given a main persistent type and some {@link QueryClause} objects.
|
* Builds actual SQL given a main persistent type and some {@link QueryClause} objects.
|
||||||
*/
|
*/
|
||||||
public class InsertClause<T extends PersistentRecord> implements QueryClause
|
public class InsertClause implements QueryClause
|
||||||
{
|
{
|
||||||
public InsertClause (
|
public InsertClause (Class<? extends PersistentRecord> pClass, Object pojo,
|
||||||
Class<? extends PersistentRecord> pClass, Object pojo, Set<String> identityFields)
|
Set<String> identityFields)
|
||||||
{
|
{
|
||||||
_pClass = pClass;
|
_pClass = pClass;
|
||||||
_pojo = pojo;
|
_pojo = pojo;
|
||||||
|
|||||||
@@ -37,13 +37,6 @@ public class Join implements QueryClause
|
|||||||
/** Indicates the join type to be used. The default is INNER. */
|
/** Indicates the join type to be used. The default is INNER. */
|
||||||
public static enum Type { INNER, LEFT_OUTER, RIGHT_OUTER };
|
public static enum Type { INNER, LEFT_OUTER, RIGHT_OUTER };
|
||||||
|
|
||||||
public Join (Class<? extends PersistentRecord> pClass, String pCol,
|
|
||||||
Class<? extends PersistentRecord> joinClass, String jCol)
|
|
||||||
{
|
|
||||||
_joinClass = joinClass;
|
|
||||||
_joinCondition = new Equals(new ColumnExp(joinClass, jCol), new ColumnExp(pClass, pCol));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Join (ColumnExp primary, ColumnExp join)
|
public Join (ColumnExp primary, ColumnExp join)
|
||||||
{
|
{
|
||||||
_joinClass = join.getPersistentClass();
|
_joinClass = join.getPersistentClass();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package com.samskivert.depot.clause;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.samskivert.depot.PersistentRecord;
|
import com.samskivert.depot.PersistentRecord;
|
||||||
|
import com.samskivert.depot.expression.ColumnExp;
|
||||||
import com.samskivert.depot.expression.SQLExpression;
|
import com.samskivert.depot.expression.SQLExpression;
|
||||||
import com.samskivert.depot.impl.ExpressionVisitor;
|
import com.samskivert.depot.impl.ExpressionVisitor;
|
||||||
|
|
||||||
|
|||||||
@@ -31,11 +31,24 @@ import com.samskivert.depot.impl.ExpressionVisitor;
|
|||||||
public class ColumnExp
|
public class ColumnExp
|
||||||
implements SQLExpression
|
implements SQLExpression
|
||||||
{
|
{
|
||||||
|
/** The name of the column we reference. */
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
/** Converts an array of column expressions to an array of just the bare names. */
|
||||||
|
public static String[] toNames (ColumnExp[] columns)
|
||||||
|
{
|
||||||
|
String[] names = new String[columns.length];
|
||||||
|
for (int ii = 0; ii < names.length; ii++) {
|
||||||
|
names[ii] = columns[ii].name;
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
public ColumnExp (Class<? extends PersistentRecord> pClass, String field)
|
public ColumnExp (Class<? extends PersistentRecord> pClass, String field)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
_pClass = pClass;
|
_pClass = pClass;
|
||||||
_pField = field;
|
this.name = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from SQLExpression
|
// from SQLExpression
|
||||||
@@ -57,18 +70,15 @@ public class ColumnExp
|
|||||||
|
|
||||||
public String getField ()
|
public String getField ()
|
||||||
{
|
{
|
||||||
return _pField;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // from Object
|
@Override // from Object
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "\"" + _pField + "\""; // TODO: qualify with record name and be uber verbose?
|
return "\"" + name + "\""; // TODO: qualify with record name and be uber verbose?
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The table that hosts the column we reference, or null. */
|
/** The table that hosts the column we reference, or null. */
|
||||||
protected final Class<? extends PersistentRecord> _pClass;
|
protected final Class<? extends PersistentRecord> _pClass;
|
||||||
|
|
||||||
/** The name of the column we reference. */
|
|
||||||
protected final String _pField;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ public class BindVisitor implements ExpressionVisitor
|
|||||||
updateClause.getWhereClause().accept(this);
|
updateClause.getWhereClause().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit (InsertClause<? extends PersistentRecord> insertClause)
|
public void visit (InsertClause insertClause)
|
||||||
{
|
{
|
||||||
DepotMarshaller<?> marsh = _types.getMarshaller(insertClause.getPersistentClass());
|
DepotMarshaller<?> marsh = _types.getMarshaller(insertClause.getPersistentClass());
|
||||||
Object pojo = insertClause.getPojo();
|
Object pojo = insertClause.getPojo();
|
||||||
@@ -266,12 +266,12 @@ public class BindVisitor implements ExpressionVisitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit (DeleteClause<? extends PersistentRecord> deleteClause)
|
public void visit (DeleteClause deleteClause)
|
||||||
{
|
{
|
||||||
deleteClause.getWhereClause().accept(this);
|
deleteClause.getWhereClause().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit (CreateIndexClause<? extends PersistentRecord> createIndexClause)
|
public void visit (CreateIndexClause createIndexClause)
|
||||||
{
|
{
|
||||||
for (Tuple<SQLExpression, Order> field : createIndexClause.getFields()) {
|
for (Tuple<SQLExpression, Order> field : createIndexClause.getFields()) {
|
||||||
field.left.accept(this);
|
field.left.accept(this);
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ public abstract class BuildVisitor implements ExpressionVisitor
|
|||||||
updateClause.getWhereClause().accept(this);
|
updateClause.getWhereClause().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit (DeleteClause<? extends PersistentRecord> deleteClause)
|
public void visit (DeleteClause deleteClause)
|
||||||
{
|
{
|
||||||
_builder.append("delete from ");
|
_builder.append("delete from ");
|
||||||
appendTableName(deleteClause.getPersistentClass());
|
appendTableName(deleteClause.getPersistentClass());
|
||||||
@@ -440,7 +440,7 @@ public abstract class BuildVisitor implements ExpressionVisitor
|
|||||||
deleteClause.getWhereClause().accept(this);
|
deleteClause.getWhereClause().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit (InsertClause<? extends PersistentRecord> insertClause)
|
public void visit (InsertClause insertClause)
|
||||||
{
|
{
|
||||||
Class<? extends PersistentRecord> pClass = insertClause.getPersistentClass();
|
Class<? extends PersistentRecord> pClass = insertClause.getPersistentClass();
|
||||||
DepotMarshaller<?> marsh = _types.getMarshaller(pClass);
|
DepotMarshaller<?> marsh = _types.getMarshaller(pClass);
|
||||||
@@ -480,7 +480,7 @@ public abstract class BuildVisitor implements ExpressionVisitor
|
|||||||
_builder.append(")");
|
_builder.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit (CreateIndexClause<? extends PersistentRecord> createIndexClause)
|
public void visit (CreateIndexClause createIndexClause)
|
||||||
{
|
{
|
||||||
_builder.append("create ");
|
_builder.append("create ");
|
||||||
if (createIndexClause.isUnique()) {
|
if (createIndexClause.isUnique()) {
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ import java.sql.ResultSetMetaData;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -46,6 +47,7 @@ import com.samskivert.depot.PersistenceContext;
|
|||||||
import com.samskivert.depot.PersistentRecord;
|
import com.samskivert.depot.PersistentRecord;
|
||||||
import com.samskivert.depot.SchemaMigration;
|
import com.samskivert.depot.SchemaMigration;
|
||||||
import com.samskivert.depot.Stats;
|
import com.samskivert.depot.Stats;
|
||||||
|
import com.samskivert.depot.annotation.Column;
|
||||||
import com.samskivert.depot.annotation.Computed;
|
import com.samskivert.depot.annotation.Computed;
|
||||||
import com.samskivert.depot.annotation.Entity;
|
import com.samskivert.depot.annotation.Entity;
|
||||||
import com.samskivert.depot.annotation.FullTextIndex;
|
import com.samskivert.depot.annotation.FullTextIndex;
|
||||||
@@ -194,6 +196,20 @@ 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())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we did not find a schema version field, freak out (but not for computed records, for
|
// if we did not find a schema version field, freak out (but not for computed records, for
|
||||||
@@ -207,32 +223,30 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
_allFields = fields.toArray(new String[fields.size()]);
|
_allFields = fields.toArray(new String[fields.size()]);
|
||||||
|
|
||||||
// now check for @Entity annotations on the entire superclass chain
|
// now check for @Entity annotations on the entire superclass chain
|
||||||
Class<?> iterClass = pClass;
|
Class<? extends PersistentRecord> iterClass = pClass.asSubclass(PersistentRecord.class);
|
||||||
do {
|
do {
|
||||||
entity = iterClass.getAnnotation(Entity.class);
|
entity = iterClass.getAnnotation(Entity.class);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
|
// add any indices needed for uniqueness constraints
|
||||||
for (UniqueConstraint constraint : entity.uniqueConstraints()) {
|
for (UniqueConstraint constraint : entity.uniqueConstraints()) {
|
||||||
String[] conFields = constraint.fieldNames();
|
List<ColumnExp> colExps = Lists.newArrayList();
|
||||||
Set<String> colSet = Sets.newHashSet();
|
for (String field : constraint.fields()) {
|
||||||
for (int ii = 0; ii < conFields.length; ii ++) {
|
FieldMarshaller<?> fm = _fields.get(field);
|
||||||
FieldMarshaller<?> fm = _fields.get(conFields[ii]);
|
|
||||||
if (fm == null) {
|
if (fm == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Unknown unique constraint field: " + conFields[ii]);
|
"Unknown unique constraint field: " + field);
|
||||||
}
|
}
|
||||||
colSet.add(fm.getColumnName());
|
colExps.add(new ColumnExp(_pClass, field));
|
||||||
}
|
}
|
||||||
_uniqueConstraints.add(colSet);
|
_indexes.add(buildIndex(constraint.name(), true, colExps));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add any explicit multicolumn or complex indices
|
||||||
for (Index index : entity.indices()) {
|
for (Index index : entity.indices()) {
|
||||||
if (_indexes.containsKey(index.name())) {
|
_indexes.add(buildIndex(index.name(), index.unique()));
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_indexes.put(index.name(), index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there are FTS indexes in the Table, map those out here for future use
|
// note any FTS indices
|
||||||
for (FullTextIndex fti : entity.fullTextIndices()) {
|
for (FullTextIndex fti : entity.fullTextIndices()) {
|
||||||
if (_fullTextIndexes.containsKey(fti.name())) {
|
if (_fullTextIndexes.containsKey(fti.name())) {
|
||||||
continue;
|
continue;
|
||||||
@@ -241,7 +255,7 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterClass = iterClass.getSuperclass();
|
iterClass = iterClass.getSuperclass().asSubclass(PersistentRecord.class);
|
||||||
|
|
||||||
} while (PersistentRecord.class.isAssignableFrom(iterClass) &&
|
} while (PersistentRecord.class.isAssignableFrom(iterClass) &&
|
||||||
!PersistentRecord.class.equals(iterClass));
|
!PersistentRecord.class.equals(iterClass));
|
||||||
@@ -385,7 +399,7 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
|
|
||||||
// make sure the keys are all null or all non-null
|
// make sure the keys are all null or all non-null
|
||||||
if (nulls == 0) {
|
if (nulls == 0) {
|
||||||
return makePrimaryKey(values);
|
return new Key<T>(_pClass, values);
|
||||||
} else if (nulls == values.length) {
|
} else if (nulls == values.length) {
|
||||||
return null;
|
return null;
|
||||||
} else if (nulls == zeros) {
|
} else if (nulls == zeros) {
|
||||||
@@ -394,7 +408,7 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
// this is a compromise that allows sensible things like (id=99, type=0) but
|
// this is a compromise that allows sensible things like (id=99, type=0) but
|
||||||
// unfortunately also allows less sensible things like (id=0, type=5) while
|
// unfortunately also allows less sensible things like (id=0, type=5) while
|
||||||
// continuing to disallow the dangerous (id=0)
|
// continuing to disallow the dangerous (id=0)
|
||||||
return makePrimaryKey(values);
|
return new Key<T>(_pClass, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw an informative error message
|
// throw an informative error message
|
||||||
@@ -413,19 +427,15 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a primary key record for the type of object handled by this marshaller, using the
|
* Creates a primary key record for the type of object handled by this marshaller, using the
|
||||||
* supplied primary key value.
|
* supplied primary key value. This is only allowed for records with single column keys.
|
||||||
*/
|
*/
|
||||||
public Key<T> makePrimaryKey (Comparable<?>... values)
|
public Key<T> makePrimaryKey (Comparable<?> value)
|
||||||
{
|
{
|
||||||
if (!hasPrimaryKey()) {
|
if (!hasPrimaryKey()) {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
getClass().getName() + " does not define a primary key");
|
getClass().getName() + " does not define a primary key");
|
||||||
}
|
}
|
||||||
String[] fields = new String[_pkColumns.size()];
|
return new Key<T>(_pClass, new Comparable<?>[] { value });
|
||||||
for (int ii = 0; ii < _pkColumns.size(); ii++) {
|
|
||||||
fields[ii] = _pkColumns.get(ii).getField().getName();
|
|
||||||
}
|
|
||||||
return new Key<T>(_pClass, fields, values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -448,7 +458,7 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
values[ii] = (Comparable<?>) keyValue;
|
values[ii] = (Comparable<?>) keyValue;
|
||||||
}
|
}
|
||||||
return makePrimaryKey(values);
|
return new Key<T>(_pClass, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -703,12 +713,6 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
{
|
{
|
||||||
log.info("Creating initial table '" + getTableName() + "'.");
|
log.info("Creating initial table '" + getTableName() + "'.");
|
||||||
|
|
||||||
final String[][] uniqueConCols = new String[_uniqueConstraints.size()][];
|
|
||||||
int kk = 0;
|
|
||||||
for (Set<String> colSet : _uniqueConstraints) {
|
|
||||||
uniqueConCols[kk++] = colSet.toArray(new String[colSet.size()]);
|
|
||||||
}
|
|
||||||
final Iterable<Index> indexen = _indexes.values();
|
|
||||||
ctx.invoke(new Modifier() {
|
ctx.invoke(new Modifier() {
|
||||||
@Override
|
@Override
|
||||||
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
||||||
@@ -722,14 +726,11 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
liaison.createTableIfMissing(
|
liaison.createTableIfMissing(
|
||||||
conn, getTableName(), fieldsToColumns(_columnFields),
|
conn, getTableName(), fieldsToColumns(_columnFields),
|
||||||
declarations, uniqueConCols, primaryKeyColumns);
|
declarations, null, primaryKeyColumns);
|
||||||
|
|
||||||
// add its indexen
|
// add its indexen
|
||||||
for (Index index : indexen) {
|
for (CreateIndexClause iclause : _indexes) {
|
||||||
String ixName = getTableName() + "_" + index.name();
|
execute(conn, builder, iclause);
|
||||||
execute(conn, builder, index.complex() ?
|
|
||||||
buildComplexIndex(ixName, index.unique(), index.name()) :
|
|
||||||
buildSimpleIndex(ixName, index.unique(), index.fields()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create our value generators
|
// create our value generators
|
||||||
@@ -752,7 +753,6 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
{
|
{
|
||||||
if (builder.newQuery(clause)) {
|
if (builder.newQuery(clause)) {
|
||||||
PreparedStatement stmt = builder.prepare(conn);
|
PreparedStatement stmt = builder.prepare(conn);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return stmt.executeUpdate();
|
return stmt.executeUpdate();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -783,9 +783,6 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
metaData = TableMetaData.load(ctx, getTableName());
|
metaData = TableMetaData.load(ctx, getTableName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a little silly, but we need a copy for name disambiguation later
|
|
||||||
Set<String> indicesCopy = Sets.newHashSet(metaData.indexColumns.keySet());
|
|
||||||
|
|
||||||
// figure out which columns we have in the table now, so that when all is said and done we
|
// figure out which columns we have in the table now, so that when all is said and done we
|
||||||
// can see what new columns we have in the table and run the creation code for any value
|
// can see what new columns we have in the table and run the creation code for any value
|
||||||
// generators that are defined on those columns (we can't just track the columns we add in
|
// generators that are defined on those columns (we can't just track the columns we add in
|
||||||
@@ -854,57 +851,17 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add any named indices that exist on the record but not yet on the table
|
// add any named indices that exist on the record but not yet on the table
|
||||||
for (final Index index : _indexes.values()) {
|
for (final CreateIndexClause iclause : _indexes) {
|
||||||
final String ixName = getTableName() + "_" + index.name();
|
if (metaData.indexColumns.containsKey(iclause.getName())) {
|
||||||
if (metaData.indexColumns.containsKey(ixName)) {
|
metaData.indexColumns.remove(iclause.getName()); // this index already exists
|
||||||
// this index already exists
|
|
||||||
metaData.indexColumns.remove(ixName);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// but this is a new, named index, so we create it
|
// but this is a new, named index, so we create it
|
||||||
log.info("Creating new index: " + ixName);
|
log.info("Creating new index: " + iclause.getName());
|
||||||
ctx.invoke(new Modifier() {
|
ctx.invoke(new Modifier() {
|
||||||
@Override
|
@Override
|
||||||
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
||||||
execute(conn, builder, index.complex() ?
|
execute(conn, builder, iclause);
|
||||||
buildComplexIndex(ixName, index.unique(), index.name()) :
|
|
||||||
buildSimpleIndex(ixName, index.unique(), index.fields()));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// now check if there are any @Entity(uniqueConstraints) that need to be created
|
|
||||||
Set<Set<String>> uniqueIndices = Sets.newHashSet(metaData.indexColumns.values());
|
|
||||||
|
|
||||||
// unique constraints are unordered and may be unnamed, so we view them only as column sets
|
|
||||||
for (Set<String> colSet : _uniqueConstraints) {
|
|
||||||
if (uniqueIndices.contains(colSet)) {
|
|
||||||
// the table already contains precisely this column set
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// else build the new constraint; we'll name it after one of its columns, adding _N
|
|
||||||
// to resolve any possible ambiguities, because using all the column names in the
|
|
||||||
// index name may exceed the maximum length of an SQL identifier
|
|
||||||
String indexName = colSet.iterator().next();
|
|
||||||
if (indicesCopy.contains(indexName)) {
|
|
||||||
int num = 1;
|
|
||||||
indexName += "_";
|
|
||||||
while (indicesCopy.contains(indexName + num)) {
|
|
||||||
num ++;
|
|
||||||
}
|
|
||||||
indexName += num;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String[] colArr = colSet.toArray(new String[colSet.size()]);
|
|
||||||
final String fName = indexName;
|
|
||||||
ctx.invoke(new Modifier() {
|
|
||||||
@Override
|
|
||||||
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
|
||||||
if (!liaison.tableContainsIndex(conn, getTableName(), fName)) {
|
|
||||||
execute(conn, builder, buildSimpleIndex(fName, true, colArr));
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -981,57 +938,49 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
return metaData;
|
return metaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CreateIndexClause<T> buildComplexIndex (String ixName, boolean unique, String localIxName)
|
protected CreateIndexClause buildIndex (String name, boolean unique)
|
||||||
throws SQLException
|
|
||||||
{
|
{
|
||||||
List<Tuple<SQLExpression, Order>> definition;
|
|
||||||
String methName = localIxName + "Definition";
|
|
||||||
|
|
||||||
Method method;
|
Method method;
|
||||||
try {
|
try {
|
||||||
method = _pClass.getMethod(methName);
|
method = _pClass.getMethod(name);
|
||||||
} catch (NoSuchMethodException nsme) {
|
} catch (NoSuchMethodException nsme) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Index flagged as complex, but no defining method '" + methName
|
"Index flagged as complex, but no defining method '" + name + "' found.", nsme);
|
||||||
+ "' found.", nsme);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object result;
|
Object result;
|
||||||
try {
|
try {
|
||||||
result = method.invoke(null);
|
return buildIndex(name, unique, method.invoke(null));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Error calling index definition method '" + methName + "'", e);
|
"Error calling index definition method '" + name + "'", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result instanceof SQLExpression) {
|
protected CreateIndexClause buildIndex (String name, boolean unique, Object config)
|
||||||
definition = new ArrayList<Tuple<SQLExpression,Order>>();
|
|
||||||
definition.add(new Tuple<SQLExpression, Order>((SQLExpression)result, Order.ASC));
|
|
||||||
|
|
||||||
} else if (result instanceof List) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<Tuple<SQLExpression, Order>> def = (List<Tuple<SQLExpression, Order>>)result;
|
|
||||||
definition = def;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Method '" + methName
|
|
||||||
+ "' must return SQLExpression or " + "List<Tuple<SQLExpression, Order>>");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CreateIndexClause<T>(_pClass, ixName, unique, definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CreateIndexClause<T> buildSimpleIndex (String ixName, boolean unique, String[] fields)
|
|
||||||
throws SQLException
|
|
||||||
{
|
{
|
||||||
List<Tuple<SQLExpression, Order>> definition = new ArrayList<Tuple<SQLExpression,Order>>();
|
List<Tuple<SQLExpression, Order>> definition = Lists.newArrayList();
|
||||||
|
if (config instanceof ColumnExp) {
|
||||||
for (String field : fields) {
|
definition.add(new Tuple<SQLExpression, Order>((ColumnExp)config, Order.ASC));
|
||||||
ColumnExp column = new ColumnExp(_pClass, field);
|
} else if (config instanceof ColumnExp[]) {
|
||||||
|
for (ColumnExp column : (ColumnExp[])config) {
|
||||||
definition.add(new Tuple<SQLExpression, Order>(column, Order.ASC));
|
definition.add(new Tuple<SQLExpression, Order>(column, Order.ASC));
|
||||||
}
|
}
|
||||||
|
} else if (config instanceof SQLExpression) {
|
||||||
return new CreateIndexClause<T>(_pClass, ixName, unique, definition);
|
definition.add(new Tuple<SQLExpression, Order>((SQLExpression)config, Order.ASC));
|
||||||
|
} else if (config instanceof Tuple) {
|
||||||
|
@SuppressWarnings("unchecked") Tuple<SQLExpression, Order> tuple =
|
||||||
|
(Tuple<SQLExpression, Order>)config;
|
||||||
|
definition.add(tuple);
|
||||||
|
} else if (config instanceof List) {
|
||||||
|
@SuppressWarnings("unchecked") List<Tuple<SQLExpression, Order>> defs =
|
||||||
|
(List<Tuple<SQLExpression, Order>>)config;
|
||||||
|
definition.addAll(defs);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Method '" + name + "' must return ColumnExp[], SQLExpression or " +
|
||||||
|
"List<Tuple<SQLExpression, Order>>");
|
||||||
|
}
|
||||||
|
return new CreateIndexClause(_pClass, getTableName() + "_" + name, unique, definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate an array of field names to an array of column names
|
// translate an array of field names to an array of column names
|
||||||
@@ -1197,12 +1146,10 @@ public class DepotMarshaller<T extends PersistentRecord>
|
|||||||
/** The fields of our object with directly corresponding table columns. */
|
/** The fields of our object with directly corresponding table columns. */
|
||||||
protected String[] _columnFields;
|
protected String[] _columnFields;
|
||||||
|
|
||||||
/** The indexes defined in @Entity annotations for this record. */
|
/** The indexes defined for this record. */
|
||||||
protected Map<String, Index> _indexes = Maps.newHashMap();
|
protected List<CreateIndexClause> _indexes = Lists.newArrayList();
|
||||||
|
|
||||||
/** The unique constraints defined in @Entity annotations for this record. */
|
|
||||||
protected Set<Set<String>> _uniqueConstraints = Sets.newHashSet();
|
|
||||||
|
|
||||||
|
/** Any full text indices defined on this entity. */
|
||||||
protected Map<String, FullTextIndex> _fullTextIndexes = Maps.newHashMap();
|
protected Map<String, FullTextIndex> _fullTextIndexes = Maps.newHashMap();
|
||||||
|
|
||||||
/** The version of our persistent object schema as specified in the class definition. */
|
/** The version of our persistent object schema as specified in the class definition. */
|
||||||
|
|||||||
@@ -34,19 +34,9 @@ import com.samskivert.depot.expression.ColumnExp;
|
|||||||
public class DepotMigrationHistoryRecord extends PersistentRecord
|
public class DepotMigrationHistoryRecord extends PersistentRecord
|
||||||
{
|
{
|
||||||
// AUTO-GENERATED: FIELDS START
|
// AUTO-GENERATED: FIELDS START
|
||||||
/** The column identifier for the {@link #ident} field. */
|
public static final Class<DepotMigrationHistoryRecord> _R = DepotMigrationHistoryRecord.class;
|
||||||
public static final String IDENT = "ident";
|
public static final ColumnExp IDENT = colexp(_R, "ident");
|
||||||
|
public static final ColumnExp WHEN_COMPLETED = colexp(_R, "whenCompleted");
|
||||||
/** The qualified column identifier for the {@link #ident} field. */
|
|
||||||
public static final ColumnExp IDENT_C =
|
|
||||||
new ColumnExp(DepotMigrationHistoryRecord.class, IDENT);
|
|
||||||
|
|
||||||
/** The column identifier for the {@link #whenCompleted} field. */
|
|
||||||
public static final String WHEN_COMPLETED = "whenCompleted";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #whenCompleted} field. */
|
|
||||||
public static final ColumnExp WHEN_COMPLETED_C =
|
|
||||||
new ColumnExp(DepotMigrationHistoryRecord.class, WHEN_COMPLETED);
|
|
||||||
// AUTO-GENERATED: FIELDS END
|
// AUTO-GENERATED: FIELDS END
|
||||||
|
|
||||||
/** Our schema version. Probably not likely to change. */
|
/** Our schema version. Probably not likely to change. */
|
||||||
@@ -68,7 +58,7 @@ public class DepotMigrationHistoryRecord extends PersistentRecord
|
|||||||
{
|
{
|
||||||
return new Key<DepotMigrationHistoryRecord>(
|
return new Key<DepotMigrationHistoryRecord>(
|
||||||
DepotMigrationHistoryRecord.class,
|
DepotMigrationHistoryRecord.class,
|
||||||
new String[] { IDENT },
|
new ColumnExp[] { IDENT },
|
||||||
new Comparable[] { ident });
|
new Comparable[] { ident });
|
||||||
}
|
}
|
||||||
// AUTO-GENERATED: METHODS END
|
// AUTO-GENERATED: METHODS END
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ public interface ExpressionVisitor
|
|||||||
public void visit (Exists<? extends PersistentRecord> exists);
|
public void visit (Exists<? extends PersistentRecord> exists);
|
||||||
public void visit (SelectClause<? extends PersistentRecord> selectClause);
|
public void visit (SelectClause<? extends PersistentRecord> selectClause);
|
||||||
public void visit (UpdateClause<? extends PersistentRecord> updateClause);
|
public void visit (UpdateClause<? extends PersistentRecord> updateClause);
|
||||||
public void visit (DeleteClause<? extends PersistentRecord> deleteClause);
|
public void visit (DeleteClause deleteClause);
|
||||||
public void visit (InsertClause<? extends PersistentRecord> insertClause);
|
public void visit (InsertClause insertClause);
|
||||||
public void visit (CreateIndexClause<? extends PersistentRecord> createIndexClause);
|
public void visit (CreateIndexClause createIndexClause);
|
||||||
public void visit (DropIndexClause<? extends PersistentRecord> dropIndexClause);
|
public void visit (DropIndexClause<? extends PersistentRecord> dropIndexClause);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class HSQLBuilder
|
|||||||
// (lower(COL1) like '%foo%') OR (lower(COL1) like '%bar%') OR ...
|
// (lower(COL1) like '%foo%') OR (lower(COL1) like '%bar%') OR ...
|
||||||
// (lower(COL2) like '%foo%') OR (lower(COL2) like '%bar%') OR ...
|
// (lower(COL2) like '%foo%') OR (lower(COL2) like '%bar%') OR ...
|
||||||
// ... and so on. Not efficient, but basically functional.
|
// ... and so on. Not efficient, but basically functional.
|
||||||
Class<? extends PersistentRecord> pClass = match.getPersistentRecord();
|
Class<? extends PersistentRecord> pClass = match.getPersistentClass();
|
||||||
|
|
||||||
// find the fields involved
|
// find the fields involved
|
||||||
String[] fields = _types.getMarshaller(pClass).
|
String[] fields = _types.getMarshaller(pClass).
|
||||||
@@ -117,7 +117,7 @@ public class HSQLBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit (CreateIndexClause<? extends PersistentRecord> createIndexClause)
|
public void visit (CreateIndexClause createIndexClause)
|
||||||
{
|
{
|
||||||
for (Tuple<SQLExpression, Order> field : createIndexClause.getFields()) {
|
for (Tuple<SQLExpression, Order> field : createIndexClause.getFields()) {
|
||||||
if (!(field.left instanceof ColumnExp)) {
|
if (!(field.left instanceof ColumnExp)) {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class MySQLBuilder
|
|||||||
@Override public void visit (FullTextMatch match)
|
@Override public void visit (FullTextMatch match)
|
||||||
{
|
{
|
||||||
_builder.append("match(");
|
_builder.append("match(");
|
||||||
Class<? extends PersistentRecord> pClass = match.getPersistentRecord();
|
Class<? extends PersistentRecord> pClass = match.getPersistentClass();
|
||||||
String[] fields =
|
String[] fields =
|
||||||
_types.getMarshaller(pClass).getFullTextIndex(match.getName()).fields();
|
_types.getMarshaller(pClass).getFullTextIndex(match.getName()).fields();
|
||||||
for (int ii = 0; ii < fields.length; ii ++) {
|
for (int ii = 0; ii < fields.length; ii ++) {
|
||||||
@@ -79,7 +79,7 @@ public class MySQLBuilder
|
|||||||
_builder.append(") against (? in boolean mode)");
|
_builder.append(") against (? in boolean mode)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void visit (DeleteClause<? extends PersistentRecord> deleteClause)
|
@Override public void visit (DeleteClause deleteClause)
|
||||||
{
|
{
|
||||||
_builder.append("delete from ");
|
_builder.append("delete from ");
|
||||||
appendTableName(deleteClause.getPersistentClass());
|
appendTableName(deleteClause.getPersistentClass());
|
||||||
@@ -103,7 +103,7 @@ public class MySQLBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit (CreateIndexClause<? extends PersistentRecord> createIndexClause)
|
public void visit (CreateIndexClause createIndexClause)
|
||||||
{
|
{
|
||||||
for (Tuple<SQLExpression, Order> field : createIndexClause.getFields()) {
|
for (Tuple<SQLExpression, Order> field : createIndexClause.getFields()) {
|
||||||
if (!(field.left instanceof ColumnExp)) {
|
if (!(field.left instanceof ColumnExp)) {
|
||||||
|
|||||||
@@ -38,16 +38,6 @@ public abstract class Conditionals
|
|||||||
public static class IsNull
|
public static class IsNull
|
||||||
implements SQLOperator
|
implements SQLOperator
|
||||||
{
|
{
|
||||||
public IsNull (String pColumn)
|
|
||||||
{
|
|
||||||
this(new ColumnExp(null, pColumn));
|
|
||||||
}
|
|
||||||
|
|
||||||
public IsNull (Class<? extends PersistentRecord> pClass, String pColumn)
|
|
||||||
{
|
|
||||||
this(new ColumnExp(pClass, pColumn));
|
|
||||||
}
|
|
||||||
|
|
||||||
public IsNull (ColumnExp column)
|
public IsNull (ColumnExp column)
|
||||||
{
|
{
|
||||||
_column = column;
|
_column = column;
|
||||||
@@ -199,17 +189,6 @@ public abstract class Conditionals
|
|||||||
/** The maximum number of keys allowed in an IN() clause. */
|
/** The maximum number of keys allowed in an IN() clause. */
|
||||||
public static final int MAX_KEYS = Short.MAX_VALUE;
|
public static final int MAX_KEYS = Short.MAX_VALUE;
|
||||||
|
|
||||||
public In (Class<? extends PersistentRecord> pClass, String pColumn, Comparable<?>... values)
|
|
||||||
{
|
|
||||||
this(new ColumnExp(pClass, pColumn), values);
|
|
||||||
}
|
|
||||||
|
|
||||||
public In (Class<? extends PersistentRecord> pClass, String pColumn,
|
|
||||||
Collection<? extends Comparable<?>> values)
|
|
||||||
{
|
|
||||||
this(new ColumnExp(pClass, pColumn), values.toArray(new Comparable<?>[values.size()]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public In (ColumnExp column, Comparable<?>... values)
|
public In (ColumnExp column, Comparable<?>... values)
|
||||||
{
|
{
|
||||||
if (values.length == 0) {
|
if (values.length == 0) {
|
||||||
@@ -329,7 +308,7 @@ public abstract class Conditionals
|
|||||||
_query = query;
|
_query = query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<? extends PersistentRecord> getPersistentRecord ()
|
public Class<? extends PersistentRecord> getPersistentClass ()
|
||||||
{
|
{
|
||||||
return _pClass;
|
return _pClass;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,58 +35,18 @@ import com.samskivert.util.StringUtil;
|
|||||||
/**
|
/**
|
||||||
* A test persistent object.
|
* A test persistent object.
|
||||||
*/
|
*/
|
||||||
@Entity(indices={ @Index(name="createdIndex", fields={"created"}) })
|
@Entity
|
||||||
public class TestRecord extends PersistentRecord
|
public class TestRecord extends PersistentRecord
|
||||||
{
|
{
|
||||||
// AUTO-GENERATED: FIELDS START
|
// AUTO-GENERATED: FIELDS START
|
||||||
/** The column identifier for the {@link #recordId} field. */
|
public static final Class<TestRecord> _R = TestRecord.class;
|
||||||
public static final String RECORD_ID = "recordId";
|
public static final ColumnExp RECORD_ID = colexp(_R, "recordId");
|
||||||
|
public static final ColumnExp NAME = colexp(_R, "name");
|
||||||
/** The qualified column identifier for the {@link #recordId} field. */
|
public static final ColumnExp AGE = colexp(_R, "age");
|
||||||
public static final ColumnExp RECORD_ID_C =
|
public static final ColumnExp HOME_TOWN = colexp(_R, "homeTown");
|
||||||
new ColumnExp(TestRecord.class, RECORD_ID);
|
public static final ColumnExp CREATED = colexp(_R, "created");
|
||||||
|
public static final ColumnExp LAST_MODIFIED = colexp(_R, "lastModified");
|
||||||
/** The column identifier for the {@link #name} field. */
|
public static final ColumnExp NUMBERS = colexp(_R, "numbers");
|
||||||
public static final String NAME = "name";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #name} field. */
|
|
||||||
public static final ColumnExp NAME_C =
|
|
||||||
new ColumnExp(TestRecord.class, NAME);
|
|
||||||
|
|
||||||
/** The column identifier for the {@link #age} field. */
|
|
||||||
public static final String AGE = "age";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #age} field. */
|
|
||||||
public static final ColumnExp AGE_C =
|
|
||||||
new ColumnExp(TestRecord.class, AGE);
|
|
||||||
|
|
||||||
/** The column identifier for the {@link #homeTown} field. */
|
|
||||||
public static final String HOME_TOWN = "homeTown";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #homeTown} field. */
|
|
||||||
public static final ColumnExp HOME_TOWN_C =
|
|
||||||
new ColumnExp(TestRecord.class, HOME_TOWN);
|
|
||||||
|
|
||||||
/** The column identifier for the {@link #created} field. */
|
|
||||||
public static final String CREATED = "created";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #created} field. */
|
|
||||||
public static final ColumnExp CREATED_C =
|
|
||||||
new ColumnExp(TestRecord.class, CREATED);
|
|
||||||
|
|
||||||
/** The column identifier for the {@link #lastModified} field. */
|
|
||||||
public static final String LAST_MODIFIED = "lastModified";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #lastModified} field. */
|
|
||||||
public static final ColumnExp LAST_MODIFIED_C =
|
|
||||||
new ColumnExp(TestRecord.class, LAST_MODIFIED);
|
|
||||||
|
|
||||||
/** The column identifier for the {@link #numbers} field. */
|
|
||||||
public static final String NUMBERS = "numbers";
|
|
||||||
|
|
||||||
/** The qualified column identifier for the {@link #numbers} field. */
|
|
||||||
public static final ColumnExp NUMBERS_C =
|
|
||||||
new ColumnExp(TestRecord.class, NUMBERS);
|
|
||||||
// AUTO-GENERATED: FIELDS END
|
// AUTO-GENERATED: FIELDS END
|
||||||
|
|
||||||
public static final int SCHEMA_VERSION = 3;
|
public static final int SCHEMA_VERSION = 3;
|
||||||
@@ -100,6 +60,7 @@ public class TestRecord extends PersistentRecord
|
|||||||
|
|
||||||
public String homeTown;
|
public String homeTown;
|
||||||
|
|
||||||
|
@Index
|
||||||
public Date created;
|
public Date created;
|
||||||
|
|
||||||
public Timestamp lastModified;
|
public Timestamp lastModified;
|
||||||
@@ -121,7 +82,7 @@ public class TestRecord extends PersistentRecord
|
|||||||
{
|
{
|
||||||
return new Key<TestRecord>(
|
return new Key<TestRecord>(
|
||||||
TestRecord.class,
|
TestRecord.class,
|
||||||
new String[] { RECORD_ID },
|
new ColumnExp[] { RECORD_ID },
|
||||||
new Comparable[] { recordId });
|
new Comparable[] { recordId });
|
||||||
}
|
}
|
||||||
// AUTO-GENERATED: METHODS END
|
// AUTO-GENERATED: METHODS END
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public class TestRepository extends DepotRepository
|
|||||||
System.out.println("Delete none " + repo.deleteAll(TestRecord.class, none) + ".");
|
System.out.println("Delete none " + repo.deleteAll(TestRecord.class, none) + ".");
|
||||||
|
|
||||||
// test collection caching
|
// test collection caching
|
||||||
Where where = new Where(new Conditionals.GreaterThan(TestRecord.RECORD_ID_C, 100));
|
Where where = new Where(new Conditionals.GreaterThan(TestRecord.RECORD_ID, 100));
|
||||||
System.out.println("100 and up: " + repo.findAll(TestRecord.class, where).size());
|
System.out.println("100 and up: " + repo.findAll(TestRecord.class, where).size());
|
||||||
System.out.println("100 and up again: " + repo.findAll(TestRecord.class, where).size());
|
System.out.println("100 and up again: " + repo.findAll(TestRecord.class, where).size());
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ public class TestRepository extends DepotRepository
|
|||||||
System.out.println("Names " + repo.findAll(TestNameRecord.class) + ".");
|
System.out.println("Names " + repo.findAll(TestNameRecord.class) + ".");
|
||||||
System.out.println("Have " + repo.findAll(TestRecord.class).size() + " records.");
|
System.out.println("Have " + repo.findAll(TestRecord.class).size() + " records.");
|
||||||
repo.deleteAll(TestRecord.class, new Where(new Conditionals.LessThan(
|
repo.deleteAll(TestRecord.class, new Where(new Conditionals.LessThan(
|
||||||
TestRecord.RECORD_ID_C, CREATE_RECORDS/2)));
|
TestRecord.RECORD_ID, CREATE_RECORDS/2)));
|
||||||
System.out.println("Now have " + repo.findAll(TestRecord.class).size() + " records.");
|
System.out.println("Now have " + repo.findAll(TestRecord.class).size() + " records.");
|
||||||
repo.deleteAll(TestRecord.class, new Where(new LiteralExp("true")));
|
repo.deleteAll(TestRecord.class, new Where(new LiteralExp("true")));
|
||||||
// // TODO: try to break our In() clause
|
// // TODO: try to break our In() clause
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import java.util.Set;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
@@ -254,29 +255,24 @@ public class GenRecordTask extends Task
|
|||||||
|
|
||||||
// generate our fields section
|
// generate our fields section
|
||||||
StringBuilder fsection = new StringBuilder();
|
StringBuilder fsection = new StringBuilder();
|
||||||
|
|
||||||
|
// add our prototype declaration
|
||||||
|
VelocityContext ctx = new VelocityContext();
|
||||||
|
ctx.put("record", rname);
|
||||||
|
fsection.append(mergeTemplate(PROTO_TMPL, ctx));
|
||||||
|
|
||||||
|
// add our ColumnExp constants
|
||||||
for (int ii = 0; ii < flist.size(); ii++) {
|
for (int ii = 0; ii < flist.size(); ii++) {
|
||||||
Field f = flist.get(ii);
|
Field f = flist.get(ii);
|
||||||
String fname = f.getName();
|
String fname = f.getName();
|
||||||
|
|
||||||
// create our velocity context
|
// create our velocity context
|
||||||
VelocityContext ctx = new VelocityContext();
|
VelocityContext fctx = (VelocityContext)ctx.clone();
|
||||||
ctx.put("record", rname);
|
fctx.put("field", fname);
|
||||||
ctx.put("field", fname);
|
fctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase());
|
||||||
ctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase());
|
|
||||||
|
|
||||||
// now generate our bits
|
// now generate our bits
|
||||||
if (declared.contains(f)) {
|
fsection.append(mergeTemplate(COL_TMPL, fctx));
|
||||||
if (fsection.length() > 0) {
|
|
||||||
fsection.append("\n");
|
|
||||||
}
|
|
||||||
fsection.append(mergeTemplate(NAME_TMPL, ctx));
|
|
||||||
}
|
|
||||||
if (!isAbstract) {
|
|
||||||
if (fsection.length() > 0) {
|
|
||||||
fsection.append("\n");
|
|
||||||
}
|
|
||||||
fsection.append(mergeTemplate(COL_TMPL, ctx));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate our methods section
|
// generate our methods section
|
||||||
@@ -284,10 +280,6 @@ public class GenRecordTask extends Task
|
|||||||
|
|
||||||
// add a getKey() method, if applicable
|
// add a getKey() method, if applicable
|
||||||
if (kflist.size() > 0) {
|
if (kflist.size() > 0) {
|
||||||
// create our velocity context
|
|
||||||
VelocityContext ctx = new VelocityContext();
|
|
||||||
ctx.put("record", rname);
|
|
||||||
|
|
||||||
StringBuilder argList = new StringBuilder();
|
StringBuilder argList = new StringBuilder();
|
||||||
StringBuilder argNameList = new StringBuilder();
|
StringBuilder argNameList = new StringBuilder();
|
||||||
StringBuilder fieldNameList = new StringBuilder();
|
StringBuilder fieldNameList = new StringBuilder();
|
||||||
@@ -470,7 +462,7 @@ public class GenRecordTask extends Task
|
|||||||
protected Class<?> _prclass;
|
protected Class<?> _prclass;
|
||||||
|
|
||||||
/** Specifies the path to the name code template. */
|
/** Specifies the path to the name code template. */
|
||||||
protected static final String NAME_TMPL = "com/samskivert/depot/tools/record_name.tmpl";
|
protected static final String PROTO_TMPL = "com/samskivert/depot/tools/record_proto.tmpl";
|
||||||
|
|
||||||
/** Specifies the path to the column code template. */
|
/** Specifies the path to the column code template. */
|
||||||
protected static final String COL_TMPL = "com/samskivert/depot/tools/record_column.tmpl";
|
protected static final String COL_TMPL = "com/samskivert/depot/tools/record_column.tmpl";
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
/** The qualified column identifier for the {@link #$field} field. */
|
public static final ColumnExp ${capfield} = colexp(_R, "$field");
|
||||||
public static final ColumnExp ${capfield}_C =
|
|
||||||
new ColumnExp(${record}.class, $capfield);
|
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
{
|
{
|
||||||
return new Key<${record}>(
|
return new Key<${record}>(
|
||||||
${record}.class,
|
${record}.class,
|
||||||
new String[] { $fieldNameList },
|
new ColumnExp[] { $fieldNameList },
|
||||||
new Comparable[] { $argNameList });
|
new Comparable[] { $argNameList });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
/** The column identifier for the {@link #$field} field. */
|
|
||||||
public static final String $capfield = "$field";
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
public static final Class<${record}> _R = ${record}.class;
|
||||||
Reference in New Issue
Block a user