1.5.8 adds support for PostgreSQL 14, fixes two bugs, and begins preparation for the impact of changes to Java's permission enforcement coming in Java 17 and later with JEP 411.
Current versions of PL/Java rely on Java security features that will be affected by JEP 411, beginning with Java 17. Java 17 itself will continue to provide the needed capabilities, with only deprecation marks and warnings added. Java 17 is also positioned as a long-term support release, so the option of continuing to run a current (1.5.8 or latest 1.6) PL/Java release without loss of function will be available, if needed, by continuing to run with Java 17.
The PL/Java 1.5 series has had a good run, and is not expected to receive backports of future, post-JEP 411 functionality.
For more on how PL/Java will adapt, please read about JEP 411 on the PL/Java wiki.
MalformedInputException: Input length = 1 in 1.5
The bug was exercised in a database where server_encoding
was SQL_ASCII
.
The more-principled treatment of SQL_ASCII
in PL/Java 1.6 has been
backported, and is described here.
Crash in autovacuum if a PL/Java functional index exists
Functional indexes over PL/Java functions can now be autovacuumed
in PG 9.5 or later. In earlier versions, a feature_not_supported
error
will be reported instead of crashing. That can be avoided by setting the
autovacuum_enabled
storage parameter to false
on any table having
a Java-based functional index, and running explicit VACUUM
periodically
on such tables. Prior to PG 8.4, there was no such per-table setting, and
the only workaround would be to forego autovacuum database-wide and use
explicit VACUUM
on some schedule.
Thanks to yazun
and ricdhen
for reporting the bugs fixed in this release.
1.5.7 is a bug-fix release, with a single issue backpatched from the 1.6
branch, correcting a problem in XML Schema validation in some non-en_US
locales.
Thanks to Christoph Berg for the report.
This release adds support for PostgreSQL 13.
It includes improvements to the JDBC 4.0 java.sql.SQLXML
API that first became
available in 1.5.1, an update of the ISO SQL/XML examples based on the Saxon
product to Saxon 10 (which now includes support for XML Query higher-order
functions in the freely-licensed Saxon-HE), some improvements to internals,
and a number of bug fixes.
PL/Java 1.5.6 can be built against recent PostgreSQL versions including 13, and older ones back to 8.2, using Java SE 8 or later. The source code avoids features newer than Java 6, so building with Java 7 or 6 should also be possible, but is no longer routinely tested. The Java version used at runtime does not have to be the same version used for building. PL/Java itself can run on any Java version 6 or later if built with Java 11 or earlier; it can run on Java 7 or later if built with Java 12 or later. PL/Java functions can be written for, and use features of, whatever Java version will be loaded at run time. See version compatibility for more detail.
PL/Java 1.5.6 cannot be built with Java 15 or later, as the Nashorn JavaScript
engine used in the build process no longer ships with Java 15. It can be built
with GraalVM, if -Dpolyglot.js.nashorn-compat
is added to the mvn
command line. It will run on Java 15 if built with an earlier JDK or with Graal.
When used with GraalVM as the runtime VM, PL/Java functions can use Graal's “polyglot” capabilities to execute code in any other language available on GraalVM. In this release, it is not yet possible to directly declare a function in a language other than Java.
java.sql.SQLXML
typeAdditions to the Adjusting.XML
API support
limiting resource usage in XML processing, controlling
resolution of external documents and resources,
validation against a schema, and integration of an
XML catalog to locally satisfy requests for external documents.
Corrections and new documentation of whitespace handling in XML values
of CONTENT
form, and implementation limitations.
Updated the dependency for these optional examples to Saxon 10. Probably the most significant of the Saxon 10 changes, for PostgreSQL's purposes, will be that the XQuery higher-order function feature is now included in the freely-licensed Saxon-HE, so that it is now possible without cost to integrate a modern XQuery 3.1 implementation that is lacking only the schema-aware feature and the typed data feature (for those, the paid Saxon-EE product is needed), and the static typing feature (which is not in any Saxon edition).
To compensate for delivering the higher-order function support in -HE, Saxonica moved certain optimizations to -EE. This seems a justifiable trade, as it is better for development purposes to have the more complete implementation of the language, leaving better optimization to be bought if and when needed.
Thanks to a tip from Saxon's developer, the returning of results to SQL is now done in a way that may incur less copying in some cases.
-Xcheck:jni
option have
been tracked down, making it practical to use -Xcheck:jni
in testing.Reference.clear
on OpenJ9 JVMcategory
, delimiter
, or storage
attribute of a user-defined type.CREATE EXTENSION ... FROM unpackaged
numvals
in SPITupleTable
detoast.h
detoast_external_attr
There is a PL/Java 1.5.6 thanks in part to Christoph Berg, Chapman Flack, Kartik Ohri, original creator Thomas Hallgren, and the many contributors to earlier versions.
The work of Kartik Ohri in summer 2020 was supported by Google Summer of Code.
This bug-fix release fixes runtime issues reported in 32-bit i386
builds, some
of which would not affect a more common 64-bit architecture, but some of which
could under the wrong circumstances, so this release should be used in
preference to 1.5.4 or 1.5.3 on any architecture.
It is featurewise identical to 1.5.4, so those release notes, below, should be consulted for the details of user-visible changes.
Thanks to Christoph Berg for the i386
testing that exposed these issues.
This minor release fixes a build issue reported with Java 11, and adds support for building with Java 13. Issues with building the javadocs in later Java versions are resolved. A work-in-progress feature that can apply the SQLXML API to other tree-structured data types is introduced.
Documentation updates include coverage of changes to Application Class Data Sharing in recent Hotspot versions, and ahead-of-time compilation using jaotc.
Otherwise, the release notes for 1.5.3, below, should be consulted for the details of recent user-visible changes.
This release adds support for PostgreSQL 12, and removes the former requirement to build with a Java release earlier than 9.
It includes a rework of of threading and resource management, improvements to
the JDBC 4.0 java.sql.SQLXML
API that first became available in 1.5.1, and
a substantially usable example providing the functionality of ISO SQL
XMLEXISTS
, XMLQUERY
, XMLTABLE
, XMLCAST
, LIKE_REGEX
,
OCCURRENCES_REGEX
, POSITION_REGEX
, SUBSTRING_REGEX
, and TRANSLATE_REGEX
.
Some bugs are fixed.
PL/Java 1.5.3 can be built against recent PostgreSQL versions including 12, and older ones back to 8.2, using Java SE 8 or later. The source code avoids features newer than Java 6, so building with Java 7 or 6 should also be possible, but is no longer routinely tested. The Java version used at runtime does not have to be the same version used for building. PL/Java itself can run on any Java version 6 or later if built with Java 11 or earlier; it can run on Java 7 or later if built with Java 12. PL/Java functions can be written for, and use features of, whatever Java version will be loaded at run time. See version compatibility for more detail.
When used with GraalVM as the runtime VM, PL/Java functions can use its “polyglot” capabilities to execute code in any other language available on GraalVM. In this release, it is not yet possible to directly declare a function in a language other than Java.
Java is multithreaded while PostgreSQL is not, requiring ways to prevent Java threads from entering PostgreSQL at the wrong times, while cleaning up native resources in PostgreSQL when PL/Java references are released, and vice versa.
PL/Java has historically used an assortment of approaches including Java object finalizers, which have long been deprecated informally, and formally since Java 9. Finalizers enter PostgreSQL from a thread of their own, and the synchronization approach used in PL/Java 1.5.2 and earlier has been associated with occasional hangs at backend exit when using an OpenJ9 JVM at runtime.
A redesigned approach using a new DualState
class was introduced in 1.5.1,
at first only used in implementing the java.sql.SQLXML
type, a newly-added
feature. In 1.5.3, other approaches used in the rest of PL/Java's code base are
migrated to use DualState
also, and all uses of the deprecated Java object
finalizers have been retired. With the new techniques, the former occasional
OpenJ9 hangs have not been observed.
This represents the most invasive change to PL/Java's thread synchronization in many years, so it may be worthwhile to reserve extra time for testing applications.
A new configuration variable,
pljava.java_thread_pg_entry
, allows adjusting the thread policy. The default
setting, allow
, preserves PL/Java's former behavior, allowing Java threads
entry into PostgreSQL one at a time, only when any thread already in PG code
has entered or returned to Java.
With object finalizers no longer used, PL/Java itself does not need the allow
mode, but there may be application code that does. Application code can be
tested by setting the error
mode, which will raise an error for any attempted
entry to PG from a thread other than the original thread that launched PL/Java.
If an application runs in error
mode with no errors, it can also be run in
block
mode, which may be more efficient, as it eliminates many locking
operations that happen in allow
or error
mode. However, if block
mode
is used with an application that has not been fully tested in error
mode
first, and the application does attempt to enter PostgreSQL from a Java thread
other than the initial one, the result can be blocked threads or a deadlocked
backend that has to be killed.
A JMX management client like JConsole
or jvisualvm
can identify threads that
are blocked, if needed. The new DualState
class also offers some statistics
that can be viewed in JConsole
, or jvisualvm
with the VisualVM-MBeans
plugin.
java.sql.SQLXML
typeSupport for this JDBC 4.0 type was added in PL/Java 1.5.1. Release 1.5.3 includes the following improvements:
SQLXML
instances. That allows the default
settings to restrict certain XML parser features as advocated by the
Open Web Application Security Project when XML content may be
coming from untrusted sources, with a simple API for relaxing those
restrictions when appropriate for XML content from a known source.PreparedStatement
, etc., an SQLXML
instance that PL/Java did not create.
For example, a PL/Java function could use another database's JDBC driver to
obtain a SQLXML
value from that database, and use that as its own return
value. Transparently, the content is copied to a PL/Java SQLXML
instance.
The copy can also be done explicitly, allowing the “Adjusting” API to be
used if the default XML parser restrictions should be relaxed.Since PL/Java 1.5.1, the supplied examples have included a not-built-by-default example supplying ISO SQL/XML features missing from core PostgreSQL. It is not built by default because it raises the minimum Java version to 8, and brings in the Saxon-HE XML-processing library.
In 1.5.3, the example now provides versions of the ISO SQL XMLEXISTS
,
XMLQUERY
, XMLTABLE
, and XMLCAST
functions based on the W3C XQuery
language as ISO SQL specifies (while PostgreSQL has an “XMLTABLE” function
since release 10 and “XMLEXISTS” since 9.1, they have
numerous limitations inherited from a library that does not support
XQuery, and additional peculiarities prior to PostgreSQL 12), and the ISO SQL
LIKE_REGEX
, OCCURRENCES_REGEX
, POSITION_REGEX
, SUBSTRING_REGEX
, and
TRANSLATE_REGEX
functions that apply XQuery regular expressions. It also
includes the XMLTEXT
function, which is rather trivial, but also missing from
core PostgreSQL, and supplied here for completeness.
As plain user-defined functions without special treatment in PostgreSQL's SQL parser, these functions cannot be used with the exact syntax specified in ISO SQL, but require simple rewriting into equivalent forms that are valid ordinary PostgreSQL function calls. The rewritten forms are intended to be easy to read and correspond closely to the ISO syntax.
While still presented as examples and not a full implementation, these functions are now intended to be substantially usable (subject to minor documented limits), and testing and reports of shortcomings are welcome.
A ResultSet
obtained from a query done in PL/Java would return the value
CLOSE_CURSORS_AT_COMMIT
to a caller of its getHoldability
method, but in
reality would become unusable as soon as the PL/Java function creating it
returned to PostgreSQL. That was fixed in PL/Java 1.5.1 for a ResultSet
obtained from a Statement
, but not for one obtained from a
PreparedStatement
. It now correctly remains usable to the end of the
transaction in either case.
Per JDBC, a Savepoint
still exists after being used in a rollback, and can be
used again; the rollback only invalidates any Savepoint
that had been created
after the one being rolled back. That should be familiar behavior, as it is the
same as PostgreSQL's own SQL SAVEPOINT
behavior. It is also correct in pgJDBC,
which has test coverage to confirm it. PL/Java has been doing it wrong.
In 1.5.3 it now has the JDBC-specified behavior. For compatibility with existing
application code, the meaning of the pljava.release_lingering_savepoints
configuration variable has been adjusted. The setting
tells PL/Java what to do if a Savepoint
still exists, neither released nor
rolled back, at the time a function exits. If on
, the savepoint is released
(committed); if off
, the savepoint is rolled back. A warning is issued in
either case.
In an existing function that used savepoints and assumed that a rolled-back
savepoint would be no longer live, it will now be normal for such a savepoint
to reach the function exit still alive. To recognize this case, PL/Java tracks
whether any savepoint has been rolled back at least once. At function exit, any
savepoint that has been neither released nor ever rolled back is disposed of
according to the release_lingering_savepoints
setting and with a warning,
as before, but any savepoint that has already been rolled back at least once
is simply released, regardless of the variable setting, and without producing
a warning.
When generating the CREATE FUNCTION
command in a deployment descriptor
according to an annotated Java function, PL/Java ordinarily gives the function
parameters names that match their Java names, unquoted. Because PostgreSQL
allows named notation when calling a function, the parameter names in its
declaration become part of its signature that cannot later be changed without
dropping and re-creating the function.
In some cases, explicit control of the SQL parameter names may be wanted,
independently of the Java names: to align with an external standard, perhaps,
or when either the SQL or the Java name would collide with a reserved word.
For that purpose, the (already slightly overloaded) @SQLType
annotation now
has a name
attribute that can specify the SQL name of the annotated parameter.
The user guide and guide for packagers contained incorrect instructions for
using Maven to build a single subproject of PL/Java (such as pljava-api
or
pljava-examples
) instead of the full project. Those have been corrected.
SQLXML
via StAX when server encoding is not UTF-8dynloader.h
nabstime
pg_attrdef.adsrc
TupleTableSlot
sFunctionCallInfoBaseData
There is a PL/Java 1.5.3 thanks in part to
Christoph Berg,
Chapman Flack,
ppKrauss
,
original creator Thomas Hallgren,
and the many contributors to earlier versions.
A pure bug-fix release, correcting a regression in 1.5.1 that was not caught
in pre-release testing, and could leave
conversions between PostgreSQL date
and java.sql.Date
off
by one day in certain timezones and times of the year.
1.5.1 added support for the newer java.time
classes from JSR 310 / JDBC 4.2,
which are recommended as superior alternatives to the
older conversions involving java.sql.Date
and related classes. The new
versions are superior in part because they do not have hidden timezone
dependencies.
However, the change to the historical java.sql.Date
conversion behavior was
inadvertent, and is fixed in this release.
During preparation of this release, other issues of longer standing were also
uncovered in the legacy conversions between PG date
, time
, and
timestamp
classes and the java.sql
types. They are detailed in
issue #200. Because they are not regressions but long-established
behavior, they are left untouched in this release, and will be fixed in
a future release.
The Java 8 java.time
conversions are free of these issues as well.
This release adds support for PostgreSQL 9.6, 10, and 11,
and plays more nicely with pg_upgrade
. If a PostgreSQL installation
is to be upgraded using pg_upgrade
, and is running a version of
PL/Java before 1.5.1, the PL/Java version should first be upgraded
in the running PostgreSQL version, and then the PostgreSQL pg_upgrade
can be done.
The documentation is expanded on the topic of shared-memory precompiled
class cache features, which can substantially improve JVM startup time
and memory footprint, and are now available across Oracle Java, OpenJDK
with Hotspot, and OpenJDK with OpenJ9. When running on OpenJ9, PL/Java
cooperates with the JVM to include even the application's classes
(those loaded with install_jar
) in the shared cache, something not
yet possible with Hotspot. While the advanced sharing feature in Oracle
Java is still subject to a commercial licensing encumbrance, the equivalent
(or superior, with OpenJ9) features in OpenJDK are not encumbered.
Significant new functionality includes new datatype mapping support:
SQL date
, time
, and timestamp
values can be mapped to the new
Java classes of the java.time
package in Java 8 and later (JSR 310 /
JDBC 4.2), which are much more faithful representations of the values
in SQL. Values of xml
type can be manipulated efficiently using the
JDBC 4.0 SQLXML
API, supporting several different APIs for XML
processing in Java.
For Java code that does not use the new date/time classes in the
java.time
package, some minor conversion inaccuracies (less than
two seconds) in the older mapping to java.sql.Timestamp
have been
corrected.
Queries from PL/Java code now produce ResultSet
s that are usable to the
end of the containing transaction, as they had already been claiming to be.
With PostgreSQL 9.6 support comes the ability to declare functions
PARALLEL { UNSAFE | RESTRICTED | SAFE }
, and with PG 10 support,
transition tables are available to triggers.
PL/Java now more consistently schema-qualifies objects in queries and DDL it generates internally, as a measure of defense-in-depth in case the database it is installed in has not been protected from CVE-2018-1058.
No schema-qualification work has been done on the example code. If the examples jar will be installed, it should be in a database that the recommended steps have been taken to secure.
1.5.1 removes the code at issue in CVE-2016-0768, which pertained to PostgreSQL large objects, but had never been documented or exposed as API.
This is not expected to break any existing code at all, based on further review showing the code in question had also been simply broken, since 2006, with no reported issues in that time. That discovery would support an argument for downgrading the severity of the reported vulnerability, but with no need to keep that code around, it is more satisfying to remove it entirely.
Developers wishing to manipulate large objects in PL/Java are able to do so using the SPI JDBC interface and the large-object SQL functions already available in every PostgreSQL version PL/Java currently supports.
PL/Java 1.5.1 can be built against recent PostgreSQL versions including 11, and older ones back to 8.2, using Java SE 8, 7, or 6. It can run using newer Java versions including Java 11. PL/Java functions can be written for, and use features of, the Java version loaded at run time. See version compatibility for more detail.
OpenJDK is supported, and can be downloaded in versions using the Hotspot or the OpenJ9 JVM. Features of modern Java VMs can drastically reduce memory footprint and startup time, in particular class-data sharing. Several choices of Java runtime now offer such features: Oracle Java has a simple class data sharing feature for the JVM itself, freely usable in all supported versions, and an “application class data sharing” feature in Java 8 and later that can also share the internal classes of PL/Java, but is a commercial feature requiring a license from Oracle. As of Java 10, the same application class sharing feature is present in OpenJDK/Hotspot, where it is freely usable without an additional license. OpenJDK/OpenJ9 includes a different, and very sophisticated, class sharing feature, freely usable from Java 8 onward. More on these features can be found in the installation docs.
PL/Java currently does not determine the necessary types of PreparedStatement
parameters from the results of PostgreSQL's own type analysis of the query
(as a network client would, when using PostgreSQL's “extended query” protocol).
PostgreSQL added the means to do so in SPI only in PostgreSQL 9.0, and a future
PL/Java major release should use it. However, this release does make two small
changes to the current behavior.
Without the query analysis results from PostgreSQL, PL/Java tries to type the prepared-statement parameters based on the types of values supplied by the application Java code. It now has two additional ways to do so:
If Java code supplies a Java user-defined type (UDT)—that is, an object
implementing the SQLData
interface—PL/Java will now call the SQLData
method getSQLTypeName
on that object and use the result to pin down
the PostgreSQL type of the parameter. Existing code should already provide
this method, but could, in the past, have returned a bogus result without
detection, as PL/Java did not use it.
Java code can use the three-argument form of setNull
to specify the exact
PostgreSQL type for a parameter, and then another method can be used to
supply a non-null value for it. If the following non-null value has
a default mapping to a different PostgreSQL type, in most cases it will
overwrite the type supplied with setNull
and re-plan the query. That was
PL/Java's existing behavior, and was not changed for this minor release.
However, the new types introduced in this release—the java.time
types
and SQLXML
—behave in the way that should become universal in a future
major release: the already-supplied PostgreSQL type will be respected, and
PL/Java will try to find a usable coercion to it.
When converting between PostgreSQL values of timestamp
or timestamptz
type
and the pre-Java 8 original JDBC type java.sql.Timestamp
, there were cases
where values earlier than 1 January 2000 would produce exceptions rather than
converting successfully. Those have been fixed.
Also, converting in the other direction, from java.sql.Timestamp
to a
PostgreSQL timestamp, an error of up to 1.998 seconds (averaging 0.999)
could be introduced.
That error has been corrected. If an application has stored Java Timestamp
s
and corresponding SQL timestamp
s generated in the past and requires them
to match, it could be affected by this change.
java.time
packageThe old, and still default, mappings in JDBC from the SQL date
, time
, and
timestamp
types to java.sql.Date
, java.sql.Time
, and java.sql.Timestamp
,
were never well suited to represent the PostgreSQL data types. The Time
and
Timestamp
classes were used to map both the with-timezone and without-timezone
variants of the corresponding SQL types and, clearly, could not represent both
equally well. These Java classes all contain timezone dependencies, requiring
the conversion to involve timezone calculations even when converting non-zoned
SQL types, and making the conversion results for non-zoned types implicitly
depend on the current PostgreSQL session timezone setting.
Applications are strongly encouraged to adopt Java 8 as a minimum language
version and use the new-in-Java-8 types in the java.time
package, which
eliminate those problems and map the SQL types much more faithfully.
For PL/Java function parameters and returns, the class in the method declaration
can simply be changed. For retrieving date/time/timestamp values from a
ResultSet
or SQLInput
object, use the variants of getObject
/ readObject
that take a Class<?>
parameter. The class to use is:
PostgreSQL type | java.time class |
---|---|
date |
LocalDate |
time without time zone |
LocalTime |
time with time zone |
OffsetTime |
timestamp without time zone |
LocalDateTime |
timestamp with time zone |
OffsetDateTime |
Details on these mappings are added to the documentation.
java.sql.SQLXML
typePL/Java has not, until now, supported the JDBC 4.0 SQLXML
type. PL/Java
functions have been able to work with PostgreSQL XML values by mapping them
as Java String
, but that conversion could introduce character encoding issues
outside the control of the XML APIs, and also has memory implications if an
application stores, or generates in queries, large XML values. Even if the
processing to be done in the application could be structured to run in constant
bounded memory while streaming through the XML, a conversion to String
requires the whole, uncompressed, character-serialized value to be brought into
the Java heap at once, and any heap-size tuning has to account for that
worst-case size. The java.sql.SQLXML
API solves those problems by allowing
XML manipulation with any of several Java XML APIs with the data remaining in
PostgreSQL native memory, never brought fully into the Java heap unless that is
what the application does. Heap sizing can be based on the just the
application's processing needs.
The SQLXML
type can take the place of String
in PL/Java function parameters
and returns simply by changing their declarations from String
to SQLXML
.
When retrieving XML values from ResultSet
or SQLInput
objects, the legacy
getObject / readObject
methods will continue to return String
for existing
application compatibility, so the specific getSQLXML / readSQLXML
methods, or
the forms of getObject / readObject
with a Class<?>
parameter and passing
SQLXML.class
, must be used. A documentation page has been
added, and the PassXML example illustrates use of the API.
A not-built-by-default new example (because it depends on Java 8 and
the Saxon-HE XML-processing library) provides a partial implementation of true
XMLQUERY
and XMLTABLE
functions for PostgreSQL, using the standard-specified
XML Query language rather than the XPath 1.0 of the native PostgreSQL functions.
A Java system property, org.postgresql.server.encoding
, is set to the
canonical name of a supported Java Charset
that corresponds to PostgreSQL's
server_encoding
setting, if one can be found. If the server encoding's name
is not recognized as any known Java Charset
, this property will be unset, and
some functionality, such as the SQLXML
API, may be limited. If a Java
Charset
does exist (or is made available through a CharsetProvider
) that
does match the PostgreSQL server encoding, but is not automatically selected
because of a naming mismatch, the org.postgresql.server.encoding
property can
be set (with a -D
in pljava.vmoptions
) to select it by name.
A ResultSet
obtained from a query done in PL/Java would return the value
CLOSE_CURSORS_AT_COMMIT
to a caller of its getHoldability
method, but in
reality would become unusable as soon as the PL/Java function creating it
returned to PostgreSQL. It now remains usable to the end of the transaction,
as claimed.
A function in PL/Java can now be annotated
parallel={UNSAFE | RESTRICTED | SAFE}
, with UNSAFE
the default.
A new user guide section explains the possibilities and
tradeoffs. (Good cases for marking a PL/Java function SAFE
may be
rare, as pushing such a function into multiple background processes
will require them all to start JVMs. But if a practical application
arises, PostgreSQL's parallel_setup_cost
can be tuned to help the
planner make good plans.)
Although RESTRICTED
and SAFE
Java functions work in simple tests,
there has been no exhaustive audit of the code to ensure that PL/Java's
internal workings never violate the behavior constraints on such functions.
The support should be considered experimental, and could be a fruitful
area for beta testing.
To accommodate the possibility of more than two billion tuples in a single
operation, the SPI implementation of the JDBC Statement
interface now
provides the JDK 8-specified executeLargeBatch
and getLargeUpdateCount
methods defined to return long
counts. The original executeBatch
and
getUpdateCount
methods remain but, obviously, cannot return counts that
exceed INT_MAX
. In case the count is too large, getUpdateCount
will throw
an ArithmeticException
; executeBatch
will store SUCCESS_NO_INFO
for
any statement in the batch that affected too many tuples to report.
For now, a ResultSetProvider
cannot be used to return more than INT_MAX
tuples, but will check that condition and throw an error to ensure predictable
behavior.
pg_upgrade
PL/Java should be upgraded to 1.5.1 in a database cluster, before that
cluster is binary-upgraded to a newer PostgreSQL version using pg_upgrade
.
A new Upgrading installation-guide section centralizes information
on both upgrading PL/Java in a database, and upgrading a database with PL/Java
in it.
In PostgreSQL, a BEFORE ROW
trigger is able to allow the proposed row
operation, allow it with modified values, or silently suppress the operation
for that row. Way back in PL/Java 1.1.0, the way to produce the ‘suppress’
outcome was for the trigger method to throw an exception. Since PL/Java 1.2.0,
however, an exception thrown in a trigger method is used to signal an error
to PostgreSQL, and there has not been a way to suppress the row operation.
The TriggerData
interface now has a suppress
method that
the trigger can invoke to suppress the operation for the row.
New attributes in the @Trigger
annotation allow the SQL generator to
create constraint triggers (a type of trigger that can be created with SQL
since PostgreSQL 9.1). Such triggers will be delivered by the PL/Java runtime
(to indicate that a constraint would be violated, a constraint trigger
method should throw an informative exception). However, the trigger method
will have access, through the TriggerData
interface, only to the properties
common to ordinary triggers; methods on that interface to retrieve properties
specific to constraint triggers have not been added for this release.
A trigger annotation can now specify tableOld="
name1"
or
tableNew="
name2"
, or both, and the PL/Java function servicing the
trigger can do SPI JDBC queries and see the transition table(s) under the
given name(s). The triggers example code has been extended with
a demonstration.
The way the Java logging system has historically been plumbed to PostgreSQL's,
as described in issue 125, can be perplexing both because it
is unaffected by later changes to the PostgreSQL settings after PL/Java is
loaded in the session, and because it has honored only log_min_messages
and ignored client_min_messages
. The second part is easy to fix, so in
1.5.1 the threshold where Java discards messages on the fast path is
determined by the finer of log_min_messages
and client_min_messages
.
The mvn
command to build PL/Java will now accept an option to provide
a useful default for pljava.libjvm_location
, when building a package for
a particular software environment where the likely path to Java is known.
The mvn
command will also accept an option to specify, by the path to
the pg_config
executable, the PostgreSQL version to build against, in
case multiple versions exist on the build host. This was already possible
by manipulating PATH
ahead of running mvn
, but the option makes it more
explicit.
A new packaging section in the build guide documents those and a number of considerations for making a PL/Java package.
byte[]
heap_form_tuple
SPI_processed
Portal->portalPos
FuncCallContext.call_cntr
SPITupleTable.alloced
and .free
IsBackgroundWorker
IsBinaryUpgrade
SPI_register_trigger_data
SPI
without SPI_push
/SPI_pop
AllocSetContextCreate
DefineCustom...Variable
(no GUC_LIST_QUOTE
in extensions)There is a PL/Java 1.5.1 thanks in part to Christoph Berg, Thom Brown, Luca Ferrari, Chapman Flack, Petr Michalek, Steve Millington, Kenneth Olson, Fabian Zeindl, original creator Thomas Hallgren, and the many contributors to earlier versions.
This, the first PL/Java numbered release since 1.4.3 in 2011, combines compatibility with the latest PostgreSQL and Java versions with modernized build and installation procedures, automatic generation of SQL deployment code from Java annotations, and many significant fixes.
Several security issues are addressed in this release. Sites already using PL/Java are encouraged to update to 1.5.0. For several of the issues below, practical measures are described to mitigate risk until an update can be completed.
CVE-2016-0766, a privilege escalation requiring an authenticated PostgreSQL connection, is closed by installing PL/Java 1.5.0 (including prereleases) or by updating PostgreSQL itself to at least 9.5.1, 9.4.6, 9.3.11, 9.2.15, 9.1.20. Vulnerable systems are only those running both an older PL/Java and an older PostgreSQL.
CVE-2016-0767, in which an authenticated PostgreSQL user with USAGE
permission on the public
schema may alter the public
schema classpath,
is closed by release 1.5.0 (including prereleases). If updating to 1.5.0
must be delayed, risk can be mitigated by revoking public EXECUTE
permission
on sqlj.set_classpath
and granting it selectively to responsible users or
roles.
This release brings a policy change to a more secure-by-default posture,
where the ability to create functions in LANGUAGE java
is no longer
automatically granted to public
, but can be selectively granted to roles
that will have that responsibility. The change reduces exposure to a known
issue present in 1.5.0 and earlier versions, that will be closed in a future
release (CVE-2016-0768, see large objects, access control below).
The new policy will be applied in a new installation; permissions will not
be changed in an upgrade, but any site can move to this policy, even before
updating to 1.5.0, with REVOKE USAGE ON LANGUAGE java FROM public;
followed by
explicit GRANT
commands for the users/roles expected to create Java
functions.
CVE-2016-2192, in which an authenticated user can alter type mappings
without owning the types involved. Exploitability is limited by other
permissions, but if type mapping is a feature being used at a site, one
can interfere with proper operation of code that relies on it. A mitigation
is simply to REVOKE EXECUTE ... FROM PUBLIC
on the sqlj.add_type_mapping
and sqlj.drop_type_mapping
functions, and grant the privilege only to
selected users or roles. As of 1.5.0, these functions require the invoker
to be superuser or own the type being mapped.
PL/Java 1.5.0 can be built against recent PostgreSQL versions including 9.5, using Java SE 8, 7, or 6. See version compatibility for more detail. OpenJDK is well supported. Support for GCJ has been dropped; features of modern Java VMs that are useful to minimize footprint and startup time, such as class-data sharing, are now more deeply covered in the installation docs.
Since 2013, PL/Java has been hosted on GitHub and built using Apache Maven. See the new build instructions for details.
Reported build issues for specific platforms have been resolved, with new platform-specific build documentation for OS X, Solaris, Ubuntu, Windows MSVC, and Windows MinGW-w64.
The build produces a redistributable installation archive usable with
the version of PostgreSQL built against and the same operating system,
architecture, and linker. The type of archive is jar
on all platforms, as
all PL/Java installations will have Java available.
The jar produced by the build is executable and will self-extract,
consulting pg_config
on the destination system to find the correct
default locations for the extracted files. Any location can be overridden.
(Enhancement requests 6, 9)
PL/Java now uses a PostgreSQL configuration variable, pljava.libjvm_location
,
to find the Java runtime to use, eliminating the past need for highly
platform-specific tricks like link-time options or runtime-loader configuration
just so that PL/Java could find Java. PostgreSQL configuration variables are
now the only form of configuration needed for PL/Java, and the libjvm_location
should be the only setting needed if file locations have not been overridden.
In PostgreSQL 9.1 and later, PL/Java can be installed with
CREATE EXTENSION pljava
. Regardless of PostgreSQL version, installation
has been simplified. Former procedures involving Deployer
or install.sql
are no longer required. Details are in the new installation instructions.
The tables used internally by PL/Java have changed. If PL/Java 1.5.0 is
loaded in a database with an existing sqlj
schema populated by an earlier
PL/Java version (1.3.0 or later), the structure will be updated without data
loss (enhancement request 12). Remember that PL/Java runs independently
in each database session where it is in use. Older PL/Java versions active in
other sessions can be disrupted by the schema change.
A trial installation of PL/Java 1.5.0 can be done in a transaction, and rolled back if desired, leaving the schema as it was. Any concurrent sessions with active older PL/Java versions will not be disrupted by the altered schema as long as the transaction remains open, but they may block for the duration, so such a test transaction should be kept short.
readSQL
and writeSQL
for base and mirror user-defined typesIn the course of fixing issue #98, the actual behavior of
readSQL
and writeSQL
with base or mirror types, which had not
previously been documented, now is, along with
other details of PL/Java's type coercion rules found only in the code.
Because machine byte order was responsible for issue #98, it now (a) is
selectable, and (b) has different, appropriate, defaults for mirror UDTs
(which need to match PostgreSQL's order) and for base UDTs (which must
stay big-endian because of how binary COPY
is specified).
A new documentation section explains in detail.
USAGE
to PUBLIC
no longer default for java
languageOf the two languages installed by PL/Java, functions that declare
LANGUAGE javau
can be created only by superusers, while those that
declare LANGUAGE java
can be created by any user or role granted the
USAGE
privilege on the language.
In the past, the language java
has been created with PostgreSQL's
default permission granting USAGE
to PUBLIC
, but PL/Java 1.5.0
leaves the permission to be explicitly granted to those users or roles
expected to create Java functions, in keeping with least-privilege
principles. See large objects, access control under known issues
for background.
Java code developed for use by PL/Java can carry in-code annotations, used by the Java compiler to generate the SQL commands to declare the new functions, types, triggers, etc. in PostgreSQL (enhancement request 1011112, though different in implementation). This eliminates the need to have Java code and the corresponding SQL commands developed in parallel, and the class of errors possible when both are not updated together. It also allows compile-time checks that the Java methods or classes being annotated are suitable (correct access modifiers, signatures, etc.) for their declared SQL purposes, rather than discovering such issues only upon loading the code into PostgreSQL and trying to use it.
The Java compiler writes the generated SQL into a “deployment descriptor”
file (pljava.ddr
by default), as specified by the SQL/JRT standard. The
file can be included in a jar
archive with the compiled code, and the
commands will be executed by PL/Java when the install_jar
function is
used to load the jar.
SQL generation is covered in the updated user documentation, and illustrated in the Hello, World example and several other supplied examples. Reference information is in the API documentation. It is currently usable to declare functions, triggers, and user-defined types, both base and composite.
The history of this feature in PL/Java is long, with the first related commits appearing in 2005, six years in advance of an enhancement request for it. It became generally usable in 2013 when building with Java SE 6 or later, using the annotation processing framework Java introduced in that release. 1.5.0 is the first PL/Java numbered release to feature it.
If you have been using the SQL generation feature in prerelease git
builds of
2013 or later, be aware that some annotation keywords have changed in finalizing
the 1.5.0 release. Java code that was compiled using the earlier keywords will
continue to work, but will have to be updated before it can be recompiled.
effects=(VOLATILE,STABLE,IMMUTABLE)
was formerly type=
type=
(an explicit SQL return type for the function)
was formerly complexType=
trust=(SANDBOXED,UNSANDBOXED)
was formerly
(RESTRICTED,UNRESTRICTED)
called=(BEFORE,AFTER,INSTEAD_OF)
was formerly when=
and conflicted with the WHEN
clause introduced for triggers
in PostgreSQL 9.0.PL/Java formerly allowed only one entry in a jar to be a deployment descriptor (that is, a file of SQL commands to be executed upon loading or unloading the jar). The SQL/JRT standard allows multiple entries to be deployment descriptors, executed in the order they are mentioned in the jar manifest, or the reverse of that order when the jar is being unloaded. PL/Java now conforms to the standard.
The behavior is useful during transition to annotation-driven deployment
descriptor generation for a project that already has a manually-maintained
deployment descriptor. PL/Java's own pljava-examples
project is an
illustration, in the midst of such a transition itself.
Note the significance placed by SQL/JRT on the order of entries in a jar manifest, whose order is normally not significant according to the Jar File Specification. Care can be needed when manipulating manifests with automated tools that may not preserve order.
Deployment descriptors have a primitive conditional-execution provision
defined in the SQL/JRT standard: commands wrapped in a
BEGIN IMPLEMENTOR
identifier construct will only be executed if the
identifier is recognized by the SQL/JRT implementation in use. The design
makes possible jars that can be installed on different database systems that
provide SQL/JRT features, with database-specific commands wrapped in
BEGIN IMPLEMENTOR
blocks with an identifier specific to the system.
By default, PL/Java recognizes the identifier postgresql
(matched without
regard to case).
PL/Java extends the standard by allowing the PostgreSQL configuration
variable pljava.implementors
to contain a list of identifiers that will
be recognized. SQL code in a deployment descriptor can conditionally add
or remove identifiers in this list to influence which subsequent implementor
blocks will be executed, giving a still-primitive but more general control
structure.
In sufficiently recent PostgreSQL versions, the same effect could be
achieved using DO
statements and PL/pgSQL control structures, but this
facility in PL/Java does not require either to be available.
SET ROLE
correctedPL/Java formerly was aware of the user ID associated with the running
session, but not any role ID that user may have acquired with SET ROLE
.
The result would commonly be failed permission checks made by PL/Java when
the session user did not have the needed permission, but had SET ROLE
to
a role that did. Likewise, within install_jar
, PL/Java would execute
deployment descriptor commands as the original session user rather than
as the user's current role, with permission failures a likely result.
Correcting this issue has changed the PL/Java API, but without a bump of major version because the prior API, while deprecated, is still available.
getOuterUserName
and executeAsOuterUser
are new, and
correctly refer to the session user or current role, when active.getSessionUserName
and executeAsSessionUser
are still
present but deprecated, and their semantics are changed. They are now
deprecated aliases for the corresponding new methods, which honor the
set role. Use cases that genuinely need to refer only to the session user
and ignore the role should be rare, and should be discussed on the mailing
list or opened as issues.Since the resolution of bug 21, PL/Java contains a regression test
to ensure that character strings passed and returned between PostgreSQL and
Java will round-trip without alteration for the full range of Unicode
characters, when the database encoding is set to UTF8
.
More considerations apply when the database encoding is anything other
than UTF8
, and especially when it is SQL_ASCII
. Please see
character encoding support for more.
CREATE EXTENSION
fails because new session needed-Xss
)TupleDesc
leak warnings with composite UDTsSeveral APIs within PostgreSQL itself have been added or changed; PL/Java now uses the current versions of these where appropriate:
find_coercion_pathway
set_stack_base
GetOuterUserId
GetUserNameFromId
GetUserIdAndSecContext
pg_attribute_*
USAGE
on the java
language to
specific users or roles responsible for creating Java functions; see
“default USAGE
permssion” under Changes.INSTEAD OF
triggers, triggers on TRUNCATE
TriggerData
interface
has no new methods to recognize these cases (that is, no added
methods analogous to isFiredAfter
, isFiredByDelete
). For a method
expressly coded to be a TRUNCATE
trigger or an INSTEAD OF
trigger,
that is not a problem, but care should be taken when coding a trigger
method to handle more than one type of trigger, or creating triggers of
these new types that call a method developed pre-PL/Java-1.5.0. Such a
method could be called with a TriggerData
argument whose existing
isFired...
methods all return false
, likely to put the method on an
unexpected code path.
A later PL/Java version should introduce trigger interfaces that better support such evolution of PostgreSQL in a type-safe way.
PRE_PREPARE
, PRE_COMMIT
, PARALLEL_ABORT
, PARALLEL_PRE_COMMIT
, and PARALLEL_COMMIT
transaction callbacks, PRE_COMMIT
subtransaction callbacksIn a dump/restore, manual intervention can be needed if the users/roles
recorded as owners of jars are missing or have been renamed. A current
thread on pgsql-hackers
should yield a better solution for
a future release.
The install_jar
function installs a jar, optionally reading deployment
descriptors from the jar and executing the install actions they contain.
It is possible for those actions to load classes from the jar just installed.
(This would be unlikely if the install actions are limited to typical setup,
function/operator/datatype creation, but likely, if the install actions also
include basic function tests, or if the setup requirements are more
interesting.)
If, for any class in the jar, the first attempt to load that class is made
while resolving a function declared STABLE
or IMMUTABLE
, a
ClassNotFoundException
results. The cause is PostgreSQL's normal treatment of
a STABLE
or IMMUTABLE
function, which relies on a snapshot from the start of
the install_jar
query, when the jar was not yet installed. A workaround is to
ensure that the install actions cause each needed class to be loaded, such as
by calling a VOLATILE
function it supplies, before calling one that is
STABLE
or IMMUTABLE
. (One could even write install actions to declare a
needed function VOLATILE
before the first call and then redeclare it.)
This issue should be resolved as part of a broader rework of class loading in a future PL/Java release.
The changes to make PL/Java build under Java SE 6 and later, with version 4.0
and later of JDBC, involved providing the specified methods so
compilation would succeed, with real implementations for some, but for others
only stub versions that throw SQLFeatureNotSupportedException
if used.
Regrettably, there is nothing in the documentation indicating which methods
have real implementations and which do not; to create such a list would require
an audit of that code. If a method throws the exception when you call it, it's
one of the unimplemented ones.
Individual methods may be fleshed out with implementations as use cases arise
that demand them, but for a long-term roadmap, it seems more promising to
reduce the overhead of maintaining another JDBC implementation by sharing
code with pgjdbc
, as has been discussed on pljava-dev.
PL/Java does interconvert between PostgreSQL and Java exceptions, but with some loss of fidelity in the two directions. PL/Java code has some access to most fields of a PostgreSQL error data structure, but only through internal PL/Java API that is not expected to remain usable, and code written for PL/Java has never quite had first-class standing in its ability to generate exceptions as information-rich as those from PostgreSQL itself.
PL/Java in some cases generates the categorized SQLException
s introduced
with JDBC 4.0, and in other cases does not.
This area may see considerable change in a future release. Thoughts on logging is a preview of some of the considerations.
COPY
Although it is possible to create a PL/Java user-defined type that accepts
a type modifier (see the example), such a type will not yet be
handled by SQL COPY
or any other operation that requires the input
or
receive
function to handle the modifier. This is left for a future release.
PL/Java 1.5.0 owes its being to original creator Thomas Hallgren and many contributors:
Daniel Blanch Bataller,
Peter Brewer,
Frank Broda,
Chapman Flack,
Marty Frasier,
Bear Giles,
Christian Hammers,
Hal Hildebrand,
Robert M. Lefkowitz,
Eugenie V. Lyzenko,
Dos Moonen,
Asif Naeem,
Kenneth Olson,
Johann Oskarsson,
Thomas G. Peters,
Srivatsan Ramanujam,
Igal Sapir,
Jeff Shaw,
Rakesh Vidyadharan,
grunjol
,
mc-soi
.
Periods in PL/Java's development have been sponsored by EnterpriseDB.
In the 1.5.0 release cycle, multiple iterations of testing effort have been generously contributed by Kilobe Systems and by Pegasystems, Inc.
Notable changes in this release:
Bugs fixed:
Feature Requests:
Bugfixes:
Note: Does not compile with Java 6. Use JDK 1.5 or 1.4.
Compiles with PostgreSQL 8.4 and 9.0.
Connection.getCatalog() has been implemented.
Bugfixes:
Other commits:
For a multi-threaded pljava function we need to adjust stack_base_ptr before calling into the backend to avoid stack depth limit exceeded errors. Previously this was done only on query execution, but we need to do it on iteration of the ResultSet as well.
When creating a variable length data type, the code was directly assigning the varlena header length rather than going through an access macro. The header format changed for the 8.3 release and this manual coding was not noticed and changed accordingly. Use SET_VARSIZE to do this correctly.
Handle passed by value data types by reading and writing directly to the Datum rather than dereferencing it.
If the call to a type output function is the first pljava call in a session, we get a crash. The first pljava call results in a SPI connection being established and torn down. The type output function was allocating the result in the SPI memory context which gets destroyed prior to returning the data to the caller. Allocate the result in the correct context to survive function exit.
Clean up a warning about byteasend and bytearecv not having a prototype when building against 9.0 as those declarations are now in a new header file.
Warning! The recent postgresql security releases changed the API of a function that PL/Java uses. The source can be built against either version, but the binaries will only run against the version they were built against. The PL/Java binaries for 1.4.0 have all been built against the latest server releases (which you should be using anyway). If you are using an older you will have to build from source. The binary releases support: 8.3 - All versions. 8.2 - 8.2.6 and up. 8.1 - 8.1.11 and up. 8.0 - 8.0.15 and up.
This release is about type mapping and the creation of new types in PL/Java. An extensive effort has gone into making the PL/Java type system extremely flexible. Not only can you map arbitrary SQL data types to java classes. You can also create new scalar types completely in Java. Read about the Changes in version 1.3.
A much improved type mapping system that will allow you to:
The PL/Java 1.2.0 release is primarily targeted at the new PostgreSQL 8.1 but full support for 8.0.x is maintained. New features include support IN/OUT parameters, improved meta-data handling, and better memory management.
PL/Java 1.1.0 includes a lot of new features such as DatabaseMetaData
,
ResultSetMetaData
, language handlers for both trusted and untrusted language,
additional semantics for functions returning SETOF
, and simple ObjectPooling.
This release resolves a couple of important security issues. The most important one is perhaps that PL/Java now is a trusted language. See Security for more info. Filip Hrbek, now member of the PL/Java project, contributed what was needed to make this happen.
Today, after a long period of fine tuning, PL/Java 1.0.0 was finally released.