Otherwise, if a data migration is registered and run after the initialization
process, we'll end up warning that this record has not yet been initialized.
In theory, you should register your data migrations prior to calling initRepos,
but I don't want to be too draconian about that. Unlike schema migrations, you
*could* conceivably mean to start your app up and let it run before running
data migrations.
This allows two separate services which share a database to assign "control" of
the schema to one of the services. The non-controlling service can be
configured to simply fail if new code is deployed to said service before new
code is deployed to the controlling service, rather than have the
non-controlling service migrate the schema out from under the controlling
service.
version is set to what we expect it to be.
Otherwise if one node reads an old value for the schema version, it will
be able to grab the migration lock as long as another node has already
completed the migration.
"order by null" can be used in a query with a "group by" in it to tell
the database to suppress the overhead of sorting the results.
(Supported in postgres and mysql.)
Changed the build visitors to have a whitelist of supported
Orders, and to NPE on a null value for the Order enum.
Note that previously "order by null" could be accomplished by passing
a null value to your OrderBy, but now the enum constant must be used.
I can change that if this disrupts anything.
I don't like to see the words "Aborting creation." when I'm in the middle of
creating databases. If we're not creating the index, fine, but don't give me
the idea that we're aborting the entire creation of the table.
- Added an IntegerIterable Transformer.
- Document that these *Iterable transformers work with List/Set/Collection...
In case it wasn't clear.
- Added a sizeHint argument to the createCollectionBuilder method, take
advantage of that in the IntegerIterable since we don't need to do any
work to find the size.
It blows up expecting a column name in the values parenthesis, but the default values string that
postgres was working seems to work. It's not in http://hsqldb.org/doc/guide/ch09.html, but so it
goes.
I would have prefered to only add this support to the Query interface, and not
clutter up DepotRepository with two additional overloaded methods. However,
that would not have been possible without duplicating a bunch of logic from
DepotRepository. Yet another reason why the Query builder approach is awesome
and the fuckloads of overloaded methods approach isn't.
enum, when we need it to be using name() instead. We just take care to send it
the results of name() instead of the enum value itself.
It would be nice to share this code with BuildVisitor.bindValue, but that would
require yet further twisting and factoring of the code, obscuring it even more.
We'll just hope that special cases like Enum and ByteEnum aren't going to keep
cropping up.
in its burning desire to support the amazing four hundred billion rows, returns
a Long for count expressions.
Clients using selectCount() won't be impacted, but clients doing more complex
counting are going to have to sprinkle in some .intValue() calls.
from Nathan). If we need to add our primary key, we do so, if we need to remove
it, we do so, and only then do we consider whether we need to migrate it (in
which case we drop and re-add it).
1. DateFuncs.dayOfWeek and dayOfMonth can now be used on Timestamp. +FromDate
variants exist for using on Date.
2. hour, minute, second, etc. are now typed Number to cope with differing
opinions on the part of the underlying SQL drivers as to whether to return
Double, Long, Integer or something else.
When we go to bind values in an update statement, we either have:
- field names and a pojo from which to extract them, in which case
transformation happens naturally when we extract the current value from the
pojo
- value expressions (like 1, or "bob") which we were previously just binding
directly to the statement, which was wrong because they need to first be
transformed in the case where the field in question has an @Transform
annotation; now we get the field marshaller for the field in question and
pass the raw value to it, so that it can do the necessary transformations in
writeToStatement()
- other expressions (like LiteralExp("true") or or IntervalExp or anything else
where the database is involved in computing the final value to be assigned to
the column).
This last case still holds the potential for badness with regard to transformed
fields. We can't magically transform the value to be stored into a field if the
database is computing the ultimate value. Say, for a contrived example, that
you had a record where you stored an int column as a String for shits and
giggles:
public class MyRecord {
@Transform(IntToStringTransformer.class)
public int someValue;
}
someValue will be a string column in the database, owing to the
IntToStringTransformer converting the int to a String.
Now you come along and think to yourself, "Hey, I want to store the current
minute in my 'int' field." and you write something like:
updatePartial(MyRecord.class, MyRecord.SOME_VALUE,
DateFuncs.minute(Exps.literal(new Timestamp(System.currentTimeMillis()))));
Well, that's going to end up trying to stuff an int-valued expression (computed
by the database) into a String field, and the shit will hit the fan.
I can't really think of a non-contrived situation where this is likely to bite
us in the ass, but I don't especially like grass covered pits like this lying
around, waiting for someone to unsuspectingly step into them.
I could fail if you try to update a transformed field with anything other than
a ValueExp (or the current value from a pojo), but that would prevent you from
doing something potentially useful and safe like copying one field to another,
which both use the same transformation.