On Sat, Oct 20, 2018 at 5:43 PM Marshall Pierce <[email protected]> wrote:
> Well, you're using internal API (DefaultDataType). It may work in >> unexpected way. Much better to create a new data type from >> SQLDataType.TIMESTAMPWITHTIMEZONE by calling asConvertedDataType(new >> YourBinding()). >> >> That data type is then reusable. Also, the cast is probably not what you >> want. It may result in an actual SQL CAST(...) expression. Field.coerce() >> is one way to switch data types on an expression. Or, you can just use >> plain SQL templating to re-create your now() function as an Instant data >> type: >> https://www.jooq.org/doc/latest/manual/sql-building/plain-sql-templating >> <https://www.google.com/url?q=https%3A%2F%2Fwww.jooq.org%2Fdoc%2Flatest%2Fmanual%2Fsql-building%2Fplain-sql-templating&sa=D&sntz=1&usg=AFQjCNFrhea7zlxsgZLgTTiA_MggvdZ3UA> >> > > Aha. Field.coerce() with asConvertedDataType() works fine. No shortage of > API to learn in jOOQ... > Well, this definitely isn't everyday API :) > I'll look into this, thanks. Specifically, this indexOf() call, which >> you've noticed as well, seems like it should be cached: >> >> https://github.com/jOOQ/jOOQ/blob/version-3.11.5/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java#L750 >> >> The question is: Where should that cache be as you're looping over your >> records in your own code. I could see some per-loop caching in >> ResultImpl.into(Table) >> > > Perhaps each Record might keep a reference to its parent Result and access > some shared cache of field data? If that's not convenient, though, I'd be > totally fine if there was some other way to make caching explicit (though > it would be a shame to lose caching for all users transparently), like > having Result provide a CachingRecordWidget that had some > recordInto(Record, Table) method that would then make it trivial to cache > the necessary metadata. > That would scratch your immediate itch but is generally a not a good idea as records are independent entities and could be placed in several results. One example is the Result.intoGroups() method, which tends to wrap sub-results in a Map. Other examples are methods like DSL.values(), which have overloads accepting a Result, which might be constructed using DSLContext.newResult(). This definitely looks easier at first than it really is. Any record can be mapped into any other record type, including a Table reference, which may or may not be generated. Blindly caching all these calls would blow up cache sizes in some systems. Of course, for large data sets, perhaps the built-in jOOQ mapping methods might just not be good enough, and you can do easily better, knowing exactly what you're doing given a particular use case. To be clear, if we had a BookTuple(book: BooksRecord, author: > AuthorsRecord, category: CategoriesRecord) type, and we populated that with > the obvious joins between books, authors, and categories, this is the type > of "cleaning up the mess" logic I was referring to the following (in mostly > Kotlin-esque syntax): > > tuples > .groupBy { it.book.id } > .values // now it's a sequence of List<BookTuple>, where each list > corresponds to one book > .map { bookTuples -> > val bookRecord = bookTuples.first().book > val authors = bookTuples.filter { it.author.id != null }.groupBy { > it.author.id }.values.map { it.first().authorNameEtc } > val categories = bookTuples.filter { it.category.id != null}.groupBy > { it.category.id}.values.map {it.first().categoryDataHere} > // construct your Book type appropriately from the above locals > } > > AFAICT this takes care of all the deduplication. > Yes, without going through it thoroughly, that looks reasonable. But again, the duplication is part of the performance problem, so surely there's a better solution from that perspective. Thanks, Lukas -- You received this message because you are subscribed to the Google Groups "jOOQ User Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
