Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 18 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@ Compile time validation for queries written in HQL, JPQL, and [Panache][].
[Panache]: https://quarkus.io/guides/hibernate-orm-panache
[Hibernate logo]: http://static.jboss.org/hibernate/images/hibernate_logo_whitebkg_200px.png

## Requirements

This project now requires at least JDK 11, but JDK 15 or above
is preferred.

## Building

Type `./gradlew` from this project directory.

This produces an artifact with the Maven coordinates
`org.hibernate:query-validator:1.0-SNAPSHOT` in your local
`org.hibernate:query-validator:2.0-SNAPSHOT` in your local
Maven repository.

It also creates a far jar `query-validator-1.0-SNAPSHOT-all.jar`
It also creates a far jar `query-validator-2.0-SNAPSHOT-all.jar`
in the `build/libs` directory of this project.

## Usage
Expand All @@ -27,9 +32,9 @@ basic JPA metadata annotations like `@Entity`, `@ManyToOne`,
mapping information like table and column names if that's what
you prefer.

1. Put `query-validator-1.0-SNAPSHOT-all.jar` in the
1. Put `query-validator-2.0-SNAPSHOT-all.jar` in the
compile-time classpath of your project. (Or depend on
`org.hibernate:query-validator:1.0-SNAPSHOT`.)
`org.hibernate:query-validator:2.0-SNAPSHOT`.)
2. Annotate a package or toplevel class with `@CheckHQL`.

#### Usage with plain Hibernate or JPA
Expand Down Expand Up @@ -107,16 +112,16 @@ Just compile your code with `javac`, or even with ECJ
(`java -jar ecj-4.6.1.jar`), with the query validator `jar` in
the classpath:

-classpath query-validator-1.0-SNAPSHOT-all.jar
-classpath query-validator-2.0-SNAPSHOT-all.jar

#### Gradle

Annoyingly, Gradle requires that the dependency on the query
validator be declared *twice*:

dependencies {
implementation 'org.hibernate:query-validator:1.0-SNAPSHOT'
annotationProcessor 'org.hibernate:query-validator:1.0-SNAPSHOT'
implementation 'org.hibernate:query-validator:2.0-SNAPSHOT'
annotationProcessor 'org.hibernate:query-validator:2.0-SNAPSHOT'
}

#### Maven
Expand All @@ -128,7 +133,7 @@ the dependency to the query validator.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>query-validator</artifactId>
<version>1.0-SNAPSHOT</version>
<version>2.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependencies>
Expand Down Expand Up @@ -161,7 +166,7 @@ manually.
processing**.
2. Then go to **Java Compiler > Annotation Processing >
Factory Path** and click **Add External JARs...** and
add `build/libs/query-validator-1.0-SNAPSHOT-all.jar`
add `build/libs/query-validator-2.0-SNAPSHOT-all.jar`
from this project directory.

Your project properties should look like this:
Expand All @@ -185,22 +190,16 @@ If the query validator doesn't run, please ensure that:

The query validator was developed and tested with:

- JDK 1.8.0
- Hibernate 5.4.10.Final
- ECJ 4.6.1
- Eclipse IDE 2019-03 to 2020-03 (JDT Core 3.17.0 to 3.18.300)
- JDK 15, JDK 17, JDK 20
- Hibernate 5.6.15.Final
- ECJ 3.33.0
- Eclipse IDE with JDT Core 3.33.0

Other versions of `javac`, ECJ, and Hibernate may or may not
work. The query validator depends on internal compiler APIs in
`javac` and ECJ, and is therefore sensitive to changes in the
compilers.

_NOTE: this version of the query validator does not work on
JDK 9 and above. The [jdk10][] branch in git is a preview of
the changes required to make it work on JDK 9-12._

[jdk10]: https://github.com/hibernate/query-validator/tree/jdk10

## Caveats

Please be aware of the following issues.
Expand All @@ -211,13 +210,6 @@ Queries are interpreted according to Hibernate's flavor of JPQL
(i.e. HQL), which is a superset of the query language defined by
the JPA specification.

One important example of how the languages are different is the
handling of function names. In the JPA spec, function names like
`SUBSTRING`, `SQRT`, and `COALESCE` are *reserved words*. In HQL,
they're just regular identifiers, and you may even write a HQL
query that directly calls a user-defined or non-portable SQL
function.

#### Function arguments are not checked

Hibernate's query translator never typechecks function arguments
Expand Down
55 changes: 29 additions & 26 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import org.gradle.internal.jvm.Jvm

plugins {
id 'java'
id 'groovy'
id 'maven'
id 'maven-publish'
id "com.github.johnrengelman.shadow" version "5.0.0"
id "com.github.johnrengelman.shadow" version "8.1.1"
}

defaultTasks 'assemble', 'publishToMavenLocal', 'shadowJar', 'test'
Expand All @@ -18,35 +15,38 @@ repositories {
}

dependencies {
compile ('org.hibernate:hibernate-core:5.4.10.Final') {
implementation ('org.hibernate:hibernate-core:5.6.15.Final') {
transitive = false
}
//explicit the Hibernate dependencies we need:
compile 'antlr:antlr:2.7.7'
compile 'javax.persistence:javax.persistence-api:2.2'
compile 'javax.transaction:javax.transaction-api:1.3'
compile 'net.bytebuddy:byte-buddy:1.10.2'
compile 'org.jboss.logging:jboss-logging:3.3.2.Final'

testRuntime ('io.quarkus:quarkus-hibernate-orm-panache:1.4.1.Final') {
implementation 'antlr:antlr:2.7.7'
implementation 'javax.persistence:javax.persistence-api:2.2'
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
implementation 'javax.transaction:javax.transaction-api:1.3'
implementation 'net.bytebuddy:byte-buddy:1.14.5'
implementation 'org.jboss.logging:jboss-logging:3.5.0.Final'

testRuntimeOnly ('io.quarkus:quarkus-hibernate-orm-panache:3.1.0.Final') {
transitive = false
}
testRuntime ('io.quarkus:quarkus-panache-common:1.4.1.Final') {
testRuntimeOnly ('io.quarkus:quarkus-panache-common:3.1.0.Final') {
transitive = false
}

compile 'org.codehaus.groovy:groovy:2.5.6:indy'
implementation 'org.apache.groovy:groovy:4.0.12'

implementation 'org.eclipse.jdt:ecj:3.33.0'

compile 'org.eclipse.jdt.core.compiler:ecj:4.6.1'
compile files(Jvm.current().toolsJar)
// testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
testImplementation 'junit:junit:4.13.2'

testCompile 'junit:junit:4.12'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
}

group = 'org.hibernate'
version = '1.0-SNAPSHOT'
version = '2.0-SNAPSHOT'
description = 'query-validator'
sourceCompatibility = '1.8'
sourceCompatibility = '8'

sourceSets {
main {
Expand All @@ -58,8 +58,8 @@ sourceSets {

shadowJar {
dependencies {
exclude(dependency('org.eclipse.jdt.core.compiler:ecj'))
exclude "tools.jar"
exclude(dependency('org.eclipse.jdt:ecj'))
// exclude "tools.jar"
}
relocate ('org.hibernate', 'org.hibernate.query.validator.hibernate') {
exclude 'org.hibernate.query.validator.*'
Expand All @@ -81,14 +81,17 @@ shadowJar {
relocate 'groovyjarjarasm', 'org.hibernate.query.validator.asm'
relocate 'groovyjarjarcommonscli', 'org.hibernate.query.validator.cli'
relocate 'groovyjarjarpicocli', 'org.hibernate.query.validator.picocli'
classifier = 'all'
archiveClassifier.set('all')
}

jar {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

publishing {
publications {
maven(MavenPublication) {
from(components.java)
artifact shadowJar
shadow(MavenPublication) { publication ->
project.shadow.component(publication)
}
}
}
Expand All @@ -103,7 +106,7 @@ tasks.withType(JavaCompile) {
}

task copyDependencies(type: Copy) {
from configurations.testRuntime
from configurations.testRuntimeClasspath
into 'test-runtime-libs'
}

2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
11 changes: 8 additions & 3 deletions src/main/java/org/hibernate/query/validator/ECJProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
* for ECJ.
*
* @see CheckHQL
*
* @author Gavin King
*/
//@SupportedAnnotationTypes(CHECK_HQL)
public class ECJProcessor extends AbstractProcessor {
Expand All @@ -81,9 +83,9 @@ private void checkHQL(CompilationUnitDeclaration unit, Compiler compiler) {
TypeElement typeElement = elements.getTypeElement(qualifiedName(type.binding));
TypeElement panacheEntity = PanacheUtils.isPanache(typeElement, processingEnv.getTypeUtils(), elements);
type.traverse(new ASTVisitor() {
Set<Integer> setParameterLabels = new HashSet<>();
Set<String> setParameterNames = new HashSet<>();
Set<String> setOrderBy = new HashSet<>();
final Set<Integer> setParameterLabels = new HashSet<>();
final Set<String> setParameterNames = new HashSet<>();
final Set<String> setOrderBy = new HashSet<>();
boolean immediatelyCalled;

@Override
Expand All @@ -92,6 +94,7 @@ public boolean visit(MessageSend messageSend, BlockScope scope) {
switch (name) {
case "getResultList":
case "getSingleResult":
case "getSingleResultOrNull":
immediatelyCalled = true;
break;
case "count":
Expand All @@ -118,6 +121,8 @@ public boolean visit(MessageSend messageSend, BlockScope scope) {
}
break;
case "createQuery":
case "createSelectionQuery":
case "createMutationQuery":
for (Expression argument : messageSend.arguments) {
if (argument instanceof StringLiteral) {
check((StringLiteral) argument, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import static org.hibernate.internal.util.StringHelper.*;
import static org.hibernate.query.validator.HQLProcessor.jpa;

/**
* @author Gavin King
*/
public abstract class ECJSessionFactory extends MockSessionFactory {

private static final Mocker<EntityPersister> entityPersister = Mocker.variadic(EntityPersister.class);
Expand Down
Loading