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.
