Commit Graph

708 Commits

Author SHA1 Message Date
Michael Bayne 780d25866c Holy plans coming together Batman, selecting computed expressions is working.
Some examples:

int max = _repo.from(TestRecord.class).load(Funcs.max(TestRecord.RECORD_ID));

List<Tuple2<String,Integer>> data = _repo.from(EnumKeyRecord.class).
    groupBy(EnumKeyRecord.NAME).ascending(EnumKeyRecord.NAME).
    select(EnumKeyRecord.NAME, Funcs.count(EnumKeyRecord.TYPE));

Still no caching integration, but the ratio of utility over boilerplate is
high.
2010-12-09 01:14:21 +00:00
Michael Bayne 800c566fc6 Use DepotTypes to keep track of the types in our query. That's it's whole
purpose in life.
2010-12-09 00:42:34 +00:00
Michael Bayne f629b267ba I'd like to be able to require that you at least can only call greatest and
least on something that was Comparable, but unfortunately, the numeric type's
only shared supertype is Number and that is not comparable.

If I require Number, then you can't do greatest(timestamp, timestamp), and if I
require Comparable, then you can't do greatest(int, double) because the
compiler can't unify those types to something that is Comparable.

I could require that you only compare apples with apples (i.e. greatest(int,
int) or greatest(double, double)), but databases will happily compare
greatest(int, double) and people are going to want to do that. I could
introduce some sort of numeric conversion expressions, but I think that's
getting too deeply into the realm of type safety for type safety's sake.
2010-12-09 00:21:44 +00:00
Michael Bayne b01eaef2d8 The type safety turtles now go all the way down. This tightens up a bit more
fast-and-looseness by propagating types through foo.eq(bar) expressions,
foo.lessThan(bar) expressions and the like.

This means a few things stopped working, like
StringFuncs.length(MyRecord.BYTE_ARRAY_FIELD), but now there's
Funcs.arrayLength() for that. Also Date functions are looser than I'd like
because there's no supertype between sql.Date and sql.Timestamp (to express a
date having type) and sql.Timestamp and sql.Time (to express a time having
type). So you can still do some foot shooting with those methods, but it's
hardly worth crying over since the foot shooting range was fully open for
business prior to this.

MSOY fixes coming presently. ProjectX fixes shortly thereafter.
2010-12-09 00:08:58 +00:00
Michael Bayne 4bb926c238 Compile the tests on every compilation. 2010-12-09 00:02:18 +00:00
Michael Bayne ce71fa01fa More use of Preconditions. 2010-12-08 20:24:36 +00:00
Michael Bayne 84758df725 Added support for joins when doing field selections:
List<Tuple2<Integer,EnumKeyRecord.Type>> jdata =
    _repo.from(TestRecord.class).
      join(TestRecord.NAME, EnumKeyRecord.NAME).
      select(TestRecord.RECORD_ID, EnumKeyRecord.TYPE);

This should eliminate the need for pesky one-off computed records when doing
ad-hoc joins.
2010-12-08 20:03:27 +00:00
Michael Bayne 0bfe3959fc Add support for extracting our column data by position rather than name. 2010-12-08 20:00:21 +00:00
Michael Bayne 44b9b4ff90 Use Exps.trueLiteral(). 2010-12-08 19:37:54 +00:00
Michael Bayne aa294033cb Clean up after our enum key testing, use trueLiteral(). 2010-12-08 19:37:25 +00:00
Michael Bayne 963a9a0fc1 Guava makes defensive programming more pleasant. 2010-12-08 19:35:50 +00:00
Michael Bayne b42ec35b09 Make this into a proper value class. 2010-12-08 19:19:22 +00:00
Michael Bayne 730f4c79ae Make the creation of true and false literals less hacky. 2010-12-08 19:18:52 +00:00
Michael Bayne 5bdc7d6746 We want to use the class that owns the column expression rather than supplying
one that may be incorrect.
2010-12-08 19:10:45 +00:00
Michael Bayne ad9f068355 Prefer a different fork to stick in it, per Ray. 2010-12-08 18:28:41 +00:00
Michael Bayne f6a2ad1000 Exciting new additions:
1. ColumnExp is now parameterized on the type of the column it represents. This
enables item number two.

2. The beginnings of a very primitive implementation of individual field
selection, which looks like:

  List<Tuple2<Integer,String>> results = from(FooRecord.class).where(
    FooRecord.ID.in(someIds)).select(FooRecord.ID, FooRecord.NAME);

I don't advise using this new functionality just yet, because it's very
primitive and will probably break if you try to do anything fancy. Plus it
doesn't interact with the cache at all yet.

However, I wanted to get the typed ColumnExp bits in there so that I can
migrate all the existing projects over and get that painful business out of the
way. Note for the jumpy: migration in this case means eliminating a bunch of
unchecked type usage warnings, rather than behavioral changes. The existing
Depot functionality continues to work exactly as is. The types are not used
except for in the new individual field selection code.

One bit of code that will break is calls to updatePartial() which used to take
a Map<ColumnExp, ?> and now take a Map<ColumnExp<?>, ?>. Since those were
already in generics land, they won't just fail with an unchecked type warning,
the compiler will reject the old call (the calls are binary compatible, so
unrecompiled code will still work fine). Fortunately the Map-taking
updatePartial is not called that much outside of MSOY, which I have already
migrated to fully parameterized ColumnExp land.
2010-12-08 08:23:27 +00:00
Michael Bayne dd85f630e4 We need to preserve our type parameter. 2010-12-08 00:42:11 +00:00
Michael Bayne fc4cda9260 Allow multiple join clauses. Added a clone() method for reusing partially
configured queries.
2010-12-08 00:41:06 +00:00
Michael Bayne 355b084292 Further QueryBuilder improvements. In any case where you may want a specially
configured clause, allow adding the clause directly. Removed some repetition by
using said methods from factory versions. Other tidying.
2010-12-08 00:23:15 +00:00
Michael Bayne fca5cb2386 Added QueryBuilder.delete() along with a bunch of sanity checking. I considered
having a separate deleteFrom(record).where(...).delete() builder, but
from(record).where(...).delete() was so much nicer that I decided that
preventing the specification of invalid clauses could be deferred from compile
to runtime.

I could do some fiddly things with return types and have from() return a
builder that then subsequently pigeon-holed you into deletability or not
depending on whether you called things like orderBy(), but to do so in Java
would require that I override every method to specialize its return type, which
presents something of a maintenance annoyance.
2010-12-07 23:41:27 +00:00
Michael Bayne 1e86fba829 Added a limit that takes only a count. 2010-12-07 23:14:29 +00:00
Michael Bayne f48a688d99 Scratch the FluentRepository, let's do things properly with a QueryBuilder.
With this you can write queries like:

  MaxPointsRecord max = from(MaxPointsRecord.class).
      override(DailyScoreRecord.class),
      where(DailyScoreRecord.KEY.eq(key)).load();

  List<DailyLeaderRecord> top = from(DailyLeaderRecord.class).
      override(DailyScoreRecord.class).
      join(DailyScoreRecord.KNIGHT_ID, KnightRecord.KNIGHT_ID).
      where(DailyScoreRecord.KEY.eq(key),
            DailyScoreRecord.POINTS.eq(max.maxPoints)).
      select();

After configuring your query, you can load(), you can select(), you can
selectKeys() and you can selectCount(). Other improvements include configuring
cache behavior (from(FooRecord.class).noCache().where(...).select()).

random() became randomOrder() because I think that seeing random() stuffed in
the middle of a query is insufficiently communicative.

Next, I'm going to look into extending the query builder to allow things like:

   from(MemberRecord.class).
       where(MemberRecord.CREATED.greaterThan(date)).
       select(MemberRecord.AVATAR_ID, MemberRecord.HOME_SCENE_ID);
   // yields List<Tuple2<Integer, Integer>>

which will require adding types to ColumnExp, which I hope to do in a
moderately backwards compatible way. If I can, I may use those types to enforce
type correctness and turn things like the following into a compiler error:

   MemberRecord.MEMBER_ID.greaterThan("bob")

If I had a more sophisticated type system, I could even make an attempt to call
greaterThan() on a ColumnExp<String> a compilation error.

If the above doesn't turn out to be a rabbit hole extraordinairre (it probably
will), I'd like to look into obviating the need for most of the FieldOverride
and FromOverride fiddling, and support things like:

   from(MemberRecord.class).
       where(MemberRecord.CREATED.greaterThan(date)).
       select(Exps.max(MemberRecord.SESSIONS));
   // yields List<Integer>

which would take Depot in the direction of being a (somewhat) type safe wrapper
around SQL. This would go a long way toward bridging the conceptual gap between
"the SQL I know I want to write" and "how the fuck do I do this with this Java
API".

I don't think I'm going to be able to get too far with the type-safe wrapper
approach without propagating types all over the place, which may result in
backwards compatibility breakage. If things get really bad, I may just have to
pinch off the Depot 1.x series and venture into the green fields of Depot 2.x.
I'll see how far I can get before taking such drastic action, however.
2010-12-07 22:49:28 +00:00
Michael Bayne 44a8fccc86 Added FluentRepository, which provides helper methods for creating all of the
various query clauses.

Something like this:

   MaxPointsRecord max = load(MaxPointsRecord.class,
       new FromOverride(DailyScoreRecord.class),
       new Where(DailyScoreRecord.KEY.eq(key)));

   List<DailyLeaderRecord> top = findAll(DailyLeaderRecord.class,
       new FromOverride(DailyScoreRecord.class),
       DailyScoreRecord.KNIGHT_ID.join(KnightRecord.KNIGHT_ID),
       new Where(Ops.and(DailyScoreRecord.KEY.eq(key),
           DailyScoreRecord.POINTS.eq(max.maxPoints))));

becomes this:

   MaxPointsRecord max = load(MaxPointsRecord.class,
       from(DailyScoreRecord.class),
       where(DailyScoreRecord.KEY.eq(key)));

   List<DailyLeaderRecord> top = findAll(DailyLeaderRecord.class,
       from(DailyScoreRecord.class),
       join(DailyScoreRecord.KNIGHT_ID, KnightRecord.KNIGHT_ID),
       where(DailyScoreRecord.KEY.eq(key),
             DailyScoreRecord.POINTS.eq(max.maxPoints)));

and the imports for Where and FromOverride go away. It's a modest improvement
in readability.

Both COL.join(OCOL) and join(COL, OCOL) are supported; one can choose based on
the aesthetic demands of an individual query.
2010-12-07 21:05:42 +00:00
Michael Bayne 569cce8276 Whitespace fix. 2010-12-07 20:58:41 +00:00
Ray Greenwell 7a1f87f2a0 IntArrayMarshaller was doing things in the wrong places to work
as a delegate for a TransformingMarshaller.
2010-12-01 20:59:12 +00:00
Michael Bayne 52f432270d Added a test for using an Enum as a record key, observed brokitude, fixed
brokitude, but did not take the opportunity to do so in a non-hacky way.
2010-12-01 19:53:03 +00:00
Michael Bayne 5f937fae61 Omit ant runtime classes. 2010-12-01 19:41:32 +00:00
Michael Bayne eaadb3228a Added support for non-ByteEnum enums, which are stored using their string name. 2010-12-01 19:36:01 +00:00
Michael Bayne fd035fd463 [maven-release-plugin] prepare for next development iteration 2010-11-20 02:54:24 +00:00
Michael Bayne 35f9d8339e [maven-release-plugin] prepare release depot-1.1 2010-11-20 02:54:12 +00:00
Michael Bayne 6365f290d9 Put our templates in src/main/resources. 2010-11-20 02:50:38 +00:00
Michael Bayne ec03ede58a Go ahead and make maven-deploy publish locally unless otherwise directed. 2010-11-18 23:06:24 +00:00
Par Winzell 47b09269ca IDEA module file for Depot. You must set M2_REPO for this to import. 2010-11-18 18:22:54 +00:00
Charlie Groves c70cf7c1c6 Fix column indices in hsqldb. Like mysql, it can't handle parenthesis around its index column expressions. 2010-11-18 00:48:20 +00:00
Charlie Groves 8206abb33d Attach guava source from maven 2010-11-16 21:34:47 +00:00
Michael Bayne c2cd1e6d9f Require that a Maven repository be specified. If you want to install locally,
use "mvn install".
2010-11-15 19:38:14 +00:00
Michael Bayne e39e7fea42 We don't actually use any Ant code in Depot. Amazing! 2010-11-15 18:03:38 +00:00
Michael Bayne 969aea38fe Reference platform docs at their new location, add link to samskivert docs. 2010-11-15 18:03:05 +00:00
Michael Bayne d1f3ed9ed9 Added a Maven Deploy target, generate XML test output. 2010-11-12 23:07:15 +00:00
Charlie Groves 206781f529 Depend on samskivert as a project and inherit its dependencies, export our own dependencies, bump to guava r07 2010-10-28 20:09:15 +00:00
Michael Bayne 1b1792aabe Hah! Perhaps there was some use in having the class be named. However, I'm not
sure what this is really testing. If the CRUD test with CustomType works, then
transforming field marshallers work, so why do we need to make sure they have a
specific class name?
2010-10-25 20:16:40 +00:00
Michael Bayne 2db4506a2b Nixed extra space. 2010-10-25 20:15:55 +00:00
Michael Bayne adb3d643b9 Clean the test classes on a basic clean. 2010-10-25 20:15:43 +00:00
Michael Bayne c7b60a1de8 No value in having the transforming marshaller be a named class. Switch to
slightly more concise code.
2010-10-25 20:09:37 +00:00
Michael Bayne ff3f0aa337 Updated with Maven dependencies. 2010-10-25 19:57:25 +00:00
Michael Bayne 5046c1d906 Unused import trimming. Type parameter cleanup. 2010-10-25 19:55:27 +00:00
Michael Bayne ec04d618c4 Nixed vestigial methods. 2010-10-25 19:53:34 +00:00
Michael Bayne 230a53faf8 Depot hasn't needed Velocity for a long time. 2010-10-22 06:00:23 +00:00
Charlie Groves c564c36e3a Headerz 2010-10-19 00:37:42 +00:00
Charlie Groves a649efac99 Missing @Overrides, extra imports 2010-10-19 00:33:31 +00:00