From dd81b161fc148f4f103c85db13e5d89c5f975ee7 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 11 Apr 2024 15:11:23 -0400 Subject: [PATCH 01/18] Document how to confirm Maven uses the right Java Issues #375 and #385 were closed as, essentially, pilot error (running Maven on a different version of Java than intended), but it would probably help to document that mvn --version does report the Java version Maven is using, so that can be easily checked. --- src/site/markdown/build/build.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/site/markdown/build/build.md b/src/site/markdown/build/build.md index d48103354..df5af711e 100644 --- a/src/site/markdown/build/build.md +++ b/src/site/markdown/build/build.md @@ -60,7 +60,13 @@ There is a "troubleshooting the build" section at the end of this page. mvn --version - succeeds. + succeeds. It reports not only the version of Maven, but the version of Java + that Maven has found and is using, which must be a Java version supported + for building PL/Java (see more on [version compatibility](versions.html)). + If Maven is not finding and using the intended Java version, the environment + variable `JAVA_HOME` can be set to point to the desired Java installation, + and `mvn --version` should then confirm that the Java being found is the + one intended. If you have more than one version installed of PostgreSQL, Java, or the compile/link tools, make sure the ones found on your search path are the From 081c93c5e94008500fa804b1b6e914ea9e6900ff Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 11 Apr 2024 17:39:30 -0400 Subject: [PATCH 02/18] Prune doc references to unsupported PG versions 17b7d7c (PR #450) dropped conditional code for PostgreSQL before 9.5, the oldest version to be supported by PL/Java 1.6.x. References to older PostgreSQL versions in the docs, however, were not pruned then. Remove those now. The docs also mentioned some paths and other details that changed with the new build system in 1.6; bring those up to date. Also, link to the page on pljava.policy from a couple more places that only touched on policy generally. These changes are not strictly about pre-9.5 PostgreSQL versions, but are details that were similarly overlooked in the PL/Java 1.5 to 1.6 transition. --- src/site/markdown/build/buildmsvc.md | 8 ---- src/site/markdown/build/package.md | 24 +++++++--- src/site/markdown/examples/saxon.md | 12 ----- src/site/markdown/install/install.md.vm | 30 ++++++------ src/site/markdown/install/locate.md.vm | 26 ++++++---- src/site/markdown/install/prepg92.md | 63 ------------------------- src/site/markdown/use/parallel.md | 4 +- src/site/markdown/use/use.md | 4 +- src/site/markdown/use/variables.md | 3 +- 9 files changed, 51 insertions(+), 123 deletions(-) delete mode 100644 src/site/markdown/install/prepg92.md diff --git a/src/site/markdown/build/buildmsvc.md b/src/site/markdown/build/buildmsvc.md index d9af41837..0e2dcb16b 100644 --- a/src/site/markdown/build/buildmsvc.md +++ b/src/site/markdown/build/buildmsvc.md @@ -21,9 +21,6 @@ PostgreSQL and PL/Java. Using a *newer* version of Visual Studio (including the Community 2015 version) will generally work, while older versions are more likely to be problematic. -* PostgreSQL 9.1 to 9.3 were built using Visual Studio 2010. -* PostgreSQL 9.4 was built using Visual Studio 2013. - ## Software Prerequisites 0. You will need an appropriate version of [Microsoft Visual Studio][msvc]. When @@ -50,11 +47,6 @@ likely to be problematic. an `INCLUDEDIR-SERVER` line, and list the directory it refers to. There should be a bunch of `*.h` files there. -0. OpenSSL headers: if using an EnterpriseDB PostgreSQL build older than 9.3, - these will be missing. They can be obtained from a 9.3 or later - EDB PostgreSQL build by copying the `include/openssl` directory and - its contents. - 0. You will need to install [Maven][mvn] and add it to your PATH so that mvn --version diff --git a/src/site/markdown/build/package.md b/src/site/markdown/build/package.md index e61c80d95..64eedde0c 100644 --- a/src/site/markdown/build/package.md +++ b/src/site/markdown/build/package.md @@ -78,11 +78,13 @@ shown in that link to disable the repacking of jars. The one part of PL/Java that could, if desired, be handled in the manner of Java libraries is `pljava-api`. This single jar file is needed on the classpath when compiling Java code that will be loaded into PL/Java in the database. -It is _not_ needed at the time that code will _run_. That means it could be -appropriate to treat `pljava-api` as a separate `-devel` package, if your -packaging guidelines encourage such a distinction. In that case, you would -exclude the `pljava-api` jar file from the main package, and produce a `-devel` -package that provides it. +That means it could be +appropriate to provide `pljava-api` in a separate `-devel` package, if your +packaging guidelines encourage such a distinction, where it would be installed +in the expected place for a conventional Java library. (The API jar must still +be included in the main package also, installed in the location where PostgreSQL +expects it. There may be no need, therefore, for the main package to depend on +the `-devel` package.) A `-devel` package providing `pljava-api` might appropriately follow java library packaging guidelines to ensure it appears on a developer's @@ -108,7 +110,7 @@ is the useful one to have in an installation target host's repository.) The PL/Java build does not automatically build javadocs. Those that go with `pljava-api` can be easily generated by running -`mvn --projects pljava-api javadoc:javadoc` to build them, then collecting +`mvn --projects pljava-api site` to build them, then collecting the `apidocs` subtree from `target/site`. They can be included in the same package as `pljava-api` or in a separate javadoc package, as your guidelines may require. @@ -126,7 +128,7 @@ been built first and installed into the build host's local Maven repository. Note that many of the examples do double duty as tests, as described in _confirming the build_ below. -When building for (and with) Java 8 or later and PostgreSQL 8.4 or later, +Unless they are not wanted, the XML examples based on the Saxon library should also be built, by adding `-Psaxon-examples` to the `mvn` command line. @@ -170,6 +172,14 @@ Some tests involving Unicode are skipped if the `server_encoding` is not `utf-8`, so it is best to run them in a server instance created with that encoding. +To simplify automated testing, the jar file that is the end product of a full +PL/Java source build contains a class that can serve as a PostgreSQL test +harness from Java's `jshell` script engine. It is documented [here][node], +and the continuous-integration scripts in PL/Java's own source-control +repository can be consulted as examples of its use. + +[node]: ../develop/node.html + ## Packaging the built items The end product of a full PL/Java source build is a jar file that functions as diff --git a/src/site/markdown/examples/saxon.md b/src/site/markdown/examples/saxon.md index 213ef9195..de4f72495 100644 --- a/src/site/markdown/examples/saxon.md +++ b/src/site/markdown/examples/saxon.md @@ -451,18 +451,6 @@ string (`\A\z` in Java syntax): That workaround would also cause the replacement to happen if the input string is completely empty to start with, which might not be what's wanted. -#### Syntax in older PostgreSQL versions - -The desugared syntax shown above can be used in PostgreSQL versions as old -as 9.5. In 9.4 and 9.3, the same syntax, but with `=>` replaced by `:=` for -the named parameters, can be used. The functions remain usable in still -earlier PostgreSQL versions, but with increasingly convoluted SQL syntax -needed to call them; before 9.3, for example, there was no `LATERAL` in a -`SELECT`, and a function could not refer to earlier `FROM` items. Before 9.0, -named-parameter notation can't be used in function calls. Before 8.4, the -functions would have to be declared without their `DEFAULT` clauses and the -`IntervalStyle` settings, and would not work with PostgreSQL interval values. - ### Minimizing startup time Saxon is a large library, and benefits greatly from precompilation into a diff --git a/src/site/markdown/install/install.md.vm b/src/site/markdown/install/install.md.vm index b34979fd2..ca56fa833 100644 --- a/src/site/markdown/install/install.md.vm +++ b/src/site/markdown/install/install.md.vm @@ -39,10 +39,9 @@ see the jar file there. __Upgrade installations__ below*. -*Not running PostgreSQL 9.1 or higher? Use +*Avoiding `CREATE EXTENSION` for some reason? Use `LOAD 'libpljava-so-${project.version}';` instead of the `CREATE EXTENSION` -command. (It works in later versions too, if you prefer it to -`CREATE EXTENSION`.) Using a Mac? Be sure to add `.bundle` at the end of the file name +command. Using a Mac? Be sure to add `.bundle` at the end of the file name in the `LOAD` command. Windows? Remove `lib` from the front. Something else? Keep reading.* @@ -187,7 +186,7 @@ Another approach is to save them to the server's configuration file. If you wish PL/Java to be available for all databases in a cluster, it may be more convenient to put the settings in the file than to issue `ALTER DATABASE` for several databases, but `pg_ctl reload` will be needed -to make changed settings effective. Starting with PostgreSQL 9.4, +to make changed settings effective. `ALTER SYSTEM` may be used as an alternative to editing the file. If you have several databases in the cluster and you favor the @@ -197,9 +196,6 @@ sure that `CREATE EXTENSION` just works, in any database where PL/Java is wanted. Different per-database settings can still be made if one database needs them. -For PostgreSQL releases [earlier than 9.2][pre92], the configuration file is -the _only_ way to make your settings persistent. - $h2 Upgrade installations PL/Java performs an upgrade installation if there is already an `sqlj` schema @@ -215,10 +211,12 @@ $h2 Usage permission Installation of PL/Java creates two "languages", `java` and `javau`. Functions that specify `LANGUAGE javau` can be created only by superusers, -and are subject to very few restrictions at runtime. Functions that specify +and PL/Java's default policy grants them some filesystem access. Functions that +specify `LANGUAGE java` can be created by any user or role that has been granted -`USAGE` permission `ON LANGUAGE java`. They run under a security manager that -denies access to the host filesystem. +`USAGE` permission `ON LANGUAGE java`. The default policy grants them no extra +permissions. The exact permissions granted in either case can be customized +in [`pljava.policy`][policy]. __Note: For implications when running on Java 17 or later, please see [JEP 411][jep411]__. @@ -237,12 +235,10 @@ $h2 Special topics Be sure to read these additional sections if: -* You are installing to [a PostgreSQL release earlier than 9.2][pre92] * You are installing on [a system using SELinux][selinux] * You are installing on [Mac OS X][osx] * You are installing on [Ubuntu][ubu] and the self-extracting jar won't work -[pre92]: prepg92.html [selinux]: selinux.html [osx]: ../build/macosx.html [ubu]: ../build/ubuntu.html @@ -254,9 +250,10 @@ $h3 Puzzling error message from `CREATE EXTENSION` ERROR: relation "see doc: do CREATE EXTENSION PLJAVA in new session" already exists -For PL/Java, `CREATE EXTENSION` (which works in PostgreSQL 9.1 and later) is a -wrapper around installation via `LOAD` (which works in all versions PL/Java -supports). A quirk of this arrangement is that PostgreSQL treats `LOAD` as a +For PL/Java, `CREATE EXTENSION` is a wrapper around installation via `LOAD` +(which was needed for PostgreSQL versions now of only historical interest, +and remains supported for cases where `CREATE EXTENSION` is too inflexible). +A quirk of this arrangement is that PostgreSQL treats `LOAD` as a no-op for the remainder of a session once the library has been loaded, so `CREATE EXTENSION pljava` works in a *fresh* session, but not in one where PL/Java's native code is already in place. @@ -283,7 +280,7 @@ Because PL/Java, by design, runs entirely in the backend process created for each connection to PostgreSQL, to configure it does not require any cluster-wide actions such as stopping or restarting the server, or editing the configuration file; any necessary settings can be made in SQL over -an ordinary connection (in PostgreSQL 9.2 and later, anyway). +an ordinary connection. _Caution: if you are installing a new, little-tested PL/Java build, be aware that in the unexpected case of a crash, the `postmaster` will kick other @@ -399,3 +396,4 @@ readable by the user running `postgres`, and set the `pljava.*` variables accordingly. [jep411]: https://github.com/tada/pljava/wiki/JEP-411 +[policy]: ../use/policy.html diff --git a/src/site/markdown/install/locate.md.vm b/src/site/markdown/install/locate.md.vm index 1564bafc0..58512c014 100644 --- a/src/site/markdown/install/locate.md.vm +++ b/src/site/markdown/install/locate.md.vm @@ -31,11 +31,9 @@ work with a `.jar` file no matter what. Relative to the root of the build tree, the jar file is found at -`pljava-packaging/target/pljava-${pgversion}-${naraol}.jar` +`pljava-packaging/target/pljava-${pgversion}.jar` -where `${pgversion}` resembles `pg9.4` and `${naraol}` is an -*architecture-os-linker* triple, for example `amd64-Linux-gpp` -or `amd64-Windows-msvc`. It contains these things: +where `${pgversion}` resembles `pg16`. The jar contains these things: `pljava/pkglibdir/libpljava-\${project.version}.so` (or `.dll`, etc.) : The architecture-dependent, native library portion of the PL/Java @@ -62,13 +60,24 @@ or `amd64-Windows-msvc`. It contains these things: : Various files scripting what `CREATE EXTENSION` or `ALTER EXTENSION ... UPDATE` really do. +`pljava/sysconfdir/pljava.policy` +: Policy file defining the Java permissions granted to the languages `java` + and `javaU`, to any custom language aliases, or to specific jars, as + described [here][policy]. + It could happen that future versions add more files in the jar before updating this page. Also, every jar file has a `MANIFEST.MF`, and this file also contains a `JarX.class` to make it self-extracting; these are not otherwise important to PL/Java. See the [installation page][inst] for how to control the self-extraction. +Another file, `Node.class`, present in this jar is also unimportant for +normal installation, but provides some facilities for automated testing, +as described [here][node]. + [examples]: ../examples/examples.html +[node]: ../develop/node.html +[policy]: ../use/policy.html Extract the needed files from this archive and place them in appropriate locations, then complete the [installation][inst]. @@ -112,11 +121,8 @@ $h3 The architecture-dependent PL/Java native library This is built by the `pljava-so` subproject. Its filename extension can depend on the operating system: `.so` on many systems, `.dll` on Windows, `.bundle` on Mac OS X / Darwin. Relative to the source root where the build was performed, it -is at the end of a long and redundant path that contains the project version -(twice), an "architecture-OS-linker" string (twice), and a build type -("plugin"), also twice. +is found in the `pljava-so/pljava-pgxs` directory. -An example, for version `${project.version}` and arch-os-linker of -`amd64-Linux-gpp` is (very deep breath): +An example for version `${project.version}` is: -`pljava-so/target/nar/pljava-so-${project.version}-amd64-Linux-gpp-plugin/lib/amd64-Linux-gpp/plugin/libpljava-so-${project.version}.so` +`pljava-so/pljava-pgxs/libpljava-so-${project.version}.so` diff --git a/src/site/markdown/install/prepg92.md b/src/site/markdown/install/prepg92.md deleted file mode 100644 index b1fb8fbff..000000000 --- a/src/site/markdown/install/prepg92.md +++ /dev/null @@ -1,63 +0,0 @@ -# Installation on PostgreSQL releases earlier than 9.2 - -In PostgreSQL releases 9.2 and later, PL/Java can be installed entirely -without disturbing the `postgresql.conf` file or reloading/restarting the -server: the configuration variables can be set interactively in a session -until PL/Java loads sucessfully, then saved with a simple -`ALTER DATABASE` _dbname_ `SET` _var_ `FROM CURRENT` for each setting -that had to be changed. - -Releases earlier than 9.2 are slightly less convenient. It is still possible -to work out the right settings in an interactive session, but once found, -the settings must be added to `postgresql.conf` to be persistent, and the -postmaster signalled (with `pg_ctl reload`) to pick up the new settings. - -Releases before 9.2 also require setting `custom_variable_classes` in -`postgresql.conf` to include the prefix `pljava`, and that assignment must -be earlier in the file than any settings of `pljava.*` variables. - -## Trying settings interactively - -It is still possible to do an exploratory session to find the variable settings -that work before touching `postgresql.conf` at all, but -the details are slightly different. - -In later PostgreSQL versions, you would typically use some `SET` commands -followed by a `LOAD` (followed, perhaps, by more `SET` commands unless you -always get things right on the first try). - -Before release 9.2, however, the order has to be `LOAD` first, which typically -will lead to an incompletely-started warning because the configuration settings -have not been made yet. _Then_, because the module has been loaded, -`pljava.*` variables will be recognized and can be set and changed until -PL/Java successfully loads, just as in the newer versions of PostgreSQL. - -Once working settings are found, edit `postgresql.conf`, make sure that -`custom_variable_classes` includes `pljava`, copy in the variable settings -that worked, and use `pg_ctl reload` to make the new settings effective. - -## But what if I want the load to fail and it doesn't? - -The procedure above relies on the way loading stops when the settings are not -right, giving you a chance to adjust them interactively. That turns out to be -a problem if there are previously-saved settings, or the original defaults, -that happen to *work* even if they are not the settings you want. In that case, -the `LOAD` command starts PL/Java right up, leaving you no chance in the -interactive session to change anything. - -To escape that behavior, there is one more very simple configuration variable, -`pljava.enable`. If it is `off`, `LOAD`ing PL/Java will always stop early and -allow you to set other variables before setting `pljava.enable` to `on`. - -To answer the hen-and-egg question of how to set `pljava.enable` to `off` -before loading the module, it _defaults_ to `off` on PostgreSQL releases -earlier than 9.2, so you will always have the chance to test your settings -interactively (and you will always have to set it explicitly `on` when -you are ready). - -If it is already `on` because of an earlier configuration saved in -`postgresql.conf`, it will be recognized in your interactive session and you -can set it `off` as needed. - -On later PostgreSQL releases with no such complications, it defaults to `on` -and can be ignored. diff --git a/src/site/markdown/use/parallel.md b/src/site/markdown/use/parallel.md index 861a621b4..11524d899 100644 --- a/src/site/markdown/use/parallel.md +++ b/src/site/markdown/use/parallel.md @@ -1,9 +1,7 @@ # PL/Java in parallel query or background worker With some restrictions, PL/Java can be used in [parallel queries][parq], from -PostgreSQL 9.6, and in some [background worker processes][bgworker] (as -introduced in PostgreSQL 9.3, though 9.5 or later is needed for support -in PL/Java). +PostgreSQL 9.6, and in some [background worker processes][bgworker]. [bgworker]: https://www.postgresql.org/docs/current/static/bgworker.html [parq]: https://www.postgresql.org/docs/current/static/parallel-query.html diff --git a/src/site/markdown/use/use.md b/src/site/markdown/use/use.md index 0f486d3b0..973717516 100644 --- a/src/site/markdown/use/use.md +++ b/src/site/markdown/use/use.md @@ -98,8 +98,8 @@ significant advantages to using the ### Parallel query -PostgreSQL 9.3 introduced [background worker processes][bgworker] -(though at least PostgreSQL 9.5 is needed for support in PL/Java), +PL/Java understands [background worker processes][bgworker] +in PostgreSQL 9.5 and later, and PostgreSQL 9.6 introduced [parallel query][parq]. For details on PL/Java in a background worker or parallel query, see diff --git a/src/site/markdown/use/variables.md b/src/site/markdown/use/variables.md index cb465c1fa..a3cf32841 100644 --- a/src/site/markdown/use/variables.md +++ b/src/site/markdown/use/variables.md @@ -40,8 +40,7 @@ These PostgreSQL configuration variables can influence PL/Java's operation: `pljava.enable` : Setting this variable `off` prevents PL/Java startup from completing, until - the variable is later set `on`. It can be useful when - [installing PL/Java on PostgreSQL versions before 9.2][pre92]. + the variable is later set `on`. It can be useful in some debugging settings. `pljava.implementors` : A list of "implementor names" that PL/Java will recognize when processing From 02bd1fe6bdcbdf94e99e919f59c075c0091d5057 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 11 Apr 2024 23:20:01 -0400 Subject: [PATCH 03/18] Update hello-world example POM plugin versions 5a21027 (PR #468) bumped the versions of Maven plugins in PL/Java's actual POMs, but not the versions in the example POM in the hello-world example. Bump those versions to match. --- src/site/markdown/use/hello.md.vm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/site/markdown/use/hello.md.vm b/src/site/markdown/use/hello.md.vm index e37ae7b00..fa3cb1c49 100644 --- a/src/site/markdown/use/hello.md.vm +++ b/src/site/markdown/use/hello.md.vm @@ -119,7 +119,7 @@ individual projects with shorter `pom.xml` files naming this as the parent. org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 9 @@ -127,7 +127,7 @@ individual projects with shorter `pom.xml` files naming this as the parent. org.apache.maven.plugins maven-jar-plugin - 2.6 + 3.3.0 From 46835bbb5a6ba22a488c6561e04fed85fca7059c Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 25 Apr 2024 17:57:43 -0400 Subject: [PATCH 04/18] Fix build output when no platform rules matched Addresses issue #485: anyone unlucky enough to build in an environment matching none of the probe methods for known platform rules would be faced with a JavaScript null-pointer exception instead of a message giving any clue where to look for the problem. --- pljava-so/pom.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pljava-so/pom.xml b/pljava-so/pom.xml index dc1df91ed..59ec48826 100644 --- a/pljava-so/pom.xml +++ b/pljava-so/pom.xml @@ -333,6 +333,7 @@ var os_name = java.lang.System.getProperty("os.name"); var implementation = null; var extension = null; + var pgxs = null; for (var index = 0; index < configuration.length; index ++) { if(configuration[index].probe(os_name)) { implementation = configuration[index]; @@ -342,10 +343,23 @@ } } - var pgxs = new org.postgresql.pljava.pgxs.AbstractPGXS(implementation); + if ( null !== implementation ) + pgxs = new org.postgresql.pljava.pgxs.AbstractPGXS(implementation); function execute() { + if ( null === pgxs ) + { + return plugin.exceptionWrap("\ +No compiling/linking rules were selected for this platform. Rules for \ +supported platforms can be found below 'var configuration = [' in \ +pljava-so/pom.xml. If you believe one of the supported platforms should have \ +matched, studying its probe: function may reveal why it did not match. \ +An expected environment variable might not be set, for example. If your \ +platform is not one of those supported, please consider adding a rule set \ +for it, and submitting a pull request so that PL/Java can support it.", true); + } + try { var files = utils.getFilesWithExtension(source_path, ".c"); From 5fefccef40c7f7f717500102a58fb8ddb666bd90 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Mon, 20 May 2024 21:31:16 -0400 Subject: [PATCH 05/18] macos-latest: now without PostgreSQL Per the 'roadmap' announced in actions/runner-images#9255, macos-latest now points to macos-14 as of Q2, and the macos-14 image does not supply any version of PostgreSQL. Bad news for the quick workflow that relies on the runner's installed version. Limit the MacOS CI to the macos-12 runner for now. That should hold until the image is removed in Q4. A workflow that installs a specified PostgreSQL version may be needed after that. Also, shorten the name of the workflow. It was too long to read in the online display of checks. And add a restrictive permissions: entry, which was missing, and its absence is not secure-by-default. --- .github/workflows/ci-runnerpg.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-runnerpg.yml b/.github/workflows/ci-runnerpg.yml index 641958e95..9eea358cd 100644 --- a/.github/workflows/ci-runnerpg.yml +++ b/.github/workflows/ci-runnerpg.yml @@ -3,7 +3,10 @@ # does not have a PostgreSQL version in the build matrix. The version that's # preinstalled is the version you get. -name: PL/Java CI with PostgreSQL version supplied by the runner +name: CI with runner-supplied PostgreSQL version + +permissions: + contents: read on: push: @@ -22,7 +25,7 @@ jobs: oscc: - os: ubuntu-latest cc: gcc - - os: macos-latest + - os: macos-12 cc: clang # - os: windows-latest # cc: msvc From b25fc7cd9f7edc0f6bf1b5581266049a5296cd8b Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 12 Jun 2024 15:39:07 -0400 Subject: [PATCH 06/18] Report PostgreSQL version found to build against --- .../org/postgresql/pljava/pgxs/PGXSUtils.java | 40 ++++++++++++++++++- pljava-so/pom.xml | 2 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java index eac54fcaa..585f2eab6 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2020-2024 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 @@ -32,6 +32,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Consumer; @@ -43,6 +44,8 @@ import java.util.regex.Pattern; import static java.lang.System.getProperty; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Stream.iterate; import static javax.script.ScriptContext.GLOBAL_SCOPE; /** @@ -314,6 +317,41 @@ public String getPgConfigProperty (String pgConfigCommand, pgConfigOutput.length() - System.lineSeparator().length()); } + /** + * Reports the detailed {@code PG_VERSION_STR} for the PostgreSQL version + * found to build against. + *

+ * This should be found as a C string literal after + * {@code #define PG_VERSION_STR} in + * includedir_server/{@code pg_config.h}. + *

+ * If the value can be found, it is logged at {@code info} level. Otherwise, + * the exception(s) responsible will be logged at {@code debug} level. + * @param includedir_server pass the result of a previous + * {@code getPgConfigProperty(..., "--includedir_server")} + */ + public void reportPostgreSQLVersion(String includedir_server) + { + Path pg_config_h = Paths.get(includedir_server, "pg_config.h"); + try + { + log.info( + defaultCharsetDecodeStrict(Files.readAllBytes(pg_config_h)) + .replaceFirst( + "(?ms).*^#define\\s++PG_VERSION_STR\\s++(?-s:(.++))$.*+", + "Found $1") + ); + } + catch ( IOException | IndexOutOfBoundsException e ) + { + log.debug( + "in reportPostgreSQLVersion: " + + iterate(e, Objects::nonNull, Throwable::getCause) + .map(Object::toString).collect(joining("\nCaused by: ")) + ); + } + } + /** * Returns a ProcessBuilder with suitable defaults and arguments added from * input function. diff --git a/pljava-so/pom.xml b/pljava-so/pom.xml index 59ec48826..368b30afc 100644 --- a/pljava-so/pom.xml +++ b/pljava-so/pom.xml @@ -66,6 +66,8 @@ Paths.get(base_dir_path, "..", "pljava", "target", "javah-include").toString() )); + utils.reportPostgreSQLVersion(includedir_server); + var base_defines = new HashMap(); base_defines.put("PLJAVA_SO_VERSION", project.parent.version); if ( cc.equalsIgnoreCase("gcc") ) From 00639c656d8489c4d9f0a5e1d0b38ce5dbce2bd3 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 12 Jun 2024 15:42:17 -0400 Subject: [PATCH 07/18] Include command/arguments in Maven debug output For the Windows cases, log the arguments before applying the forWindowsCRuntime() transformation (but indicating, in the message, that it will be applied). Eliminate the debug logging of the script text in ScriptingMojo and ReportScriptingMojo; Maven itself, when producing debug output, will have dumped that to the log perhaps twice already (when reading the configuration, and when configuring the mojo). --- .../org/postgresql/pljava/pgxs/PGXSUtils.java | 16 ++++++++++++++-- .../pljava/pgxs/ReportScriptingMojo.java | 3 +-- .../postgresql/pljava/pgxs/ScriptingMojo.java | 3 +-- pljava-so/pom.xml | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java index 585f2eab6..1c33c345b 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java @@ -159,9 +159,21 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) context.setAttribute("buildPaths", (Function, Map>) this::buildPaths, GLOBAL_SCOPE); + context.setAttribute("runCommand", - (ToIntFunction) this::runCommand, - GLOBAL_SCOPE); + (ToIntFunction) b -> + { + log.debug("To run: " + b.command()); + return runCommand(b); + }, GLOBAL_SCOPE); + + context.setAttribute("runWindowsCRuntimeCommand", + (ToIntFunction) b -> + { + log.debug("To run (needs WindowsCRuntime transformation): " + + b.command()); + return runCommand(forWindowsCRuntime(b)); + }, GLOBAL_SCOPE); /* * Also provide a specialized method useful for a script that may diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java index f37577fd4..868bcaaaf 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2020-2024 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 @@ -70,7 +70,6 @@ private void setReportScript() utils = new PGXSUtils(project, getLog()); ScriptEngine engine = utils.getScriptEngine(script); String scriptText = script.getValue(); - getLog().debug(scriptText); engine.eval(scriptText); reportScript = ((Invocable)engine).getInterface(ReportScript.class); } diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java index be5e7c0bc..289d707bf 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2020-2024 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 @@ -66,7 +66,6 @@ public void execute () throws MojoExecutionException, MojoFailureException utils = new PGXSUtils(project, getLog()); String scriptText = script.getValue(); ScriptEngine engine = utils.getScriptEngine(script); - getLog().debug(scriptText); engine.getContext().setAttribute("session", session, ScriptContext.GLOBAL_SCOPE); diff --git a/pljava-so/pom.xml b/pljava-so/pom.xml index 368b30afc..ab7c30bf6 100644 --- a/pljava-so/pom.xml +++ b/pljava-so/pom.xml @@ -241,7 +241,7 @@ l.addAll(files); }); compileProcess.directory(output_dir.toFile()); - return runCommand(utils.forWindowsCRuntime(compileProcess)); + return runWindowsCRuntimeCommand(compileProcess); }, link : function(cc, flags, files, target_path) { @@ -258,7 +258,7 @@ l.addAll(of("-L" + pkglibdir, "-Bdynamic", "-lpostgres")); }); linkingProcess.directory(target_path.toFile()); - return runCommand(utils.forWindowsCRuntime(linkingProcess)); + return runWindowsCRuntimeCommand(linkingProcess); } }, From 96a1690162f23a1543b6225a0a8c7cb90d2ec65c Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 12 Jun 2024 15:42:26 -0400 Subject: [PATCH 08/18] Javadoc/whitespace cleanup and slight refactoring As dubious as combining any refactoring with a Javadoc/whitespace cleanup may be, it was preferable to writing new Javadoc to try to explain why it was factored as it was (with some script engine bindings being added in PGXSUtils.getScriptEngine and others in ScriptingMojo.execute, especially as that didn't match where the underlying methods lived). Adjusts javadoc options to include package-access types and members in pljava-pgxs, as some of those are exported to the script engine and ought to be documented. --- pljava-pgxs/pom.xml | 2 + .../postgresql/pljava/pgxs/AbstractPGXS.java | 73 ++++-- .../org/postgresql/pljava/pgxs/PGXSUtils.java | 232 ++++++++++++------ .../pljava/pgxs/ReportScriptingMojo.java | 104 ++++---- .../postgresql/pljava/pgxs/ScriptingMojo.java | 116 ++++----- 5 files changed, 314 insertions(+), 213 deletions(-) diff --git a/pljava-pgxs/pom.xml b/pljava-pgxs/pom.xml index b3d3de753..c53ff1e22 100644 --- a/pljava-pgxs/pom.xml +++ b/pljava-pgxs/pom.xml @@ -170,6 +170,8 @@ function executeReport(report, locale) */ "-locale", locale.toString(), "-quiet", + "--show-members", "package", + "--show-types", "package", /* * Options that are passed to the doclet. */ diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/AbstractPGXS.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/AbstractPGXS.java index 642e06753..09d2a6511 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/AbstractPGXS.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/AbstractPGXS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2020-2024 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 @@ -21,33 +21,59 @@ import java.util.stream.Collectors; /** - * Class to act as a blueprint for platform specific build configurations in - * pljava-so/pom.xml + * Class to act as a blueprint for platform-specific build configurations in a + * {@code pom.xml}. + *

+ * A {@code scripted-goal} configuration in the POM should contain a script + * that somehow selects and supplies a concrete implementation of this abstract + * class. + *

+ * In {@code pljava-so/pom.xml}, a block of {@code application/javascript} is + * supplied that contains a {@code configuration} array of JS objects, each of + * which has a {@code name} entry, a {@code probe} function returning true on + * some supported platform, and the necessary functions to serve as an + * implementation of this class. The script selects one whose probe succeeds + * and, using JSR 223 magic, makes an instance of this class from it. + *

+ * The script can make use of convenience methods implemented here, and also + * a number of items (such as a {@code runCommand} function) presupplied in the + * script engine's binding scope by + * {@link PGXSUtils#getScriptEngine PGXSUtils.getScriptEngine} and by + * {@link ScriptingMojo#execute ScriptingMojo.execute}). */ public abstract class AbstractPGXS { - /** - * Add instructions for compiling the pljava-so C files on your platform - * by implementing this method in your configuration block. + * Performs platform-specific compilation of a set of {@code .c} files with + * the specified compiler, target path, includes, defines, and flags. + *

+ * An implementation should make any needed adjustments to the includes, + * defines, and flags, format everything appropriately for the compiler + * in question, execute it, and return an exit status (zero on success). */ - public abstract int compile(String compiler, List files, Path targetPath, - List includes, Map defines, - List flags); + public abstract int compile( + String compiler, List files, Path targetPath, + List includes, Map defines, List flags); /** - * Add instructions for linking and producing the pljava-so shared library - * artifact on your platform by implementing this method in your - * configuration block. + * Performs platform-specific linking of a set of object files with + * the specified linker and flags, to produce the shared object at the + * specified target path. + *

+ * An implementation should make any needed adjustments to the flags, format + * everything appropriately for the linker in question, execute it, and + * return an exit status (zero on success). */ - public abstract int link(String linker, List flags, List files, Path targetPath); + public abstract int link( + String linker, List flags, List files, Path targetPath); /** * Returns a list with all items prefixed with correct include flag symbol. * * This is the default implementation for formatting the list of includes, - * and prefixes the includes with -I. For compilers like MSVC that require - * different symbols, override this method in your configuration block. + * and prefixes the includes with {@code -I}. For compilers like MSVC that + * require different formatting, the script should supply an overriding + * implementation of this method. */ public List formatIncludes(List includesList) { @@ -56,12 +82,13 @@ public List formatIncludes(List includesList) } /** - * Returns a list with all defines prefixed correctly. + * Returns a list with all defines represented correctly. * - * This is the default implementation for formatting the list of defines. - * Each item is prefixed with -D. If the define is associated with a value, - * adds equal symbol also followed by the value. If your linker expects a - * different format, override the method in your configuration block. + * This is the default implementation for formatting the map of defines. + * Each item is prefixed with {@code -D}. If the name is mapped to a + * non-null value, an {@code =} is appended, followed by the value. For + * compilers like MSVC that require different formatting, the script should + * supply an overriding implementation of this method. */ public List formatDefines(Map definesMap) { @@ -76,11 +103,11 @@ public List formatDefines(Map definesMap) } /** - * Returns the input pg_config property as a list of individual flags split - * at whitespace, except when quoted, and the quotes removed. + * Returns the requested {@code pg_config} property as a list of individual + * flags split at whitespace, except when quoted, and the quotes removed. *

* The assumed quoting convention is single straight quotes around regions - * to be protected, which do not have to be the entire argument. This method + * to be protected, which do not have to be an entire argument. This method * doesn't handle a value that contains a single quote as content; * the intended convention for that case doesn't seem to be documented, and * PostgreSQL's own build breaks in such a case, so there is little need, diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java index 1c33c345b..bb216106b 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/PGXSUtils.java @@ -46,7 +46,7 @@ import static java.lang.System.getProperty; import static java.util.stream.Collectors.joining; import static java.util.stream.Stream.iterate; -import static javax.script.ScriptContext.GLOBAL_SCOPE; +import static javax.script.ScriptContext.ENGINE_SCOPE; /** * Utility methods to simplify and hide the bland implementation details @@ -77,11 +77,47 @@ public PGXSUtils (MavenProject project, Log log) } /** - * Returns a ScriptEngine with some basic utilities for scripting. + * Returns a ScriptEngine with some useful engine-scoped bindings + * supplied for the convenience of the script. + *

+ * These bindings are placed in the engine's scope: + *

+ *
project
The Maven project instance + *
utils
This object + *
error, warn, info, debug
Consumers of {@link CharSequence} that + * will log a message through Maven with the corresponding severity + *
diag
A BiConsumer of {@link Diagnostic.Kind} and a + * {@link CharSequence}, to log a message through Maven with its severity + * determined by the {@code Diagnostic.Kind}. + *
runCommand
A function from {@link ProcessBuilder} to {@code int} + * that will run the specified command and return its exit status. The + * command and arguments are first logged through Maven at {@code debug} + * level. + *
runWindowsCRuntimeCommand
A function from {@link ProcessBuilder} + * to {@code int} that will apply the + * {@link #forWindowsCRuntime forWindowsCRuntime} transformation to the + * arguments and then run the specified command and return its exit + * status. The command and arguments are first logged through Maven at + * {@code debug} level, and before the transformation is applied. + *
buildPaths
Separates a list of pathnames into those that belong + * on a class path and those that belong on a module path. + *
getPgConfigProperty
Returns the output of {@code pg_config} when + * run with the given single argument. + *
isProfileActive
Predicate indicating whether a named Maven profile + * is active. + *
quoteStringForC
Transforms a {@code String} into a C string + * literal representing it. + *
resolve
A direct reference to the {code Path.resolve} overload + * with {@code Path} parameter types, to work around some versions of + * graaljs being unable to determine which overload a script intends. + *
setProjectProperty
Sets a property of the Maven project to a + * supplied value. + *
* * @param script the script block element in the configuration block of the - * plugin in the project - * @return ScriptEngine based on the engine and mime type provided in the + * plugin in the project object model. Its {@code mimetype} or + * {@code engine} attribute will be used to find a suitable engine + * @return ScriptEngine based on the engine and/or MIME type provided in the * script block */ ScriptEngine getScriptEngine(PlexusConfiguration script) @@ -111,8 +147,9 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) " mimetype defined."); else { - ScriptEngineManager manager = new ScriptEngineManager( - new ScriptEngineLoader(ScriptingMojo.class.getClassLoader())); + ScriptEngineManager manager = + new ScriptEngineManager(new ScriptEngineLoader( + ScriptingMojo.class.getClassLoader())); if (engineName != null) engine = manager.getEngineByName(engineName); @@ -137,6 +174,15 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) log.error(e); } + ScriptContext context = engine.getContext(); + + /* + * Give the script convenient access to the Maven project and this + * object. + */ + context.setAttribute("project", project, ENGINE_SCOPE); + context.setAttribute("utils", this, ENGINE_SCOPE); + /* * Give the script some convenient methods for logging to the Maven log. * Only supply the versions with one CharSequence parameter, in case of @@ -144,36 +190,14 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) * have another way to get access to the Log instance and use its other * methods; these are just for convenience. */ - ScriptContext context = engine.getContext(); - context.setAttribute("debug", - (Consumer) log::debug, GLOBAL_SCOPE); context.setAttribute("error", - (Consumer) log::error, GLOBAL_SCOPE); + (Consumer) log::error, ENGINE_SCOPE); context.setAttribute("warn", - (Consumer) log::warn, GLOBAL_SCOPE); + (Consumer) log::warn, ENGINE_SCOPE); context.setAttribute("info", - (Consumer) log::info, GLOBAL_SCOPE); - context.setAttribute("isProfileActive", - (Function) this::isProfileActive, - GLOBAL_SCOPE); - context.setAttribute("buildPaths", - (Function, Map>) this::buildPaths, - GLOBAL_SCOPE); - - context.setAttribute("runCommand", - (ToIntFunction) b -> - { - log.debug("To run: " + b.command()); - return runCommand(b); - }, GLOBAL_SCOPE); - - context.setAttribute("runWindowsCRuntimeCommand", - (ToIntFunction) b -> - { - log.debug("To run (needs WindowsCRuntime transformation): " + - b.command()); - return runCommand(forWindowsCRuntime(b)); - }, GLOBAL_SCOPE); + (Consumer) log::info, ENGINE_SCOPE); + context.setAttribute("debug", + (Consumer) log::debug, ENGINE_SCOPE); /* * Also provide a specialized method useful for a script that may @@ -199,14 +223,62 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) break; } } - ), GLOBAL_SCOPE); + ), ENGINE_SCOPE); /* - * Give the script convenient access to the Maven project and this - * object. + * Supply a runCommand function to which the script can supply + * a ProcessBuilder after configuring it as needed, and an alias + * runWindowsCRuntimeCommand that does the same, but applies the + * forWindowsCRuntime transformation to the ProcessBuilder's arguments + * first. Two aliases are used so that the command arguments can be + * logged (at debug level) in either case, and before the transformation + * is applied, in the Windows case. */ - context.setAttribute("project", project, GLOBAL_SCOPE); - context.setAttribute("utils", this, GLOBAL_SCOPE); + context.setAttribute("runCommand", + (ToIntFunction) b -> + { + log.debug("To run: " + b.command()); + return runCommand(b); + }, ENGINE_SCOPE); + + context.setAttribute("runWindowsCRuntimeCommand", + (ToIntFunction) b -> + { + log.debug("To run (needs WindowsCRuntime transformation): " + + b.command()); + return runCommand(forWindowsCRuntime(b)); + }, ENGINE_SCOPE); + + /* + * Convenient access to some other methods provided here. + */ + context.setAttribute("buildPaths", + (Function, Map>) this::buildPaths, + ENGINE_SCOPE); + + context.setAttribute("getPgConfigProperty", + (Function) p -> + { + try + { + return getPgConfigProperty(p); + } + catch ( Exception e ) + { + log.error(e); + return null; + } + }, ENGINE_SCOPE); + + context.setAttribute("isProfileActive", + (Function) this::isProfileActive, + ENGINE_SCOPE); + + context.setAttribute("quoteStringForC", + (Function) this::quoteStringForC, ENGINE_SCOPE); + + context.setAttribute("setProjectProperty", + (BiConsumer)this::setProjectProperty, ENGINE_SCOPE); /* * A graaljs bug (graalvm/graaljs#254) means that when you are passing @@ -215,7 +287,7 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) * (Path,Path) function to make it a little more blindingly obvious. */ context.setAttribute("resolve", (BinaryOperator)Path::resolve, - GLOBAL_SCOPE); + ENGINE_SCOPE); return engine; } @@ -225,7 +297,7 @@ ScriptEngine getScriptEngine(PlexusConfiguration script) * escaped where appropriate using the C conventions. * * @param s string to be escaped - * @return a C compatible String enclosed in double quotes + * @return a C string literal representing s */ public String quoteStringForC (String s) { @@ -276,7 +348,8 @@ else if (-1 != m.start(2)) // things with specific escapes } /** - * Returns the string decoded from input bytes using default platform charset. + * Returns the string decoded from input bytes using default platform + * charset. * * @param bytes byte array to be decoded * @return string decoded from input bytes @@ -291,30 +364,27 @@ public String defaultCharsetDecodeStrict (byte[] bytes) } /** - * Returns the output, decoded using default platform charset, of the input - * command executed with the input argument. + * Returns the output, decoded using default platform charset, of the + * {@code pg_config} command executed with the single supplied argument. *

- * If the input parameter {@code pgConfigCommand} is empty or null, - * {@code pg_config} is used as the default value. If multiple version of - * {@code pg_config} are available or {@code pg_config} is not present on - * the path, consider passing an absolute path to {@code pg_config}. It is - * also recommended that only a single property be passed at a time. + * If multiple versions of {@code pg_config} are available or + * {@code pg_config} is not present on the path, the system property + * {@code pgsql.pgconfig} should be set as an absolute path to the desired + * executable. * - * @param pgConfigCommand pg_config command to execute * @param pgConfigArgument argument to be passed to the command * @return output of the input command executed with the input argument * @throws IOException if unable to read output of the command * @throws InterruptedException if command does not complete successfully */ - public String getPgConfigProperty (String pgConfigCommand, - String pgConfigArgument) + public String getPgConfigProperty (String pgConfigArgument) throws IOException, InterruptedException { - if (pgConfigCommand == null || pgConfigCommand.isEmpty()) - pgConfigCommand = "pg_config"; + String pgConfigCommand = + System.getProperty("pgsql.pgconfig", "pg_config"); - ProcessBuilder processBuilder = new ProcessBuilder(pgConfigCommand, - pgConfigArgument); + ProcessBuilder processBuilder = + new ProcessBuilder(pgConfigCommand, pgConfigArgument); processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); Process process = processBuilder.start(); process.getOutputStream().close(); @@ -365,8 +435,19 @@ public void reportPostgreSQLVersion(String includedir_server) } /** - * Returns a ProcessBuilder with suitable defaults and arguments added from - * input function. + * Sets the value of a property for the current project. + * + * @param property key to use for property + * @param value the value of property to set + */ + public void setProjectProperty (String property, String value) + { + project.getProperties().setProperty(property, value); + } + + /** + * Returns a ProcessBuilder with suitable defaults and arguments added + * by the supplied consumer. * * @param consumer function which adds arguments to the ProcessBuilder * @return ProcessBuilder with input arguments and suitable defaults @@ -408,7 +489,7 @@ public int runCommand(ProcessBuilder processBuilder) * Returns true if the profile with given name exists and is active, false * otherwise. *

- * A warning is logged if the no profile with the input name exists in the + * A warning is logged if no profile with the input name exists in the * current project. * * @param profileName name of profile to check @@ -431,8 +512,13 @@ public boolean isProfileActive(String profileName) } /** - * Returns a map with two elements with {@code classpath} and {@code modulepath} - * as keys and their joined string paths as the respective values. + * Returns a two-element map with with {@code classpath} and + * {@code modulepath} as keys and their joined string paths as the + * respective values. + *

+ * For each supplied element, + * {@link #shouldPlaceOnModulepath shouldPlaceOnModulepath} is used to + * determine which path the element is added to. * * @param elements list of elements to build classpath and modulepath from * @return a map containing the {@code classpath} and {@code modulepath} @@ -449,7 +535,8 @@ public Map buildPaths(List elements) { if (element.contains(pathSeparator)) log.warn(String.format("cannot add %s to path because " + - "it contains path separator %s", element, pathSeparator)); + "it contains path separator %s", + element, pathSeparator)); else if (shouldPlaceOnModulepath(element)) modulepathElements.add(element); else @@ -469,11 +556,13 @@ else if (shouldPlaceOnModulepath(element)) * Returns true if the element should be placed on the module path. *

* An file path element should be placed on the module path if it points to - * 1) a directory with a top level {@code module-info.class} file - * 2) a {@code JAR} file having a {@code module-info.class} entry or the + *

    + *
  1. a directory with a top level {@code module-info.class} file + *
  2. a {@code JAR} file having a {@code module-info.class} entry or the * {@code Automatic-Module-Name} as a manifest attribute + *
* - * @param filePath the filepath to check whether is a module + * @param filePath the filepath to check * @return true if input path should go on modulepath, false otherwise * @throws IOException any thrown by the underlying file operations */ @@ -504,9 +593,10 @@ public boolean shouldPlaceOnModulepath(String filePath) } /** - * Returns the list of files with given extension in the input directory. + * Returns a list of files with given extension in and below + * the input directory. * - * @param sourceDirectory to list files inside + * @param sourceDirectory root of the tree of files to list * @param extension to filter files to be selected * @return list of strings of absolute paths of files */ @@ -529,9 +619,9 @@ public List getFilesWithExtension(Path sourceDirectory, } /* - * The same method is duplicated in pljava-packaging/Node.java . While making - * changes to this method, review the other occurrence also and replicate the - * changes there if desirable. + * This method is duplicated in pljava-packaging/Node.java. If making + * changes to this method, review the other occurrence also and replicate + * the changes there if desirable. */ /** * Adjust the command arguments of a {@code ProcessBuilder} so that they @@ -539,7 +629,7 @@ public List getFilesWithExtension(Path sourceDirectory, * the argument parsing algorithm of the usual C run-time code, when it is * known that the command will not be handled first by {@code cmd}. *

- * This transformation must account for the way the C runtime will + * This transformation must account for the way the Windows C runtime will * ultimately parse the parameters apart, and also for the behavior of * Java's runtime in assembling the command line that the invoked process * will receive. @@ -548,7 +638,7 @@ public List getFilesWithExtension(Path sourceDirectory, * should result from parsing. * @return The same ProcessBuilder, with the argument list rewritten as * necessary to produce the original list as a result of Windows C runtime - * parsing, + * parsing. * @throws IllegalArgumentException if the ProcessBuilder does not have at * least the first command element (the executable to run) * @throws UnsupportedOperationException if the arguments passed, or system diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java index 868bcaaaf..4990daa1a 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ReportScriptingMojo.java @@ -27,13 +27,14 @@ import java.util.Locale; /** - * Maven plugin goal to use JavaScript for configuring + * Maven plugin goal to use JavaScript (or another JSR 223 script engine) + * for configuring * {@link org.apache.maven.reporting.MavenReport} during the * {@link LifecyclePhase#SITE}. *

- * This plugin goal intends to allow the use of JavaScript during {@code SITE} + * This plugin goal intends to allow the use of scripting in the {@code SITE} * lifecycle phase with the help of {@link ReportScript}. The motivation behind - * this is the inability to use Maven AntRun during {@code SITE} phase. + * this is the inability to use Maven AntRun in the {@code SITE} phase. */ @Mojo(name = "scripted-report") @Execute(phase = LifecyclePhase.NONE) @@ -80,15 +81,17 @@ private void setReportScript() } /** - * Returns the path relative to the target site directory of the this report. + * Queries the script for the report output path relative to the target site + * directory. + *

* This value will be used by {@code Maven} to provide a link to the report * from {@code index.html}. *

* Calls {@code setReportScript} to ensure that the instance of * {@link ReportScript} is available. Invokes - * {@code fun getOutputName(report)} defined in the JavaScript snippet - * associated with the report. No default implementation is provided. User - * must implement the method in JavaScript. + * {@code getOutputName(report)} defined by the script snippet + * associated with the report. No default implementation is provided; the + * script must implement this method. */ @Override public String getOutputName () @@ -98,15 +101,15 @@ public String getOutputName () } /** - * Returns false if this report will produce output through a - * supplied {@link Sink}, true if it is 'external', producing its output - * some other way. + * Queries the script to return false if this report will produce output + * through a supplied {@link Sink}, or true if it is 'external', producing + * its output some other way. *

* Calls {@code setReportScript} to ensure that the instance of * {@link ReportScript} is available. Invokes - * {@code fun isExternalReport(report)} if defined in the javascript - * snippet associated with the report. Otherwise, the {@code super} - * implementation is invoked effectively. + * {@code isExternalReport(report)} if defined in the script + * snippet associated with the report. Otherwise, the implementation + * inherited by this class is effectively invoked. */ @Override public boolean isExternalReport () @@ -116,14 +119,14 @@ public boolean isExternalReport () } /** - * Returns the name of this report used by {@code Maven} for displaying in - * {@code index.html}. + * Queries the script for the name of this report to be used + * by {@code Maven} for display in {@code index.html}. *

* Calls {@code setReportScript} to ensure that the instance of * {@link ReportScript} is available. Invokes - * {@code fun getName(report, locale)} defined in the javascript - * snippet associated with the report. No default implementation is provided - * . User must implement the method in javascript. + * {@code getName(report, locale)} defined by the script + * snippet associated with the report. No default implementation is + * provided; the script must implement this method. */ @Override public String getName (Locale locale) @@ -133,14 +136,14 @@ public String getName (Locale locale) } /** - * Returns the description of this report, used by {@code Maven} to display - * report description in {@code index.html}. + * Queries the script for the description of this report, to be used + * by {@code Maven} for display in {@code index.html}. *

* Calls {@code setReportScript} to ensure that the instance of * {@link ReportScript} is available. Invokes - * {@code fun getDescription(report, locale)} defined in the javascript - * snippet associated with the report. No default implementation is provided - * . User must implement the method in javascript. + * {@code getDescription(report, locale)} defined in the script + * snippet associated with the report. No default implementation is + * provided; the script must implement this method. */ @Override public String getDescription (Locale locale) @@ -150,14 +153,15 @@ public String getDescription (Locale locale) } /** - * Returns the category name of this report, used by {@code Maven} to display - * the report under the correct in {@code index.html}. + * Queries the script for the category name of this report, used + * by {@code Maven} to place the report under the correct heading + * in {@code index.html}. *

* Calls {@code setReportScript} to ensure that the instance of * {@link ReportScript} is available. Invokes - * {@code fun getCategoryName(report)} if defined in the javascript - * snippet associated with the report. Otherwise, the {@code super} - * implementation is invoked effectively. + * {@code getCategoryName(report)} if defined by the script + * snippet associated with the report. Otherwise, the implementation + * inherited by this class is effectively invoked. */ @Override public String getCategoryName () @@ -167,13 +171,13 @@ public String getCategoryName () } /** - * Returns true if a report can be generated, false otherwise. + * Queries the script as to whether this report can be generated. *

* Calls {@code setReportScript} to ensure that the instance of * {@link ReportScript} is available. Invokes - * {@code fun canGenerateReport(report)} if defined in the javascript - * snippet. Otherwise, the {@code super} implementation is invoked - * effectively. + * {@code canGenerateReport(report)} if defined by the script + * snippet. Otherwise, the implementation inherited by this class is + * effectively invoked. */ @Override public boolean canGenerateReport () @@ -186,9 +190,9 @@ public boolean canGenerateReport () * {@inheritDoc} *

* Calls {@code setReportScript} to ensure that the instance of - * {@link ReportScript} is available. Invokes the - * {@code fun executeReport(report, locale)} with the instance of the - * current report. + * {@link ReportScript} is available. Invokes its + * {@code executeReport(report, locale)}, passing this instance and + * the supplied locale. */ @Override protected void executeReport (Locale locale) throws MavenReportException @@ -229,7 +233,7 @@ public String getOutputEncoding () /** * Default implementation for * {@link ReportScript#isExternalReport(ReportScriptingMojo)}. Invoked if - * {@code fun isExternalReport(report)} is not defined in the javascript + * {@code isExternalReport(report)} is not defined in the script * snippet associated with the report. */ boolean isExternalReportDefault () @@ -240,7 +244,7 @@ boolean isExternalReportDefault () /** * Default implementation of * {@link ReportScript#getCategoryName(ReportScriptingMojo)}. Invoked if - * {@code fun getCategoryName(report)} is not defined in the javascript + * {@code getCategoryName(report)} is not defined in the script * snippet associated with the report. */ String getCategoryNameDefault () @@ -251,7 +255,7 @@ String getCategoryNameDefault () /** * Default implementation of * {@link ReportScript#canGenerateReport(ReportScriptingMojo)}. Invoked if - * {@code fun canGenerateReport(report)} is not defined in the javascript + * {@code canGenerateReport(report)} is not defined in the script * snippet associated with the report. */ boolean canGenerateReportDefault () @@ -263,16 +267,17 @@ boolean canGenerateReportDefault () * Wraps the input object in a {@link MavenReportException}. * * The exception returned is constructed as follows: - * 1) If {@code object} is null, the exception message indicates the same. - * 2) If {@code object} is already a {@link MavenReportException}, return it - * as is. - * 3) If {@code object} is any other {@link Throwable}, set it as the cause - * for the exception. - * {@link MavenReportException} with {@code object} as its cause. - * 4) If {@code object} is a {@link String}, set it as the message of the - * exception. - * 5) For all other case, the message of the exception is set in this format - * , Class Name of object: String representation of object. + *

    + *
  • If {@code object} is null, the exception message indicates the same. + *
  • If {@code object} is already a {@link MavenReportException}, it is + * returned as is. + *
  • If {@code object} is any other {@link Throwable}, it is used as + * the wrapping exception's cause. + *
  • If {@code object} is a {@link String}, it is used as + * the wrapping exception's message. + *
  • If it is any other object, the wrapping exception's message is set in + * this format: Class mame of object: String representation of object. + *
* * @param object to wrap in MavenReportException * @return object wrapped inside a {@link MavenReportException} @@ -286,7 +291,8 @@ else if (object instanceof MavenReportException) else if (object instanceof Throwable) { Throwable t = (Throwable) object; - MavenReportException exception = new MavenReportException(t.getMessage()); + MavenReportException exception = + new MavenReportException(t.getMessage()); exception.initCause(t); return exception; } diff --git a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java index 289d707bf..489f679bd 100644 --- a/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java +++ b/pljava-pgxs/src/main/java/org/postgresql/pljava/pgxs/ScriptingMojo.java @@ -25,18 +25,20 @@ import org.codehaus.plexus.configuration.PlexusConfiguration; import javax.script.Invocable; -import javax.script.ScriptContext; import javax.script.ScriptEngine; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; +import static javax.script.ScriptContext.ENGINE_SCOPE; + /** - * Maven plugin goal to use JavaScript during any of build lifecycle phases. + * Maven plugin goal to use JavaScript (or another JSR 223 script engine) + * during any of build lifecycle phases. *

- * The Mojo provides a limited subset of the functionality provided Maven AntRun - * Plugin. This is intentional to simplify usage as this maven plugin is - * specifically targeted at building Pl/Java native code. + * The Mojo provides a limited subset of the functionality of the Maven AntRun + * Plugin. This is intentional to simplify usage, as this Maven plugin is + * specifically targeted at building PL/Java native code. */ @Mojo(name = "scripted-goal", defaultPhase = LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.TEST) @@ -55,8 +57,17 @@ public class ScriptingMojo extends AbstractMojo private PGXSUtils utils; /** - * Executes the javascript code inside {@code script} tag inside plugin + * Executes the script code inside the {@code script} tag in the plugin * configuration. + *

+ * Uses {@link PGXSUtils#getScriptEngine PGXSUtils.getScriptEngine} + * to instantiate the engine, and then makes these items available in + * the engine's scope (in addition to those placed there by + * {@link PGXSUtils#getScriptEngine getScriptEngine} itself): + *

+ *
session
The Maven session object + *
plugin
This object + *
*/ @Override public void execute () throws MojoExecutionException, MojoFailureException @@ -67,19 +78,14 @@ public void execute () throws MojoExecutionException, MojoFailureException String scriptText = script.getValue(); ScriptEngine engine = utils.getScriptEngine(script); - engine.getContext().setAttribute("session", session, - ScriptContext.GLOBAL_SCOPE); - engine.getContext().setAttribute("plugin", this, - ScriptContext.GLOBAL_SCOPE); - engine.put("quoteStringForC", - (Function) utils::quoteStringForC); - engine.put("setProjectProperty", - (BiConsumer) this::setProjectProperty); - engine.put("getPgConfigProperty", - (Function) this::getPgConfigProperty); + engine.getContext().setAttribute("session", session, ENGINE_SCOPE); + engine.getContext().setAttribute("plugin", this, ENGINE_SCOPE); + engine.eval(scriptText); - GoalScript goal = ((Invocable) engine).getInterface(GoalScript.class); + GoalScript goal = + ((Invocable) engine).getInterface(GoalScript.class); + AbstractMojoExecutionException exception = goal.execute(); if (exception != null) throw exception; @@ -95,63 +101,33 @@ public void execute () throws MojoExecutionException, MojoFailureException } /** - * Sets the value of a property for the current project. - * - * @param property key to use for property - * @param value the value of property to set - */ - public void setProjectProperty (String property, String value) - { - project.getProperties().setProperty(property, value); - } - - /** - * Returns the value of a pg_config property. - * - * @param property property whose value is to be retrieved from pg_config - * @return output of pg_config executed with the input property as argument - */ - public String getPgConfigProperty (String property) - { - try - { - String pgConfigCommand = System.getProperty("pgsql.pgconfig"); - return utils.getPgConfigProperty(pgConfigCommand, property); - } - catch (Exception e) - { - getLog().error(e); - return null; - } - } - - /** - * Wraps the input object in a {@link AbstractMojoExecutionException}. + * Wraps the input object in an {@link AbstractMojoExecutionException}. * * The returned exception is constructed as follows: - * 1) If {@code object} is null, then {@link MojoExecutionException} is used - * to wrap and the message indicates that null value was thrown by the script. - * 2) If {@code object} is already a {@link MojoExecutionException}, return - * it as is. - * 3) If {@code object} is already a {@link MojoFailureException}, return it - * as is. - * - * For the steps, below the wrapping exception is chosen according to the - * the value of {@code scriptFailure} parameter. - * - * 4) If {@code object} is any other {@link Throwable}, set it as the cause - * for the exception. - * 5) If {@code object} is a {@link String}, set it as the message of the - * exception. - * 6) For all other case, the message of the exception is set in this format - * , Class Name of object: String representation of object. + *
    + *
  • If {@code object} is null, then {@link MojoExecutionException} is + * used to wrap and the message indicates that a null value was thrown + * by the script. + *
  • If {@code object} is already a {@link MojoExecutionException}, it is + * returned as is. + *
  • If {@code object} is already a {@link MojoFailureException}, it is + * returned as is. + *
  • For the steps below, the wrapping exception is chosen according to + * the value of the {@code scriptFailure} parameter. + *
  • If {@code object} is any other {@link Throwable}, set it as + * the wrapping exception's cause. + *
  • If {@code object} is a {@link String}, set it as the wrapping + * exception's message. + *
  • For any other object, the message of the exception is set in + * this format: Class name of object: String representation of object. + *
* - * @param object to wrap in AbstractMojoExecutionException - * @param scriptFailure if true, use a MojoExecutionException for wrapping - * otherwise use MojoFailureException. this parameter - * is ignored, if the object is null or instance of + * @param object an object to wrap in an AbstractMojoExecutionException + * @param scriptFailure if true, use a MojoExecutionException for wrapping, + * otherwise use MojoFailureException. This parameter + * is ignored if the object is null or an instance of * MojoExecutionException or MojoFailureException - * @return object wrapped inside a {@link AbstractMojoExecutionException} + * @return object wrapped inside an {@link AbstractMojoExecutionException} */ public AbstractMojoExecutionException exceptionWrap(Object object, boolean scriptFailure) From a3a3927c721e7bbd5d58442564003b334d2b0ffb Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Fri, 14 Jun 2024 19:16:54 -0400 Subject: [PATCH 09/18] Hush recent javac annotation-processor warnings Recent versions of javac warn that annotation processing might not happen in the future unless --processor, --processor-path, --processor-module-path, or some -proc option is explicitly given. Nothing was going to break, because the POMs where annotation processing needs to happen already set --processor-module-path. But that doesn't silence the warning. Only an explicit -proc:full or -processor org.postgresql.pljava.annotation.processing.DDRProcessor accomplishes that. Because -proc:full is unrecognized before Java 21, but the longwinded -processor spec works in all supported versions, the longwinded form is used here (even though it seems a complete waste of the elegance of the original processor discovery scheme). Warnings were also appearing in a couple of compilations where no annotation processing was needed or expected. When compiling the PGXS plugin, the warning appeared because an unexpected and unneeded processor org.eclipse.sisu.space.SisuIndexAPT6 was being found in one of the 70 classpath elements glommed together to build a Maven plugin. When building the pljava-packaging classes, the POM names the other PL/Java modules as dependencies (because they must exist before they can be packaged), with the side effect of adding them to the classpath, so PL/Java's processor is found, though not needed for the packaging code. In both of those modules, add -proc:none (which is recognized in all supported versions; only -proc:full was newer). The longwinded approach of naming an exact processor class might be hygienically preferable to the broad -proc:full, as less prone to surprises when another processor like SisuIndexAPT6 happens to exist on the classpath. (Assuming the other processor is nonmalicious, and is looking for annotations the code being compiled doesn't use, the processor wouldn't be expected to do anything, yielding surprise of the mildest possible kind. Still, anyone very averse to surprise might prefer to name the expected processor explicitly.) --- pljava-examples/pom.xml | 5 +++++ pljava-packaging/pom.xml | 3 +++ pljava-pgxs/pom.xml | 8 ++++++++ pljava/pom.xml | 5 +++++ 4 files changed, 21 insertions(+) diff --git a/pljava-examples/pom.xml b/pljava-examples/pom.xml index 497d6a4d9..6c9cd8562 100644 --- a/pljava-examples/pom.xml +++ b/pljava-examples/pom.xml @@ -58,6 +58,11 @@ --processor-module-path ${basedir}/../pljava-api/target/pljava-api-${project.version}.jar + + + org.postgresql.pljava.annotation.processing.DDRProcessor + +
diff --git a/pljava-packaging/pom.xml b/pljava-packaging/pom.xml index ee19ad959..66cb2c594 100644 --- a/pljava-packaging/pom.xml +++ b/pljava-packaging/pom.xml @@ -172,6 +172,9 @@ function execute() compile + + none + diff --git a/pljava-pgxs/pom.xml b/pljava-pgxs/pom.xml index c53ff1e22..414816cc7 100644 --- a/pljava-pgxs/pom.xml +++ b/pljava-pgxs/pom.xml @@ -56,6 +56,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + none + + + org.apache.maven.plugins maven-plugin-plugin diff --git a/pljava/pom.xml b/pljava/pom.xml index 52491f1c1..85c5e0b07 100644 --- a/pljava/pom.xml +++ b/pljava/pom.xml @@ -30,6 +30,11 @@ --processor-module-path ${basedir}/../pljava-api/target/pljava-api-${project.version}.jar + + + org.postgresql.pljava.annotation.processing.DDRProcessor + + From f9e962ff322c1fa632395d50d4852f655e3ec0b0 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sun, 16 Jun 2024 14:46:18 -0400 Subject: [PATCH 10/18] Move javadoc paragraph attached to wrong method --- .../pljava/annotation/Operator.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pljava-api/src/main/java/org/postgresql/pljava/annotation/Operator.java b/pljava-api/src/main/java/org/postgresql/pljava/annotation/Operator.java index 7e7fe0df3..0b60808bb 100644 --- a/pljava-api/src/main/java/org/postgresql/pljava/annotation/Operator.java +++ b/pljava-api/src/main/java/org/postgresql/pljava/annotation/Operator.java @@ -115,6 +115,16 @@ * different, so the two functions can be distinguished by overloading). A * typical case would be the twin of a cross-type function like {@code add} * that is commutative, so using the same name makes sense. + *

+ * When derived by commutation, the synthetic function simply calls the + * base function with the parameters swapped. For negation, the base + * function must return {@code boolean} or {@code Boolean}, and the + * synthetic function returns true for false, false for true, and null + * for null. This will give familiar SQL behavior in many cases. For a base + * function with {@code onNullInput=CALLED}, if it can return non-null + * boolean results on some null inputs, it may be necessary to code + * a negator or commutator by hand if the synthetic one would not have + * the intended semantics. */ String[] synthetic() default {}; @@ -129,16 +139,6 @@ * (which must be different) reversed. A typical case would be the twin of a * cross-type operator like {@code +} that is commutative, so using the same * name makes sense. - *

- * When derived by commutation, the synthetic function simply calls the - * base function with the parameters swapped. For negation, the base - * function must return {@code boolean} or {@code Boolean}, and the - * synthetic function returns true for false, false for true, and null - * for null. This will give familiar SQL behavior in many cases. For a base - * function with {@code onNullInput=CALLED}, if it can return non-null - * boolean results on some null inputs, it may be necessary to code - * a negator or commutator by hand if the synthetic one would not have - * the intended semantics. */ String[] commutator() default {}; From 278e8c16b16f3c8369e1830b25e06c897bcb9d30 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 2 Oct 2024 20:45:52 -0400 Subject: [PATCH 11/18] Symbols renamed in PostgreSQL v17 Credit to Francisco Miguel Biete Banon in PR #501. Simplified so the code now simply uses the new names (introduced in postgres/postgres@393b559), and defines them in older PG versions for compatibility. --- pljava-so/src/main/c/InstallHelper.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pljava-so/src/main/c/InstallHelper.c b/pljava-so/src/main/c/InstallHelper.c index 2cb5a9cb3..488ee0a66 100644 --- a/pljava-so/src/main/c/InstallHelper.c +++ b/pljava-so/src/main/c/InstallHelper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2023 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2024 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 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,9 @@ #include "pljava/PgObject.h" #include "pljava/type/String.h" +#if PG_VERSION_NUM < 170000 +#define AmAutoVacuumWorkerProcess() IsAutoVacuumWorkerProcess() +#define AmBackgroundWorkerProcess() IsBackgroundWorker /* * As of 9.6.1, IsBackgroundWorker still does not * have PGDLLIMPORT, but MyBgworkerEntry != NULL can be used in MSVC instead. @@ -50,11 +54,11 @@ * One thing it's needed for is to avoid dereferencing MyProcPort in a * background worker, where it's not set. */ -#include #if defined(_MSC_VER) #include #define IsBackgroundWorker (MyBgworkerEntry != NULL) #endif +#endif /* PG_VERSION_NUM < 170000 */ /* * The name of the table the extension scripts will create to pass information @@ -90,7 +94,7 @@ bool pljavaViableXact() char *pljavaDbName() { - if ( IsAutoVacuumWorkerProcess() || IsBackgroundWorker ) + if ( AmAutoVacuumWorkerProcess() || AmBackgroundWorkerProcess() ) { char *shortlived; static char *longlived; @@ -110,7 +114,7 @@ char *pljavaDbName() static char *origUserName() { - if ( IsAutoVacuumWorkerProcess() || IsBackgroundWorker ) + if ( AmAutoVacuumWorkerProcess() || AmBackgroundWorkerProcess() ) { char *shortlived; static char *longlived; @@ -354,8 +358,8 @@ char *pljavaFnOidToLibPath(Oid fnOid, char **langName, bool *trusted) bool InstallHelper_shouldDeferInit() { - if ( IsBackgroundWorker || IsAutoVacuumWorkerProcess() ) - return true; + if ( AmAutoVacuumWorkerProcess() || AmBackgroundWorkerProcess() ) + return true; if ( ! IsBinaryUpgrade ) return false; From 603197d5ab2c1b8c8f90075dff3114d687ad1afd Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 2 Oct 2024 20:53:23 -0400 Subject: [PATCH 12/18] Use SPI_restore_connection only in PG < 10 SPI_restore_connection was defined as a noop since PostgreSQL 10, and the compatibility macro has been removed in postgres/postgres@75680c3. Because PL/Java 1.6 purports to still run on PostgreSQL 9.5, continue to use the function in PG < 10. Credit to Francisco Miguel Biete Banon in PR #501. --- pljava-so/src/main/c/PgSavepoint.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pljava-so/src/main/c/PgSavepoint.c b/pljava-so/src/main/c/PgSavepoint.c index b387ac6ac..45fcca81e 100644 --- a/pljava-so/src/main/c/PgSavepoint.c +++ b/pljava-so/src/main/c/PgSavepoint.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2024 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 @@ -187,7 +187,9 @@ Java_org_postgresql_pljava_internal_PgSavepoint__1rollback(JNIEnv* env, jclass c PG_TRY(); { unwind(RollbackAndReleaseCurrentSubTransaction, xid, nestLevel); +#if PG_VERSION_NUM < 100000 SPI_restore_connection(); +#endif } PG_CATCH(); { From 95b5962d906b0904fed6e0fe036ed54f9325fa16 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 3 Oct 2024 20:04:19 -0400 Subject: [PATCH 13/18] Bump DDRProcessor latest_tested to 23 No issues observed in compiling manually (without the Maven directive specifying an earlier --release) on Oracle JDK 23 GA. cd pljava-api/src/main/java /var/tmp/jdk-23/bin/javac -d ../../../target/classes/ \ -Xlint:unchecked -Xlint:-removal --module-version 1.6-SNAPSHOT \ $(find . -name '*.java') cd ../../.. /var/tmp/jdk-23/bin/jar cf target/pljava-api-1.6-SNAPSHOT.jar \ -C target/classes . cd ../pljava/src/main/java /var/tmp/jdk-23/bin/javac --module-version 1.6-SNAPSHOT \ -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 \ -Xlint:unchecked -Xlint:-removal $(find . -name '*.java') cd ../../../ /var/tmp/jdk-23/bin/jar cf target/pljava-1.6-SNAPSHOT.jar \ -C target/classes . cd ../pljava-examples/src/main/java /var/tmp/jdk-23/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 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-packaging --- .../postgresql/pljava/annotation/processing/DDRProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pljava-api/src/main/java/org/postgresql/pljava/annotation/processing/DDRProcessor.java b/pljava-api/src/main/java/org/postgresql/pljava/annotation/processing/DDRProcessor.java index 465f5ddf4..262ec227d 100644 --- a/pljava-api/src/main/java/org/postgresql/pljava/annotation/processing/DDRProcessor.java +++ b/pljava-api/src/main/java/org/postgresql/pljava/annotation/processing/DDRProcessor.java @@ -173,7 +173,7 @@ public SourceVersion getSupportedSourceVersion() * Update latest_tested to be the latest Java release on which this * annotation processor has been tested without problems. */ - int latest_tested = 22; + int latest_tested = 23; int ordinal_9 = SourceVersion.RELEASE_9.ordinal(); int ordinal_latest = latest_tested - 9 + ordinal_9; From 7ed491891f7dcb789a0ea3289059434f83ec6229 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 3 Oct 2024 20:11:30 -0400 Subject: [PATCH 14/18] Bring the JEP 411 warnings up to date As of Java 23, the necessary mechanisms have not yet been disabled. (There is probably, though, with increasing versions, an increasing risk of Java internals that lack doPrivileged and will end up needing to leak into policy.) --- pljava-so/src/main/c/Backend.c | 2 +- src/site/markdown/use/policy.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pljava-so/src/main/c/Backend.c b/pljava-so/src/main/c/Backend.c index 30569c2e0..e4324babb 100644 --- a/pljava-so/src/main/c/Backend.c +++ b/pljava-so/src/main/c/Backend.c @@ -1942,7 +1942,7 @@ void Backend_warnJEP411(bool isCommit) "Those changes will come in releases after Java 17."), errhint( "For migration planning, this version of PL/Java can still " - "enforce policy in Java versions up to and including 22, " + "enforce policy in Java versions up to and including 23, " "and Java 17 and 21 are positioned as long-term support releases. " "For details on how PL/Java will adapt, please bookmark " "https://github.com/tada/pljava/wiki/JEP-411") diff --git a/src/site/markdown/use/policy.md b/src/site/markdown/use/policy.md index 9d0e3f800..df423a293 100644 --- a/src/site/markdown/use/policy.md +++ b/src/site/markdown/use/policy.md @@ -373,7 +373,7 @@ release, so relying on it is not recommended. The developers of Java have elected to phase out important language features used by PL/Java to enforce policy. The changes will come in releases after Java 17. For migration planning, this version of PL/Java can still enable -policy enforcement in Java versions up to and including 22, and Java 17 and 21 +policy enforcement in Java versions up to and including 23, and Java 17 and 21 are positioned as long-term support releases. (There is a likelihood, increasing with later Java versions, even before policy stops being enforceable, that some internal privileged operations by Java itself, or other libraries, From 2df56f1b143f8d44a7b5be42c6b0eb510314f131 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sun, 6 Oct 2024 14:04:45 -0400 Subject: [PATCH 15/18] Remove more pre-PL/Java-1.6 remnants from docs The build system introduced in 1.6 fixed the "Windows might get -Dpljava.libjvmdefault wrong" issue. Also, by no longer trying to capture compiler/linker messages and classify them, it has fixed the "Not all [ERROR]s are errors" issue. In 1.6, both the pljava and pljava-api jars must be present in $SHAREDIR/pljava at runtime. So a package maintainer may choose to include the API jar additionally in a -devel package that places it where users' development tools will expect, but may not omit it from the base package that installs it where the runtime needs it. --- src/site/markdown/build/build.md | 32 +++++++--------------------- src/site/markdown/build/buildmsvc.md | 23 +------------------- src/site/markdown/build/package.md | 23 +++++++++----------- 3 files changed, 19 insertions(+), 59 deletions(-) diff --git a/src/site/markdown/build/build.md b/src/site/markdown/build/build.md index d48103354..6dae93d64 100644 --- a/src/site/markdown/build/build.md +++ b/src/site/markdown/build/build.md @@ -222,30 +222,6 @@ build issues that are commonly asked about.* [btwp]: https://github.com/tada/pljava/wiki/Build-tips -#### Not all `[ERROR]`s are errors - -In the part of the build that compiles the native code, you may see lines of -output starting with `[ERROR]`, but the build completes and shows success for -all subprojects. - -Maven is capturing output from the C compiler and adding a tag at the front of -each line. If the line from the C compiler contains the string `warning:` then -Maven adds a `[WARNING]` tag at the front of the line; otherwise it adds -`[ERROR]`. That is how Maven can turn a multiple-line warning, like - -``` -type/String.c: In function 'String_createJavaString': -type/String.c:132:43: warning: conversion to 'jlong' from 'Size' may change - the sign of the result [-Wsign-conversion] - bytebuf = JNI_newDirectByteBuffer(utf8, srcLen); - ^ -``` - -(where only the second line contains `warning:`) into what looks like one -`[WARNING]` and several `[ERROR]`s. - -If the compiler reports any actual errors, the build will fail. - #### Capture the output of `mvn -X` The `-X` option will add a lot of information on the details of Maven's @@ -259,3 +235,11 @@ On the first run, Maven will produce a lot of output while downloading all of the dependencies needed to complete the build. It is better, if the build fails, to simply run Maven again and capture the output of that run, which will not include all of the downloading activity. + +As an alternative, the flood of messages reflecting successful dependency +downloads in a first run can be suppressed by adding this option on the `mvn` +command line: + +``` +-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn +``` diff --git a/src/site/markdown/build/buildmsvc.md b/src/site/markdown/build/buildmsvc.md index 0e2dcb16b..715a05426 100644 --- a/src/site/markdown/build/buildmsvc.md +++ b/src/site/markdown/build/buildmsvc.md @@ -211,26 +211,5 @@ dependency when [building your own projects that _use_ PL/Java][jproj]. ### Troubleshooting the build -If something fails, two tricks may be helpful. The C compilation may produce -a lot of nuisance warnings, because the Maven plugin driving it enables many -types of warning that would be impractical to fix. With many warnings it may -be difficult to pick out messages that matter. - -If the link step of the build reports that the symbol `rint` is undefined you -are probably using an older version of Visual Studio (2010) with a newer version -of Postgresql (9.4). This symbol is defined in Visual Studio 2013 and later and -the Postgresql 9.4 headers lack the appropriate conditional options for the -older compilers. You will need to use a newer version of Visual Studio. - -On a machine with many cores, messages from several compilation threads may be -intermingled in the output so that related messages are hard to identify. -The option `-Dnar.cores=1` will force the messages into a sequential order -(and has little effect on the speed of a PL/Java build). - -The `-X` option will add a lot of information on the details of Maven's -build activities. - - mvn -X -Dnar.cores=1 clean install - -There is a more comprehensive "troubleshooting the build" section +There is an extensive "troubleshooting the build" section on the [main build page][mbp]. diff --git a/src/site/markdown/build/package.md b/src/site/markdown/build/package.md index 64eedde0c..346791829 100644 --- a/src/site/markdown/build/package.md +++ b/src/site/markdown/build/package.md @@ -25,13 +25,6 @@ When building a package, you are encouraged to set the default `pljava.libjvm_location` to the library of a JRE version that is expected to be present on your platform. -**Note:** when building on Windows, the `-Dpljava.libjvmdefault` option is -likely to produce a failed build or the wrong stored value for the library -path. A fix for this option on Windows is unlikely (see [issue 190][bug190]); -if preparing a package for Windows, it will be simplest to use a patch that -changes the definition of `PLJAVA_LIBJVMDEFAULT` in -`pljava-so/src/main/c/Backend.c`. - [locatejvm]: ../install/locatejvm.html [bug190]: https://github.com/tada/pljava/issues/190 @@ -139,7 +132,7 @@ the package. `-Dpljava.libjvmdefault=`_path/to/jvm-shared-object_ : As suggested earlier, please use this option to build a useful default -into PL/Java for the `pljava.libjvm_location` PostgreSQL variable, users +into PL/Java for the `pljava.libjvm_location` PostgreSQL variable, so users of your package will not need to set that variable before `CREATE EXTENSION pljava` works. @@ -189,8 +182,11 @@ those needed to support `ALTER EXTENSION UPGRADE`. It also contains the `pljava-api` jar, needed for developing Java code to use in a database with PL/Java, and the `pljava-examples` jar. As discussed above, -these may be omitted from a base package and supplied separately, if packaging -guidelines require. +the examples jar may be omitted from a base package and supplied separately, +if packaging guidelines require, and the API jar may be included also in a +`-devel` package that installs it in a standard Java-library location. (However, +the API jar cannot be omitted from the base package; it is needed at runtime, in +the `SHAREDIR/pljava` location where the extension expects it.) The self-extracting jar consults `pg_config` at the time of extraction to determine where the files should be installed. @@ -226,9 +222,10 @@ will have on the target system. In addition to the files named in the self-extractor's output, additional files could be included in the package (if guidelines require the README -or COPYRIGHT, for example). As discussed above, the `pljava-api` jar could -be filtered from the list if it will be delivered in a separate `-devel` -package, and the same could be done for `pljava-examples`. +or COPYRIGHT, for example). As discussed above, the `pljava-examples` jar could +be filtered from the list if it will be delivered in a separate +package, and the `pljava-api` jar could be additionally delivered in a separate +`-devel` package (but must not be excluded from the base package). [install]: ../install/install.html From 471d74930f0c5bed6679ea064ae9f737c6efd5df Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sat, 19 Oct 2024 19:36:25 -0400 Subject: [PATCH 16/18] Update releasenotes.md and versions.md --- src/site/markdown/build/versions.md | 12 ++-- src/site/markdown/releasenotes.md.vm | 95 ++++++++++++++++++++++++---- 2 files changed, 90 insertions(+), 17 deletions(-) diff --git a/src/site/markdown/build/versions.md b/src/site/markdown/build/versions.md index c6dc83c2f..9966e14f3 100644 --- a/src/site/markdown/build/versions.md +++ b/src/site/markdown/build/versions.md @@ -1,6 +1,6 @@ # Versions of external packages needed to build and use PL/Java -As of spring 2024, the following version constraints are known. +As of fall 2024, the following version constraints are known. ## Java @@ -25,9 +25,9 @@ That also allows PL/Java to take advantage of recent Java implementation advances such as [class data sharing][cds]. Some builds of Java 20 are affected by a bug, [JDK-8309515][]. PL/Java will -report an error if detects it is affected by that bug, and the solution can be -to use a Java version earlier than 20, or one recent enough to have the bug -fixed. The bug is fixed in Java 21. +report an error if it detects it is affected by that bug, and the solution can +be to use a Java version earlier than 20, or one recent enough to have the bug +fixed. The bug was fixed in Java 21. PL/Java has been successfully used with [Oracle Java][orj] and with [OpenJDK][], which is available with @@ -67,6 +67,6 @@ The PL/Java 1.6 series does not support PostgreSQL earlier than 9.5. More current PostgreSQL versions, naturally, are the focus of development and receive more attention in testing. -PL/Java 1.6.7 has been successfully built and run on at least one platform -with PostgreSQL versions from 16 to 9.5, the latest maintenance +PL/Java 1.6.8 has been successfully built and run on at least one platform +with PostgreSQL versions from 17 to 9.5, the latest maintenance release for each. diff --git a/src/site/markdown/releasenotes.md.vm b/src/site/markdown/releasenotes.md.vm index 74dddd8c5..66f722c6f 100644 --- a/src/site/markdown/releasenotes.md.vm +++ b/src/site/markdown/releasenotes.md.vm @@ -10,6 +10,90 @@ #set($ghbug = 'https://github.com/tada/pljava/issues/') #set($ghpull = 'https://github.com/tada/pljava/pull/') +$h2 PL/Java 1.6.8 + +This is the eighth minor update in the PL/Java 1.6 series. It adds support +for PostgreSQL 17, confirms compatibility with Java 23, and makes some slight +build-process improvements to simplify troubleshooting reported build problems. +Further information on the changes may be found below. + +$h3 Version compatibility + +PL/Java 1.6.8 can be built against recent PostgreSQL versions including 17, and +older ones back to 9.5, using Java SE 9 or later. 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 9 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][versions] for more detail. + +Some builds of Java 20 are affected by a bug, [JDK-8309515][]. PL/Java will +report an error if it detects it is affected by that bug, and the solution can +be to use a Java version earlier than 20, or one recent enough to have the bug +fixed. The bug was fixed in Java 21. + +$h3 Changes + +$h4 Build system + +While building the PL/Java native code, Maven output will include the full +`PG_VERSION_STR` from the PostgreSQL development files that have been found +to build against. The string includes platform, compiler, and build notes, as +reported by the `version` function in SQL. This information should always be +included when reporting a PL/Java native build issue, so including it in the +Maven build output will make issues easier to report. + +When building with Maven's `-X` / `--debug` option for additional debug output, +the command arguments of the constructed compiling and linking commands will be +included in the output, which can be useful in troubleshooting a build problem. +The arguments are shown just as the compiler/linker is meant to ultimately +receive them; on a Unix-like platform, that is the Java `List` exactly as seen +with `ProcessBuilder.command()`. On Windows, that `List` is shown just before +the final application of extra quoting that simply ensures the compiler/linker +receives it correctly. + +When building with a platform or environment that does not satisfy the `probe` +predicate of any of the included platform build rules, a Maven error message +will clearly say so. In earlier versions, an uninformative null pointer +exception resulted instead. The new message includes guidance on how to add a +build rule set for a new platform or environment, and possibly contribute it for +inclusion in PL/Java. + +$h4 Documentation + +The build documentation now prominently notes that `mvn --version` will show the +version of Java that Maven has found to use for the build. There had been build +issues reported that could be traced to Maven finding a different Java +installation than expected, when that version was not usable to build +PL/Java 1.6. + +The documentation has been shorn of many lingering references to PostgreSQL +versions older than 9.5, the oldest that PL/Java 1.6 supports, and other +holdovers from pre-1.6 PL/Java. + +$h3 Enhancement requests addressed + +* [PostgreSQL 17 support](${ghpull}499) + +$h3 Bugs fixed + +* [Unhelpful output when build fails because no platform rules matched](${ghbug}485) + +$h3 Credits + +Thanks in release 1.6.8 to Francisco Miguel Biete Banon for determining the +changes needed for PostgreSQL 17. + +$h2 Earlier releases + +## A nice thing about using Velocity is that each release can be entered at +## birth using h2 as its main heading, h3 and below within ... and then, when +## it is moved under 'earlier releases', just define those variables to be +## one heading level finer. Here goes: +#set($h2 = '###') +#set($h3 = '####') +#set($h4 = '#####') +#set($h5 = '######') + $h2 PL/Java 1.6.7 This is the seventh minor update in the PL/Java 1.6 series. It adds support @@ -82,17 +166,6 @@ Mantzios, `hunterpayne`, `kamillo`. [JDK-8329295]: https://bugs.openjdk.org/browse/JDK-8329295 -$h2 Earlier releases - -## A nice thing about using Velocity is that each release can be entered at -## birth using h2 as its main heading, h3 and below within ... and then, when -## it is moved under 'earlier releases', just define those variables to be -## one heading level finer. Here goes: -#set($h2 = '###') -#set($h3 = '####') -#set($h4 = '#####') -#set($h5 = '######') - $h2 PL/Java 1.6.6 This is the sixth minor update in the PL/Java 1.6 series. It adds support From ec09b58f5ad39a91881bb38ccc87d8014cff7019 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sat, 19 Oct 2024 19:36:56 -0400 Subject: [PATCH 17/18] Poke migration-management versions for 1.6.8 --- .../main/java/org/postgresql/pljava/internal/InstallHelper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/pljava/src/main/java/org/postgresql/pljava/internal/InstallHelper.java b/pljava/src/main/java/org/postgresql/pljava/internal/InstallHelper.java index 9bf94232d..d9bd12a85 100644 --- a/pljava/src/main/java/org/postgresql/pljava/internal/InstallHelper.java +++ b/pljava/src/main/java/org/postgresql/pljava/internal/InstallHelper.java @@ -991,6 +991,7 @@ void migrateFrom( SchemaVariant sv, Connection c, Statement s) UNREL20040120 ("5e4131738cd095b7ff6367d64f809f6cec6a7ba7"), EMPTY (null); + static final SchemaVariant REL_1_6_8 = REL_1_6_0; static final SchemaVariant REL_1_6_7 = REL_1_6_0; static final SchemaVariant REL_1_6_6 = REL_1_6_0; static final SchemaVariant REL_1_6_5 = REL_1_6_0; From 9de9217ebe76ee86f51d21ea0f65bf5fa9c75027 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sat, 19 Oct 2024 19:45:22 -0400 Subject: [PATCH 18/18] Add control file in preparation for next release Now that 1.6.8 is released, the next release should include an extension SQL file allowing upgrade from 1.6.8. --- pljava-packaging/build.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pljava-packaging/build.xml b/pljava-packaging/build.xml index 95e4dd33c..ef469be94 100644 --- a/pljava-packaging/build.xml +++ b/pljava-packaging/build.xml @@ -255,6 +255,10 @@ jos.close(); simple update is possible, just repeat the next entry, with the from-version changed. --> +