Digest for jooq-user@googlegroups.com - 14 updates in 3 topics

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Digest for jooq-user@googlegroups.com - 14 updates in 3 topics

http://groups.google.com/group/jooq-user/topics mailing list
Lukas Eder <[hidden email]>: Aug 30 08:57AM +0200

Dear group,
We have noticed a significant regression in the jOOQ 3.12 Open Source
Edition's code generator when using it with PostgreSQL. The regression has
been fixed on jOOQ 3.13 and backported to jOOQ 3.12.1:
We will publish 3.12.1 early next week to address this issue.
Thank you very much for your understanding
Lukas Eder <[hidden email]>: Aug 30 09:33AM +0200

Hi Matthias,
Thank you very much for your nice words. I will comment on your questions
> - The Java 11+ supporting distribution, "which includes more optimal API
> usage, depending on new Java 9-11 APIs" - can you be a bit more specific?
> Which newer JDK APIs are leveraged? Examples?
First off, for the avoidance of doubt, both the Java 8+ distribution and
the Java 11+ distribution *support* Java 11 starting from jOOQ 3.12. We
already integration tested jOOQ 3.11 with Java 11, but did not officially
support it.
Starting from jOOQ 3.12, we wanted to be able to use new API in one of our
distributions. Two such API usages that I can remember right now are:
- The java.util.concurrent.Flow API, for the new reactive integration.
While the industry has standardised reactive APIs to be backed by the
reactive streams SPI, the JDK has cloned the creative streams SPI in Flow.
We're expecting third party libraries to slowly migrate towards Flow, and
we wanted to be ready for that already today. For users, it is transparent
whether jOOQ's ResultQuery implements org.reactivestreams.Publisher or
Flow.Publisher, or both.
- Some reflection APIs have changed incompatibly in Java 9, especially when
trying to reflectively call default methods on proxies. It is not possible
to get this right on Java 9+ without calling the new APIs using e.g.
We'll find additional API in the future that we'll be able to use for
whatever reason in the Java 11+ distribution only.
Regarding distributions and editions, we only want to offer a single jOOQ
Open Source Edition distribution. We had two options:
- Make it support Java 8+
- Make it support Java 11+
Java 11 is not adopted well enough yet to bump the jOOQ Open Source
Edition's dependency to Java 11, so we picked Java 8. The commercial
editions have several distributions now, supporting:
- Java 6 - 7 (Starting with 3.12 for Enterprise Edition only - the websites
will be updated soon to reflect this change)
- Java 8 - 10 (All commercial editions)
- Java 11+ (All commercial editions)
> - Can you give examples for the procedural language API? How does that
> work?
We will soon update the manual and blog about it in much detail. In
essence, with jOOQ 3.12, you can write anonymous blocks such as PL/SQL's:
i INT := 0;
i := i + 1;
Or with jOOQ:
Variable<Integer> i = var(unquotedName("i"), INTEGER);
insertInto(T, COL).values(i),
You can also parse parts of it using DSLContext.parser().parseStatement(),
and combine the resulting statement expression with other, dynamic jOOQ
logic. This API is our first step towards pushing more complex logic into
the database in a vendor agnostic way. We're already emulating quite a few
things in these anonymous blocks (will be documented in the manual and blog
post), and we'll continue evolving the API using procedure definition APIs,
trigger APIs, etc.
An exciting new area for jOOQ!
- Native JSON/JSONB support: Can you show an example?
We'll also blog about this soon. The code generator will pick up these
types automatically and produce a Field<JSON>. This just takes care of
writing the right binding / reading code, such that e.g. in PostgreSQL, you
no longer have to do that manually. The new org.jooq.JSON and
org.jooq.JSONB types are currently just wrappers for String data.
> - You write "...immutable query object model, with all the secondary
> benefits like caching of generated SQL..." Is this "immutable query object
> model" in internal change? Is there a (new) user facing API?
At first, this will be an internal change, although we will make the API
public from the beginning, for early user feedback.
Then, it will turn into a new user facing API and replace the current
"model API" (SelectQuery, UpdateQuery, etc.) as well as obsolete the
VisitListener. The goal is that users will be able to:
- Construct jOOQ queries entirely using this model, instead of the DSL,
where this makes sense (in more sophisticated use cases)
- Transform the queries using this model using pattern matching or other
techniques (imagine matching all ACCOUNT tables and replacing them by
(SELECT * FROM ACCOUNT WHERE CUSTOMER_ID = ?) derived tables for row level
We don't have any preview yet. We'll evaluate numerous options, including:
- Writing this API in another JVM language that already supports ADTs and
pattern matching, e.g. Scala or Kotlin
- Writing this API in Java with a strong forward compatibility focus for
the goodies we'll get with Amber (record types, sealed types, pattern
matching) and Valhalla (value types)
We don't know yet.
> And: Will generated SQL be cached internally now somehow (or was that the
> case already)?
We'll start caching SQL fragments or entire SQL statements for improved
performance. We currently cannot do that for any jOOQ QueryPart because:
- QueryParts are mutable, hence it is almost impossible to detect in any
QueryPart if any sub-QueryPart was modified since the SQL string was cached
- Configuration and Settings are mutable, and they define things like
SQLDialect, render mapping, upper/lower case keywords/identifiers, etc
We could have made some heuristics and document a very complicated and
buggy cache, but we opted for simply not caching generated SQL.
In the future, with this new query object model, it will be possible for
users to treat SQL queries (even dynamic ones) as constants and reuse the
SQL string that is generated only once for the entire application. This is
also possible today, but only with manual plumbing on a per-query basis.
We'll expect a tremendous performance improvement in the client from this.
[hidden email]: Aug 30 04:18AM -0700

Hi Lukas,
Thanks for the new release! I played around with jOOQ for Postgres last
week and I am happy to see that two things I wanted to work around (JSONB
support and using Instant) no longer need work from my side :)
Two questions:
1. I can't find the new 3.12 jOOQ version in Maven Central, whereas the
previous versions are available there. Do you publish those version upon
release? How long does it take from releasing new version to having it
available in Maven Central?
2. Could you also provide an example how to use Instant instead of
OffsetDateTime for generated records from Postgres? Or will it now use
Instant by default?
Thanks for the heads up about PostgreSQL regression.
Lukas Eder <[hidden email]>: Aug 30 01:30PM +0200

Hi Krzysztof,
Thank you very much for your email.
> previous versions are available there. Do you publish those version upon
> release? How long does it take from releasing new version to having it
> available in Maven Central?
Are you looking in the right "Maven Central"? :) It's right there:
There's a mirror that often shows up in google searches, which is often
referenced by people not finding latest jOOQ versions...
Could you also provide an example how to use Instant instead of
> OffsetDateTime for generated records from Postgres? Or will it now use
> Instant by default?
You use a forcedType and force it to INSTANT. See e.g.:
I hope this helps,
David Karlsen <[hidden email]>: Aug 30 01:32PM +0200

I started seeing
java.lang.IllegalArgumentException: Field
(cast("APPDATA"."T_ADDRESS"."CREATED_DT" as timestamp)) is not
contained in Row ("APPDATA"."T_ADDRESS"."ID",
at com.edb.fs.tac.jfr.srv.service.customer.CustomerServiceIntegrationTest.createDuplicateCustomer(CustomerServiceIntegrationTest.kt:178)
with 3.12.0 (upgrade from 3.11.12).
code in question:
override fun updateCustomer(customer: Customer): Customer {
this.dslContext.newRecord(T_CUSTOMER, customer)
.with(T_CUSTOMER.ID, BigInteger.valueOf(customer.id!!))
BigInteger.valueOf(customer.version ?: 0L))
.with(T_CUSTOMER.UPDATED_DT, customer.updatedTimestamp ?:
.with(T_CUSTOMER.CREATED_DT, customer.createdTimestamp ?:
.with(T_CUSTOMER.FIRSTNAME, customer.firstName)
.with(T_CUSTOMER.LASTNAME, customer.lastName)
return getCustomer(customer.orgId, customer.customerId) ?: throw
David J. M. Karlsen - http://www.linkedin.com/in/davidkarlsen
Lukas Eder <[hidden email]>: Aug 30 01:37PM +0200

Hi David,
Thank you very much for your message.
Where does this cast come from? I cannot see it in your Kotlin code. Is
this jOOQ's Record::with method, or a Kotlin extension method? Also, do
note that the stack trace fragment you've posted is from
createDuplicateCustomer(), but you posted the code of updateCustomer().
On Fri, Aug 30, 2019 at 1:32 PM David Karlsen <[hidden email]>
[hidden email]: Aug 30 12:07PM -0700

Thank you Lukas for your response.
Regarding Maven, I meant mvnrepository.com, which as you say is often
returned in Google results. I wasn't aware it may be returning some cached
view only. Will know for the future :) Sorry for the confusion.
Thanks for directing me to relevant parts in documentation. I also found
example provided by you in the related GitHub ticket
https://github.com/jOOQ/jOOQ/issues/7952. I will give a try with 3.12.1
<type>(?i:TIMESTAMP\ WITH\ TIME\ ZONE)</type>
W dniu piątek, 30 sierpnia 2019 13:30:48 UTC+2 użytkownik Lukas Eder
Matthias Kurz <[hidden email]>: Aug 30 01:12PM -0700

as always, thanks for your precious time and your detailed answer!
Questions left:
- Is the procedural language API included in your cheapest commercial
offering, the "Express" edition? Meaning, if I want to make use of _all_
jOOQ's new, advanced commercial features, is it enough to purchase the
Express edition (even though I use Postgres and won't use any database
offered by the Express edition)? Will the only distinction between the
different jOOQ _commercial_ editions be the number of database products
each _commercial_ edition supports? Or will you start to offer some
commercial features e.g. only starting with "Professional", holding them
back for "Express" users?
Further: Do you plan a (maybe cheaper than "Express") option to purchase
only the commercial features? E.g. using Postgres, but not interested in
any of the database products your commercial editions offer, I just want to
unlock all the commercial features for Postgres. What do you think?
- When you talk about "row level security" - do you mean actually rls on
database level (like https://www.postgresql.org/docs/11/ddl-rowsecurity.html)?
Or do you talk about "row level security" in a sense that jOOQ just adds
"WHERE user_id = xxx" to each query?
On Friday, 30 August 2019 09:33:32 UTC+2, Lukas Eder wrote:
"Victor Noël" <[hidden email]>: Aug 30 06:35AM -0700

I think I'm a bit thick with this, but I just can't wrap my head around the
difference (and more importantly the need) for both Allow and Require
annotations with jooq-checker.
Maybe it's because my use case does not need both, so let me explain what
it is:
- I have some code (maybe used by different applications, so it's kind of
library code) that do db related stuffs, and if it is possible, I want this
code as generic as possible w.r.t. the database dialect
- because I mostly use postgresql, sometimes I use postgresql-specific
features (still in library code)
- in some specific cases, I DO know which database I am using (disclaimer:
it's postgresql :P) for my application (so it's not library code)
What I did is annotate most of this code with `Allow(SQLDialect.DEFAULT)`
and when it wasn't enough, I used `Allow(SQLDIALECT.POSTGRES)`.
Some questions:
- I'm not sure it is correct to use the DEFAULT dialect for this, but I
suppose it is?
- I don't see the need for Require here, is it only needed when I am
working with multiple dialects (not DEFAULT) at the same?
- Is Allow some kind of architecture-level rule while Require some kind of
class-level assertion?
Thanks for any help to understand this :)
Lukas Eder <[hidden email]>: Aug 30 04:51PM +0200

Hi Victor,
Put shortly, Allow is a disjunction (OR) whereas Require is a conjunction
- @Allow({ ORACLE, POSTGRES }) means that you allow for both of these
dialects to be used in general. No other dialect may be used (e.g. MYSQL).
If an API supports only one of the two dialects, e.g. CONNECT BY (supported
by Oracle), then it is still allowed.
- @Require({ ORACLE, POSTGRES }) will now require *both* Oracle and
PostgreSQL support on any API. In this case, CONNECT BY will no longer
work, because it is not supported by PostgreSQL
In your case, you could just use @Allow(POSTGRES) only. You don't have to
Allow(DEFAULT), I don't think this adds much value. If you're only working
with a single RDBMS, you don't need @Require. But you could add it, and
then add a second dialect in the future, should you choose to support
another RDBMS.
Perhaps, code explains this better? Here's the implementation from
boolean allowedFail = true;
for (SQLDialect a : allowed) {
for (SQLDialect s : supported) {
if (a.supports(s)) {
allowedFail = false;
break allowedLoop;
if (allowedFail)
return error.apply("The allowed dialects in scope " + allowed + " do
not include any of the supported dialects: " + supported);
boolean requiredFail = false;
for (SQLDialect r : required) {
for (SQLDialect s : supported)
if (r.supports(s))
continue requiredLoop;
requiredFail = true;
break requiredLoop;
if (requiredFail)
return error.apply("Not all of the required dialects " + required + "
from the current scope are supported " + supported);
I hope this helps.
"Victor Noël" <[hidden email]>: Aug 30 07:56AM -0700

Yes, it does help, what I was missing is that if I need to have code that
works with TWO dialect at the same time, I need `Require` to force my code
to be compatible with both. `Allow` wouldn't help with this.
Following this, I'm wondering what would be the use case for `Allow` then:
is there some case when it makes sense to allow two different dialects?
You wouldn't want to mix in a same query two dialects, and if it's in
different queries, then you juste need to apply two different `Require`
annotation on different scope.
Does this make sense?
Le vendredi 30 août 2019 16:51:30 UTC+2, Lukas Eder a écrit :
Lukas Eder <[hidden email]>: Aug 30 05:19PM +0200

Think in terms of trees of code.
On the package level, you'll allow Oracle and PostgreSQL
On most class levels, you'll require both
On some specialised DAOs, you'll require only *either* Oracle *or*
PostgreSQL, e.g. you'll have an OracleCustomerDAO and a
PostgresCustomerDAO, because those queries needed special tuning, or
And on another, third, specialised service, you're going to use H2, but
you'll limit that to only this one service. So, you'll add another Allow
(and Require) H2 annotation.
We may have overengineered this a bit, but think of it as a two way access
control list. Allow grants additional dialects. Require revokes them again,
but instead of revoking, we chose requiring as a verb, with the inverse set
of dialects to be passed, because that's more practical. Thinking of it (to
add to the confusion), we *could* support an additional @Deny annotation ;-)
"Victor Noël" <[hidden email]>: Aug 30 08:28AM -0700

I see ok.
Technically, I feel like I could just use Require to express your example
and things would be as expressive I feel (this is related to the fact that
at the lowest scope, you never want to mix two dialect at the same time).
But as I said in my first post, I believe it could make sense to have
different reasons for
- allowing only some dialects: it is an architectural choice, for example a
team says that only Oracle and Postgres can be used and that should be
inforced for the whole code base, which btw is a good motivation for
- requiring some dialects in a given scope to be sure we are not
introducing bugs by using incompatible dialects, this matches well with the
example you gave.
Thank you for taking the time, I think everything is clear for me now :)
Le vendredi 30 août 2019 17:19:38 UTC+2, Lukas Eder a écrit :
<[hidden email]>: Aug 29 09:32AM +0400

I am very sorry for the trouble and for this letter!
But I have no other choice!
My name is Narges, I am transgender and live in Iran.
It's no secret that Iran is the most homophobic country in the world.
Representatives of LGBT communities are criminally prosecuted in our country and hated fiercely.
They can even be executed in public.
In our country, a real hell for homosexuals.
In remote areas of the country, LGBT people are beaten, tortured, raped and even executed with shocking regularity.
Thanks to a 1987 bill that legalized sexual change,
parents of homosexual children regularly force them to undergo hormonal treatment against their will,
and for the sex change operation, local bandits kill.
Recently, my beloved Gul was kidnapped by police and asked for a ransom, otherwise she would face a death penalty (before that she had already been lashed).
These scum are asking for 25 thousand dollars.
I ask all LGBT people and just kind people to help us in this trouble.
I want to redeem my beloved and flee from this damned country to civilization, where we can live in peace!
Every dollar is important to us, help as much as you can!
If suddenly everything works out, then I plan to fight this situation in Iran and make an LGBT fund for compatriots.
My friend is a programmer. He advised me to write and send this email to different people and ask for money in bitcoins.
Since it is absolutely anonymous for me and for you.
He also said that it is very easy to replenish.
Here is my btc wallet (if your really ready): bc1qlq7z2xy4tw0wd46lnsexq9fgqquuryus2x5txw
Peace to your home.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to [hidden email].