Skip to content

Commit 37c9da0

Browse files
committed
Merge bug/REL1_6_STABLE/issue515 into REL1_6_STABLE
Merges PR #519.
2 parents 6653a22 + fc16b49 commit 37c9da0

File tree

5 files changed

+170
-52
lines changed

5 files changed

+170
-52
lines changed

pljava-api/src/main/java/org/postgresql/pljava/annotation/SQLAction.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004-2020 Tada AB and other contributors, as listed below.
2+
* Copyright (c) 2004-2025 Tada AB and other contributors, as listed below.
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the The BSD 3-Clause License
@@ -22,14 +22,33 @@
2222
/**
2323
* Annotation that supplies verbatim commands to be copied into the
2424
* deployment descriptor.
25-
*
26-
* Strings supplied within a single SQLAction annotation will be copied
27-
* in the order supplied. Strings from different SQLAction annotations, and
28-
* generated code for functions, will be assembled in an order that can be
29-
* influenced by 'provides' and 'requires' labels. No snippet X will be
30-
* emitted ahead of any snippets that provide what X requires. The "remove"
31-
* actions will be assembled in the reverse of that order.
32-
*
25+
*<p>
26+
* Strings supplied to {@link #install install} or {@link #remove remove} within
27+
* a single {@code SQLAction} annotation become code snippets emitted into the
28+
* deployment descriptor's {@code INSTALL} or {@code REMOVE} section,
29+
* respectively, in the order supplied.
30+
*<p>
31+
* Snippets from different {@code SQLAction} annotations,
32+
* and snippets generated by annotations on functions, types, and such, will be
33+
* assembled in an order that can be influenced by {@link #provides provides}
34+
* and {@link #requires requires} labels. No snippet X will be emitted as an
35+
* {@code INSTALL} action ahead of any snippets that provide what X requires.
36+
* The sense of that dependency is reversed when ordering {@code REMOVE}
37+
* snippets.
38+
*<h2>Conditional execution</h2>
39+
*<p>
40+
* An {@code SQLAction} may supply an {@code install} snippet that tests some
41+
* condition at the time of deployment and adjusts the
42+
* {@code pljava.implementors} setting to include or not include a specific
43+
* {@code <implementor name>}, controlling whether actions later in
44+
* the deployment descriptor that are annotated with that
45+
* {@code <implementor name>} will be executed. The {@code SQLAction} that
46+
* controls whether an {@code <implementor name>} will be recognized should use
47+
* {@link #provides provides} with exactly that name, which is implicitly
48+
* 'required' by statements that use that name as
49+
* {@link #implementor implementor}. For details on this usage, which involves
50+
* a different ordering rule, see "conditional execution" in
51+
* {@link org.postgresql.pljava.annotation the package documentation}.
3352
* @author Thomas Hallgren - pre-Java6 version
3453
* @author Chapman Flack (Purdue Mathematics) - updated to Java6,
3554
* added SQLAction
@@ -58,6 +77,10 @@
5877
* generated in such an order that other objects that 'require' labels
5978
* 'provided' by this come later in the output for install actions, and
6079
* earlier for remove actions.
80+
*<p>
81+
* For use of this element on an {@code SQLAction} that tests a condition
82+
* to control conditional execution, see "conditional execution" in
83+
* {@link SQLAction the class description}.
6184
*/
6285
String[] provides() default {};
6386

Lines changed: 96 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015-2023 Tada AB and other contributors, as listed below.
2+
* Copyright (c) 2015-2025 Tada AB and other contributors, as listed below.
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the The BSD 3-Clause License
@@ -13,6 +13,7 @@
1313
/**
1414
* Annotations for use in Java code to generate the SQLJ Deployment Descriptor
1515
* automatically.
16+
* <h2>Eliminating error-prone hand-maintained SQL scripts</h2>
1617
* <p>
1718
* To define functions or types in PL/Java requires more than one step. The
1819
* Java code must be written, compiled to a jar, and made available to the
@@ -22,55 +23,65 @@
2223
* version that undoes it when uninstalling the jar) can be written in a
2324
* prescribed form and stored inside the jar itself as an "SQLJ Deployment
2425
* Descriptor", and processed automatically when the jar is installed in or
25-
* removed from the backend.
26+
* removed from the DBMS.
2627
* <p>
2728
* To write the deployment descriptor by hand can be tedious and error-prone,
2829
* as it must largely duplicate the method and type declarations in the
2930
* Java code, but using SQL's syntax and types in place of Java's. Instead,
3031
* when the annotations in this package are used in the Java code, the Java
31-
* compiler itself will generate a deployment descriptor file, ready to include
32-
* with the compiled classes to make a complete SQLJ jar.
32+
* compiler itself will generate a deployment descriptor (DDR) file, ready to
33+
* include with the compiled classes to make a complete SQLJ jar.
3334
* <p>
3435
* Automatic descriptor generation requires attention to a few things.
3536
* <ul>
3637
* <li>The {@code pljava-api} jar must be on the Java compiler's class path.
3738
* (All but the simplest PL/Java functions probably refer to some class in
3839
* PL/Java's API anyway, in which case the jar would already have to be on
3940
* the class path.)
41+
* <li>Java compilers older than Java 23 will automatically find and use
42+
* PL/Java's DDR processor as long as the {@code pljava-api} jar is on the class
43+
* path. Starting in Java 23, the compiler will not do so automatically, and a
44+
* {@code -processor org.postgresql.pljava.annotation.processing.DDRProcessor}
45+
* option is also needed on the {@code javac} command line. (Warnings about this
46+
* are issued starting in Java 21, though the processor is still used
47+
* automatically, with the warnings, until Java 23.)
4048
* <li>When recompiling after changing only a few sources, it is possible the
4149
* Java compiler will only process a subset of the source files containing
4250
* annotations. If so, it may generate an incomplete deployment descriptor,
4351
* and a clean build may be required to ensure the complete descriptor is
4452
* written.
45-
* <li>Additional options are available when invoking the Java compiler, and
46-
* can be specified with <code>-Aoption=value</code> on the command line:
53+
* </ul>
54+
* <h2>New compiler options when generating the deployment descriptor</h2>
55+
* <p>Additional options are available when invoking the Java compiler, and
56+
* can be specified with {@code -Aoption=value} on the command line:
4757
* <dl>
48-
* <dt><code>ddr.output</code>
58+
* <dt>{@code ddr.output}
4959
* <dd>The file name to be used for the generated deployment descriptor.
5060
* If not specified, the file will be named <code>pljava.ddr</code> and found
5161
* in the top directory of the tree where the compiled class files are written.
52-
* <dt><code>ddr.name.trusted</code>
62+
* <dt>{@code ddr.name.trusted}
5363
* <dd>The language name that will be used to declare methods that are
5464
* annotated to have {@link org.postgresql.pljava.annotation.Function.Trust#SANDBOXED} behavior. If not
55-
* specified, the name <code>java</code> will be used. It must match the name
65+
* specified, the name {@code java} will be used. It must match the name
5666
* used for the "trusted" language declaration when PL/Java was installed.
57-
* <dt><code>ddr.name.untrusted</code>
67+
* <dt>{@code ddr.name.untrusted}
5868
* <dd>The language name that will be used to declare methods that are
5969
* annotated to have {@link org.postgresql.pljava.annotation.Function.Trust#UNSANDBOXED} behavior. If not
60-
* specified, the name <code>javaU</code> will be used. It must match the name
70+
* specified, the name {@code javaU} will be used. It must match the name
6171
* used for the "untrusted" language declaration when PL/Java was installed.
62-
* <dt><code>ddr.implementor</code>
72+
* <dt>{@code ddr.implementor}
6373
* <dd>The identifier (defaulting to {@code PostgreSQL} if not specified here)
6474
* that will be used in the {@code <implementor block>}s wrapping any SQL
6575
* generated from elements that do not specify their own. If this is set to a
6676
* single hyphen (-), elements that specify no implementor will produce plain
6777
* {@code <SQL statement>}s not wrapped in {@code <implementor block>}s.
68-
* <dt><code>ddr.reproducible</code>
78+
* <dt>{@code ddr.reproducible}
6979
* <dd>When {@code true} (the default), SQL statements are written to the
7080
* deployment descriptor in an order meant to be consistent across successive
7181
* compilations of the same sources. This option is further discussed below.
7282
* </dl>
73-
* <li>The deployment descriptor may contain statements that cannot succeed if
83+
* <h2>Controlling order of statements in the deployment descriptor</h2>
84+
* <p>The deployment descriptor may contain statements that cannot succeed if
7485
* placed in the wrong order, and to keep a manually-edited script in a workable
7586
* order while adding and modifying code can be difficult. Most of the
7687
* annotations in this package accept arbitrary {@code requires} and
@@ -80,12 +91,13 @@
8091
* compiler, except that it will make sure not to write anything that
8192
* {@code requires} some string <em>X</em> into the generated script
8293
* before whatever {@code provides} it.
83-
* <li>There can be multiple ways to order the statements in the deployment
94+
* <h3>Effect of {@code ddr.reproducible}</h3>
95+
* <p>There can be multiple ways to order the statements in the deployment
8496
* descriptor to satisfy the given {@code provides} and {@code requires}
8597
* relationships. While the compiler will always write the descriptor in an
8698
* order that satisfies those relationships, when the {@code ddr.reproducible}
8799
* option is {@code false}, the precise order may differ between successive
88-
* compilations of the same sources, which <em>should</em> not affect successful
100+
* compilations of the same sources, which <em>should not</em> affect successful
89101
* loading and unloading of the jar with {@code install_jar} and
90102
* {@code remove_jar}. In testing, this can help to confirm that all of the
91103
* needed {@code provides} and {@code requires} relationships have been
@@ -94,6 +106,74 @@
94106
* orders, chosen arbitrarily but consistently between multiple compilations as
95107
* long as the sources are unchanged. This can be helpful in software
96108
* distribution when reproducible output is wanted.
109+
* <h2>Conditional execution in the deployment descriptor</h2>
110+
* <p>The deployment-descriptor syntax fixed by the ISO SQL/JRT standard has
111+
* a rudimentary conditional-inclusion feature based on
112+
* {@code <implementor block>}s.
113+
* SQL statements wrapped in {@code BEGIN}/{@code END} with an
114+
* {@code <implementor name>} are executed only if that name is recognized
115+
* by the DBMS when installing or removing the jar. Statements in the deployment
116+
* descriptor that are not wrapped in an {@code <implementor block>} are
117+
* executed unconditionally.
118+
* <p>PL/Java's descriptor generator normally emits statements
119+
* as {@code <implementor block>}s, using the name {@code PostgreSQL}
120+
* (or the value of the {@code ddr.implementor} option if present on
121+
* the compiler command line) by default, or a specific name supplied
122+
* with {@code implementor=} to one of the annotations in this package.
123+
* <p>When loading or unloading a jar file and processing its deployment
124+
* descriptor, PL/Java 'recognizes' any implementor name listed in the runtime
125+
* setting {@code pljava.implementors}, which contains only {@code PostgreSQL}
126+
* by default.
127+
* <p>The {@code pljava.implementors} setting can be changed, even by SQL
128+
* statements within a deployment descriptor, to affect which subsequent
129+
* statements will be executed. An SQL statement may test some condition and
130+
* set {@code pljava.implementors} accordingly. In PL/Java's supplied examples,
131+
* <a href=
132+
"https://github.com/tada/pljava/blob/REL1_6_STABLE/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/ConditionalDDR.java"
133+
>ConditionalDDR</a> illustrates this approach to conditional execution.
134+
* <p>Naturally, this scheme requires the SQL generator to emit the statement
135+
* that tests the condition earlier in the deployment descriptor than
136+
* the statements relying on the {@code <implementor name>} being set.
137+
* Building on the existing ability to control the order of statements
138+
* using {@code provides} and {@code requires} elements, an {@code implementor}
139+
* element specified in the annotation for a statement is treated also as
140+
* an implicit {@code requires} for that name, so the programmer only needs
141+
* to place an explicit {@code provides} element on whatever
142+
* {@link SQLAction SQLAction} tests the condition and determines if the name
143+
* will be recognized.
144+
* <p>The {@code provides}/{@code requires} relationship so created differs
145+
* in three ways from other {@code provides}/{@code requires} relationships:
146+
* <ul>
147+
* <li>It does not reverse for generating {@code remove} actions.
148+
* Normal dependencies must be reversed for that case, so dependent objects
149+
* are removed before those they depend on. By contrast, a condition determining
150+
* the setting of an implementor name must be evaluated before the name
151+
* is needed, whether the jar is being installed or removed.
152+
* <li>If it does not have an explicit {@code remove} action (the usual case),
153+
* its {@code install} action (the condition test and setting of the name)
154+
* is used both when installing and removing.
155+
* <li>It is weak. The SQL generator does not flag an error if the implicit
156+
* {@code requires} for an implementor name is not satisfied by any annotation's
157+
* {@code provides} in the visible Java sources. It is possible the name may be
158+
* set some other way in the DBMS environment where the jar is to be deployed.
159+
* Faced with statements that require such 'unprovided' implementor names,
160+
* the SQL generator just falls back to emitting them as late in the deployment
161+
* descriptor as possible, after all other statements that do not depend
162+
* on them.
97163
* </ul>
164+
* <h3>Matching {@code implementor} and {@code provides}</h3>
165+
* <p>Given the 'weak' nature of the {@code implementor}/{@code provides}
166+
* relationship, an error will not be reported if a spelling or upper/lower case
167+
* difference prevents identifying an {@code <implementor name>} with the
168+
* {@code provides} string of an annotated statement intended to match it.
169+
* The resulting deployment descriptor may have a workable order
170+
* as a result of the fallback ordering rules, or may have a mysteriously
171+
* unworkable order, particularly of the {@code remove} actions.
172+
* <p>According to the ISO SQL/JRT standard, an {@code <implementor name>} is
173+
* an SQL identifier, having a case-insensitive matching behavior unless quoted.
174+
* PL/Java, however, treats a {@code provides} value as an arbitrary Java string
175+
* that can only match exactly, and so PL/Java's SQL generator will successfully
176+
* match up {@code implementor} and {@code provides} strings <em>only when
177+
* they are identical in spelling and case</em>.
98178
*/
99179
package org.postgresql.pljava.annotation;

pljava-api/src/main/java/org/postgresql/pljava/annotation/processing/DDRProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2004-2024 Tada AB and other contributors, as listed below.
2+
* Copyright (c) 2004-2025 Tada AB and other contributors, as listed below.
33
*
44
* All rights reserved. This program and the accompanying materials
55
* are made available under the terms of the The BSD 3-Clause License
@@ -6074,7 +6074,7 @@ interface Snippet
60746074
*/
60756075
default DependTag implementorTag()
60766076
{
6077-
return new DependTag.Explicit(implementorName().pgFolded());
6077+
return new DependTag.Explicit(implementorName().nonFolded());
60786078
}
60796079
/**
60806080
* Return an array of SQL commands (one complete command to a string) to

0 commit comments

Comments
 (0)