diff --git a/pljava-api/src/main/java/org/postgresql/pljava/annotation/SQLAction.java b/pljava-api/src/main/java/org/postgresql/pljava/annotation/SQLAction.java index face77719..a1ff47377 100644 --- a/pljava-api/src/main/java/org/postgresql/pljava/annotation/SQLAction.java +++ b/pljava-api/src/main/java/org/postgresql/pljava/annotation/SQLAction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2025 Tada AB and other contributors, as listed below. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the The BSD 3-Clause License @@ -22,14 +22,33 @@ /** * Annotation that supplies verbatim commands to be copied into the * deployment descriptor. - * - * Strings supplied within a single SQLAction annotation will be copied - * in the order supplied. Strings from different SQLAction annotations, and - * generated code for functions, will be assembled in an order that can be - * influenced by 'provides' and 'requires' labels. No snippet X will be - * emitted ahead of any snippets that provide what X requires. The "remove" - * actions will be assembled in the reverse of that order. - * + *
+ * Strings supplied to {@link #install install} or {@link #remove remove} within + * a single {@code SQLAction} annotation become code snippets emitted into the + * deployment descriptor's {@code INSTALL} or {@code REMOVE} section, + * respectively, in the order supplied. + *
+ * Snippets from different {@code SQLAction} annotations, + * and snippets generated by annotations on functions, types, and such, will be + * assembled in an order that can be influenced by {@link #provides provides} + * and {@link #requires requires} labels. No snippet X will be emitted as an + * {@code INSTALL} action ahead of any snippets that provide what X requires. + * The sense of that dependency is reversed when ordering {@code REMOVE} + * snippets. + *
+ * An {@code SQLAction} may supply an {@code install} snippet that tests some
+ * condition at the time of deployment and adjusts the
+ * {@code pljava.implementors} setting to include or not include a specific
+ * {@code
+ * For use of this element on an {@code SQLAction} that tests a condition
+ * to control conditional execution, see "conditional execution" in
+ * {@link SQLAction the class description}.
*/
String[] provides() default {};
diff --git a/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java b/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java
index ca5af21cf..932113bdd 100644
--- a/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java
+++ b/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2023 Tada AB and other contributors, as listed below.
+ * Copyright (c) 2015-2025 Tada AB and other contributors, as listed below.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the The BSD 3-Clause License
@@ -13,6 +13,7 @@
/**
* Annotations for use in Java code to generate the SQLJ Deployment Descriptor
* automatically.
+ *
* To define functions or types in PL/Java requires more than one step. The
* Java code must be written, compiled to a jar, and made available to the
@@ -22,14 +23,14 @@
* version that undoes it when uninstalling the jar) can be written in a
* prescribed form and stored inside the jar itself as an "SQLJ Deployment
* Descriptor", and processed automatically when the jar is installed in or
- * removed from the backend.
+ * removed from the DBMS.
*
* To write the deployment descriptor by hand can be tedious and error-prone,
* as it must largely duplicate the method and type declarations in the
* Java code, but using SQL's syntax and types in place of Java's. Instead,
* when the annotations in this package are used in the Java code, the Java
- * compiler itself will generate a deployment descriptor file, ready to include
- * with the compiled classes to make a complete SQLJ jar.
+ * compiler itself will generate a deployment descriptor (DDR) file, ready to
+ * include with the compiled classes to make a complete SQLJ jar.
*
* Automatic descriptor generation requires attention to a few things.
* Additional options are available when invoking the Java compiler, and
+ * can be specified with {@code -Aoption=value} on the command line:
* The deployment descriptor may contain statements that cannot succeed if
* placed in the wrong order, and to keep a manually-edited script in a workable
* order while adding and modifying code can be difficult. Most of the
* annotations in this package accept arbitrary {@code requires} and
@@ -80,12 +91,13 @@
* compiler, except that it will make sure not to write anything that
* {@code requires} some string X into the generated script
* before whatever {@code provides} it.
- * There can be multiple ways to order the statements in the deployment
* descriptor to satisfy the given {@code provides} and {@code requires}
* relationships. While the compiler will always write the descriptor in an
* order that satisfies those relationships, when the {@code ddr.reproducible}
* option is {@code false}, the precise order may differ between successive
- * compilations of the same sources, which should not affect successful
+ * compilations of the same sources, which should not affect successful
* loading and unloading of the jar with {@code install_jar} and
* {@code remove_jar}. In testing, this can help to confirm that all of the
* needed {@code provides} and {@code requires} relationships have been
@@ -94,6 +106,74 @@
* orders, chosen arbitrarily but consistently between multiple compilations as
* long as the sources are unchanged. This can be helpful in software
* distribution when reproducible output is wanted.
+ * The deployment-descriptor syntax fixed by the ISO SQL/JRT standard has
+ * a rudimentary conditional-inclusion feature based on
+ * {@code PL/Java's descriptor generator normally emits statements
+ * as {@code When loading or unloading a jar file and processing its deployment
+ * descriptor, PL/Java 'recognizes' any implementor name listed in the runtime
+ * setting {@code pljava.implementors}, which contains only {@code PostgreSQL}
+ * by default.
+ * The {@code pljava.implementors} setting can be changed, even by SQL
+ * statements within a deployment descriptor, to affect which subsequent
+ * statements will be executed. An SQL statement may test some condition and
+ * set {@code pljava.implementors} accordingly. In PL/Java's supplied examples,
+ * ConditionalDDR illustrates this approach to conditional execution.
+ * Naturally, this scheme requires the SQL generator to emit the statement
+ * that tests the condition earlier in the deployment descriptor than
+ * the statements relying on the {@code The {@code provides}/{@code requires} relationship so created differs
+ * in three ways from other {@code provides}/{@code requires} relationships:
+ * Given the 'weak' nature of the {@code implementor}/{@code provides}
+ * relationship, an error will not be reported if a spelling or upper/lower case
+ * difference prevents identifying an {@code According to the ISO SQL/JRT standard, an {@code
- * In this example, an SQLAction (with the default implementor name PostgreSQL
- * so it should always execute) tests some condition and, based on the result,
- * adds {@code LifeIsGood} to the list of recognized implementor names.
+ * In this example, an {@code SQLAction} (with the default implementor name
+ * {@code PostgreSQL} so it should always execute) tests some condition and,
+ * based on the result, adds {@code LifeIsGood} to the list of recognized
+ * implementor names.
*
- * Later SQLActions with that implementor name should also be executed, while
- * those with a different, unrecognized implementor should not.
+ * Later {@code SQLAction}s with that implementor name should also be executed,
+ * while those with a different, unrecognized implementor should not.
*
* That is what happens at deployment (or undeployment) time, when the
* jar has been loaded into the target database and the deployment descriptor is
* being processed.
*
- * The {@code provides} and {@code requires} attributes matter at
+ * The {@code provides} attributes matter at
* compile time: they are hints to the DDR generator so it will be sure
- * to write the SQLAction that tests the condition ahead of the ones that
- * depend on the condition having been tested. The example illustrates that an
- * SQLAction's {@code implementor} is treated as an implicit {@code requires}.
- * Unlike an explicit one, it is weak: if there is nothing declared that
- * {@code provides} it, that's not an error; affected SQLActions will just be
- * placed as late in the generated DDR as other dependencies allow, in case
- * something in the preceding actions will be setting those implementor tags.
+ * to write the {@code SQLAction} that tests the condition ahead of whatever
+ * depends on the condition having been tested. The example illustrates that
+ * {@code implementor} is treated also as an implicit {@code requires}.
*
- * The implicit {@code requires} derived from an {@code implementor} is also
- * special in another way: it does not have its sense reversed when generating
- * the "undeploy" actions of the deployment descriptor. Ordinary requirements
- * do, so the dependent objects get dropped before the things they depend on.
- * But the code for setting a conditional implementor tag has to be placed
- * ahead of the uses of the tag, whether deploying or undeploying.
+ * Note: while ISO SQL/JRT specifies that an {@code
- * An {@code SQLAction} setting an implementor tag does not need to have any
- * {@code remove=} actions. If it does not (the usual case), its
+ * The dependency created when matching {@code implementor} to {@code provides}
+ * differs in three ways from an explicit dependency between {@code requires}
+ * and {@code provides}:
+ *
* This example adds {@code LifeIsGood} ahead of the prior content of
* {@code pljava.implementors}. Simply replacing the value would stop the
@@ -64,8 +77,8 @@
* local, so it is reverted when the transaction completes.
*
* In addition to the goodness-of-life examples, this file also generates
- * one or more statements setting PostgreSQL-version-based implementor tags that
- * are relied on by various other examples in this directory.
+ * one or more statements setting PostgreSQL-version-based implementor names
+ * that are relied on by various other examples in this directory.
*/
@SQLAction(provides={"LifeIsGood","LifeIsNotGood"}, install=
"SELECT CASE 42 WHEN 42 THEN " +
diff --git a/src/site/markdown/use/variables.md b/src/site/markdown/use/variables.md
index 87be1205a..a26055327 100644
--- a/src/site/markdown/use/variables.md
+++ b/src/site/markdown/use/variables.md
@@ -65,7 +65,8 @@ These PostgreSQL configuration variables can influence PL/Java's operation:
only on a system recognizing that name. By default, this list contains only
the entry `postgresql`. A deployment descriptor that contains commands with
other implementor names can achieve a rudimentary kind of conditional
- execution if earlier commands adjust this list of names. _Commas separate
+ execution if earlier commands adjust this list of names, as described
+ [here][condex]. _Commas separate
elements of this list. Elements that are not regular identifiers need to be
surrounded by double-quotes; prior to PostgreSQL 11, that syntax can be used
directly in a `SET` command, while in 11 and after, such a value needs to be
@@ -213,6 +214,7 @@ These PostgreSQL configuration variables can influence PL/Java's operation:
[vmop]: ../install/vmoptions.html
[sqlascii]: charsets.html#Using_PLJava_with_server_encoding_SQL_ASCII
[addm]: ../install/vmoptions.html#Adding_to_the_set_of_readable_modules
+[condex]: ../pljava-api/apidocs/org.postgresql.pljava/org/postgresql/pljava/annotation/package-summary.html#conditional-execution-in-the-deployment-descriptor-heading
[policy]: policy.html
[unenforced]: unenforced.html
[mappedudt]: ../pljava-api/apidocs/org.postgresql.pljava/org/postgresql/pljava/annotation/MappedUDT.html
Eliminating error-prone hand-maintained SQL scripts
*
@@ -37,40 +38,50 @@
* (All but the simplest PL/Java functions probably refer to some class in
* PL/Java's API anyway, in which case the jar would already have to be on
* the class path.)
+ *
+ * -Aoption=value on the command line:
+ * New compiler options when generating the deployment descriptor
+ *
- *
- * ddr.output
+ * pljava.ddr and found
* in the top directory of the tree where the compiled class files are written.
- * ddr.name.trusted
+ * java will be used. It must match the name
+ * specified, the name {@code java} will be used. It must match the name
* used for the "trusted" language declaration when PL/Java was installed.
- * ddr.name.untrusted
+ * javaU will be used. It must match the name
+ * specified, the name {@code javaU} will be used. It must match the name
* used for the "untrusted" language declaration when PL/Java was installed.
- * ddr.implementor
+ * ddr.reproducible
+ * Controlling order of statements in the deployment descriptor
+ * Effect of {@code ddr.reproducible}
+ * Conditional execution in the deployment descriptor
+ *
+ *
+ * Matching {@code implementor} and {@code provides}
+ *
+ *
*