Skip to content

Support building/using PL/Java on Java 26 - #547

Merged
jcflack merged 8 commits into
REL1_6_STABLEfrom
trackjdk/REL1_6_STABLE/jdk26bld
Aug 14, 2026
Merged

Support building/using PL/Java on Java 26#547
jcflack merged 8 commits into
REL1_6_STABLEfrom
trackjdk/REL1_6_STABLE/jdk26bld

Conversation

@jcflack

@jcflack jcflack commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This pull request enables PL/Java to build and run with Java 26, but does not bring any PL/Java API changes corresponding to any new features in the JDK 26 release notes. Some new features brought by Java 26's inclusion of the JDBC 4.5 maintenance release could merit future work:

  • Verbatim syntax in JDBC SQL. JDBC now specifies that the recognition of JDBC escapes and the ? parameter placeholder should not take place between {\ and \} (spelled in a Java string literal as {\\ and \\}, respectively), and that \\ in such a region (\\\\ in a Java literal) represents a literal backslash.
    • This is a convenient way to write SQL that uses the ? character, which has become more common with recent additions to the language. However:
    • The specification is debilitatingly vague. It is silent as to whether those delimiters are scanned for blindly in the user-supplied SQL text, or with respect to existing SQL lexical rules for quoting and comments. Unless or until this oversight is remedied in an erratum or another maintenance release, grossly incompatible JDBC driver implementations are likely to result.
    • The way PGJDBC implements the feature could be looked to for an example, but PGJDBC, so far, does not seem to be implementing it, instead retaining a longstanding nonstandard convention where ?? represents a literal ?.
    • There is so much wrong with PL/Java's nativeSQL method that it would be difficult to add this feature without risk of changing behavior, be it even already-broken behavior, that is being relied on. A future major release that revamps the JDBC layer would be a better target for this change.
    • Although different from PGJDBC's ?? convention, PL/Java does provide a way to include ? in SQL when needed. It is a consequence of the failure of PL/Java's nativeSQL method to understand comments, while it does understand quoting. The string /*'*/?/*'*/ will therefore be seen by PL/Java as containing a ? that should be left alone because inside quotes, while PostgreSQL will recognize it as a ? surrounded by comments. This should be covered in PL/Java's documentation.
    • SQL in deployment descriptors is parsed by a different method that is differently broken: it does understand /* ... */ comments (and also // comments, even though those aren't a thing), which would seem to make the /*'*/?/*'*/ technique unusable. But because this method only recognizes comments that follow whitespace, the technique can still be used as long as no whitespace precedes it.
  • New JDBC types DECFLOAT and JSON.
    • These new members of java.sql.Types and java.sql.JDBCType will be present when running on Java 26 or later, but PL/Java has no new behavior tied to those types.
  • AutoCloseable implemented by several JDBC interfaces.
    • The functionality is supplied by default methods on those interfaces, requiring no new support in PL/Java. However:
    • The change was incompatible with PL/Java's old internal implementations of Blob and Clob, so those implementations are now different internally.
    • Those legacy implementations were only partial to begin with, and are probably little used, if at all.
    • Examples/regression tests have been added to capture what did and didn't previously work and ensure the new internal implementation is at least as complete as the old one.
    • A future major release that revamps JDBC support should replace these Blob and Clob implementations completely with versions that actually manipulate PostgreSQL large objects. That would bring the behavior in line with PGJDBC.

Naturally, no patch will begin using Java 26 features within PL/Java itself until a future major release adopts a newer minimum build version.

These examples preserve a snapshot of how PL/Java's existing, ancient,
Blob support can (and can't) be used.
These examples preserve a snapshot of how PL/Java's existing, ancient,
Clob support can (and can't, mostly can't) be used.
BlobValue was implemented as a subclass of InputStream, which cannot be
compiled under Java 26 because JDBC 4.5 makes Blob AutoCloseable with
incompatible exception typing for close().

It was a quite incomplete implementation anyway: limited to 2GB and with
several methods unimplemented. The offline SerialBlob found in the
javax.sql.rowset.serial package is also limited to 2GB and with some
methods unusable (at least when instantiated from a byte[], as here),
but it is more complete than BlobValue.

The C code was depending on an internal getContents method of BlobValue,
Now it uses the documented interface methods, so should be able to use
objects of any class that (correctly) implements Blob (provided, still,
that the length doesn't exceed 2GB).

This is not an effort to improve the java.sql.Blob support significantly,
but just to make it no worse and also compatible with Java 26. This
implementation remains essentially a veneer that doesn't do anything
better than using the {get,update,set,read,write}Bytes methods, and
probably has never seen much use for exactly that reason.
ClobValue was implemented as a subclass of Reader, which cannot be
compiled under Java 26 because JDBC 4.5 makes Clob AutoCloseable with
incompatible exception typing for close().

It was a badly incomplete implementation anyway: limited to 2Gchars and
with several methods unimplemented. The offline SerialClob found in the
javax.sql.rowset.serial package is also limited to 2Gchars and with some
methods unusable (at least when instantiated from a char[], as here),
but it is more complete than ClobValue.

Even the partial work that was done to integrate BlobValue into PL/Java's
legacy type system had not been done for ClobValue; compared to the working
tests in the LegacyBlob example, several of the corresponding tests in
the LegacyClob example did not work.

Some still don't, but a few more do work now, thanks to having the
AsciiStream and CharacterStream methods no longer going through Clob now
at all. That's good enough for now: this is not an effort to improve the
java.sql.Clob support significantly, but just to make it no worse and also
compatible with Java 26. This implementation remains essentially a veneer
that doesn't do anything better than using the {get,update,set,read,write}
String methods, and probably has never seen much use for exactly
that reason.
Those examples that do work after this refactoring, including ones that
didn't before, are now run with SQLAction in the deployment descriptor
so that at least the current state of limited utility can be preserved.
No issues observed in compiling manually (without the Maven
directive specifying an earlier --release) on Oracle JDK 25 GA.

cd pljava-api/src/main/java
/var/tmp/jdk-26.0.1/bin/javac -d ../../../target/classes/ \
 -Xlint:unchecked -Xlint:-removal --module-version 1.6-SNAPSHOT \
 $(find . -name '*.java')
cd ../../..
/var/tmp/jdk-26.0.1/bin/jar cf target/pljava-api-1.6-SNAPSHOT.jar \
 -C target/classes .

cd ../pljava/src/main/java
/var/tmp/jdk-26.0.1/bin/javac --module-version 1.6-SNAPSHOT \
 -d ../../../target/classes/ \
 -h ../../../target/javah-include \
 --module-path ../../../../pljava-api/target/pljava-api-1.6-SNAPSHOT.jar \
 --processor-module-path \
  ../../../../pljava-api/target/pljava-api-1.6-SNAPSHOT.jar \
 -Xlint:unchecked -Xlint:-removal $(find . -name '*.java')
cd ../../../
/var/tmp/jdk-26.0.1/bin/jar cf target/pljava-1.6-SNAPSHOT.jar \
 -C target/classes .

cd ../pljava-examples/src/main/java
/var/tmp/jdk-26.0.1/bin/javac -d ../../../target/classes/ \
 --module-path ../../../../pljava-api/target/pljava-api-1.6-SNAPSHOT.jar \
 --processor-module-path \
  ../../../../pljava-api/target/pljava-api-1.6-SNAPSHOT.jar \
 --class-path \
  ~/.m2/repository/net/sf/saxon/Saxon-HE/10.9/Saxon-HE-10.9.jar: \
 -Xlint:unchecked -Xlint:-removal \
 --add-modules org.postgresql.pljava $(find . -name '*.java')
cd ../../../target/classes
cp -r ../../src/main/resources/* .
zip -r ../pljava-examples-1.6-SNAPSHOT.jar *
# zip because jar m doesn't preserve order of manifest entries
cd ../../../
# with dir of intended pg_config version on PATH:
mvn clean install --projects pljava-pgxs,pljava-so,pljava-packaging
PostgreSQL adopted the inttypes.h format macros in 18, but continues
to define the older ..._FORMAT macros, so those are what should be used
for compatibility across versions.
Aliases for subqueries in a FROM clause became optional in PG 16
(postgres/postgres@bcedd8f, as an extension to the standard), but are
strictly required in earlier versions.
@jcflack
jcflack merged commit 58a38d0 into REL1_6_STABLE Aug 14, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant