columns in the results to match the FieldMarshaller column names, so we have
to use those rather than the field names. Also, shadowed fields need to use
the column names of the fields that they're shadowing.
date from date(). We should probably just modify DateFuncs.date to
return a date in both cases (perhaps with a separate DateFun.DateCast
class), but for now it's easier to have MySQL return a timestamp as
well.
the terminator (we encode the terminator as a different character).
This is somewhat nicer when inspecting an encoded String, and allows
for a future in which the decoder easily counts the number of terminator
characters and pre-allocates the storage, if we so desired.
There are some optimizations that could probably be made, but
for now I defer to the new One Rule of Optimization:
"Do not optimize for performance unless it does not weird the code or
it Really Matters".
- continue to terminate Strings with a newline
- turn newlines inside a String into "\n"
- turn null elements into "\0".
This is one additional character when encoding nulls, but
I think it may improve readability..
contains generic type information which would allow a transformer to do the
right thing with a field of, say, type Set<Integer>.
If we had unit tests for StringIterable, I'd know that I didn't just break it.
I'd also know that it worked in the first place. :)
to the ternary operator are boolean constants, don't use the ternary operator.
a ? true : x == a || x
a ? x : true == !a || x
a ? false : x == !a && x
a ? x : false == a && x
case, seeing it fail, then adding the code to handle it was rather satisfying.
I'm not jumping on the TDD bandwagon or anything, but libraries like Depot are
clear cases where vigorous unit testing is a big win.
- Revamped column type determination to use a mechanism that supports
delegation and does not rely on a heap of instanceof calls (which results in
runtime failure rather than compile time failure when a new column type is
added)
- Discovered that HSQLDB (at least) does not handle Byte, Short and Float
correctly. It returns them as Integer, Integer and Double respectively, which
then causes failure when trying to write those values back to the fields. We
work around this by converting non-null results to the correct type after we
get them back from the JDBC driver.
This is an unimplemented proposal for handling non-basic types in Depot in an
extensible way, instead of continuing down the road of the ByteEnum-style
hackery that we've been doing to date. The basic design is as follows:
Annotate either a field or a class with @Transform and specify the classname of
a Transformer in that annotation. For example:
public class MyRecord extends PersistentRecord {
@Transform(Transformers.CommaSeparatedString.class)
public String[] cities;
}
will cause "cities" to be combined into a single string (comma separated)
before storing in the database, and split back into a string array from the
single string when read from the database.
Alternatively, one can annotate a type:
@Transform(ByteEnumTransformer.class)
public interface ByteEnum { ... }
If Depot sees a field of non-basic type, it will look for a @Transform
annotation on the field's type (and any interfaces implemented by that type or
its parent types, which is not auto-magic). If it finds one, it will use it.
Otherwise it will fall back to what it does now (which I think is to just foist
the object off to JDBC and hope for the best).
Comments and suggestions are invited.
verbose) mechanisms to accomodate his needs. We freak out as early as possible
to save the developer a time wasting debugging session in situations where they
update only one or the other of the persistent and runtime class, or make a
typo, or get the types wrong, etc.