[#5245] Add org.jooq.Allow and org.jooq.Require annotation and a SQLDialectChecker using JSR-308 and the checker framework
This commit is contained in:
parent
09344c4d45
commit
ae40bd5c27
3
jOOQ-checker/.gitignore
vendored
Normal file
3
jOOQ-checker/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/target
|
||||
/.idea
|
||||
/*.iml
|
||||
22
jOOQ-checker/LICENSE.txt
Normal file
22
jOOQ-checker/LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Other licenses:
|
||||
-----------------------------------------------------------------------------
|
||||
Commercial licenses for this work are available. These replace the above
|
||||
ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
database integrations.
|
||||
|
||||
For more information, please visit: http://www.jooq.org/licenses
|
||||
45
jOOQ-checker/pom.xml
Normal file
45
jOOQ-checker/pom.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq-parent</artifactId>
|
||||
<version>3.9.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq-checker</artifactId>
|
||||
<name>jOOQ Checker</name>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.jooq.org/inc/LICENSE.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</licenses>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq.checker;
|
||||
|
||||
import static com.sun.source.util.TreePath.getPath;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.checkerframework.javacutil.TreeUtils.elementFromDeclaration;
|
||||
import static org.checkerframework.javacutil.TreeUtils.elementFromUse;
|
||||
import static org.checkerframework.javacutil.TreeUtils.enclosingMethod;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
||||
import org.jooq.Allow;
|
||||
import org.jooq.Require;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Support;
|
||||
|
||||
import org.checkerframework.framework.source.Result;
|
||||
import org.checkerframework.framework.source.SourceChecker;
|
||||
import org.checkerframework.framework.source.SourceVisitor;
|
||||
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
|
||||
/**
|
||||
* A checker to compare {@link SQLDialect} from a use-site {@link Require}
|
||||
* annotation with a declaration-site {@link Support} annotation.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class SQLDialectChecker extends SourceChecker {
|
||||
|
||||
@Override
|
||||
protected SourceVisitor<?, ?> createSourceVisitor() {
|
||||
return new SourceVisitor<Void, Void>(this) {
|
||||
|
||||
@Override
|
||||
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
|
||||
try {
|
||||
ExecutableElement elementFromUse = elementFromUse(node);
|
||||
Support support = elementFromUse.getAnnotation(Support.class);
|
||||
|
||||
// In the absence of a @Support annotation, or if no SQLDialect is supplied,
|
||||
// all jOOQ API method calls will type check.
|
||||
if (support != null && support.value().length > 0) {
|
||||
Element enclosing = elementFromDeclaration(enclosingMethod(getPath(root, node)));
|
||||
|
||||
EnumSet<SQLDialect> supported = EnumSet.copyOf(asList(support.value()));
|
||||
EnumSet<SQLDialect> allowed = EnumSet.noneOf(SQLDialect.class);
|
||||
EnumSet<SQLDialect> required = EnumSet.allOf(SQLDialect.class);
|
||||
EnumSet<SQLDialect> x;
|
||||
|
||||
while (enclosing != null) {
|
||||
Allow allow = enclosing.getAnnotation(Allow.class);
|
||||
Require require = enclosing.getAnnotation(Require.class);
|
||||
|
||||
if (allow != null)
|
||||
allowed.addAll(asList(allow.value()));
|
||||
|
||||
if (require != null)
|
||||
required.retainAll(asList(require.value()));
|
||||
|
||||
enclosing = enclosing.getEnclosingElement();
|
||||
}
|
||||
|
||||
if (allowed.isEmpty())
|
||||
error(node, "No jOOQ API usage is allowed at current scope. Use @Allow.");
|
||||
|
||||
if (required.isEmpty())
|
||||
error(node, "No jOOQ API usage is allowed at current scope due to conflicting @Require specification.");
|
||||
|
||||
x = EnumSet.copyOf(allowed);
|
||||
x.retainAll(supported);
|
||||
if (x.isEmpty())
|
||||
error(node, "None of the supported dialects (" + supported + ") are allowed in the current scope (" + allowed + ")");
|
||||
|
||||
if (!supported.containsAll(required))
|
||||
error(node, "Not all of the required dialects (" + required + ") from the current scope are supported (" + supported + ")");
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
print(new Printer() {
|
||||
@Override
|
||||
public void print(PrintWriter t) {
|
||||
e.printStackTrace(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return super.visitMethodInvocation(node, p);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void error(Object node, String message) {
|
||||
getChecker().report(Result.failure(message, node), node);
|
||||
}
|
||||
|
||||
void print(Printer printer) {
|
||||
try (PrintWriter writer = new PrintWriter(new FileWriter("error.txt"))){
|
||||
writer.println("This is probably a bug in jOOQ-checker.");
|
||||
writer.println("Please report this bug here: https://github.com/jOOQ/jOOQ/issues/new");
|
||||
writer.println("---------------------------------------------------------------------");
|
||||
|
||||
printer.print(writer);
|
||||
}
|
||||
catch (IOException ignore) {}
|
||||
}
|
||||
|
||||
interface Printer {
|
||||
void print(PrintWriter writer);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* This package contains useful checkers that work with JSR 308 and the checker
|
||||
* framework.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
* @see <a href="http://types.cs.washington.edu/checker-framework">http://types.
|
||||
* cs.washington.edu/checker-framework</a>
|
||||
*/
|
||||
package org.jooq.checker;
|
||||
22
jOOQ-checker/src/main/resources/META-INF/LICENSE.txt
Normal file
22
jOOQ-checker/src/main/resources/META-INF/LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Other licenses:
|
||||
-----------------------------------------------------------------------------
|
||||
Commercial licenses for this work are available. These replace the above
|
||||
ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
database integrations.
|
||||
|
||||
For more information, please visit: http://www.jooq.org/licenses
|
||||
2
jOOQ-checker/src/main/resources/META-INF/README.txt
Normal file
2
jOOQ-checker/src/main/resources/META-INF/README.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Thanks for downloading jOOQ.
|
||||
Please visit http://www.jooq.org for more information.
|
||||
2
jOOQ-examples/jOOQ-checker-framework-example/.gitignore
vendored
Normal file
2
jOOQ-examples/jOOQ-checker-framework-example/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/jooq-flyway-example.iml
|
||||
22
jOOQ-examples/jOOQ-checker-framework-example/LICENSE.txt
Normal file
22
jOOQ-examples/jOOQ-checker-framework-example/LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Other licenses:
|
||||
-----------------------------------------------------------------------------
|
||||
Commercial licenses for this work are available. These replace the above
|
||||
ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
database integrations.
|
||||
|
||||
For more information, please visit: http://www.jooq.org/licenses
|
||||
12
jOOQ-examples/jOOQ-checker-framework-example/README.md
Normal file
12
jOOQ-examples/jOOQ-checker-framework-example/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
Thanks for downloading jOOQ.
|
||||
Please visit http://www.jooq.org for more information.
|
||||
|
||||
To install and run this example, simply check it out and run the following Maven command
|
||||
|
||||
```
|
||||
$ pwd
|
||||
/path/to/checkout/dir
|
||||
$ cd jOOQ-examples/jOOQ-flyway-example
|
||||
...
|
||||
$ mvn clean install
|
||||
```
|
||||
37
jOOQ-examples/jOOQ-checker-framework-example/output.txt
Normal file
37
jOOQ-examples/jOOQ-checker-framework-example/output.txt
Normal file
@ -0,0 +1,37 @@
|
||||
java.lang.NullPointerException
|
||||
at org.jooq.checker.SQLDialectChecker$1.visitMethodInvocation(SQLDialectChecker.java:101)
|
||||
at org.jooq.checker.SQLDialectChecker$1.visitMethodInvocation(SQLDialectChecker.java:79)
|
||||
at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1477)
|
||||
at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:68)
|
||||
at com.sun.source.util.TreeScanner.visitExpressionStatement(TreeScanner.java:243)
|
||||
at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1302)
|
||||
at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:68)
|
||||
at com.sun.source.util.TreeScanner.scan(TreeScanner.java:91)
|
||||
at com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:162)
|
||||
at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:918)
|
||||
at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:68)
|
||||
at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:81)
|
||||
at com.sun.source.util.TreeScanner.visitMethod(TreeScanner.java:144)
|
||||
at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:800)
|
||||
at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:68)
|
||||
at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:81)
|
||||
at com.sun.source.util.TreeScanner.scan(TreeScanner.java:91)
|
||||
at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:99)
|
||||
at com.sun.source.util.TreeScanner.visitClass(TreeScanner.java:133)
|
||||
at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:720)
|
||||
at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:50)
|
||||
at org.checkerframework.framework.source.SourceVisitor.visit(SourceVisitor.java:70)
|
||||
at org.checkerframework.framework.source.SourceChecker.typeProcess(SourceChecker.java:939)
|
||||
at org.checkerframework.javacutil.AbstractTypeProcessor$AttributionTaskListener.finished(AbstractTypeProcessor.java:209)
|
||||
at com.sun.tools.javac.api.ClientCodeWrapper$WrappedTaskListener.finished(ClientCodeWrapper.java:681)
|
||||
at com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:111)
|
||||
at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1342)
|
||||
at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1296)
|
||||
at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
|
||||
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
|
||||
at com.sun.tools.javac.main.Main.compile(Main.java:523)
|
||||
at com.sun.tools.javac.main.Main.compile(Main.java:381)
|
||||
at com.sun.tools.javac.main.Main.compile(Main.java:370)
|
||||
at com.sun.tools.javac.main.Main.compile(Main.java:361)
|
||||
at com.sun.tools.javac.Main.compile(Main.java:56)
|
||||
at com.sun.tools.javac.Main.main(Main.java:42)
|
||||
71
jOOQ-examples/jOOQ-checker-framework-example/pom.xml
Normal file
71
jOOQ-examples/jOOQ-checker-framework-example/pom.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq-checker-framework-example</artifactId>
|
||||
<version>3.9.0-SNAPSHOT</version>
|
||||
<name>jOOQ Checker Framework Example</name>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.jooq.org/inc/LICENSE.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<org.jooq.version>3.9.0-SNAPSHOT</org.jooq.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Database access -->
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
<version>${org.jooq.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq-checker</artifactId>
|
||||
<version>${org.jooq.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>properties</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<fork>true</fork>
|
||||
<annotationProcessors>
|
||||
<annotationProcessor>org.jooq.checker.SQLDialectChecker</annotationProcessor>
|
||||
</annotationProcessors>
|
||||
<compilerArgs>
|
||||
<arg>-Xbootclasspath/p:1.8</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,35 @@
|
||||
package org.jooq.example.checker;
|
||||
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
|
||||
import org.jooq.Allow;
|
||||
import org.jooq.Require;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
// The class requires both H2 and MySQL
|
||||
// The inherited @Allow annotation from the package allows only MySQL, though.
|
||||
@Require({ SQLDialect.H2, SQLDialect.MYSQL })
|
||||
public class CheckerTests {
|
||||
|
||||
// @Allow = MySQL (inherited from package)
|
||||
// @Require = { H2, MySQL } (inherited from class)
|
||||
public static void doesntCompileBecauseH2IsNotAllowedAndMySQLIsNotSupported() {
|
||||
DSL.array(2);
|
||||
}
|
||||
|
||||
// @Allow = { H2, MySQL (inherited from package) }
|
||||
// @Require = { H2, MySQL } (inherited from class)
|
||||
@Allow(H2)
|
||||
public static void doesntCompileBecauseMySQLIsNotSupported() {
|
||||
DSL.array(2);
|
||||
}
|
||||
|
||||
// @Allow = { H2, MySQL (inherited from package) }
|
||||
// @Require = { H2, MySQL } (inherited from class)
|
||||
@Allow(H2)
|
||||
@Require(H2)
|
||||
public static void compiles() {
|
||||
DSL.array(2);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package org.jooq.example.checker;
|
||||
import static org.jooq.example.checker.db.h2.Tables.AUTHOR;
|
||||
import static org.jooq.example.checker.db.h2.Tables.BOOK;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
|
||||
import org.jooq.Require;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@Require(
|
||||
value = { SQLDialect.H2, SQLDialect.MYSQL }
|
||||
)
|
||||
public class ShouldntCompile {
|
||||
|
||||
@Require({SQLDialect.H2, SQLDialect.MYSQL})
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (Connection c = DriverManager.getConnection("jdbc:h2:~/checker-test", "sa", "")) {
|
||||
Result<?> result =
|
||||
DSL.using(c)
|
||||
.select(
|
||||
AUTHOR.FIRST_NAME,
|
||||
AUTHOR.LAST_NAME,
|
||||
BOOK.ID,
|
||||
BOOK.TITLE,
|
||||
DSL.array(1)
|
||||
)
|
||||
.from(AUTHOR)
|
||||
.join(BOOK)
|
||||
.on(AUTHOR.ID.eq(BOOK.AUTHOR_ID))
|
||||
.connectBy("abc")
|
||||
.orderBy(BOOK.ID.asc())
|
||||
.fetch();
|
||||
|
||||
System.out.println(result);
|
||||
}
|
||||
}
|
||||
|
||||
public static void x() {
|
||||
DSL.array(2);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Enable jOOQ API usage with MySQL for the whole package.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@Allow(MYSQL)
|
||||
package org.jooq.example.checker;
|
||||
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
|
||||
import org.jooq.Allow;
|
||||
@ -0,0 +1,3 @@
|
||||
DROP SCHEMA IF EXISTS checker;
|
||||
|
||||
CREATE SCHEMA checker;
|
||||
@ -0,0 +1,12 @@
|
||||
CREATE SEQUENCE checker.s_author_id START WITH 1;
|
||||
|
||||
CREATE TABLE checker.author (
|
||||
id INT NOT NULL,
|
||||
first_name VARCHAR(50),
|
||||
last_name VARCHAR(50) NOT NULL,
|
||||
date_of_birth DATE,
|
||||
year_of_birth INT,
|
||||
address VARCHAR(50),
|
||||
|
||||
CONSTRAINT pk_t_author PRIMARY KEY (ID)
|
||||
);
|
||||
@ -0,0 +1,17 @@
|
||||
CREATE TABLE checker.book (
|
||||
id INT NOT NULL,
|
||||
author_id INT NOT NULL,
|
||||
title VARCHAR(400) NOT NULL,
|
||||
|
||||
CONSTRAINT pk_t_book PRIMARY KEY (id),
|
||||
CONSTRAINT fk_t_book_author_id FOREIGN KEY (author_id) REFERENCES author(id)
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO checker.author VALUES (next value for checker.s_author_id, 'George', 'Orwell', '1903-06-25', 1903, null);
|
||||
INSERT INTO checker.author VALUES (next value for checker.s_author_id, 'Paulo', 'Coelho', '1947-08-24', 1947, null);
|
||||
|
||||
INSERT INTO checker.book VALUES (1, 1, '1984');
|
||||
INSERT INTO checker.book VALUES (2, 1, 'Animal Farm');
|
||||
INSERT INTO checker.book VALUES (3, 2, 'O Alquimista');
|
||||
INSERT INTO checker.book VALUES (4, 2, 'Brida');
|
||||
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
|
||||
<log4j:configuration>
|
||||
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d{ABSOLUTE} %5p [%-50c{4}] - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<priority value="debug" />
|
||||
<appender-ref ref="stdout" />
|
||||
</root>
|
||||
</log4j:configuration>
|
||||
175
jOOQ/src/main/java/org/jooq/Allow.java
Normal file
175
jOOQ/src/main/java/org/jooq/Allow.java
Normal file
@ -0,0 +1,175 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import static java.lang.annotation.ElementType.CONSTRUCTOR;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.PACKAGE;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.CUBRID;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.DEFAULT;
|
||||
import static org.jooq.SQLDialect.DERBY;
|
||||
import static org.jooq.SQLDialect.FIREBIRD;
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.MARIADB;
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.SQL99;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Allow a set of {@link SQLDialect} to be supported by any jOOQ statement in
|
||||
* the scope of this annotation.
|
||||
* <p>
|
||||
* This annotation can be used at the use-site of jOOQ API at any given scope
|
||||
* {@link ElementType#PACKAGE}, {@link ElementType#TYPE},
|
||||
* {@link ElementType#METHOD} in order to specify that the given scope allows
|
||||
* ANY of the supplied {@link SQLDialect} to be supported by all usage of jOOQ
|
||||
* API within the scope. For example:
|
||||
* <p>
|
||||
* <code><pre>
|
||||
* // Allow only MYSQL or ORACLE dialect support to be used within the class scope
|
||||
* @Allow(MYSQL, ORACLE)
|
||||
* public class MySQLAndOracleDAO {
|
||||
*
|
||||
* // Allow rule from class applies to this method
|
||||
* public void mysqlAndOracleMethod() {
|
||||
* DSL.using(configuration)
|
||||
* .insertInto(TABLE, TABLE.COLUMN)
|
||||
* .values(1)
|
||||
* // This type checks as it works on both MySQL and Oracle
|
||||
* .onDuplicateKeyUpdate()
|
||||
* .set(TABLE.COLUMN, 2)
|
||||
* .execute();
|
||||
* }
|
||||
*
|
||||
* // Refine class Allow rule with additional requirement
|
||||
* @Require(ORACLE)
|
||||
* public void oracleOnlyMethod() {
|
||||
* DSL.using(configuration)
|
||||
* .mergeInto(TABLE)
|
||||
* .using(selectOne())
|
||||
* .on(TABLE.COLUMN.eq(1))
|
||||
* .whenMatchedThenUpdate()
|
||||
* .set(TABLE.COLUMN, 2)
|
||||
* .whenNotMatchedThenInsert(TABLE.COLUMN)
|
||||
* .values(1)
|
||||
* .execute();
|
||||
* }
|
||||
* }
|
||||
* </pre></code>
|
||||
* <p>
|
||||
* Type checking for these annotations can be supplied by
|
||||
* <code>org.jooq.checker.SQLDialectChecker</code> from the jOOQ-checker module.
|
||||
* <h2>Rules:</h2>
|
||||
* <ul>
|
||||
* <li>In the absence of any {@link Allow} annotation, no jOOQ API usage is
|
||||
* allowed.</li>
|
||||
* <li>The combination of all {@link Allow} and {@link Require} annotations is
|
||||
* applied for any given scope.</li>
|
||||
* <li>Nested packages are not creating nested scopes.</li>
|
||||
* <li>If a versioned {@link SQLDialect} is allowed (rather than a
|
||||
* {@link SQLDialect#family()}), then the allowed version, all of its
|
||||
* {@link SQLDialect#predecessor()}, and its {@link SQLDialect#family()} are
|
||||
* allowed.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Lukas Eder
|
||||
* @see Require
|
||||
*/
|
||||
@Target({ METHOD, CONSTRUCTOR, TYPE, PACKAGE })
|
||||
@Retention(RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface Allow {
|
||||
|
||||
/**
|
||||
* A list of jOOQ {@link SQLDialect} which are required on any jOOQ API
|
||||
* method that is annotated with {@link Support}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
SQLDialect[] value() default {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CUBRID,
|
||||
DEFAULT,
|
||||
SQL99,
|
||||
DERBY,
|
||||
FIREBIRD,
|
||||
H2,
|
||||
HSQLDB,
|
||||
MARIADB,
|
||||
MYSQL,
|
||||
POSTGRES,
|
||||
SQLITE,
|
||||
};
|
||||
}
|
||||
129
jOOQ/src/main/java/org/jooq/Require.java
Normal file
129
jOOQ/src/main/java/org/jooq/Require.java
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import static java.lang.annotation.ElementType.CONSTRUCTOR;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.PACKAGE;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Require a set of {@link SQLDialect} to be supported by any jOOQ statement in
|
||||
* the scope of this annotation.
|
||||
* <p>
|
||||
* This annotation can be used at the use-site of jOOQ API at any given scope
|
||||
* {@link ElementType#PACKAGE}, {@link ElementType#TYPE},
|
||||
* {@link ElementType#METHOD} in order to specify that the given scope requires
|
||||
* ALL of the supplied {@link SQLDialect} to be supported by all usage of jOOQ
|
||||
* API within the scope. For example:
|
||||
* <p>
|
||||
* <code><pre>
|
||||
* // Allow only MYSQL or ORACLE dialect support to be used within the class scope
|
||||
* @Allow(MYSQL, ORACLE)
|
||||
* public class MySQLAndOracleDAO {
|
||||
*
|
||||
* // Allow rule from class applies to this method
|
||||
* public void mysqlAndOracleMethod() {
|
||||
* DSL.using(configuration)
|
||||
* .insertInto(TABLE, TABLE.COLUMN)
|
||||
* .values(1)
|
||||
* // This type checks as it works on both MySQL and Oracle
|
||||
* .onDuplicateKeyUpdate()
|
||||
* .set(TABLE.COLUMN, 2)
|
||||
* .execute();
|
||||
* }
|
||||
*
|
||||
* // Refine class Allow rule with additional requirement
|
||||
* @Require(ORACLE)
|
||||
* public void oracleOnlyMethod() {
|
||||
* DSL.using(configuration)
|
||||
* .mergeInto(TABLE)
|
||||
* .using(selectOne())
|
||||
* .on(TABLE.COLUMN.eq(1))
|
||||
* .whenMatchedThenUpdate()
|
||||
* .set(TABLE.COLUMN, 2)
|
||||
* .whenNotMatchedThenInsert(TABLE.COLUMN)
|
||||
* .values(1)
|
||||
* .execute();
|
||||
* }
|
||||
* }
|
||||
* </pre></code>
|
||||
* <p>
|
||||
* Type checking for these annotations can be supplied by
|
||||
* <code>org.jooq.checker.SQLDialectChecker</code> from the jOOQ-checker module.
|
||||
* <p>
|
||||
* Type checking for these annotations can be supplied by
|
||||
* <code>org.jooq.checker.SQLDialectChecker</code> from the jOOQ-checker module.
|
||||
* <h2>Rules:</h2>
|
||||
* <ul>
|
||||
* <li>In the absence of any {@link Allow} annotation, no jOOQ API usage is
|
||||
* allowed.</li>
|
||||
* <li>The combination of all {@link Allow} and {@link Require} annotations is
|
||||
* applied for any given scope.</li>
|
||||
* <li>Nested packages are not creating nested scopes.</li>
|
||||
* <li>If a versioned {@link SQLDialect} is required (rather than a
|
||||
* {@link SQLDialect#family()}), then the required version, any of its
|
||||
* {@link SQLDialect#predecessor()}, or its {@link SQLDialect#family()} are
|
||||
* required.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Lukas Eder
|
||||
* @see Allow
|
||||
*/
|
||||
@Target({ METHOD, CONSTRUCTOR, TYPE, PACKAGE })
|
||||
@Retention(RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface Require {
|
||||
|
||||
/**
|
||||
* A list of jOOQ {@link SQLDialect} which are required on any jOOQ API
|
||||
* method that is annotated with {@link Support}.
|
||||
*/
|
||||
SQLDialect[] value() default {};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user