diff --git a/jOOQ-checker/.gitignore b/jOOQ-checker/.gitignore
new file mode 100644
index 0000000000..e8e5bad2d2
--- /dev/null
+++ b/jOOQ-checker/.gitignore
@@ -0,0 +1,3 @@
+/target
+/.idea
+/*.iml
\ No newline at end of file
diff --git a/jOOQ-checker/LICENSE.txt b/jOOQ-checker/LICENSE.txt
new file mode 100644
index 0000000000..7ab3d18350
--- /dev/null
+++ b/jOOQ-checker/LICENSE.txt
@@ -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
\ No newline at end of file
diff --git a/jOOQ-checker/pom.xml b/jOOQ-checker/pom.xml
new file mode 100644
index 0000000000..d132b3f452
--- /dev/null
+++ b/jOOQ-checker/pom.xml
@@ -0,0 +1,45 @@
+
+
+
+ 4.0.0
+
+
+ org.jooq
+ jooq-parent
+ 3.9.0-SNAPSHOT
+
+
+ org.jooq
+ jooq-checker
+ jOOQ Checker
+
+
+
+ Apache License, Version 2.0
+ http://www.jooq.org/inc/LICENSE.txt
+ repo
+
+
+
+
+
+
+
+
+
+
+
+
+ org.jooq
+ jooq
+
+
+
+ org.checkerframework
+ checker
+ 2.0.0
+
+
+
+
\ No newline at end of file
diff --git a/jOOQ-checker/src/main/java/org/jooq/checker/SQLDialectChecker.java b/jOOQ-checker/src/main/java/org/jooq/checker/SQLDialectChecker.java
new file mode 100644
index 0000000000..4581fbfb35
--- /dev/null
+++ b/jOOQ-checker/src/main/java/org/jooq/checker/SQLDialectChecker.java
@@ -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(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 supported = EnumSet.copyOf(asList(support.value()));
+ EnumSet allowed = EnumSet.noneOf(SQLDialect.class);
+ EnumSet required = EnumSet.allOf(SQLDialect.class);
+ EnumSet 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);
+ }
+}
diff --git a/jOOQ-checker/src/main/java/org/jooq/checker/package-info.java b/jOOQ-checker/src/main/java/org/jooq/checker/package-info.java
new file mode 100644
index 0000000000..67d1a9a0ac
--- /dev/null
+++ b/jOOQ-checker/src/main/java/org/jooq/checker/package-info.java
@@ -0,0 +1,9 @@
+/**
+ * This package contains useful checkers that work with JSR 308 and the checker
+ * framework.
+ *
+ * @author Lukas Eder
+ * @see http://types.
+ * cs.washington.edu/checker-framework
+ */
+package org.jooq.checker;
diff --git a/jOOQ-checker/src/main/resources/META-INF/LICENSE.txt b/jOOQ-checker/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000000..7ab3d18350
--- /dev/null
+++ b/jOOQ-checker/src/main/resources/META-INF/LICENSE.txt
@@ -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
\ No newline at end of file
diff --git a/jOOQ-checker/src/main/resources/META-INF/README.txt b/jOOQ-checker/src/main/resources/META-INF/README.txt
new file mode 100644
index 0000000000..3e6e227e05
--- /dev/null
+++ b/jOOQ-checker/src/main/resources/META-INF/README.txt
@@ -0,0 +1,2 @@
+Thanks for downloading jOOQ.
+Please visit http://www.jooq.org for more information.
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/.gitignore b/jOOQ-examples/jOOQ-checker-framework-example/.gitignore
new file mode 100644
index 0000000000..0fd7a02083
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/.gitignore
@@ -0,0 +1,2 @@
+/target
+/jooq-flyway-example.iml
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/LICENSE.txt b/jOOQ-examples/jOOQ-checker-framework-example/LICENSE.txt
new file mode 100644
index 0000000000..7ab3d18350
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/LICENSE.txt
@@ -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
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/README.md b/jOOQ-examples/jOOQ-checker-framework-example/README.md
new file mode 100644
index 0000000000..c97f65e0e9
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/README.md
@@ -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
+```
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/output.txt b/jOOQ-examples/jOOQ-checker-framework-example/output.txt
new file mode 100644
index 0000000000..7878b3db8c
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/output.txt
@@ -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)
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/pom.xml b/jOOQ-examples/jOOQ-checker-framework-example/pom.xml
new file mode 100644
index 0000000000..fd8f99e620
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+
+ org.jooq
+ jooq-checker-framework-example
+ 3.9.0-SNAPSHOT
+ jOOQ Checker Framework Example
+
+
+
+ Apache License, Version 2.0
+ http://www.jooq.org/inc/LICENSE.txt
+ repo
+
+
+
+
+ UTF-8
+ 3.9.0-SNAPSHOT
+
+
+
+
+
+
+ org.jooq
+ jooq
+ ${org.jooq.version}
+
+
+ org.jooq
+ jooq-checker
+ ${org.jooq.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 2.3
+
+
+
+ properties
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.3
+
+ 1.8
+ 1.8
+ true
+
+ org.jooq.checker.SQLDialectChecker
+
+
+ -Xbootclasspath/p:1.8
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/CheckerTests.java b/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/CheckerTests.java
new file mode 100644
index 0000000000..e9cdeae073
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/CheckerTests.java
@@ -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);
+ }
+}
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/ShouldntCompile.java b/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/ShouldntCompile.java
new file mode 100644
index 0000000000..599b3a33ac
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/ShouldntCompile.java
@@ -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);
+ }
+}
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/package-info.java b/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/package-info.java
new file mode 100644
index 0000000000..24ebfb91ea
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/java/org/jooq/example/checker/package-info.java
@@ -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;
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V1__initialise_database.sql b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V1__initialise_database.sql
new file mode 100644
index 0000000000..ae39dfc707
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V1__initialise_database.sql
@@ -0,0 +1,3 @@
+DROP SCHEMA IF EXISTS checker;
+
+CREATE SCHEMA checker;
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V2__create_author_table.sql b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V2__create_author_table.sql
new file mode 100644
index 0000000000..480c50d2e8
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V2__create_author_table.sql
@@ -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)
+);
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V3__create_book_table_and_add_records.sql b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V3__create_book_table_and_add_records.sql
new file mode 100644
index 0000000000..fa0b3c690f
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/db/migration/V3__create_book_table_and_add_records.sql
@@ -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');
\ No newline at end of file
diff --git a/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/log4j.xml b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/log4j.xml
new file mode 100644
index 0000000000..617678bd22
--- /dev/null
+++ b/jOOQ-examples/jOOQ-checker-framework-example/src/main/resources/log4j.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jOOQ/src/main/java/org/jooq/Allow.java b/jOOQ/src/main/java/org/jooq/Allow.java
new file mode 100644
index 0000000000..8f07cf070d
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/Allow.java
@@ -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.
+ *
+ * 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:
+ *
+ *
+ * // 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();
+ * }
+ * }
+ *
+ *
+ * Type checking for these annotations can be supplied by
+ * org.jooq.checker.SQLDialectChecker from the jOOQ-checker module.
+ *
Rules:
+ *
+ *
In the absence of any {@link Allow} annotation, no jOOQ API usage is
+ * allowed.
+ *
The combination of all {@link Allow} and {@link Require} annotations is
+ * applied for any given scope.
+ *
Nested packages are not creating nested scopes.
+ *
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.
+ *
+ *
+ * @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,
+ };
+}
diff --git a/jOOQ/src/main/java/org/jooq/Require.java b/jOOQ/src/main/java/org/jooq/Require.java
new file mode 100644
index 0000000000..f4ac9034f0
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/Require.java
@@ -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.
+ *
+ * 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:
+ *
+ *
+ * // 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();
+ * }
+ * }
+ *
+ *
+ * Type checking for these annotations can be supplied by
+ * org.jooq.checker.SQLDialectChecker from the jOOQ-checker module.
+ *
+ * Type checking for these annotations can be supplied by
+ * org.jooq.checker.SQLDialectChecker from the jOOQ-checker module.
+ *
Rules:
+ *
+ *
In the absence of any {@link Allow} annotation, no jOOQ API usage is
+ * allowed.
+ *
The combination of all {@link Allow} and {@link Require} annotations is
+ * applied for any given scope.
+ *
Nested packages are not creating nested scopes.
+ *
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.
+ *
+ *
+ * @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 {};
+}