Hi there,

I've had a look at your prototype now with the debugger. I'll comment at
the end of this E-Mail, responding to your latest E-Mail first

2015-04-20 20:04 GMT+02:00 <[email protected]>:

>
>
>> I'll get back to you with more feedback once I've seen jooq4hibernate.
>>
>
>
> Thank you very much.
> I just find out that in the project QueryDSL, there is a little
> documentation that describe the same approach.
> QueryDSL for sure have JPA native support using JPQL and metamodel based
> on entity (infact in our architecture I discuss with my collegues to use
> this instead of jOOQ, to rewrite some statements written with Criteria) but
> it also have SQL support.
>
Here
> http://www.querydsl.com/static/querydsl/2.1.0/reference/html/ch02s02.html
> is described how to use SQL metadata to handle query with Hibernate Native
> Query (in the chapter 2.2.14).
>

Hmm, there's no magic in QueryDSL like the magic you've implemented in
jooq4hibernate. QueryDSL has different sets of query APIs for different
backends. The documentation page you've linked is used to produce JPQL, not
SQL...

QueryDSL is a higher-abstraction query API than jOOQ. Timo aims for
supporting any sort of backend, including MongoDB, Java Collections, etc.
similar to .NET's LINQ. jOOQ is only about SQL, and thus abstracts less
from JDBC and from the SQL language. This obviously makes QueryDSL better
suited for JPQL, and jOOQ better suited for SQL.

Now, about jooq4hibernate. I'm actually impressed that you've managed to
extract that much information from the jOOQ AST and transform it into a
Hibernate SQLQuery with additional meta information. I can imagine that it
might add value to your projects where you know exactly what you're doing,
and why you're doing it.

Here are some comments to the questions in DefaultSQLQueryAnalyzer:

 * Open "issues"\question:
 * 1) Do i use the correct Clause to extract the information that i need?
 * Select\join table, excluding any subquery only on the main query, and
their join conditions.
 * Is it correct check for Clause.SELECT_FROM in the context.clauses() for
this purpose?

Probably, although, I'm not 100% sure if I understand the question

 * 2) In clause TABLE_REFERENCE in some cases the queryPart is Table in
others TableList
 * A simple select with alias specified return Table the same select
without alias seems to return TableList with one element inside.
 * To extract the table from tableList actually I use the reflection on the
superClass to retrieve the wrapperList, assuming that contains Objects
implementing Table interface.

This is an interesting observation. There's definitely some Javadoc missing
on VisitContext.queryPart(). The problem here is that you're implementing
"clauseStart()", which emits the start of a Clause *before* all the clauses
QueryParts are emitted. The order of calls is this (pseudo code):

- clauseStart(TABLE)
- clauseStart(TABLE_REFERENCE)
- visitStart(... the actual QueryPart ...)

This can be seen in the code of AbstractContext.visit(QueryPart):

            // Issue start clause events
            //
-----------------------------------------------------------------
            Clause[] clauses = visitListeners.length > 0 ? clause(part) :
null;
            if (clauses != null)
                for (int i = 0; i < clauses.length; i++)
                    start(clauses[i]); // This is when
clauseStart(TABLE_REFERENCE) is called

            // Perform the actual visiting, or recurse into the replacement
            //
-----------------------------------------------------------------
            QueryPart original = part;
            QueryPart replacement = start(part); // This is when your
ctx.queryPart() reference becomes available

            if (original == replacement)
                visit0(original);
            else
                visit0(replacement);

            end(replacement);

            // Issue end clause events
            //
-----------------------------------------------------------------
            if (clauses != null)
                for (int i = clauses.length - 1; i >= 0; i--)
                    end(clauses[i]);

You should probably move some of the logic from clauseStart() to
visitStart(). clauseStart() and clauseEnd() events are useful to track the
beginning and the end of a whole Clause, i.e. including keywords and
everything.

We'll fix this in the next minor (or major) release. Probably,
VisitContext.queryPart() should return null within clauseStart() and
clauseEnd(). I'm tracking this as:
https://github.com/jOOQ/jOOQ/issues/4249

 * 3) For the case of TableList and case of Field I retrieve information
needed with reflection. Can i do in some other way?

This should be resolved once you switch from clauseStart() to visitStart().
The QueryPart is simply "stale".

 *  4) In TABLE_REFERENCE if the alias is not specified, it seems to return
"join" as table.getName(). See isValidAlias (I actually exclude "join" as
valid name alias, this is dangerous because if for some reason, some table
has declared with 'join' alias, this is ignored!).

Same thing. You won't get the "join" in TABLE_REFERENCE, once you switch to
visitStart()

 *  5) To trigger the VisitListener, I use
DSL.using(configuration).renderContext().visit(select); Is it ok? I want to
avoid select.getSQL() just to trigger the VisitListener.

I also noticed this. This is correct, and much better than using attach()
and getSQL(), as it will not modify the state of your select reference.
Note that the following two are the same:

DSL.using(configuration).renderContext().visit(select);
DSL.using(configuration).render(select);

The latter actually returns the SQL string that you need.

 *  6) Just to report, it's not an issue here. For some clauses, if i try
to print the queryPart, a stackoverflowexception will be trown.

Yes, this can happen because you re-enter your VisitListener indefinitely.
This probably happens when you attach your Configuration/VisitListener to
the query part.



I think with the above input, your existing prototype will become a lot
simpler. For us, it's extremely valuable to see you using the VisitListener
like that. We obviously got 1-2 things wrong, and we obviously have to
better document this part of jOOQ. Looking forward to your further
experiments!

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.

Reply via email to