From 40788c11f29171d12a9ec910d22dc593d5f8dde3 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sun, 20 Aug 2023 20:32:46 -0400 Subject: [PATCH 01/25] Assume dlfcn.h exists except on Windows postgres/postgres@ca1e855 --- pljava-so/src/main/c/Backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pljava-so/src/main/c/Backend.c b/pljava-so/src/main/c/Backend.c index 287652fd2..9c60e5c73 100644 --- a/pljava-so/src/main/c/Backend.c +++ b/pljava-so/src/main/c/Backend.c @@ -28,7 +28,7 @@ #include #if PG_VERSION_NUM >= 120000 - #ifdef HAVE_DLOPEN + #if defined(HAVE_DLOPEN) || PG_VERSION_NUM >= 160000 && ! defined(WIN32) #include #endif #define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL) From 2511321530cf1ccdb0e4a95cdf35ab8a64c40f78 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sun, 20 Aug 2023 20:41:35 -0400 Subject: [PATCH 02/25] Rely on __func__ being supported postgres/postgres@320f92b --- pljava-so/src/main/c/Function.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pljava-so/src/main/c/Function.c b/pljava-so/src/main/c/Function.c index a46c0e6dd..f975fbe56 100644 --- a/pljava-so/src/main/c/Function.c +++ b/pljava-so/src/main/c/Function.c @@ -34,6 +34,10 @@ #include #include +#if PG_VERSION_NUM >= 160000 +#define PG_FUNCNAME_MACRO __func__ +#endif + #ifdef _MSC_VER # define strcasecmp _stricmp # define strncasecmp _strnicmp From e004f0a25e0b8e503c0c2377ade9def969aff48b Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Tue, 22 Aug 2023 16:24:29 -0400 Subject: [PATCH 03/25] Upstream has refactored aclcheck functions postgres/postgres@c727f51 --- pljava-so/src/main/c/Function.c | 2 +- pljava-so/src/main/c/type/AclId.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pljava-so/src/main/c/Function.c b/pljava-so/src/main/c/Function.c index f975fbe56..3a2bd5b10 100644 --- a/pljava-so/src/main/c/Function.c +++ b/pljava-so/src/main/c/Function.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2022 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 diff --git a/pljava-so/src/main/c/type/AclId.c b/pljava-so/src/main/c/type/AclId.c index 504b8cf6a..81b31538d 100644 --- a/pljava-so/src/main/c/type/AclId.c +++ b/pljava-so/src/main/c/type/AclId.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 Tada AB and other contributors, as listed below. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the The BSD 3-Clause License @@ -22,6 +22,12 @@ #include "org_postgresql_pljava_internal_AclId.h" #include "pljava/Exception.h" +#if PG_VERSION_NUM >= 160000 +#include +#define pg_namespace_aclcheck(oid,rid,mode) \ + object_aclcheck(NamespaceRelationId, (oid), (rid), (mode)) +#endif + static jclass s_AclId_class; static jmethodID s_AclId_init; static jfieldID s_AclId_m_native; From 5559b8a13b6d91e34136dc59133c1c2042cda4f3 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 23 Aug 2023 11:10:50 -0400 Subject: [PATCH 04/25] Add Java 17 names for XML implementation props Java 17 adds (and prominently documents in the java.xml module-info javadocs), new, standardized, easy-to-remember names for a dozen or so of the XML implementation-specific properties and features. And the standardized names are ... different from the old ones. More names to feed into setFirstSupported{Feature,Property} when trying to adjust things. The naming headaches are now visible outside of just the implementation module, because there are new standardized names for a Transformer property and feature also, which are used in the XSLT example code in PassXML. So this is a good time to factor a setFirstSupported(...) generic function out of the various copies buried in SQLXMLImpl, and expose it in the Adjusting.XML API so client code can use it too, and use it that way in that example. The Adjusting.XML API was added in some haste, and used to say "the adjusting methods are best-effort and do not provide an indication of whether the requested adjustment was made". In fact it was pushed with some debug code doing exception stacktraces to standard error, which may have been an annoyance at any site that was using the feature heavily. Take this opportunity to do something more systematic, and add a lax(boolean) method allowing it to be tailored. Stacktraces will still be logged if no tailoring is done, but may be more concise, as all of the exceptions that might be encountered in a chain of adjustments will be chained together with addSuppressed(), and common stacktrace elements should be elided when those are logged. In passing, copyedit some Adjusting.XML javadoc to use styleguide-favored third-person rather than second-person phrasing. --- .../java/org/postgresql/pljava/Adjusting.java | 200 +++++++++++-- .../pljava/example/annotation/PassXML.java | 58 ++-- .../postgresql/pljava/jdbc/SQLXMLImpl.java | 271 +++++++++++------- 3 files changed, 383 insertions(+), 146 deletions(-) diff --git a/pljava-api/src/main/java/org/postgresql/pljava/Adjusting.java b/pljava-api/src/main/java/org/postgresql/pljava/Adjusting.java index 9a2d379b7..b8e322567 100644 --- a/pljava-api/src/main/java/org/postgresql/pljava/Adjusting.java +++ b/pljava-api/src/main/java/org/postgresql/pljava/Adjusting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2019-2023 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,9 @@ import java.io.Reader; import java.sql.SQLException; import java.sql.SQLXML; +import java.util.List; +import static java.util.Objects.requireNonNull; +import java.util.function.Consumer; import javax.xml.stream.XMLInputFactory; // for javadoc import javax.xml.stream.XMLResolver; // for javadoc import javax.xml.stream.XMLStreamReader; @@ -126,16 +129,139 @@ public static final class XML { private XML() { } // no instances + /** + * Attempts a given action (typically to set something) using a given + * value, trying one or more supplied keys in order until the action + * succeeds with no exception. + *

+ * This logic is common to the + * {@link Parsing#setFirstSupportedFeature setFirstSupportedFeature} + * and + * {@link Parsing#setFirstSupportedProperty setFirstSupportedProperty} + * methods, and is exposed here because it may be useful for other + * tasks in Java's XML APIs, such as configuring {@code Transformer}s. + *

+ * If any attempt succeeds, null is returned. If no attempt + * succeeds, the first exception caught is returned, with any + * exceptions from the subsequent attempts retrievable from it with + * {@link Exception#getSuppressed getSuppressed}. The return is + * immediate, without any remaining names being tried, if an exception + * is caught that is not assignable to a class in the + * expected list. Such an exception will be passed to the + * onUnexpected handler if that is non-null; otherwise, + * it will be returned (or added to the suppressed list of the + * exception to be returned) just as expected exceptions are. + * @param setter typically a method reference for a method that + * takes a string key and some value. + * @param value the value to pass to the setter + * @param expected a list of exception classes that can be foreseen + * to indicate that a key was not recognized, and the operation + * should be retried with the next possible key. + * @param onUnexpected invoked, if non-null, on an {@code Exception} + * that is caught and matches nothing in the expected list, instead + * of returning it. If this parameter is null, such an exception is + * returned (or added to the suppressed list of the exception to be + * returned), just as for expected exceptions, but the return is + * immediate, without trying remaining names, if any. + * @param names one or more String keys to be tried in order until + * the action succeeds. + * @return null if any attempt succeeded, otherwise an exception, + * which may have further exceptions in its suppressed list. + */ + public static Exception setFirstSupported( + SetMethod setter, V value, + List> expected, + Consumer onUnexpected, String... names) + { + requireNonNull(expected); + Exception caught = null; + for ( String name : names ) + { + try + { + setter.set(name, value); + return null; + } + catch ( Exception e ) + { + boolean benign = + expected.stream().anyMatch(c -> c.isInstance(e)); + + if ( benign || null == onUnexpected ) + { + if ( null == caught ) + caught = e; + else + caught.addSuppressed(e); + } + else + onUnexpected.accept(e); + + if ( ! benign ) + break; + } + } + return caught; + } + + /** + * A functional interface fitting various {@code setFeature} or + * {@code setProperty} methods in Java XML APIs. + *

+ * The XML APIs have a number of methods on various interfaces that can + * be used to set some property or feature, and can generally be + * assigned to this functional interface by bound method reference, and + * used with {@link #setFirstSupported setFirstSupported}. + */ + @FunctionalInterface + public interface SetMethod + { + void set(String key, T value) throws Exception; + } + /** * Interface with methods to adjust the restrictions on XML parsing * that are commonly considered when XML content might be from untrusted * sources. *

- * The adjusting methods are best-effort and do not provide an - * indication of whether the requested adjustment was made. Not all of + * The adjusting methods are best-effort; not all of * the adjustments are available for all flavors of {@code Source} or * {@code Result} or for all parser implementations or versions the Java - * runtime may supply. + * runtime may supply. Cases where a requested adjustment has not been + * made are handled as follows: + *

+ * Any sequence of adjustment calls will ultimately be followed by a + * {@code get}. During the sequence of adjustments, exceptions caught + * are added to a signaling list or to a quiet list, where "added to" + * means that if either list has a first exception, any caught later are + * attached to that exception with + * {@link Exception#addSuppressed addSuppressed}. + *

+ * For each adjustment (and depending on the type of underlying + * {@code Source} or {@code Result}), one or more exception types will + * be 'expected' as indications that an identifying key or value for + * that adjustment was not recognized. This implementation may continue + * trying to apply the adjustment, using other keys that have at times + * been used to identify it. Expected exceptions caught during these + * attempts form a temporary list (a first exception and those attached + * to it by {@code addSuppressed}). Once any such attempt succeeds, the + * adjustment is considered made, and any temporary expected exceptions + * list from the adjustment is discarded. If no attempt succeeded, the + * temporary list is retained, by adding its head exception to the quiet + * list. + *

+ * Any exceptions caught that are not instances of any of the 'expected' + * types are added to the signaling list. + *

+ * When {@code get} is called, the head exception on the signaling list, + * if any, is thrown. Otherwise, the head exception on the quiet list, + * if any, is logged at [@code WARNING} level. + *

+ * During a chain of adjustments, {@link #lax lax()} can be called to + * tailor the handling of the quiet list. A {@code lax()} call applies + * to whatever exceptions have been added to the quiet list up to that + * point. To discard them, call {@code lax(true)}; to move them to the + * signaling list, call {@code lax(false)}. */ public interface Parsing> { @@ -173,14 +299,14 @@ public interface Parsing> /** * For a feature that may have been identified by more than one URI - * in different parsers or versions, try passing the supplied + * in different parsers or versions, tries passing the supplied * value with each URI from names in order until * one is not rejected by the underlying parser. */ T setFirstSupportedFeature(boolean value, String... names); /** - * Make a best effort to apply the recommended, restrictive + * Makes a best effort to apply the recommended, restrictive * defaults from the OWASP cheat sheet, to the extent they are * supported by the underlying parser, runtime, and version. *

@@ -196,7 +322,7 @@ public interface Parsing> /** * For a parser property (in DOM parlance, attribute) that may have * been identified by more than one URI in different parsers or - * versions, try passing the supplied value with each URI + * versions, tries passing the supplied value with each URI * from names in order until one is not rejected by the * underlying parser. *

@@ -278,7 +404,7 @@ public interface Parsing> T accessExternalSchema(String protocols); /** - * Set an {@link EntityResolver} of the type used by SAX and DOM + * Sets an {@link EntityResolver} of the type used by SAX and DOM * (optional operation). *

* This method only succeeds for a {@code SAXSource} or @@ -297,7 +423,7 @@ public interface Parsing> T entityResolver(EntityResolver resolver); /** - * Set a {@link Schema} to be applied during SAX or DOM parsing + * Sets a {@link Schema} to be applied during SAX or DOM parsing *(optional operation). *

* This method only succeeds for a {@code SAXSource} or @@ -316,6 +442,31 @@ public interface Parsing> * already. */ T schema(Schema schema); + + /** + * Tailors the treatment of 'quiet' exceptions during a chain of + * best-effort adjustments. + *

+ * See {@link Parsing the class description} for an explanation of + * the signaling and quiet lists. + *

+ * This method applies to whatever exceptions may have been added to + * the quiet list by best-effort adjustments made up to that point. + * They can be moved to the signaling list with {@code lax(false)}, + * or simply discarded with {@code lax(true)}. In either case, the + * quiet list is left empty when {@code lax} returns. + *

+ * At the time a {@code get} method is later called, any exception + * at the head of the signaling list will be thrown (possibly + * wrapped in an exception permitted by {@code get}'s {@code throws} + * clause), with any later exceptions on that list retrievable from + * the head exception with + * {@link Exception#getSuppressed getSuppressed}. Otherwise, any + * exception at the head of the quiet list (again with any later + * ones attached as its suppressed list) will be logged at + * {@code WARNING} level. + */ + T lax(boolean discard); } /** @@ -347,12 +498,17 @@ public interface Source extends Parsing>, javax.xml.transform.Source { /** - * Return an object of the expected {@code Source} subtype + * Returns an object of the expected {@code Source} subtype * reflecting any adjustments made with the other methods. + *

+ * Refer to {@link Parsing the {@code Parsing} class description} + * and the {@link Parsing#lax lax()} method for how any exceptions + * caught while applying best-effort adjustments are handled. * @return an implementing object of the expected Source subtype * @throws SQLException for any reason that {@code getSource} might * have thrown when supplying the corresponding non-Adjusting - * subtype of Source. + * subtype of Source, or for reasons saved while applying + * adjustments. */ T get() throws SQLException; } @@ -392,12 +548,16 @@ public interface Result extends Parsing>, javax.xml.transform.Result { /** - * Return an object of the expected {@code Result} subtype + * Returns an object of the expected {@code Result} subtype * reflecting any adjustments made with the other methods. + * Refer to {@link Parsing the {@code Parsing} class description} + * and the {@link Parsing#lax lax()} method for how any exceptions + * caught while applying best-effort adjustments are handled. * @return an implementing object of the expected Result subtype * @throws SQLException for any reason that {@code getResult} might * have thrown when supplying the corresponding non-Adjusting - * subtype of Result. + * subtype of Result, or for reasons saved while applying + * adjustments. */ T get() throws SQLException; } @@ -428,7 +588,7 @@ public interface Result public interface SourceResult extends Result { /** - * Supply the {@code Source} instance that is the source of the + * Supplies the {@code Source} instance that is the source of the * content. *

* This method must be called before any of the inherited adjustment @@ -484,7 +644,8 @@ SourceResult set(javax.xml.transform.stax.StAXSource source) throws SQLException; /** - * Provide the content to be copied in the form of a {@code String}. + * Provides the content to be copied in the form of a + * {@code String}. *

* An exception from the pattern of {@code Source}-typed arguments, * this method simplifies retrofitting adjustments into code that @@ -507,11 +668,14 @@ SourceResult set(javax.xml.transform.dom.DOMSource source) throws SQLException; /** - * Return the result {@code SQLXML} instance ready for handing off + * Returns the result {@code SQLXML} instance ready for handing off * to PostgreSQL. *

- * This method must be called after any of the inherited adjustment - * methods. + * The handling/logging of exceptions normally handled in a + * {@code get} method happens here for a {@code SourceResult}. + *

+ * Any necessary calls of the inherited adjustment methods must be + * made before this method is called. */ SQLXML getSQLXML() throws SQLException; } diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java index e735376c2..3c0605759 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -36,6 +36,7 @@ import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.HashMap; @@ -65,6 +66,7 @@ import javax.xml.validation.SchemaFactory; import org.postgresql.pljava.Adjusting; +import static org.postgresql.pljava.Adjusting.XML.setFirstSupported; import org.postgresql.pljava.annotation.Function; import org.postgresql.pljava.annotation.MappedUDT; import org.postgresql.pljava.annotation.SQLAction; @@ -518,33 +520,51 @@ private static void prepareXMLTransform(String name, SQLXML source, int how, builtin ? TransformerFactory.newDefaultInstance() : TransformerFactory.newInstance(); - String exf = - "http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions"; - String ecl = "jdk.xml.transform.extensionClassLoader"; + + String legacy_pfx = "http://www.oracle.com/xml/jaxp/properties/"; + String java17_pfx = "jdk.xml."; + String exf_sfx = "enableExtensionFunctions"; + + String ecl_legacy = "jdk.xml.transform.extensionClassLoader"; + String ecl_java17 = "jdk.xml.extensionClassLoader"; + Source src = sxToSource(source, how, adjust); + try { - try - { - tf.setFeature(exf, enableExtensionFunctions); - } - catch ( TransformerConfigurationException e ) + Exception e; + + e = setFirstSupported(tf::setFeature, enableExtensionFunctions, + List.of(TransformerConfigurationException.class), null, + java17_pfx + exf_sfx, legacy_pfx + exf_sfx); + + if ( null != e ) { - logMessage("WARNING", - "non-builtin transformer: ignoring " + e.getMessage()); + if ( builtin ) + throw new SQLException( + "Configuring XML transformation: " + e.getMessage(), e); + else + logMessage("WARNING", + "non-builtin transformer: ignoring " + e.getMessage()); } if ( withJava ) { - try - { - tf.setAttribute(ecl, - Thread.currentThread().getContextClassLoader()); - } - catch ( IllegalArgumentException e ) + e = setFirstSupported(tf::setAttribute, + Thread.currentThread().getContextClassLoader(), + List.of(IllegalArgumentException.class), null, + ecl_java17, ecl_legacy); + + if ( null != e ) { - logMessage("WARNING", - "non-builtin transformer: ignoring " + e.getMessage()); + if ( builtin ) + throw new SQLException( + "Configuring XML transformation: " + + e.getMessage(), e); + else + logMessage("WARNING", + "non-builtin transformer: ignoring " + + e.getMessage()); } } diff --git a/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java b/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java index 1b3bb2a00..95655ccd7 100644 --- a/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java +++ b/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -157,9 +157,13 @@ /* ... for Adjusting API for Source / Result */ import java.io.StringReader; +import java.util.List; +import static javax.xml.XMLConstants.ACCESS_EXTERNAL_DTD; +import static javax.xml.XMLConstants.ACCESS_EXTERNAL_SCHEMA; import javax.xml.parsers.ParserConfigurationException; import javax.xml.validation.Schema; import org.postgresql.pljava.Adjusting; +import static org.postgresql.pljava.Adjusting.XML.setFirstSupported; import org.xml.sax.EntityResolver; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; @@ -4144,14 +4148,72 @@ Writable finish() throws IOException, SQLException AdjustingJAXPParser> implements Adjusting.XML.Parsing { + static final Logger s_logger = + Logger.getLogger("org.postgresql.pljava.jdbc"); + + private static final String JDK17 = "jdk.xml."; private static final String LIMIT = - "http://www.oracle.com/xml/jaxp/properties/"; + "http://www.oracle.com/xml/jaxp/properties/"; // "legacy" since 17 - /* - * Can get these from javax.xml.XMLConstants once assuming Java >= 7. + private Exception m_signaling; + private Exception m_quiet; + + protected void addSignaling(Exception e) + { + if ( null == e ) + return; + if ( null == m_signaling ) + m_signaling = e; + else + m_signaling.addSuppressed(e); + } + + protected void addQuiet(Exception e) + { + if ( null == e ) + return; + if ( null == m_quiet ) + m_quiet = e; + else + m_quiet.addSuppressed(e); + } + + protected boolean anySignaling() + { + return null != m_signaling; + } + + /** + * Returns whatever is on the signaling list, while logging (at + * {@code WARNING} level) whatever is on the quiet list. + *

+ * Both lists are left cleared. + * @return the head exception on the signaling list, or null if none */ - private static final String ACCESS = - "http://javax.xml.XMLConstants/property/accessExternal"; + protected Exception exceptions() + { + Exception e = m_quiet; + m_quiet = null; + if ( null != e ) + s_logger.log(WARNING, + "some XML processing limits were not successfully adjusted", + e); + e = m_signaling; + m_signaling = null; + return e; + } + + @Override + public T lax(boolean discard) + { + if ( null != m_quiet ) + { + if ( ! discard ) + addSignaling(m_quiet); + m_quiet = null; + } + return (T)this; + } @Override public T defaults() @@ -4165,6 +4227,7 @@ public T defaults() public T elementAttributeLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "elementAttributeLimit", LIMIT + "elementAttributeLimit"); } @@ -4172,6 +4235,7 @@ public T elementAttributeLimit(int limit) public T entityExpansionLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "entityExpansionLimit", LIMIT + "entityExpansionLimit"); } @@ -4179,6 +4243,7 @@ public T entityExpansionLimit(int limit) public T entityReplacementLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "entityReplacementLimit", LIMIT + "entityReplacementLimit"); } @@ -4186,6 +4251,7 @@ public T entityReplacementLimit(int limit) public T maxElementDepth(int depth) { return setFirstSupportedProperty(depth, + JDK17 + "maxElementDepth", LIMIT + "maxElementDepth"); } @@ -4193,6 +4259,7 @@ public T maxElementDepth(int depth) public T maxGeneralEntitySizeLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "maxGeneralEntitySizeLimit", LIMIT + "maxGeneralEntitySizeLimit"); } @@ -4200,6 +4267,7 @@ public T maxGeneralEntitySizeLimit(int limit) public T maxParameterEntitySizeLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "maxParameterEntitySizeLimit", LIMIT + "maxParameterEntitySizeLimit"); } @@ -4207,6 +4275,7 @@ public T maxParameterEntitySizeLimit(int limit) public T maxXMLNameLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "maxXMLNameLimit", LIMIT + "maxXMLNameLimit"); } @@ -4214,19 +4283,20 @@ public T maxXMLNameLimit(int limit) public T totalEntitySizeLimit(int limit) { return setFirstSupportedProperty(limit, + JDK17 + "totalEntitySizeLimit", LIMIT + "totalEntitySizeLimit"); } @Override public T accessExternalDTD(String protocols) { - return setFirstSupportedProperty(protocols, ACCESS + "DTD"); + return setFirstSupportedProperty(protocols, ACCESS_EXTERNAL_DTD); } @Override public T accessExternalSchema(String protocols) { - return setFirstSupportedProperty(protocols, ACCESS + "Schema"); + return setFirstSupportedProperty(protocols, ACCESS_EXTERNAL_SCHEMA); } @Override @@ -4314,7 +4384,6 @@ static class SAXDOMErrorHandler implements ErrorHandler */ static final Pattern s_wrapelement = Pattern.compile( "^cvc-elt\\.1(?:\\.a)?+:.*pljava-content-wrap"); - final Logger m_logger = Logger.getLogger("org.postgresql.pljava.jdbc"); private int m_wrapCount; static SAXDOMErrorHandler instance(boolean wrapped) @@ -4364,7 +4433,8 @@ public void fatalError(SAXParseException exception) throws SAXException @Override public void warning(SAXParseException exception) throws SAXException { - m_logger.log(WARNING, exception.getMessage(), exception); + AdjustingJAXPParser.s_logger + .log(WARNING, exception.getMessage(), exception); } } @@ -4526,6 +4596,19 @@ public AdjustingSourceResult set(String source) return set(new StreamSource(new StringReader(source))); } + @Override + public AdjustingSourceResult get() throws SQLException + { + return this; // for this class, get is a noop + } + + @Override + public AdjustingSourceResult lax(boolean discard) + { + theAdjustable().lax(discard); + return this; + } + @Override public SQLXML getSQLXML() throws SQLException { @@ -4535,6 +4618,10 @@ public SQLXML getSQLXML() throws SQLException if ( null == m_copier ) throw new IllegalStateException( "AdjustingSourceResult getSQLXML called before set"); + + // Exception handling/logging for adjustments will happen in + // theAdjustable().get(), during finish() here. + Writable result = null; try { @@ -4578,12 +4665,6 @@ private Adjusting.XML.Source theAdjustable() return m_copier.getAdjustable(); } - @Override - public AdjustingSourceResult get() throws SQLException - { - return this; // for this class, get is a noop - } - @Override public AdjustingSourceResult allowDTD(boolean v) { @@ -4748,8 +4829,11 @@ public StreamResult get() throws SQLException throw new IllegalStateException( "AdjustingStreamResult get() called more than once"); + // Exception handling/logging for theVerifierSource happens here XMLReader xr = theVerifierSource().get().getXMLReader(); + OutputStream os; + try { m_vwo.setVerifier(new Verifier(xr)); @@ -4759,18 +4843,29 @@ public StreamResult get() throws SQLException { throw normalizedException(e); } + StreamResult sr; + if ( m_preferWriter ) sr = new StreamResult( new OutputStreamWriter(os, m_serverCS.newEncoder())); else sr = new StreamResult(os); + m_vwo = null; m_verifierSource = null; m_serverCS = null; + return sr; } + @Override + public AdjustingStreamResult lax(boolean discard) + { + theVerifierSource().lax(discard); + return this; + } + @Override public AdjustingStreamResult allowDTD(boolean v) { @@ -4860,7 +4955,6 @@ static class AdjustingSAXSource private XMLReader m_xr; private InputSource m_is; private boolean m_wrapped; - private SAXException m_except; private boolean m_hasCalledDefaults; static class Dummy extends AdjustingSAXSource @@ -4940,7 +5034,7 @@ private SAXParserFactory theFactory() private XMLReader theReader() { - if ( null != m_except ) + if ( anySignaling() ) return null; if ( null != m_spf ) @@ -4949,16 +5043,12 @@ private XMLReader theReader() { m_xr = m_spf.newSAXParser().getXMLReader(); } - catch ( SAXException e ) - { - m_except = e; - return null; - } - catch ( ParserConfigurationException e ) + catch ( SAXException | ParserConfigurationException e ) { - m_except = new SAXException(e.getMessage(), e); + addSignaling(e); return null; } + m_spf = null; if ( m_wrapped ) m_xr = new SAXUnwrapFilter(m_xr); @@ -4991,9 +5081,11 @@ public SAXSource get() throws SQLException throw new IllegalStateException( "AdjustingSAXSource get() called more than once"); - XMLReader xr; - if ( null != m_except || null == (xr = theReader()) ) - throw normalizedException(m_except); + XMLReader xr = theReader(); + + Exception e = exceptions(); + if ( null != e ) + throw normalizedException(e); SAXSource ss = new SAXSource(xr, m_is); m_xr = null; @@ -5031,18 +5123,11 @@ public AdjustingSAXSource setFirstSupportedFeature( if ( null == r ) // pending exception, nothing to be done return this; - for ( String name : names ) - { - try - { - r.setFeature(name, value); - break; - } - catch ( SAXNotRecognizedException | SAXNotSupportedException e ) - { - e.printStackTrace(); // XXX - } - } + addQuiet(setFirstSupported(r::setFeature, value, + List.of(SAXNotRecognizedException.class, + SAXNotSupportedException.class), + this::addSignaling, names)); + return this; } @@ -5054,22 +5139,11 @@ public AdjustingSAXSource setFirstSupportedProperty( if ( null == r ) // pending exception, nothing to be done return this; - for ( String name : names ) - { - try - { - r.setProperty(name, value); - break; - } - catch ( SAXNotRecognizedException e ) - { - e.printStackTrace(); // XXX - } - catch ( SAXNotSupportedException e ) - { - e.printStackTrace(); // XXX - } - } + addQuiet(setFirstSupported(r::setProperty, value, + List.of(SAXNotRecognizedException.class, + SAXNotSupportedException.class), + this::addSignaling, names)); + return this; } @@ -5227,6 +5301,8 @@ public StAXSource get() throws SQLException if ( null == m_xif ) throw new IllegalStateException( "AdjustingStAXSource get() called more than once"); + + StAXSource ss = null; try { XMLStreamReader xsr = m_xif.createXMLStreamReader( @@ -5234,12 +5310,18 @@ public StAXSource get() throws SQLException if ( m_wrapped ) xsr = new StAXUnwrapFilter(xsr); m_xif = null; // too late for any more adjustments - return new StAXSource(xsr); + ss = new StAXSource(xsr); } catch ( Exception e ) { - throw normalizedException(e); + addSignaling(e); } + + Exception e = exceptions(); + if ( null != e ) + throw normalizedException(e); + + return ss; } @Override @@ -5286,18 +5368,9 @@ public AdjustingStAXSource setFirstSupportedFeature( boolean value, String... names) { XMLInputFactory xif = theFactory(); - for ( String name : names ) - { - try - { - xif.setProperty(name, value); - break; - } - catch ( IllegalArgumentException e ) - { - e.printStackTrace(); // XXX - } - } + addQuiet(setFirstSupported(xif::setProperty, value, + List.of(IllegalArgumentException.class), + this::addSignaling, names)); return this; } @@ -5306,18 +5379,9 @@ public AdjustingStAXSource setFirstSupportedProperty( Object value, String... names) { XMLInputFactory xif = theFactory(); - for ( String name : names ) - { - try - { - xif.setProperty(name, value); - break; - } - catch ( IllegalArgumentException e ) - { - e.printStackTrace(); // XXX - } - } + addQuiet(setFirstSupported(xif::setProperty, value, + List.of(IllegalArgumentException.class), + this::addSignaling, names)); return this; } } @@ -5367,23 +5431,30 @@ public DOMSource get() throws SQLException if ( null == m_dbf ) throw new IllegalStateException( "AdjustingDOMSource get() called more than once"); + + DOMSource ds = null; try { DocumentBuilder db = m_dbf.newDocumentBuilder(); db.setErrorHandler(SAXDOMErrorHandler.instance(m_wrapped)); if ( null != m_resolver ) db.setEntityResolver(m_resolver); - DOMSource ds = new DOMSource(db.parse(m_is)); + ds = new DOMSource(db.parse(m_is)); if ( m_wrapped ) domUnwrap(ds); m_dbf = null; m_is = null; - return ds; } catch ( Exception e ) { - throw normalizedException(e); + addSignaling(e); } + + Exception e = exceptions(); + if ( null != e ) + throw normalizedException(e); + + return ds; } @Override @@ -5405,18 +5476,9 @@ public AdjustingDOMSource setFirstSupportedFeature( boolean value, String... names) { DocumentBuilderFactory dbf = theFactory(); - for ( String name : names ) - { - try - { - dbf.setFeature(name, value); - break; - } - catch ( ParserConfigurationException e ) - { - e.printStackTrace(); // XXX - } - } + addQuiet(setFirstSupported(dbf::setFeature, value, + List.of(ParserConfigurationException.class), + this::addSignaling, names)); return this; } @@ -5425,18 +5487,9 @@ public AdjustingDOMSource setFirstSupportedProperty( Object value, String... names) { DocumentBuilderFactory dbf = theFactory(); - for ( String name : names ) - { - try - { - dbf.setAttribute(name, value); - break; - } - catch ( IllegalArgumentException e ) - { - e.printStackTrace(); // XXX - } - } + addQuiet(setFirstSupported(dbf::setAttribute, value, + List.of(IllegalArgumentException.class), + this::addSignaling, names)); return this; } From 17b7d7cc70a521b490ec09498d68567a9b282761 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 23 Aug 2023 11:53:56 -0400 Subject: [PATCH 05/25] PG compatibility horizon to 9.5 PostgreSQL 9.5 has been advertised as the oldest supported version for PL/Java 1.6.x since 1.6.0. Declutter by removing conditional code lingering from support of older versions. In passing, add a couple SPI constants that showed up later while my back was turned. --- .../example/annotation/ConditionalDDR.java | 49 +-- .../example/annotation/Enumeration.java | 22 +- .../pljava/example/annotation/JDBC42_21.java | 9 +- .../pljava/example/annotation/PGF1010962.java | 9 +- .../pljava/example/annotation/PassXML.java | 24 +- .../pljava/example/annotation/PreJSR310.java | 7 +- .../annotation/RecordParameterDefaults.java | 7 +- .../example/annotation/SetOfRecordTest.java | 8 +- .../pljava/example/annotation/Triggers.java | 8 +- .../example/annotation/TypeRoundTripper.java | 12 +- .../annotation/UnicodeRoundTripTest.java | 9 +- .../example/annotation/VarlenaUDTTest.java | 12 +- .../example/annotation/XMLRenderedTypes.java | 13 +- pljava-so/src/main/c/Backend.c | 354 +++++++----------- pljava-so/src/main/c/DualState.c | 6 +- pljava-so/src/main/c/Exception.c | 10 +- pljava-so/src/main/c/ExecutionPlan.c | 10 +- pljava-so/src/main/c/Function.c | 11 +- pljava-so/src/main/c/InstallHelper.c | 129 +------ pljava-so/src/main/c/SPI.c | 11 +- pljava-so/src/main/c/Session.c | 26 +- pljava-so/src/main/c/TypeOid.c | 6 +- pljava-so/src/main/c/VarlenaWrapper.c | 116 +----- pljava-so/src/main/c/XactListener.c | 4 +- pljava-so/src/main/c/type/AclId.c | 6 +- pljava-so/src/main/c/type/Array.c | 12 +- pljava-so/src/main/c/type/Oid.c | 18 +- pljava-so/src/main/c/type/SQLXMLImpl.c | 18 +- pljava-so/src/main/c/type/String.c | 4 - pljava-so/src/main/c/type/Timestamp.c | 18 +- pljava-so/src/main/c/type/Type.c | 36 +- pljava-so/src/main/c/type/UDT.c | 11 +- pljava-so/src/main/c/type/byte_array.c | 22 +- pljava-so/src/main/include/pljava/Backend.h | 8 +- pljava-so/src/main/include/pljava/Exception.h | 10 +- pljava-so/src/main/include/pljava/pljava.h | 38 +- .../org/postgresql/pljava/internal/SPI.java | 5 +- src/site/markdown/build/versions.md | 2 +- 38 files changed, 255 insertions(+), 825 deletions(-) diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/ConditionalDDR.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/ConditionalDDR.java index 0140f4372..253a03086 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/ConditionalDDR.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/ConditionalDDR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2023 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 @@ -64,7 +64,7 @@ * local, so it is reverted when the transaction completes. *

* In addition to the goodness-of-life examples, this file also generates - * several statements setting PostgreSQL-version-based implementor tags that + * one or more statements setting PostgreSQL-version-based implementor tags that * are relied on by various other examples in this directory. */ @SQLAction(provides={"LifeIsGood","LifeIsNotGood"}, install= @@ -78,51 +78,12 @@ ) @SQLAction(implementor="LifeIsGood", install= - "SELECT javatest.logmessage('INFO', 'Looking good!')" + "SELECT javatest.logmessage('INFO', 'ConditionlDDR looking good!')" ) @SQLAction(implementor="LifeIsNotGood", install= - "SELECT javatest.logmessage('WARNING', 'This should not be executed')" -) - -@SQLAction(provides="postgresql_ge_80300", install= - "SELECT CASE WHEN" + - " 80300 <= CAST(current_setting('server_version_num') AS integer)" + - " THEN set_config('pljava.implementors', 'postgresql_ge_80300,' || " + - " current_setting('pljava.implementors'), true) " + - "END" -) - -@SQLAction(provides="postgresql_ge_80400", install= - "SELECT CASE WHEN" + - " 80400 <= CAST(current_setting('server_version_num') AS integer)" + - " THEN set_config('pljava.implementors', 'postgresql_ge_80400,' || " + - " current_setting('pljava.implementors'), true) " + - "END" -) - -@SQLAction(provides="postgresql_ge_90000", install= - "SELECT CASE WHEN" + - " 90000 <= CAST(current_setting('server_version_num') AS integer)" + - " THEN set_config('pljava.implementors', 'postgresql_ge_90000,' || " + - " current_setting('pljava.implementors'), true) " + - "END" -) - -@SQLAction(provides="postgresql_ge_90100", install= - "SELECT CASE WHEN" + - " 90100 <= CAST(current_setting('server_version_num') AS integer)" + - " THEN set_config('pljava.implementors', 'postgresql_ge_90100,' || " + - " current_setting('pljava.implementors'), true) " + - "END" -) - -@SQLAction(provides="postgresql_ge_90300", install= - "SELECT CASE WHEN" + - " 90300 <= CAST(current_setting('server_version_num') AS integer)" + - " THEN set_config('pljava.implementors', 'postgresql_ge_90300,' || " + - " current_setting('pljava.implementors'), true) " + - "END" + "SELECT javatest.logmessage('WARNING', " + + " 'ConditionalDDR: This should not be executed')" ) @SQLAction(provides="postgresql_ge_100000", install= diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Enumeration.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Enumeration.java index 2fcee7df1..359bb2871 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Enumeration.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Enumeration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2023 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,16 +21,12 @@ /** * Confirms the mapping of PG enum and Java String, and arrays of each, as * parameter and return types. - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. PostgreSQL before 8.3 - * did not have enum types. */ -@SQLAction(provides="mood type", implementor="postgresql_ge_80300", +@SQLAction(provides="mood type", install="CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy')", remove="DROP TYPE mood" ) -@SQLAction(implementor="postgresql_ge_80300", +@SQLAction( requires={"textToMood", "moodToText", "textsToMoods", "moodsToTexts"}, install={ "SELECT textToMood('happy')", @@ -41,26 +37,22 @@ ) public class Enumeration { - @Function(requires="mood type", provides="textToMood", type="mood", - implementor="postgresql_ge_80300") + @Function(requires="mood type", provides="textToMood", type="mood") public static String textToMood(String s) { return s; } - @Function(requires="mood type", provides="moodToText", - implementor="postgresql_ge_80300") + @Function(requires="mood type", provides="moodToText") public static String moodToText(@SQLType("mood")String s) { return s; } - @Function(requires="mood type", provides="textsToMoods", type="mood", - implementor="postgresql_ge_80300") + @Function(requires="mood type", provides="textsToMoods", type="mood") public static Iterator textsToMoods(String[] ss) { return Arrays.asList(ss).iterator(); } - @Function(requires="mood type", provides="moodsToTexts", - implementor="postgresql_ge_80300") + @Function(requires="mood type", provides="moodsToTexts") public static Iterator moodsToTexts(@SQLType("mood[]")String[] ss) { return Arrays.asList(ss).iterator(); diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/JDBC42_21.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/JDBC42_21.java index 1b0d35e28..ff2c23116 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/JDBC42_21.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/JDBC42_21.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2022 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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,20 +14,15 @@ import org.postgresql.pljava.annotation.Function; import org.postgresql.pljava.annotation.SQLAction; -import org.postgresql.pljava.example.annotation.ConditionalDDR; // for javadoc - /** * Exercise new mappings between date/time types and java.time classes * (JDBC 4.2 change 21). *

* Defines a method {@link #javaSpecificationGE javaSpecificationGE} that may be * of use for other examples. - *

- * Relies on PostgreSQL-version-specific implementor tags set up in the - * {@link ConditionalDDR} example. */ @SQLAction( - implementor="postgresql_ge_90300",requires="TypeRoundTripper.roundTrip", + requires="TypeRoundTripper.roundTrip", install={ " SELECT" + " CASE WHEN every(orig = roundtripped)" + diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PGF1010962.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PGF1010962.java index 2b06f481e..747f2ef6d 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PGF1010962.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PGF1010962.java @@ -10,12 +10,8 @@ /** * A gnarly test of TupleDesc reference management, crafted by Johann Oskarsson * for bug report 1010962 on pgFoundry. - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. Before PostgreSQL 8.4, - * there is no array of {@code RECORD}, which this test requires. */ -@SQLAction(requires="1010962 func", implementor="postgresql_ge_80400", +@SQLAction(requires="1010962 func", install={ "CREATE TYPE javatest.B1010962 AS ( b1_val float8, b2_val int)", @@ -51,8 +47,7 @@ public class PGF1010962 * @param receiver Looks polymorphic, but expects an array of A1010962 * @return 0 */ - @Function(schema="javatest", provides="1010962 func", - implementor="postgresql_ge_80400") + @Function(schema="javatest", provides="1010962 func") public static int complexParam( ResultSet receiver[] ) throws SQLException { diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java index e735376c2..d7d8c2a9f 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -112,16 +112,7 @@ "END" ) -@SQLAction(implementor="postgresql_ge_80400", - provides="postgresql_xml_ge84", - install= - "SELECT CASE (SELECT 1 FROM pg_type WHERE typname = 'xml') WHEN 1" + - " THEN set_config('pljava.implementors', 'postgresql_xml_ge84,' || " + - " current_setting('pljava.implementors'), true) " + - "END" -) - -@SQLAction(implementor="postgresql_xml_ge84", requires="echoXMLParameter", +@SQLAction(implementor="postgresql_xml", requires="echoXMLParameter", install= "WITH" + " s(how) AS (SELECT generate_series(1, 7))," + @@ -146,7 +137,7 @@ " r" ) -@SQLAction(implementor="postgresql_xml_ge84", requires="proxiedXMLEcho", +@SQLAction(implementor="postgresql_xml", requires="proxiedXMLEcho", install= "WITH" + " s(how) AS (SELECT unnest('{1,2,4,5,6,7}'::int[]))," + @@ -170,7 +161,7 @@ " r" ) -@SQLAction(implementor="postgresql_xml_ge84", requires="lowLevelXMLEcho", +@SQLAction(implementor="postgresql_xml", requires="lowLevelXMLEcho", install={ "SELECT" + " preparexmlschema('schematest', $$" + @@ -702,7 +693,7 @@ private static SQLXML echoSQLXML(SQLXML sx, int howin, int howout) * still be exercised by calling this method, explicitly passing * {@code adjust => NULL}. */ - @Function(schema="javatest", implementor="postgresql_xml_ge84", + @Function(schema="javatest", implementor="postgresql_xml", provides="lowLevelXMLEcho") public static SQLXML lowLevelXMLEcho( SQLXML sx, int how, @SQLType(defaultValue={}) ResultSet adjust) @@ -1046,12 +1037,9 @@ public static SQLXML mockedXMLEcho(String chars) /** * Text-typed variant of lowLevelXMLEcho (does not require XML type). - *

- * It does declare a parameter default, limiting it to PostgreSQL 8.4 or - * later. */ @Function(schema="javatest", name="lowLevelXMLEcho", - type="text", implementor="postgresql_ge_80400") + type="text") public static SQLXML lowLevelXMLEcho_(@SQLType("text") SQLXML sx, int how, @SQLType(defaultValue={}) ResultSet adjust) throws SQLException diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PreJSR310.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PreJSR310.java index e430e25d1..726d46a5d 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PreJSR310.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PreJSR310.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -29,9 +29,6 @@ * Some tests of pre-JSR 310 date/time/timestamp conversions. *

* For now, just {@code java.sql.Date}, thanks to issue #199. - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. */ @SQLAction(provides="language java_tzset", install={ "SELECT sqlj.alias_java_language('java_tzset', true)" @@ -39,7 +36,7 @@ "DROP LANGUAGE java_tzset" }) -@SQLAction(implementor="postgresql_ge_90300", // needs LATERAL +@SQLAction( requires="issue199", install={ "SELECT javatest.issue199()" }) diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java index 09d3dbbe8..34e1aeb75 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -28,9 +28,6 @@ * function. *

* Also tests the proper DDR generation of defaults for such parameters. - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. */ @SQLAction( provides = "paramtypeinfo type", // created in Triggers.java @@ -64,7 +61,6 @@ public class RecordParameterDefaults implements ResultSetProvider @Function( requires = "paramtypeinfo type", schema = "javatest", - implementor = "postgresql_ge_80400", // supports function param DEFAULTs type = "javatest.paramtypeinfo" ) public static ResultSetProvider paramDefaultsRecord( @@ -87,7 +83,6 @@ public static ResultSetProvider paramDefaultsRecord( */ @Function( requires = "foobar tables", // created in Triggers.java - implementor = "postgresql_ge_80400", // supports function param DEFAULTs schema = "javatest" ) public static String paramDefaultsNamedRow( diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/SetOfRecordTest.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/SetOfRecordTest.java index 13fce44d4..49abf1382 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/SetOfRecordTest.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/SetOfRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -26,12 +26,8 @@ * Example implementing the {@code ResultSetHandle} interface, to return * the {@link ResultSet} from any SQL {@code SELECT} query passed as a string * to the {@link #executeSelect executeSelect} function. - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. Before PostgreSQL 8.4, - * there was no {@code =} or {@code DISTINCT FROM} operator between row types. */ -@SQLAction(requires="selecttorecords fn", implementor="postgresql_ge_80400", +@SQLAction(requires="selecttorecords fn", install= " SELECT " + " CASE WHEN r IS DISTINCT FROM ROW('Foo'::varchar, 1::integer, 1.5::float, " + diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Triggers.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Triggers.java index 804ef9d83..bfdbf8c0f 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Triggers.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/Triggers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -38,8 +38,8 @@ * also create a function and trigger that uses transition tables. *

* This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. Constraint triggers - * appear in PG 9.1, transition tables in PG 10. + * version, set up in the {@link ConditionalDDR} example. Transition tables + * appear in PG 10. */ @SQLAction( provides = "foobar tables", @@ -135,10 +135,8 @@ public static void examineRows(TriggerData td) /** * Throw exception if value to be inserted is 44. - * Constraint triggers first became available in PostgreSQL 9.1. */ @Function( - implementor = "postgresql_ge_90100", requires = "foobar tables", provides = "constraint triggers", schema = "javatest", diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/TypeRoundTripper.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/TypeRoundTripper.java index df613c266..8c3151556 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/TypeRoundTripper.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/TypeRoundTripper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -36,8 +36,6 @@ import org.postgresql.pljava.annotation.SQLAction; import org.postgresql.pljava.annotation.SQLType; -import org.postgresql.pljava.example.annotation.ConditionalDDR; // for javadoc - /** * A class to simplify testing of PL/Java's mappings between PostgreSQL and * Java/JDBC types. @@ -94,11 +92,8 @@ * (VALUES (timestamptz '2017-08-21 18:25:29.900005Z')) AS p(orig), * roundtrip(p) AS (roundtripped timestamptz); * - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. */ -@SQLAction(implementor = "postgresql_ge_90300", // funcs see earlier FROM items +@SQLAction( requires = {"TypeRoundTripper.roundTrip", "point mirror type"}, install = { " SELECT" + @@ -309,8 +304,7 @@ private TypeRoundTripper() { } @Function( schema = "javatest", type = "RECORD", - provides = "TypeRoundTripper.roundTrip", - implementor = "postgresql_ge_80400" // supports function param DEFAULTs + provides = "TypeRoundTripper.roundTrip" ) public static boolean roundTrip( ResultSet in, @SQLType(defaultValue="") String classname, diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java index 4f2c0ec47..6b06d4d9a 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2023 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 @@ -35,11 +35,10 @@ * if {@code matched} is false or the original and returned arrays or strings * do not match as seen in SQL. *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example, and also sets its own. + * This example sets an {@code implementor} tag based on a PostgreSQL condition, + * as further explained in the {@link ConditionalDDR} example. */ -@SQLAction(provides="postgresql_unicodetest", - implementor="postgresql_ge_90000", install= +@SQLAction(provides="postgresql_unicodetest", install= "SELECT CASE" + " WHEN 'UTF8' = current_setting('server_encoding')" + " THEN set_config('pljava.implementors', 'postgresql_unicodetest,' ||" + diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/VarlenaUDTTest.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/VarlenaUDTTest.java index ae1be8991..c9982490e 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/VarlenaUDTTest.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/VarlenaUDTTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015- Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2023 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 @@ -29,14 +29,12 @@ * characters. That makes it easy to test how big a value gets correctly stored * and retrieved. It should be about a GB, but in issue 52 was failing at 32768 * because of a narrowing assignment in the native code. - *

- * This example relies on {@code implementor} tags reflecting the PostgreSQL - * version, set up in the {@link ConditionalDDR} example. */ -@SQLAction(requires="varlena UDT", implementor="postgresql_ge_80300", install= +@SQLAction(requires="varlena UDT", install= " SELECT CASE v::text = v::javatest.VarlenaUDTTest::text " + -" WHEN true THEN javatest.logmessage('INFO', 'works for ' || v) " + -" ELSE javatest.logmessage('WARNING', 'fails for ' || v) " + +" WHEN true " + +" THEN javatest.logmessage('INFO', 'VarlenaUDTTest works for ' || v) " + +" ELSE javatest.logmessage('WARNING', 'VarlenaUDTTest fails for ' || v) " + " END " + " FROM (VALUES (('32767')), (('32768')), (('65536')), (('1048576'))) " + " AS t ( v )" diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java index 871e96445..5cd21326f 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2019-2023 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 @@ -27,19 +27,10 @@ *

* Everything mentioning the type XML here needs a conditional implementor tag * in case of being loaded into a PostgreSQL instance built without that type. - * The {@code pg_node_tree} type appears in 9.1. */ -@SQLAction(implementor="postgresql_ge_90100", - provides="postgresql_xml_ge91", - install= - "SELECT CASE (SELECT 1 FROM pg_type WHERE typname = 'xml') WHEN 1" + - " THEN set_config('pljava.implementors', 'postgresql_xml_ge91,' || " + - " current_setting('pljava.implementors'), true) " + - "END" -) public class XMLRenderedTypes { - @Function(schema="javatest", implementor="postgresql_xml_ge91") + @Function(schema="javatest", implementor="postgresql_xml") public static SQLXML pgNodeTreeAsXML(@SQLType("pg_node_tree") SQLXML pgt) throws SQLException { diff --git a/pljava-so/src/main/c/Backend.c b/pljava-so/src/main/c/Backend.c index 287652fd2..5a3512d9d 100644 --- a/pljava-so/src/main/c/Backend.c +++ b/pljava-so/src/main/c/Backend.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -58,10 +59,6 @@ #include "pljava/SPI.h" #include "pljava/type/String.h" -#if PG_VERSION_NUM >= 90300 -#include "utils/timeout.h" -#endif - /* Include the 'magic block' that PostgreSQL 8.2 and up will use to ensure * that a module is not loaded into an incompatible server. */ @@ -250,152 +247,133 @@ static bool javaGE17 = false; static void initsequencer(enum initstage is, bool tolerant); -#if PG_VERSION_NUM >= 90100 - static bool check_libjvm_location( - char **newval, void **extra, GucSource source); - static bool check_vmoptions( - char **newval, void **extra, GucSource source); - static bool check_modulepath( - char **newval, void **extra, GucSource source); - static bool check_policy_urls( - char **newval, void **extra, GucSource source); - static bool check_enabled( - bool *newval, void **extra, GucSource source); - static bool check_java_thread_pg_entry( - int *newval, void **extra, GucSource source); - - /* Check hooks will always allow "setting" a value that is the same as - * current; otherwise, it would be frustrating to have just found settings - * that work, and be unable to save them with ALTER DATABASE SET ... because - * the check hook is called for that too, and would say it is too late.... - */ +static bool check_libjvm_location( + char **newval, void **extra, GucSource source); +static bool check_vmoptions( + char **newval, void **extra, GucSource source); +static bool check_modulepath( + char **newval, void **extra, GucSource source); +static bool check_policy_urls( + char **newval, void **extra, GucSource source); +static bool check_enabled( + bool *newval, void **extra, GucSource source); +static bool check_java_thread_pg_entry( + int *newval, void **extra, GucSource source); + +/* Check hooks will always allow "setting" a value that is the same as + * current; otherwise, it would be frustrating to have just found settings + * that work, and be unable to save them with ALTER DATABASE SET ... because + * the check hook is called for that too, and would say it is too late.... + */ - static bool check_libjvm_location( - char **newval, void **extra, GucSource source) - { - if ( initstage < IS_CAND_JVMOPENED ) - return true; - if ( libjvmlocation == *newval ) - return true; - if ( libjvmlocation && *newval && 0 == strcmp(libjvmlocation, *newval) ) - return true; - GUC_check_errmsg( - "too late to change \"pljava.libjvm_location\" setting"); - GUC_check_errdetail( - "Changing the setting can have no effect after " - "PL/Java has found and opened the library it points to."); - GUC_check_errhint( - "To try a different value, exit this session and start a new one."); - return false; - } +static bool check_libjvm_location( + char **newval, void **extra, GucSource source) +{ + if ( initstage < IS_CAND_JVMOPENED ) + return true; + if ( libjvmlocation == *newval ) + return true; + if ( libjvmlocation && *newval && 0 == strcmp(libjvmlocation, *newval) ) + return true; + GUC_check_errmsg( + "too late to change \"pljava.libjvm_location\" setting"); + GUC_check_errdetail( + "Changing the setting can have no effect after " + "PL/Java has found and opened the library it points to."); + GUC_check_errhint( + "To try a different value, exit this session and start a new one."); + return false; +} - static bool check_vmoptions( - char **newval, void **extra, GucSource source) - { - if ( initstage < IS_JAVAVM_OPTLIST ) - return true; - if ( vmoptions == *newval ) - return true; - if ( vmoptions && *newval && 0 == strcmp(vmoptions, *newval) ) - return true; - GUC_check_errmsg( - "too late to change \"pljava.vmoptions\" setting"); - GUC_check_errdetail( - "Changing the setting can have no effect after " - "PL/Java has started the Java virtual machine."); - GUC_check_errhint( - "To try a different value, exit this session and start a new one."); - return false; - } +static bool check_vmoptions( + char **newval, void **extra, GucSource source) +{ + if ( initstage < IS_JAVAVM_OPTLIST ) + return true; + if ( vmoptions == *newval ) + return true; + if ( vmoptions && *newval && 0 == strcmp(vmoptions, *newval) ) + return true; + GUC_check_errmsg( + "too late to change \"pljava.vmoptions\" setting"); + GUC_check_errdetail( + "Changing the setting can have no effect after " + "PL/Java has started the Java virtual machine."); + GUC_check_errhint( + "To try a different value, exit this session and start a new one."); + return false; +} - static bool check_modulepath( - char **newval, void **extra, GucSource source) - { - if ( initstage < IS_JAVAVM_OPTLIST ) - return true; - if ( modulepath == *newval ) - return true; - if ( modulepath && *newval && 0 == strcmp(modulepath, *newval) ) - return true; - GUC_check_errmsg( - "too late to change \"pljava.module_path\" setting"); - GUC_check_errdetail( - "Changing the setting has no effect after " - "PL/Java has started the Java virtual machine."); - GUC_check_errhint( - "To try a different value, exit this session and start a new one."); - return false; - } +static bool check_modulepath( + char **newval, void **extra, GucSource source) +{ + if ( initstage < IS_JAVAVM_OPTLIST ) + return true; + if ( modulepath == *newval ) + return true; + if ( modulepath && *newval && 0 == strcmp(modulepath, *newval) ) + return true; + GUC_check_errmsg( + "too late to change \"pljava.module_path\" setting"); + GUC_check_errdetail( + "Changing the setting has no effect after " + "PL/Java has started the Java virtual machine."); + GUC_check_errhint( + "To try a different value, exit this session and start a new one."); + return false; +} - static bool check_policy_urls( - char **newval, void **extra, GucSource source) - { - if ( initstage < IS_JAVAVM_OPTLIST ) - return true; - if ( policy_urls == *newval ) - return true; - if ( policy_urls && *newval && 0 == strcmp(policy_urls, *newval) ) - return true; - GUC_check_errmsg( - "too late to change \"pljava.policy_urls\" setting"); - GUC_check_errdetail( - "Changing the setting has no effect after " - "PL/Java has started the Java virtual machine."); - GUC_check_errhint( - "To try a different value, exit this session and start a new one."); - return false; - } +static bool check_policy_urls( + char **newval, void **extra, GucSource source) +{ + if ( initstage < IS_JAVAVM_OPTLIST ) + return true; + if ( policy_urls == *newval ) + return true; + if ( policy_urls && *newval && 0 == strcmp(policy_urls, *newval) ) + return true; + GUC_check_errmsg( + "too late to change \"pljava.policy_urls\" setting"); + GUC_check_errdetail( + "Changing the setting has no effect after " + "PL/Java has started the Java virtual machine."); + GUC_check_errhint( + "To try a different value, exit this session and start a new one."); + return false; +} - static bool check_enabled( - bool *newval, void **extra, GucSource source) - { - if ( initstage < IS_PLJAVA_ENABLED ) - return true; - if ( *newval ) - return true; - GUC_check_errmsg( - "too late to change \"pljava.enable\" setting"); - GUC_check_errdetail( - "Start-up has progressed past the point where it is checked."); - GUC_check_errhint( - "For another chance, exit this session and start a new one."); - return false; - } +static bool check_enabled( + bool *newval, void **extra, GucSource source) +{ + if ( initstage < IS_PLJAVA_ENABLED ) + return true; + if ( *newval ) + return true; + GUC_check_errmsg( + "too late to change \"pljava.enable\" setting"); + GUC_check_errdetail( + "Start-up has progressed past the point where it is checked."); + GUC_check_errhint( + "For another chance, exit this session and start a new one."); + return false; +} - static bool check_java_thread_pg_entry( - int *newval, void **extra, GucSource source) - { - if ( initstage < IS_PLJAVA_FOUND ) - return true; - if ( java_thread_pg_entry == *newval ) - return true; - GUC_check_errmsg( - "too late to change \"pljava.java_thread_pg_entry\" setting"); - GUC_check_errdetail( - "Start-up has progressed past the point where it is checked."); - GUC_check_errhint( - "For another chance, exit this session and start a new one."); - return false; - } -#endif +static bool check_java_thread_pg_entry( + int *newval, void **extra, GucSource source) +{ + if ( initstage < IS_PLJAVA_FOUND ) + return true; + if ( java_thread_pg_entry == *newval ) + return true; + GUC_check_errmsg( + "too late to change \"pljava.java_thread_pg_entry\" setting"); + GUC_check_errdetail( + "Start-up has progressed past the point where it is checked."); + GUC_check_errhint( + "For another chance, exit this session and start a new one."); + return false; +} -#if PG_VERSION_NUM < 90100 -#define errdetail_internal errdetail -#define ASSIGNHOOK(name,type) \ - static bool \ - CppConcat(assign_,name)(type newval, bool doit, GucSource source); \ - static bool \ - CppConcat(assign_,name)(type newval, bool doit, GucSource source) -#define ASSIGNRETURN(thing) return (thing) -#define ASSIGNRETURNIFCHECK(thing) if (doit) ; else return (thing) -#define ASSIGNRETURNIFNXACT(thing) \ - if (! deferInit && pljavaViableXact()) ; else return (thing) -#define ASSIGNSTRINGHOOK(name) \ - static const char * \ - CppConcat(assign_,name)(const char *newval, bool doit, GucSource source); \ - static const char * \ - CppConcat(assign_,name)(const char *newval, bool doit, GucSource source) -#else #define ASSIGNHOOK(name,type) \ static void \ CppConcat(assign_,name)(type newval, void *extra); \ @@ -406,7 +384,6 @@ static void initsequencer(enum initstage is, bool tolerant); #define ASSIGNRETURNIFNXACT(thing) \ if (! deferInit && pljavaViableXact()) ; else return #define ASSIGNSTRINGHOOK(name) ASSIGNHOOK(name, const char *) -#endif #define ASSIGNENUMHOOK(name) ASSIGNHOOK(name,int) #define ENUMBOOTVAL(entry) ((entry).val) @@ -796,18 +773,13 @@ static void initsequencer(enum initstage is, bool tolerant) * are just function parameters with evaluation order unknown. */ StringInfoData buf; -#if PG_VERSION_NUM >= 90200 -#define MOREHINT \ - appendStringInfo(&buf, \ - "using ALTER DATABASE %s SET ... FROM CURRENT or ", \ - pljavaDbName()), -#else -#define MOREHINT -#endif + ereport(NOTICE, ( errmsg("PL/Java successfully started after adjusting settings"), (initStringInfo(&buf), - MOREHINT + appendStringInfo(&buf, \ + "using ALTER DATABASE %s SET ... FROM CURRENT or ", \ + pljavaDbName()), errhint("The settings that worked should be saved (%s" "in the \"%s\" file). For a reminder of what has been set, " "try: SELECT name, setting FROM pg_settings WHERE name LIKE" @@ -816,7 +788,7 @@ static void initsequencer(enum initstage is, bool tolerant) superuser() ? PG_GETCONFIGOPTION("config_file") : "postgresql.conf")))); -#undef MOREHINT + if ( loadAsExtensionFailed ) { #if PG_VERSION_NUM < 130000 @@ -902,7 +874,7 @@ static void reLogWithChangedLevel(int level) else if ( ERRCODE_WARNING == category || ERRCODE_NO_DATA == category || ERRCODE_SUCCESSFUL_COMPLETION == category ) sqlstate = ERRCODE_INTERNAL_ERROR; -#if PG_VERSION_NUM >= 90500 + edata->elevel = level; edata->sqlerrcode = sqlstate; PG_TRY(); @@ -916,43 +888,6 @@ static void reLogWithChangedLevel(int level) } PG_END_TRY(); FreeErrorData(edata); -#else - if (!errstart(level, edata->filename, edata->lineno, - edata->funcname, NULL)) - { - FreeErrorData(edata); - return; - } - - errcode(sqlstate); - if (edata->message) - errmsg("%s", edata->message); - if (edata->detail) - errdetail("%s", edata->detail); - if (edata->detail_log) - errdetail_log("%s", edata->detail_log); - if (edata->hint) - errhint("%s", edata->hint); - if (edata->context) - errcontext("%s", edata->context); /* this may need to be trimmed */ -#if PG_VERSION_NUM >= 90300 - if (edata->schema_name) - err_generic_string(PG_DIAG_SCHEMA_NAME, edata->schema_name); - if (edata->table_name) - err_generic_string(PG_DIAG_TABLE_NAME, edata->table_name); - if (edata->column_name) - err_generic_string(PG_DIAG_COLUMN_NAME, edata->column_name); - if (edata->datatype_name) - err_generic_string(PG_DIAG_DATATYPE_NAME, edata->datatype_name); - if (edata->constraint_name) - err_generic_string(PG_DIAG_CONSTRAINT_NAME, edata->constraint_name); -#endif - if (edata->internalquery) - internalerrquery(edata->internalquery); - - FreeErrorData(edata); - errfinish(0); -#endif } void _PG_init() @@ -969,8 +904,7 @@ void _PG_init() * preparing the launch options before it is launched. PostgreSQL knows what * it is, but won't directly say; give it some choices and it'll pick one. * Alternatively, let Maven or Ant determine and add a -D at build time from - * the path.separator property. Maybe that's cleaner? This only works for - * PG_VERSION_NUM >= 90100. + * the path.separator property. Maybe that's cleaner? */ sep = first_path_var_separator(":;"); if ( NULL == sep ) @@ -1340,12 +1274,7 @@ static void pljavaQuickDieHandler(int signum) } static sigjmp_buf recoverBuf; -static void terminationTimeoutHandler( -#if PG_VERSION_NUM >= 90300 -#else - int signum -#endif -) +static void terminationTimeoutHandler() { kill(MyProcPid, SIGQUIT); @@ -1387,12 +1316,7 @@ static void _destroyJavaVM(int status, Datum dummy) { Invocation ctx; #ifdef USE_PLJAVA_SIGHANDLERS - -#if PG_VERSION_NUM >= 90300 TimeoutId tid; -#else - pqsigfunc saveSigAlrm; -#endif Invocation_pushBootContext(&ctx); if(sigsetjmp(recoverBuf, 1) != 0) @@ -1404,24 +1328,13 @@ static void _destroyJavaVM(int status, Datum dummy) return; } -#if PG_VERSION_NUM >= 90300 tid = RegisterTimeout(USER_TIMEOUT, terminationTimeoutHandler); enable_timeout_after(tid, 5000); -#else - saveSigAlrm = pqsignal(SIGALRM, terminationTimeoutHandler); - enable_sig_alarm(5000, false); -#endif elog(DEBUG2, "shutting down the Java virtual machine"); JNI_destroyVM(s_javaVM); -#if PG_VERSION_NUM >= 90300 disable_timeout(tid, false); -#else - disable_sig_alarm(false); - pqsignal(SIGALRM, saveSigAlrm); -#endif - #else Invocation_pushBootContext(&ctx); elog(DEBUG2, "shutting down the Java virtual machine"); @@ -1646,12 +1559,7 @@ static jint initializeJavaVM(JVMOptList *optList) #define GUCBOOTVAL(v) (v), #define GUCBOOTASSIGN(a, v) #define GUCFLAGS(f) (f), - -#if PG_VERSION_NUM >= 90100 #define GUCCHECK(h) (h), -#else -#define GUCCHECK(h) -#endif #define BOOL_GUC(name, short_desc, long_desc, valueAddr, bootValue, context, \ flags, check_hook, assign_hook, show_hook) \ @@ -1685,11 +1593,7 @@ static jint initializeJavaVM(JVMOptList *optList) #define PLJAVA_LIBJVMDEFAULT "libjvm" #endif -#if PG_VERSION_NUM >= 90200 #define PLJAVA_ENABLE_DEFAULT true -#else -#define PLJAVA_ENABLE_DEFAULT false -#endif #if PG_VERSION_NUM < 110000 #define PLJAVA_IMPLEMENTOR_FLAGS GUC_LIST_INPUT | GUC_LIST_QUOTE diff --git a/pljava-so/src/main/c/DualState.c b/pljava-so/src/main/c/DualState.c index e557231e5..17d32ab21 100644 --- a/pljava-so/src/main/c/DualState.c +++ b/pljava-so/src/main/c/DualState.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -44,10 +44,6 @@ extern void pljava_ExecutionPlan_initialize(void); #include "pljava/SQLInputFromTuple.h" #include "pljava/VarlenaWrapper.h" -#if PG_VERSION_NUM < 80400 -#include /* heap_freetuple was there then */ -#endif - static jclass s_DualState_class; static jmethodID s_DualState_resourceOwnerRelease; diff --git a/pljava-so/src/main/c/Exception.c b/pljava-so/src/main/c/Exception.c index 071b8cf49..ccac4e7b8 100644 --- a/pljava-so/src/main/c/Exception.c +++ b/pljava-so/src/main/c/Exception.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -59,7 +59,13 @@ Exception_featureNotSupported(const char* requestedFeature, const char* introVer appendStringInfoString(&buf, requestedFeature); appendStringInfoString(&buf, " lacks support in PostgreSQL version "); appendStringInfo(&buf, "%d.%d", - PG_VERSION_NUM / 10000, (PG_VERSION_NUM / 100) % 100); + PG_VERSION_NUM / 10000, +#if PG_VERSION_NUM >= 100000 + (PG_VERSION_NUM) % 10000 +#else + (PG_VERSION_NUM / 100) % 100 +#endif + ); appendStringInfoString(&buf, ". It was introduced in version "); appendStringInfoString(&buf, introVersion); diff --git a/pljava-so/src/main/c/ExecutionPlan.c b/pljava-so/src/main/c/ExecutionPlan.c index 6ff53eb49..ed39bc0fe 100644 --- a/pljava-so/src/main/c/ExecutionPlan.c +++ b/pljava-so/src/main/c/ExecutionPlan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -278,9 +278,7 @@ JNIEXPORT jobject JNICALL Java_org_postgresql_pljava_internal_ExecutionPlan__1prepare(JNIEnv* env, jclass clazz, jobject key, jstring jcmd, jobjectArray paramTypes) { jobject result = 0; -#if PG_VERSION_NUM >= 90200 int spi_ret; -#endif BEGIN_NATIVE STACK_BASE_VARS STACK_BASE_PUSH(env) @@ -321,16 +319,12 @@ Java_org_postgresql_pljava_internal_ExecutionPlan__1prepare(JNIEnv* env, jclass /* Make the plan durable */ p2l.longVal = 0L; /* ensure that the rest is zeroed out */ -#if PG_VERSION_NUM >= 90200 spi_ret = SPI_keepplan(ePlan); if ( 0 == spi_ret ) p2l.ptrVal = ePlan; else Exception_throwSPI("keepplan", spi_ret); -#else - p2l.ptrVal = SPI_saveplan(ePlan); - SPI_freeplan(ePlan); /* Get rid of original, nobody can see it */ -#endif + result = JNI_newObjectLocked( s_ExecutionPlan_class, s_ExecutionPlan_init, /* (jlong)0 as resource owner: the saved plan isn't transient */ diff --git a/pljava-so/src/main/c/Function.c b/pljava-so/src/main/c/Function.c index a46c0e6dd..4428f240f 100644 --- a/pljava-so/src/main/c/Function.c +++ b/pljava-so/src/main/c/Function.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2022 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -41,15 +41,6 @@ #define PARAM_OIDS(procStruct) (procStruct)->proargtypes.values -#if 90305<=PG_VERSION_NUM || \ - 90209<=PG_VERSION_NUM && PG_VERSION_NUM<90300 || \ - 90114<=PG_VERSION_NUM && PG_VERSION_NUM<90200 || \ - 90018<=PG_VERSION_NUM && PG_VERSION_NUM<90100 || \ - 80422<=PG_VERSION_NUM && PG_VERSION_NUM<90000 -#else -#error "Need fallback for heap_copy_tuple_as_datum" -#endif - #define COUNTCHECK(refs, prims) ((jshort)(((refs) << 8) | ((prims) & 0xff))) jobject pljava_Function_NO_LOADER; diff --git a/pljava-so/src/main/c/InstallHelper.c b/pljava-so/src/main/c/InstallHelper.c index 30af880ae..2cb5a9cb3 100644 --- a/pljava-so/src/main/c/InstallHelper.c +++ b/pljava-so/src/main/c/InstallHelper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2023 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 @@ -10,17 +10,11 @@ * Chapman Flack */ #include -#if PG_VERSION_NUM >= 90300 #include -#else -#include -#endif #include #include #include -#if PG_VERSION_NUM >= 90100 #include -#endif #include #include #include @@ -30,20 +24,15 @@ #include #include #include -#if PG_VERSION_NUM >= 80400 #include -#endif #include #if PG_VERSION_NUM >= 120000 #include #define GetNamespaceOid(k1) \ GetSysCacheOid1(NAMESPACENAME, Anum_pg_namespace_oid, k1) -#elif PG_VERSION_NUM >= 90000 -#define GetNamespaceOid(k1) GetSysCacheOid1(NAMESPACENAME, k1) #else -#define SearchSysCache1(cid, k1) SearchSysCache(cid, k1, 0, 0, 0) -#define GetNamespaceOid(k1) GetSysCacheOid(NAMESPACENAME, k1, 0, 0, 0) +#define GetNamespaceOid(k1) GetSysCacheOid1(NAMESPACENAME, k1) #endif #include "pljava/InstallHelper.h" @@ -55,47 +44,17 @@ #include "pljava/type/String.h" /* - * Before 9.1, there was no creating_extension. Before 9.5, it did not have - * PGDLLIMPORT and so was not visible in Windows. In either case, just define - * it to be false, but also define CREATING_EXTENSION_HACK if on Windows and - * it needs to be tested for in some roundabout way. - */ -#if PG_VERSION_NUM < 90100 || defined(_MSC_VER) && PG_VERSION_NUM < 90500 -#define creating_extension false -#if PG_VERSION_NUM >= 90100 -#define CREATING_EXTENSION_HACK -#endif -#endif - -/* - * Before 9.1, there was no IsBinaryUpgrade. Before 9.5, it did not have - * PGDLLIMPORT and so was not visible in Windows. In either case, just define - * it to be false; Windows users may have trouble using pg_upgrade to versions - * earlier than 9.5, but with the current version being 9.6 that should be rare. - */ -#if PG_VERSION_NUM < 90100 || defined(_MSC_VER) && PG_VERSION_NUM < 90500 -#define IsBinaryUpgrade false -#endif - -/* - * Before 9.3, there was no IsBackgroundWorker. As of 9.6.1 it still does not + * As of 9.6.1, IsBackgroundWorker still does not * have PGDLLIMPORT, but MyBgworkerEntry != NULL can be used in MSVC instead. - * However, until 9.3.3, even that did not have PGDLLIMPORT, and there's not - * much to be done about it. BackgroundWorkerness won't be detected in MSVC - * for 9.3.0 through 9.3.2. * * One thing it's needed for is to avoid dereferencing MyProcPort in a * background worker, where it's not set. */ -#if PG_VERSION_NUM < 90300 || defined(_MSC_VER) && PG_VERSION_NUM < 90303 -#define IsBackgroundWorker false -#else #include #if defined(_MSC_VER) #include #define IsBackgroundWorker (MyBgworkerEntry != NULL) #endif -#endif /* * The name of the table the extension scripts will create to pass information @@ -112,7 +71,7 @@ static jfieldID s_InstallHelper_MANAGE_CONTEXT_LOADER; static bool extensionExNihilo = false; -static void checkLoadPath( bool *livecheck); +static void checkLoadPath(void); static void getExtensionLoadPath(void); static char *origUserName(); @@ -153,7 +112,6 @@ static char *origUserName() { if ( IsAutoVacuumWorkerProcess() || IsBackgroundWorker ) { -#if PG_VERSION_NUM >= 90500 char *shortlived; static char *longlived; if ( NULL == longlived ) @@ -163,14 +121,6 @@ static char *origUserName() pfree(shortlived); } return longlived; -#else - ereport(ERROR, ( - errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("PL/Java in a background or autovacuum worker not supported " - "in this PostgreSQL version"), - errhint("PostgreSQL 9.5 is the first version in which " - "such usage is supported."))); -#endif } return MyProcPort->user_name; } @@ -178,22 +128,17 @@ static char *origUserName() char const *pljavaClusterName() { /* - * If PostgreSQL isn't at least 9.5, there can't BE a cluster name, and if - * it is, then there's always one (even if it is an empty string), so - * PG_GETCONFIGOPTION is safe. + * In PostgreSQL of at least 9.5, there's always one (even if it is an empty + * string), so PG_GETCONFIGOPTION is safe. */ -#if PG_VERSION_NUM < 90500 - return ""; -#else return PG_GETCONFIGOPTION("cluster_name"); -#endif } void pljavaCheckExtension( bool *livecheck) { if ( ! creating_extension ) { - checkLoadPath( livecheck); + checkLoadPath(); return; } if ( NULL != livecheck ) @@ -216,29 +161,17 @@ void pljavaCheckExtension( bool *livecheck) * on Windows. So if livecheck isn't null, this function only needs to proceed * as far as the CREATING_EXTENSION_HACK and then return. */ -static void checkLoadPath( bool *livecheck) +static void checkLoadPath() { List *l; Node *ut; LoadStmt *ls; -#if PG_VERSION_NUM >= 80300 PlannedStmt *ps; -#else - Query *ps; -#endif -#ifndef CREATING_EXTENSION_HACK - if ( NULL != livecheck ) - return; -#endif if ( NULL == ActivePortal ) return; - l = ActivePortal-> -#if PG_VERSION_NUM >= 80300 - stmts; -#else - parseTrees; -#endif + l = ActivePortal->stmts; + if ( NULL == l ) return; if ( 1 < list_length( l) ) @@ -249,15 +182,10 @@ static void checkLoadPath( bool *livecheck) elog(DEBUG2, "got null for first statement from ActivePortal"); return; } -#if PG_VERSION_NUM >= 80300 + if ( T_PlannedStmt == nodeTag(ut) ) { ps = (PlannedStmt *)ut; -#else - if ( T_Query == nodeTag(ut) ) - { - ps = (Query *)ut; -#endif if ( CMD_UTILITY != ps->commandType ) { elog(DEBUG2, "ActivePortal has PlannedStmt command type %u", @@ -272,22 +200,8 @@ static void checkLoadPath( bool *livecheck) } } if ( T_LoadStmt != nodeTag(ut) ) -#ifdef CREATING_EXTENSION_HACK - if ( T_CreateExtensionStmt == nodeTag(ut) ) - { - if ( NULL != livecheck ) - { - *livecheck = true; - return; - } - getExtensionLoadPath(); - if ( NULL != pljavaLoadPath ) - pljavaLoadingAsExtension = true; - } -#endif - return; - if ( NULL != livecheck ) return; + ls = (LoadStmt *)ut; if ( NULL == ls->filename ) { @@ -555,14 +469,9 @@ char *InstallHelper_hello() nativeVer = String_createJavaStringFromNTS(SO_VERSION_STRING); serverBuiltVer = String_createJavaStringFromNTS(PG_VERSION_STR); -#if PG_VERSION_NUM >= 90100 InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, /* collation */ NULL, NULL); -#else - InitFunctionCallInfoData(fcinfo, NULL, 0, - NULL, NULL); -#endif runningVer = DatumGetTextP(pgsql_version(&fcinfo)); serverRunningVer = String_createJavaString(runningVer); pfree(runningVer); @@ -614,15 +523,9 @@ void InstallHelper_groundwork() bool snapshot_set = false; Invocation_pushInvocation(&ctx); ctx.function = Function_INIT_WRITER; -#if PG_VERSION_NUM >= 80400 if ( ! ActiveSnapshotSet() ) { PushActiveSnapshot(GetTransactionSnapshot()); -#else - if ( NULL == ActiveSnapshot ) - { - ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); -#endif snapshot_set = true; } PG_TRY(); @@ -644,11 +547,7 @@ void InstallHelper_groundwork() JNI_deleteLocalRef(jlptq); if ( snapshot_set ) { -#if PG_VERSION_NUM >= 80400 PopActiveSnapshot(); -#else - ActiveSnapshot = NULL; -#endif } Invocation_popInvocation(false); } @@ -656,11 +555,7 @@ void InstallHelper_groundwork() { if ( snapshot_set ) { -#if PG_VERSION_NUM >= 80400 PopActiveSnapshot(); -#else - ActiveSnapshot = NULL; -#endif } Invocation_popInvocation(true); PG_RE_THROW(); diff --git a/pljava-so/src/main/c/SPI.c b/pljava-so/src/main/c/SPI.c index ea104bd9f..3d891b30d 100644 --- a/pljava-so/src/main/c/SPI.c +++ b/pljava-so/src/main/c/SPI.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -94,14 +94,19 @@ void SPI_initialize(void) CONFIRMCONST(SPI_OK_INSERT_RETURNING); CONFIRMCONST(SPI_OK_DELETE_RETURNING); CONFIRMCONST(SPI_OK_UPDATE_RETURNING); -#if PG_VERSION_NUM >= 80400 CONFIRMCONST(SPI_OK_REWRITTEN); -#endif #if PG_VERSION_NUM >= 100000 CONFIRMCONST(SPI_OK_REL_REGISTER); CONFIRMCONST(SPI_OK_REL_UNREGISTER); CONFIRMCONST(SPI_OK_TD_REGISTER); #endif +#if PG_VERSION_NUM >= 150000 + CONFIRMCONST(SPI_OK_MERGE); +#endif + +#if PG_VERSION_NUM >= 110000 + CONFIRMCONST(SPI_OPT_NONATOMIC); +#endif } /**************************************** diff --git a/pljava-so/src/main/c/Session.c b/pljava-so/src/main/c/Session.c index be4a2ccab..f551cb5b7 100644 --- a/pljava-so/src/main/c/Session.c +++ b/pljava-so/src/main/c/Session.c @@ -1,10 +1,14 @@ /* - * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden - * Distributed under the terms shown in the file COPYRIGHT - * found in the root folder of this project or at - * http://eng.tada.se/osprojects/COPYRIGHT.html + * Copyright (c) 2004-2023 Tada AB and other contributors, as listed below. * - * @author Thomas Hallgren + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the The BSD 3-Clause License + * which accompanies this distribution, and is available at + * http://opensource.org/licenses/BSD-3-Clause + * + * Contributors: + * Tada AB + * Chapman Flack */ #include #include @@ -45,9 +49,6 @@ Java_org_postgresql_pljava_internal_Session__1setUser( * a finally block after an exception. */ BEGIN_NATIVE_NO_ERRCHECK -#if 80402<=PG_VERSION_NUM || \ - 80309<=PG_VERSION_NUM && PG_VERSION_NUM<80400 || \ - 80215<=PG_VERSION_NUM && PG_VERSION_NUM<80300 if (InSecurityRestrictedOperation()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg( "cannot set parameter \"%s\" within security-restricted operation", @@ -59,15 +60,6 @@ Java_org_postgresql_pljava_internal_Session__1setUser( else secContext &= ~SECURITY_LOCAL_USERID_CHANGE; SetUserIdAndSecContext(AclId_getAclId(aclId), secContext); -#elif PG_VERSION_NUM>=80206 - (void)secContext; /* away with your unused-variable warnings! */ - GetUserIdAndContext(&dummy, &wasLocalChange); - SetUserIdAndContext(AclId_getAclId(aclId), (bool)isLocalChange); -#else - (void)secContext; - (void)dummy; - SetUserId(AclId_getAclId(aclId)); -#endif END_NATIVE return wasLocalChange ? JNI_TRUE : JNI_FALSE; } diff --git a/pljava-so/src/main/c/TypeOid.c b/pljava-so/src/main/c/TypeOid.c index 0fce9ad17..810053268 100644 --- a/pljava-so/src/main/c/TypeOid.c +++ b/pljava-so/src/main/c/TypeOid.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2019-2023 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 @@ -50,10 +50,6 @@ JNIEXPORT void JNICALL Java_org_postgresql_pljava_jdbc_TypeOid__1dummy(JNIEnv * CONFIRMCONST(VARCHAROID); CONFIRMCONST(OIDOID); CONFIRMCONST(BPCHAROID); - -#if PG_VERSION_NUM >= 90100 CONFIRMCONST(PG_NODE_TREEOID); -#endif - CONFIRMCONST(TRIGGEROID); } diff --git a/pljava-so/src/main/c/VarlenaWrapper.c b/pljava-so/src/main/c/VarlenaWrapper.c index 5805ace13..cb1d9e7a5 100644 --- a/pljava-so/src/main/c/VarlenaWrapper.c +++ b/pljava-so/src/main/c/VarlenaWrapper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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,13 +21,8 @@ #endif #include - -#if PG_VERSION_NUM < 80400 -#define RegisterSnapshotOnOwner(s,o) NULL -#else #include #include -#endif #include "org_postgresql_pljava_internal_VarlenaWrapper_Input_State.h" #include "org_postgresql_pljava_internal_VarlenaWrapper_Output_State.h" @@ -41,37 +36,7 @@ #define GetOldestSnapshot() NULL #endif -#if PG_VERSION_NUM < 90400 -/* - * There aren't 'indirect' varlenas yet, IS_EXTERNAL_ONDISK is just IS_EXTERNAL, - * and VARATT_EXTERNAL_GET_POINTER is private inside tuptoaster.c; copy it here. - */ -#define VARATT_IS_EXTERNAL_ONDISK VARATT_IS_EXTERNAL -#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \ -do { \ - varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \ - memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \ -} while (0) -#endif - -#if PG_VERSION_NUM < 80300 -#define VARSIZE_ANY(PTR) VARSIZE(PTR) -#define VARSIZE_ANY_EXHDR(PTR) (VARSIZE(PTR) - VARHDRSZ) -#define SET_VARSIZE(PTR, len) VARATT_SIZEP(PTR) = len & VARATT_MASK_SIZE -struct varatt_external -{ - int32 va_extsize; /* the only piece used here */ -}; -#undef VARATT_EXTERNAL_GET_POINTER -#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \ -do { \ - (toast_pointer).va_extsize = \ - ((varattrib *)(attr))->va_content.va_external.va_extsize; \ -} while (0) -#define _VL_TYPE varattrib * -#else #define _VL_TYPE struct varlena * -#endif #if PG_VERSION_NUM < 140000 #define VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) ((toast_pointer).va_extsize) @@ -102,37 +67,6 @@ static jfieldID s_VarlenaWrapper_Input_State_varlena; * final reallocation and copy will happen. */ -#if PG_VERSION_NUM < 90500 -/* - * There aren't 'expanded' varlenas yet. Copy some defs (in simplified form) - * and pretend there are. - */ -typedef struct ExpandedObjectHeader ExpandedObjectHeader; - -typedef Size (*EOM_get_flat_size_method) (ExpandedObjectHeader *eohptr); -typedef void (*EOM_flatten_into_method) (ExpandedObjectHeader *eohptr, - void *result, Size allocated_size); - -typedef struct ExpandedObjectMethods -{ - EOM_get_flat_size_method get_flat_size; - EOM_flatten_into_method flatten_into; -} ExpandedObjectMethods; - -struct ExpandedObjectHeader -{ - int32 magic; - MemoryContext eoh_context; -}; - -#define EOH_init_header(eohptr, methods, obj_context) \ - do {(eohptr)->magic = -1; (eohptr)->eoh_context = (obj_context);} while (0) - -#define EOHPGetRWDatum(eohptr) (eohptr) -#define DatumGetEOHP(d) (d) -#define VARATT_IS_EXTERNAL_EXPANDED(attr) false -#endif - static Size VOS_get_flat_size(ExpandedObjectHeader *eohptr); static void VOS_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size); @@ -189,7 +123,6 @@ jobject pljava_VarlenaWrapper_Input( vl = (_VL_TYPE) DatumGetPointer(d); -#if PG_VERSION_NUM >= 90400 if ( VARATT_IS_EXTERNAL_INDIRECT(vl) ) /* at most once; can't be nested */ { struct varatt_indirect redirect; @@ -197,7 +130,6 @@ jobject pljava_VarlenaWrapper_Input( vl = (_VL_TYPE)redirect.pointer; d = PointerGetDatum(vl); } -#endif parked = VARSIZE_ANY(vl); actual = toast_raw_datum_size(d) - VARHDRSZ; @@ -342,25 +274,11 @@ jobject pljava_VarlenaWrapper_Output(MemoryContext parent, ResourceOwner ro) Datum pljava_VarlenaWrapper_adopt(jobject vlw) { Ptr2Long p2l; -#if PG_VERSION_NUM < 90500 - ExpandedObjectHeader *eohptr; - Size final_size; - void *final_result; -#endif p2l.longVal = JNI_callLongMethodLocked(vlw, s_VarlenaWrapper_adopt, pljava_DualState_key()); -#if PG_VERSION_NUM >= 90500 + return PointerGetDatum(p2l.ptrVal); -#else - eohptr = p2l.ptrVal; - if ( -1 != eohptr->magic ) - return PointerGetDatum(eohptr); - final_size = VOS_get_flat_size(eohptr); - final_result = MemoryContextAlloc(eohptr->eoh_context, final_size); - VOS_flatten_into(eohptr, final_result, final_size); - return PointerGetDatum(final_result); -#endif } static Size VOS_get_flat_size(ExpandedObjectHeader *eohptr) @@ -376,9 +294,6 @@ static void VOS_flatten_into(ExpandedObjectHeader *eohptr, ExpandedVarlenaOutputStreamHeader *evosh = (ExpandedVarlenaOutputStreamHeader *)eohptr; ExpandedVarlenaOutputStreamNode *node = evosh->tail; -#if PG_VERSION_NUM < 90500 - ExpandedVarlenaOutputStreamNode *next; -#endif Assert(allocated_size == evosh->total_size); SET_VARSIZE(result, allocated_size); @@ -391,25 +306,6 @@ static void VOS_flatten_into(ExpandedObjectHeader *eohptr, result = (char *)result + node->size; } while ( node != evosh->tail ); - -#if PG_VERSION_NUM < 90500 - /* - * It's been flattened into the same context; the original nodes can be - * freed so the 2x memory usage doesn't last longer than necessary. Freeing - * them retail isn't ideal, but this is back-compatibility code. Remember - * the first one wasn't a separate allocation. - */ - node = node->next; /* this is the head, the one that can't be pfreed */ - evosh->tail = node; /* tail is now head, the non-pfreeable node */ - node = node->next; - while ( node != evosh->tail ) - { - next = node->next; - pfree(node); - node = next; - } - pfree(evosh); -#endif } void pljava_VarlenaWrapper_initialize(void) @@ -495,7 +391,6 @@ JNIEXPORT void JNICALL Java_org_postgresql_pljava_internal_VarlenaWrapper_00024Input_00024State__1unregisterSnapshot (JNIEnv *env, jobject _this, jlong snapshot, jlong ro) { -#if PG_VERSION_NUM >= 80400 BEGIN_NATIVE_NO_ERRCHECK Ptr2Long p2lsnap; Ptr2Long p2lro; @@ -503,7 +398,6 @@ Java_org_postgresql_pljava_internal_VarlenaWrapper_00024Input_00024State__1unreg p2lro.longVal = ro; UnregisterSnapshotFromOwner(p2lsnap.ptrVal, p2lro.ptrVal); END_NATIVE -#endif } /* @@ -517,10 +411,8 @@ Java_org_postgresql_pljava_internal_VarlenaWrapper_00024Input_00024State__1detoa { Ptr2Long p2lvl; Ptr2Long p2lcxt; -#if PG_VERSION_NUM >= 80400 Ptr2Long p2lsnap; Ptr2Long p2lro; -#endif Ptr2Long p2ldetoasted; _VL_TYPE detoasted; MemoryContext prevcxt; @@ -530,10 +422,8 @@ Java_org_postgresql_pljava_internal_VarlenaWrapper_00024Input_00024State__1detoa p2lvl.longVal = vl; p2lcxt.longVal = cxt; -#if PG_VERSION_NUM >= 80400 p2lsnap.longVal = snap; p2lro.longVal = resOwner; -#endif prevcxt = MemoryContextSwitchTo((MemoryContext)p2lcxt.ptrVal); @@ -547,10 +437,8 @@ Java_org_postgresql_pljava_internal_VarlenaWrapper_00024Input_00024State__1detoa s_VarlenaWrapper_Input_State_varlena, p2ldetoasted.longVal); pfree(p2lvl.ptrVal); -#if PG_VERSION_NUM >= 80400 if ( 0 != snap ) UnregisterSnapshotFromOwner(p2lsnap.ptrVal, p2lro.ptrVal); -#endif dbb = JNI_newDirectByteBuffer( VARDATA(detoasted), VARSIZE_ANY_EXHDR(detoasted)); diff --git a/pljava-so/src/main/c/XactListener.c b/pljava-so/src/main/c/XactListener.c index 543c2cd46..096326184 100644 --- a/pljava-so/src/main/c/XactListener.c +++ b/pljava-so/src/main/c/XactListener.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -41,11 +41,9 @@ case XACT_EVENT_##c: \ CASE( PREPARE ); CASE( PRE_COMMIT ); CASE( PRE_PREPARE ); -#if PG_VERSION_NUM >= 90500 CASE( PARALLEL_COMMIT ); CASE( PARALLEL_ABORT ); CASE( PARALLEL_PRE_COMMIT ); -#endif } JNI_callStaticVoidMethod(s_XactListener_class, diff --git a/pljava-so/src/main/c/type/AclId.c b/pljava-so/src/main/c/type/AclId.c index 504b8cf6a..a9f570667 100644 --- a/pljava-so/src/main/c/type/AclId.c +++ b/pljava-so/src/main/c/type/AclId.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -184,11 +184,7 @@ Java_org_postgresql_pljava_internal_AclId__1getName(JNIEnv* env, jobject aclId) { result = String_createJavaStringFromNTS( GetUserNameFromId( -#if PG_VERSION_NUM >= 90500 AclId_getAclId(aclId), /* noerr= */ false -#else - AclId_getAclId(aclId) -#endif ) ); } diff --git a/pljava-so/src/main/c/type/Array.c b/pljava-so/src/main/c/type/Array.c index 232fc05aa..b2e654482 100644 --- a/pljava-so/src/main/c/type/Array.c +++ b/pljava-so/src/main/c/type/Array.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -51,11 +51,7 @@ ArrayType* createArrayType(jsize nElems, size_t elemSize, Oid elemType, bool wit v->dataoffset = (int32)dataoffset; MemoryContextSwitchTo(currCtx); -#if PG_VERSION_NUM < 80300 - ARR_SIZE(v) = nBytes; -#else SET_VARSIZE(v, nBytes); -#endif ARR_NDIM(v) = 1; ARR_ELEMTYPE(v) = elemType; *((int*)ARR_DIMS(v)) = nElems; @@ -88,14 +84,8 @@ static jvalue _Array_coerceDatum(Type self, Datum arg) JNI_setObjectArrayElement(objArray, idx, obj.l); JNI_deleteLocalRef(obj.l); -#if PG_VERSION_NUM < 80300 - values = att_addlength(values, elemLength, PointerGetDatum(values)); - values = (char*)att_align(values, elemAlign); -#else values = att_addlength_datum(values, elemLength, PointerGetDatum(values)); values = (char*)att_align_nominal(values, elemAlign); -#endif - } } result.l = (jobject)objArray; diff --git a/pljava-so/src/main/c/type/Oid.c b/pljava-so/src/main/c/type/Oid.c index aecb67e01..37bb89b2e 100644 --- a/pljava-so/src/main/c/type/Oid.c +++ b/pljava-so/src/main/c/type/Oid.c @@ -1,10 +1,14 @@ /* - * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden - * Distributed under the terms shown in the file COPYRIGHT - * found in the root folder of this project or at - * http://eng.tada.se/osprojects/COPYRIGHT.html + * Copyright (c) 2004-2023 Tada AB and other contributors, as listed below. * - * @author Thomas Hallgren + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the The BSD 3-Clause License + * which accompanies this distribution, and is available at + * http://opensource.org/licenses/BSD-3-Clause + * + * Contributors: + * Tada AB + * Chapman Flack */ #include @@ -256,11 +260,7 @@ Java_org_postgresql_pljava_internal_Oid__1forTypeName(JNIEnv* env, jclass cls, j PG_TRY(); { int32 typmod = 0; -#if PG_VERSION_NUM < 90400 - parseTypeString(typeNameOrOid, &typeId, &typmod); -#else parseTypeString(typeNameOrOid, &typeId, &typmod, 0); -#endif } PG_CATCH(); { diff --git a/pljava-so/src/main/c/type/SQLXMLImpl.c b/pljava-so/src/main/c/type/SQLXMLImpl.c index 16b483b37..157f4251b 100644 --- a/pljava-so/src/main/c/type/SQLXMLImpl.c +++ b/pljava-so/src/main/c/type/SQLXMLImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2018-2023 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 @@ -50,9 +50,7 @@ static bool _SQLXML_canReplaceType(Type self, Type other) #if defined(XMLOID) Type_getOid(other) == XMLOID || #endif -#if PG_VERSION_NUM >= 90100 Type_getOid(other) == PG_NODE_TREEOID || /* a synthetic rendering */ -#endif Type_getOid(other) == TEXTOID; } @@ -86,17 +84,12 @@ static Datum _SQLXML_coerceObject(Type self, jobject sqlxml) s_SQLXML_class, s_SQLXML_adopt, sqlxml, Type_getOid(self)); Datum d = pljava_VarlenaWrapper_adopt(vw); JNI_deleteLocalRef(vw); -#if PG_VERSION_NUM >= 90500 if ( VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)) ) return TransferExpandedObject(d, CurrentMemoryContext); -#endif -#if PG_VERSION_NUM >= 90200 + MemoryContextSetParent( GetMemoryChunkContext(DatumGetPointer(d)), CurrentMemoryContext); -#else - if ( CurrentMemoryContext != GetMemoryChunkContext(DatumGetPointer(d)) ) - d = PointerGetDatum(PG_DETOAST_DATUM_COPY(d)); -#endif + return d; } @@ -134,18 +127,15 @@ static Type _SQLXML_obtain(Oid typeId) #if defined(XMLOID) static Type xmlInstance; #endif -#if PG_VERSION_NUM >= 90100 static Type pgNodeTreeInstance; -#endif + switch ( typeId ) { -#if PG_VERSION_NUM >= 90100 case PG_NODE_TREEOID: allowedId = PG_NODE_TREEOID; synthetic = true; cache = &pgNodeTreeInstance; break; -#endif default: if ( TEXTOID == typeId ) { diff --git a/pljava-so/src/main/c/type/String.c b/pljava-so/src/main/c/type/String.c index e380be326..8b4623942 100644 --- a/pljava-so/src/main/c/type/String.c +++ b/pljava-so/src/main/c/type/String.c @@ -226,11 +226,7 @@ text* String_createText(jstring javaString) /* Allocate and initialize the text structure. */ result = (text*)palloc(varSize); -#if PG_VERSION_NUM < 80300 - VARATT_SIZEP(result) = varSize; /* Total size of structure, not just data */ -#else SET_VARSIZE(result, varSize); /* Total size of structure, not just data */ -#endif memcpy(VARDATA(result), denc, dencLen); if(denc != sid.data) diff --git a/pljava-so/src/main/c/type/Timestamp.c b/pljava-so/src/main/c/type/Timestamp.c index 2cbdba9ee..7cd76a6c2 100644 --- a/pljava-so/src/main/c/type/Timestamp.c +++ b/pljava-so/src/main/c/type/Timestamp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -405,23 +405,7 @@ static Datum _Timestamptz_coerceObject(Type self, jobject ts) */ static int32 Timestamp_getTimeZone(pg_time_t time) { -#if defined(_MSC_VER) && ( \ - 100000<=PG_VERSION_NUM && PG_VERSION_NUM<100002 || \ - 90600<=PG_VERSION_NUM && PG_VERSION_NUM< 90607 || \ - 90500<=PG_VERSION_NUM && PG_VERSION_NUM< 90511 || \ - 90400<=PG_VERSION_NUM && PG_VERSION_NUM< 90416 || \ - PG_VERSION_NUM < 90321 ) - /* This is gross, but pg_tzset has a cache, so not as gross as you think. - * There is some renewed interest on pgsql-hackers to find a good answer for - * the MSVC PGDLLIMPORT nonsense, so this may not have to stay gross. - */ - char const *tzname = PG_GETCONFIGOPTION("timezone"); - struct pg_tm* tx = pg_localtime(&time, pg_tzset(tzname)); -#elif PG_VERSION_NUM < 80300 - struct pg_tm* tx = pg_localtime(&time, global_timezone); -#else struct pg_tm* tx = pg_localtime(&time, session_timezone); -#endif if ( NULL == tx ) ereport(ERROR, ( errcode(ERRCODE_DATA_EXCEPTION), diff --git a/pljava-so/src/main/c/type/Type.c b/pljava-so/src/main/c/type/Type.c index a0d181e2f..188e86e78 100644 --- a/pljava-so/src/main/c/type/Type.c +++ b/pljava-so/src/main/c/type/Type.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2022 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -30,42 +30,11 @@ #include "pljava/HashMap.h" #include "pljava/SPI.h" -#if PG_VERSION_NUM < 80300 -typedef enum CoercionPathType -{ - COERCION_PATH_NONE, /* failed to find any coercion pathway */ - COERCION_PATH_FUNC, /* apply the specified coercion function */ - COERCION_PATH_RELABELTYPE, /* binary-compatible cast, no function */ - COERCION_PATH_ARRAYCOERCE, /* need an ArrayCoerceExpr node */ - COERCION_PATH_COERCEVIAIO /* need a CoerceViaIO node */ -} CoercionPathType; - -static CoercionPathType fcp(Oid targetTypeId, Oid sourceTypeId, - CoercionContext ccontext, Oid *funcid); -static CoercionPathType fcp(Oid targetTypeId, Oid sourceTypeId, - CoercionContext ccontext, Oid *funcid) -{ - if ( find_coercion_pathway(targetTypeId, sourceTypeId, ccontext, funcid) ) - return *funcid != InvalidOid ? - COERCION_PATH_FUNC : COERCION_PATH_RELABELTYPE; - else - return COERCION_PATH_NONE; -} -#define find_coercion_pathway fcp -#endif - -#if PG_VERSION_NUM < 90500 -#define DomainHasConstraints(x) true -#endif - #if PG_VERSION_NUM < 110000 static Oid BOOLARRAYOID; static Oid CHARARRAYOID; static Oid FLOAT8ARRAYOID; static Oid INT8ARRAYOID; -#if PG_VERSION_NUM < 80400 -static Oid INT2ARRAYOID; -#endif #endif static HashMap s_typeByOid; @@ -1055,9 +1024,6 @@ void Type_initialize(void) CHARARRAYOID = get_array_type(CHAROID); FLOAT8ARRAYOID = get_array_type(FLOAT8OID); INT8ARRAYOID = get_array_type(INT8OID); -#if PG_VERSION_NUM < 80400 - INT2ARRAYOID = get_array_type(INT2OID); -#endif #endif initializeTypeBridges(); diff --git a/pljava-so/src/main/c/type/UDT.c b/pljava-so/src/main/c/type/UDT.c index d351038fc..1f33b0afc 100644 --- a/pljava-so/src/main/c/type/UDT.c +++ b/pljava-so/src/main/c/type/UDT.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -29,10 +30,6 @@ #include "pljava/SQLInputFromTuple.h" #include "pljava/SQLOutputToTuple.h" -#if PG_VERSION_NUM >= 90000 -#include -#endif - /* * This code, as currently constituted, makes these assumptions that limit how * Java can implement a (scalar) UDT: @@ -183,11 +180,7 @@ static Datum coerceScalarObject(UDT self, jobject value) { /* Assign the correct length. */ -#if PG_VERSION_NUM < 80300 - VARATT_SIZEP(buffer.data) = buffer.len; -#else SET_VARSIZE(buffer.data, buffer.len); -#endif } else if(dataLen != buffer.len) { diff --git a/pljava-so/src/main/c/type/byte_array.c b/pljava-so/src/main/c/type/byte_array.c index d17630842..91e3103a0 100644 --- a/pljava-so/src/main/c/type/byte_array.c +++ b/pljava-so/src/main/c/type/byte_array.c @@ -1,10 +1,14 @@ /* - * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden - * Distributed under the terms shown in the file COPYRIGHT - * found in the root folder of this project or at - * http://eng.tada.se/osprojects/COPYRIGHT.html + * Copyright (c) 2004-2023 Tada AB and other contributors, as listed below. * - * @author Thomas Hallgren + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the The BSD 3-Clause License + * which accompanies this distribution, and is available at + * http://opensource.org/licenses/BSD-3-Clause + * + * Contributors: + * Tada AB + * Chapman Flack */ #include "pljava/Exception.h" #include "pljava/type/Type_priv.h" @@ -40,11 +44,7 @@ static Datum _byte_array_coerceObject(Type self, jobject byteArray) int32 byteaSize = length + VARHDRSZ; bytes = (bytea*)palloc(byteaSize); -#if PG_VERSION_NUM < 80300 - VARATT_SIZEP(bytes) = byteaSize; -#else SET_VARSIZE(bytes, byteaSize); -#endif JNI_getByteArrayRegion((jbyteArray)byteArray, 0, length, (jbyte*)VARDATA(bytes)); } else if(JNI_isInstanceOf(byteArray, s_BlobValue_class)) @@ -55,11 +55,7 @@ static Datum _byte_array_coerceObject(Type self, jobject byteArray) byteaSize = (int32)(length + VARHDRSZ); bytes = (bytea*)palloc(byteaSize); -#if PG_VERSION_NUM < 80300 - VARATT_SIZEP(bytes) = byteaSize; -#else SET_VARSIZE(bytes, byteaSize); -#endif byteBuffer = JNI_newDirectByteBuffer((void*)VARDATA(bytes), length); if(byteBuffer != 0) diff --git a/pljava-so/src/main/include/pljava/Backend.h b/pljava-so/src/main/include/pljava/Backend.h index 16c29cdbd..e0e8ca30b 100644 --- a/pljava-so/src/main/include/pljava/Backend.h +++ b/pljava-so/src/main/include/pljava/Backend.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -53,13 +53,7 @@ void Backend_warnJEP411(bool isCommit); #error The macro PG_GETCONFIGOPTION needs to be renamed. #endif -#if PG_VERSION_NUM >= 90100 #define PG_GETCONFIGOPTION(key) GetConfigOption(key, false, true) -#elif PG_VERSION_NUM >= 90000 -#define PG_GETCONFIGOPTION(key) GetConfigOption(key, true) -#else -#define PG_GETCONFIGOPTION(key) GetConfigOption(key) -#endif #ifdef __cplusplus } diff --git a/pljava-so/src/main/include/pljava/Exception.h b/pljava-so/src/main/include/pljava/Exception.h index a2edad91a..d524dd062 100644 --- a/pljava-so/src/main/include/pljava/Exception.h +++ b/pljava-so/src/main/include/pljava/Exception.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -17,14 +17,6 @@ #include "pljava/PgObject.h" -#if PG_VERSION_NUM < 90500 -#ifdef __GNUC__ -#define pg_attribute_printf(f,a) __attribute__((format(printf, f, a))) -#else -#define pg_attribute_printf(f,a) -#endif -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/pljava-so/src/main/include/pljava/pljava.h b/pljava-so/src/main/include/pljava/pljava.h index 8da93ff6c..6a2e298c9 100644 --- a/pljava-so/src/main/include/pljava/pljava.h +++ b/pljava-so/src/main/include/pljava/pljava.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2021 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -37,6 +37,7 @@ extern int vsnprintf(char* buf, size_t count, const char* format, va_list arg); #include #include #include +#include /* * AssertVariableIsOfType appeared in PG9.3. Can test for the macro directly. @@ -65,23 +66,6 @@ extern int vsnprintf(char* buf, size_t count, const char* format, va_list arg); ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE #endif -/* - * GETSTRUCT require "access/htup_details.h" to be included in PG9.3 - */ -#if PG_VERSION_NUM >= 90300 -#include "access/htup_details.h" -#endif - -/* - * PG_*_{MIN,MAX} macros (which happen, conveniently, to match Java's datatypes - * (the signed ones, anyway), appear in PG 9.5. Could test for them directly, - * but explicit version conditionals may be easier to find and prune when the - * back-compatibility horizon passes them. Here are only the ones being used. - */ -#if PG_VERSION_NUM < 90500 -#define PG_INT32_MAX (0x7FFFFFFF) -#endif - /* * This symbol was spelled without the underscores prior to PG 14. */ @@ -118,28 +102,10 @@ extern MemoryContext JavaMemoryContext; * stack_base_ptr was static before PG 8.1. By executive decision, PL/Java now * has 8.1 as a back compatibility limit; no empty #defines here for earlier. */ -#if 90104<=PG_VERSION_NUM || \ - 90008<=PG_VERSION_NUM && PG_VERSION_NUM<90100 || \ - 80412<=PG_VERSION_NUM && PG_VERSION_NUM<90000 || \ - 80319<=PG_VERSION_NUM && PG_VERSION_NUM<80400 #define NEED_MISCADMIN_FOR_STACK_BASE #define _STACK_BASE_TYPE pg_stack_base_t #define _STACK_BASE_SET saveStackBasePtr = set_stack_base() #define _STACK_BASE_RESTORE restore_stack_base(saveStackBasePtr) -#else -extern -#if PG_VERSION_NUM < 80300 -DLLIMPORT -#else -PGDLLIMPORT -#endif -char* stack_base_ptr; -#define _STACK_BASE_TYPE char* -#define _STACK_BASE_SET \ - saveStackBasePtr = stack_base_ptr; \ - stack_base_ptr = (char*)&saveMainThreadId -#define _STACK_BASE_RESTORE stack_base_ptr = saveStackBasePtr -#endif #define STACK_BASE_VARS \ void* saveMainThreadId = 0; \ diff --git a/pljava/src/main/java/org/postgresql/pljava/internal/SPI.java b/pljava/src/main/java/org/postgresql/pljava/internal/SPI.java index 9151ad100..98ac19932 100644 --- a/pljava/src/main/java/org/postgresql/pljava/internal/SPI.java +++ b/pljava/src/main/java/org/postgresql/pljava/internal/SPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2019 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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 @@ -53,6 +53,9 @@ public class SPI public static final int OK_REL_REGISTER = 15; public static final int OK_REL_UNREGISTER = 16; public static final int OK_TD_REGISTER = 17; + public static final int OK_MERGE = 18; + + public static final int OPT_NONATOMIC = 1 << 0; /** * Execute a command using the internal SPI_exec function. diff --git a/src/site/markdown/build/versions.md b/src/site/markdown/build/versions.md index a759a20b9..1c201a21c 100644 --- a/src/site/markdown/build/versions.md +++ b/src/site/markdown/build/versions.md @@ -62,7 +62,7 @@ versions 4.3.0 or later are recommended in order to avoid a ## PostgreSQL -The PL/Java 1.6 series does not commit to support PostgreSQL earlier than 9.5. +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. From 46a41cd18c95e520ed042916c691fa2b125d735b Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 23 Aug 2023 12:02:08 -0400 Subject: [PATCH 06/25] Run another example as a regression test Going through all the examples for version-conditional bits showed at least one more deserving inclusion as a regression test. Also tidy a couple examples to use out={...} instead of some throwaway composite type. And put a query in more of the traditional uppercase-keywords form. --- .../annotation/RecordParameterDefaults.java | 19 ++---- .../annotation/UnicodeRoundTripTest.java | 65 +++++++++---------- .../example/annotation/XMLRenderedTypes.java | 15 ++++- 3 files changed, 47 insertions(+), 52 deletions(-) diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java index 34e1aeb75..291eb990b 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/RecordParameterDefaults.java @@ -19,7 +19,6 @@ import org.postgresql.pljava.ResultSetProvider; import org.postgresql.pljava.annotation.Function; -import org.postgresql.pljava.annotation.SQLAction; import org.postgresql.pljava.annotation.SQLType; /** @@ -29,17 +28,6 @@ *

* Also tests the proper DDR generation of defaults for such parameters. */ -@SQLAction( - provides = "paramtypeinfo type", // created in Triggers.java - install = { - "CREATE TYPE javatest.paramtypeinfo AS (" + - " name text, pgtypename text, javaclass text, tostring text" + - ")" - }, - remove = { - "DROP TYPE javatest.paramtypeinfo" - } -) public class RecordParameterDefaults implements ResultSetProvider { /** @@ -59,10 +47,11 @@ public class RecordParameterDefaults implements ResultSetProvider * */ @Function( - requires = "paramtypeinfo type", schema = "javatest", - type = "javatest.paramtypeinfo" - ) + out = { + "name text", "pgtypename text", "javaclass text", "tostring text" + } + ) public static ResultSetProvider paramDefaultsRecord( @SQLType(defaultValue={})ResultSet params) throws SQLException diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java index 6b06d4d9a..c317dab25 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/UnicodeRoundTripTest.java @@ -48,50 +48,43 @@ @SQLAction(requires="unicodetest fn", implementor="postgresql_unicodetest", install= -" with " + -" usable_codepoints ( cp ) as ( " + -" select generate_series(1,x'd7ff'::int) " + -" union all " + -" select generate_series(x'e000'::int,x'10ffff'::int) " + +" WITH " + +" usable_codepoints ( cp ) AS ( " + +" SELECT generate_series(1,x'd7ff'::int) " + +" UNION ALL " + +" SELECT generate_series(x'e000'::int,x'10ffff'::int) " + " ), " + -" test_inputs ( groupnum, cparray, s ) as ( " + -" select " + -" cp / 1024 as groupnum, " + -" array_agg(cp order by cp), string_agg(chr(cp), '' order by cp) " + -" from usable_codepoints " + -" group by groupnum " + +" test_inputs ( groupnum, cparray, s ) AS ( " + +" SELECT " + +" cp / 1024 AS groupnum, " + +" array_agg(cp ORDER BY cp), string_agg(chr(cp), '' ORDER BY cp) " + +" FROM usable_codepoints " + +" GROUP BY groupnum " + " ), " + -" test_outputs as ( " + -" select groupnum, cparray, s, unicodetest(s, cparray) as roundtrip " + -" from test_inputs " + +" test_outputs AS ( " + +" SELECT groupnum, cparray, s, unicodetest(s, cparray) AS roundtrip " + +" FROM test_inputs " + " ), " + -" test_failures as ( " + -" select * " + -" from test_outputs " + -" where " + -" cparray != (roundtrip).cparray or s != (roundtrip).s " + -" or not (roundtrip).matched " + +" test_failures AS ( " + +" SELECT * " + +" FROM test_outputs " + +" WHERE " + +" cparray != (roundtrip).cparray OR s != (roundtrip).s " + +" OR NOT (roundtrip).matched " + " ), " + -" test_summary ( n_failing_groups, first_failing_group ) as ( " + -" select count(*), min(groupnum) from test_failures " + +" test_summary ( n_failing_groups, first_failing_group ) AS ( " + +" SELECT count(*), min(groupnum) FROM test_failures " + " ) " + -" select " + -" case when n_failing_groups > 0 then " + +" SELECT " + +" CASE WHEN n_failing_groups > 0 THEN " + " javatest.logmessage('WARNING', n_failing_groups || " + " ' 1k codepoint ranges had mismatches, first is block starting 0x' || " + " to_hex(1024 * first_failing_group)) " + -" else " + +" ELSE " + " javatest.logmessage('INFO', " + " 'all Unicode codepoint ranges roundtripped successfully.') " + -" end " + -" from test_summary" -) -@SQLAction( - install= - "CREATE TYPE unicodetestrow AS " + - "(matched boolean, cparray integer[], s text)", - remove="DROP TYPE unicodetestrow", - provides="unicodetestrow type" +" END " + +" FROM test_summary" ) public class UnicodeRoundTripTest { /** @@ -110,8 +103,8 @@ public class UnicodeRoundTripTest { * @param rs OUT (matched, cparray, s) as described above * @return true to indicate the OUT tuple is not null */ - @Function(type="unicodetestrow", - requires="unicodetestrow type", provides="unicodetest fn") + @Function(out={"matched boolean", "cparray integer[]", "s text"}, + provides="unicodetest fn") public static boolean unicodetest(String s, int[] ints, ResultSet rs) throws SQLException { boolean ok = true; diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java index 5cd21326f..812233d15 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/XMLRenderedTypes.java @@ -28,9 +28,22 @@ * Everything mentioning the type XML here needs a conditional implementor tag * in case of being loaded into a PostgreSQL instance built without that type. */ +@SQLAction(implementor="postgresql_xml", requires="pgNodeTreeAsXML", install= +"WITH" + +" a(t) AS (SELECT adbin FROM pg_catalog.pg_attrdef LIMIT 1)" + +" SELECT" + +" CASE WHEN pgNodeTreeAsXML(t) IS DOCUMENT" + +" THEN javatest.logmessage('INFO', 'pgNodeTreeAsXML ok')" + +" ELSE javatest.logmessage('WARNING', 'pgNodeTreeAsXML ng')" + +" END" + +" FROM a" +) public class XMLRenderedTypes { - @Function(schema="javatest", implementor="postgresql_xml") + @Function( + schema="javatest", implementor="postgresql_xml", + provides="pgNodeTreeAsXML" + ) public static SQLXML pgNodeTreeAsXML(@SQLType("pg_node_tree") SQLXML pgt) throws SQLException { From 57e9609b538c611089c6f2d29e0074ea56560d35 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 24 Aug 2023 18:02:55 -0400 Subject: [PATCH 07/25] Expose the lax() method in the example code A couple of the supplied examples strive to be usable for real work, so this new method should be available there too. --- .../org/postgresql/pljava/example/annotation/PassXML.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java index 3c0605759..f2a706585 100644 --- a/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java +++ b/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java @@ -809,7 +809,9 @@ T applyAdjustments(ResultSet adjust, T axp) for ( int i = 1; i <= n; ++i ) { String k = rsmd.getColumnLabel(i); - if ( "allowDTD".equalsIgnoreCase(k) ) + if ( "lax".equalsIgnoreCase(k) ) + axp.lax(adjust.getBoolean(i)); + else if ( "allowDTD".equalsIgnoreCase(k) ) axp.allowDTD(adjust.getBoolean(i)); else if ( "externalGeneralEntities".equalsIgnoreCase(k) ) axp.externalGeneralEntities(adjust.getBoolean(i)); From e25b7c40bec6f0caa58f9267a76ccb689b5fff96 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Thu, 24 Aug 2023 18:32:00 -0400 Subject: [PATCH 08/25] Clean up a bogus javadoc comment That was one I must have written on far too little coffee. Hardly any of it bore any connection to reality. Ah. In my defense, it had been more coherent once, but did not get updated with c9f6a20. --- .../postgresql/pljava/internal/VarlenaWrapper.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pljava/src/main/java/org/postgresql/pljava/internal/VarlenaWrapper.java b/pljava/src/main/java/org/postgresql/pljava/internal/VarlenaWrapper.java index 89594488e..44432000b 100644 --- a/pljava/src/main/java/org/postgresql/pljava/internal/VarlenaWrapper.java +++ b/pljava/src/main/java/org/postgresql/pljava/internal/VarlenaWrapper.java @@ -1182,12 +1182,11 @@ public Thread newThread(Runnable r) * wraps a {@code ByteBuffer} and the {@link Output.State Output.State} * that protects it. *

- * {@code BufferWrapper} installs itself as the inherited - * {@code m_state} field, so {@code ByteBufferInputStream}'s methods - * synchronize on it rather than the {@code State} object, for no - * interference with the writing thread. The {@code pin} and - * {@code unpin} methods, of course, forward to those of the - * native state object. + * {@code BufferWrapper} installs itself as the + * {@code ByteBufferInputStream}'s lock object, so its methods + * synchronize on this rather than anything that would interfere with + * the writing thread. The {@code pin} and {@code unpin} methods, + * of course, forward to those of the native state object. */ static class BufferWrapper extends ByteBufferInputStream From 8353f6fe8eef1b55b9569200c0b3d19303afc346 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sat, 26 Aug 2023 14:33:05 -0400 Subject: [PATCH 09/25] Ax ancient Java version in PL/Java 1.6.x docs As PL/Java 1.6.x requires Java >= 9, it makes little sense for a lingering javadoc comment to say you need Java 1.6 for something. --- .../postgresql/pljava/annotation/package-info.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java b/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java index de7309e5b..ca5af21cf 100644 --- a/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java +++ b/pljava-api/src/main/java/org/postgresql/pljava/annotation/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2023 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 @@ -33,11 +33,10 @@ *

* Automatic descriptor generation requires attention to a few things. *

    - *
  • A Java 6 or later Java compiler is required, and at least the - * pljava-api jar must be on its class path. (The full - * pljava.jar would also work, but only pljava-api - * is required.) The jar must be on the class path in any case in order to - * compile PL/Java code. + *
  • The {@code pljava-api} jar must be on the Java compiler's class path. + * (All but the simplest PL/Java functions probably refer to some class in + * PL/Java's API anyway, in which case the jar would already have to be on + * the class path.) *
  • When recompiling after changing only a few sources, it is possible the * Java compiler will only process a subset of the source files containing * annotations. If so, it may generate an incomplete deployment descriptor, From df912daeac564daabc5047d2d2fe05fb7374d21e Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Fri, 1 Sep 2023 19:31:45 -0400 Subject: [PATCH 10/25] Fix unchecked warning introduced in 5559ba1 Factor the work of lax() into a static method on AdjustingJAXPParser but push the instance methods down to the concrete subclasses, which can return 'this' with the expected type and no unchecked warning. --- .../postgresql/pljava/jdbc/SQLXMLImpl.java | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java b/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java index 95655ccd7..bd8c8b64c 100644 --- a/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java +++ b/pljava/src/main/java/org/postgresql/pljava/jdbc/SQLXMLImpl.java @@ -4203,16 +4203,20 @@ protected Exception exceptions() return e; } - @Override - public T lax(boolean discard) + /** + * Common factor of subclass {@link #lax() lax()} instance methods. + *

    + * The work is done here, but the instance methods are implemented + * per-subclass to avoid unchecked casting of 'this'. + */ + protected static void lax(AdjustingJAXPParser o, boolean discard) { - if ( null != m_quiet ) + if ( null != o.m_quiet ) { if ( ! discard ) - addSignaling(m_quiet); - m_quiet = null; + o.addSignaling(o.m_quiet); + o.m_quiet = null; } - return (T)this; } @Override @@ -5093,6 +5097,13 @@ public SAXSource get() throws SQLException return ss; } + @Override + public AdjustingSAXSource lax(boolean discard) + { + lax(this, discard); + return this; + } + @Override public AdjustingSAXSource defaults() { @@ -5215,6 +5226,13 @@ public SAXResult get() throws SQLException return sr; } + @Override + public AdjustingSAXResult lax(boolean discard) + { + lax(this, discard); + return this; + } + @Override public AdjustingSAXResult xIncludeAware(boolean v) { @@ -5324,6 +5342,13 @@ public StAXSource get() throws SQLException return ss; } + @Override + public AdjustingStAXSource lax(boolean discard) + { + lax(this, discard); + return this; + } + @Override public AdjustingStAXSource allowDTD(boolean v) { return setFirstSupportedFeature( v, XMLInputFactory.SUPPORT_DTD); @@ -5457,6 +5482,13 @@ public DOMSource get() throws SQLException return ds; } + @Override + public AdjustingDOMSource lax(boolean discard) + { + lax(this, discard); + return this; + } + @Override public AdjustingDOMSource xIncludeAware(boolean v) { From bff1d880f6c3cfd2a6891345f8cbae017fdf802c Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Mon, 4 Sep 2023 21:28:16 -0400 Subject: [PATCH 11/25] Skip handleFirstOptions for javadoc >= 19 In older Java versions, it was necessary to pass along the initial javadoc arguments (the ones a file manager would care about) in a separate step before calling the tool. Starting in 19, that's not only no longer necessary, but fails with "--module-source-path specified more than once". --- pljava-examples/pom.xml | 6 ++++-- pljava/pom.xml | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pljava-examples/pom.xml b/pljava-examples/pom.xml index 320788c27..497d6a4d9 100644 --- a/pljava-examples/pom.xml +++ b/pljava-examples/pom.xml @@ -230,11 +230,13 @@ function executeReport(report, locale) * A special file manager that will rewrite the RELDOTS seen in * -linkoffline above. The options a file manager recognizes must be the * first ones in args; handleFirstOptions below returns at the first one - * the file manager doesn't know what to do with. + * the file manager doesn't know what to do with. Java 19 seems to have + * learned to pass the args to the file manager without the fuss here. */ var rmgr = new org.postgresql.pljava.pgxs.RelativizingFileManager( smgr, Charset.forName(report.outputEncoding)); - rmgr.handleFirstOptions(args); + if ( 0 > v.compareTo(java.lang.Runtime.Version.parse("19-ea")) ) + rmgr.handleFirstOptions(args); var task = tool.getTask(null, rmgr, diagListener, null, args, null); if (task.call()) diff --git a/pljava/pom.xml b/pljava/pom.xml index 51eb86f51..52491f1c1 100644 --- a/pljava/pom.xml +++ b/pljava/pom.xml @@ -182,11 +182,15 @@ function executeReport(report, locale) * A special file manager that will rewrite the RELDOTS seen in * -linkoffline above. The options a file manager recognizes must be the * first ones in args; handleFirstOptions below returns at the first one - * the file manager doesn't know what to do with. + * the file manager doesn't know what to do with. Java 19 seems to have + * learned to pass the args to the file manager without the fuss here. */ var rmgr = new org.postgresql.pljava.pgxs.RelativizingFileManager( smgr, Charset.forName(report.outputEncoding)); - rmgr.handleFirstOptions(args); + + var v = java.lang.Runtime.version(); + if ( 0 > v.compareTo(java.lang.Runtime.Version.parse("19-ea")) ) + rmgr.handleFirstOptions(args); var task = tool.getTask(null, rmgr, diagListener, null, args, null); if (task.call()) From 6a64e915b7f1c60e2465038a5c081c78a09a6bf0 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Mon, 4 Sep 2023 21:29:57 -0400 Subject: [PATCH 12/25] Improve NEWLINE pattern Old one could fail depending on previous matching activity, possibly because of the use of \G (which I should have explained better in a comment, back when I thought I knew why I was doing it). The documented behavior of ^ $ and \z and reluctant quantifiers make for a simpler and more dependable version. Addresses issue #455. --- .../org/postgresql/pljava/sqlgen/Lexicals.java | 2 +- pljava-api/src/test/java/LexicalsTest.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pljava-api/src/main/java/org/postgresql/pljava/sqlgen/Lexicals.java b/pljava-api/src/main/java/org/postgresql/pljava/sqlgen/Lexicals.java index 85bdc66bc..1b6e014a0 100644 --- a/pljava-api/src/main/java/org/postgresql/pljava/sqlgen/Lexicals.java +++ b/pljava-api/src/main/java/org/postgresql/pljava/sqlgen/Lexicals.java @@ -279,7 +279,7 @@ private Lexicals() { } // do not instantiate * engine, letting it handle the details. */ public static final Pattern NEWLINE = Pattern.compile( - "(?ms:$(?:(?except newline, for any Java-recognized newline. diff --git a/pljava-api/src/test/java/LexicalsTest.java b/pljava-api/src/test/java/LexicalsTest.java index 174258115..89b94d07f 100644 --- a/pljava-api/src/test/java/LexicalsTest.java +++ b/pljava-api/src/test/java/LexicalsTest.java @@ -29,6 +29,8 @@ import static org.postgresql.pljava.sqlgen.Lexicals.ISO_AND_PG_IDENTIFIER_CAPTURING; +import static + org.postgresql.pljava.sqlgen.Lexicals.NEWLINE; import static org.postgresql.pljava.sqlgen.Lexicals.SEPARATOR; import static @@ -45,6 +47,22 @@ public class LexicalsTest extends TestCase { public LexicalsTest(String name) { super(name); } + public void testNewline() throws Exception + { + Matcher m = NEWLINE.matcher("abcd\nefgh"); + m.region(4, 9); + assertTrue("newline 0", m.lookingAt()); + assertTrue("newline 1", m.lookingAt()); + + m.reset("abcd\r\nefgh").region(4, 10); + assertTrue("newline 2", m.lookingAt()); + assertEquals("\r\n", m.group()); + + m.reset("abcd\n\refgh").region(4, 10); + assertTrue("newline 3", m.lookingAt()); + assertEquals("\n", m.group()); + } + public void testSeparator() throws Exception { Pattern allTheRest = Pattern.compile(".*", Pattern.DOTALL); From c9b3473cc83fe316aa0ed564390705a7195a07dc Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Tue, 5 Sep 2023 11:54:48 -0400 Subject: [PATCH 13/25] Javadoc >= 17 rejects non-HTML5 attributes Instead of relying on valign to match the parameters to their descriptions, give the tables the class "striped", which is described in the javadoc-supplied stylesheet.css as one of the "Styles for user-provided tables". --- .../pljava/management/Commands.java | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/pljava/src/main/java/org/postgresql/pljava/management/Commands.java b/pljava/src/main/java/org/postgresql/pljava/management/Commands.java index 0cdafa254..df3884388 100644 --- a/pljava/src/main/java/org/postgresql/pljava/management/Commands.java +++ b/pljava/src/main/java/org/postgresql/pljava/management/Commands.java @@ -88,18 +88,18 @@ *

    SELECT sqlj.install_jar(<jar_url>, <jar_name>, <deploy>); *
    *

    Parameters

    - *
    + *
    Parameters for sqlj.install_jar(url...)
    * - * + * * * * - * + * * * * - * + * * @@ -109,20 +109,20 @@ *
    SELECT sqlj.install_jar(<jar_image>, <jar_name>, <deploy>); *
    *

    Parameters

    - *
    Parameters for sqlj.install_jar(url...)
    jar_urljar_urlThe URL that denotes the location of the jar that should be loaded
    jar_namejar_nameThis is the name by which this jar can be referenced once it has been * loaded
    deploydeployTrue if the jar should be deployed according to a {@link * org.postgresql.pljava.management.SQLDeploymentDescriptor deployment * descriptor}, false otherwise
    Parameters for + *
    * - * + * * * * - * + * * * * - * + * * @@ -136,17 +136,17 @@ *
    SELECT sqlj.replace_jar(<jar_url>, <jar_name>, <redeploy>); *
    *

    Parameters

    - *
    Parameters for * sqlj.install_jar(bytea...)
    jar_imagejar_imageThe byte array that constitutes the contents of the jar that should be * loaded
    jar_namejar_nameThis is the name by which this jar can be referenced once it has been * loaded
    deploydeployTrue if the jar should be deployed according to a {@link * org.postgresql.pljava.management.SQLDeploymentDescriptor deployment * descriptor}, false otherwise
    + *
    Parameters for sqlj.replace_jar(url...)
    * - * + * * * * - * + * * * * - * + * *
    Parameters for sqlj.replace_jar(url...)
    jar_urljar_urlThe URL that denotes the location of the jar that should be loaded
    jar_namejar_nameThe name of the jar to be replaced
    redeployredeployTrue if the old and new jar should be undeployed and deployed according * to their respective {@link * org.postgresql.pljava.management.SQLDeploymentDescriptor deployment @@ -157,19 +157,19 @@ *
    SELECT sqlj.replace_jar(<jar_image>, <jar_name>, <redeploy>); *
    *

    Parameters

    - *
    Parameters for + *
    * - * + * * * * - * + * * * * - * + * *
    Parameters for * sqlj.replace_jar(bytea...)
    jar_imagejar_imageThe byte array that constitutes the contents of the jar that should be * loaded
    jar_namejar_nameThe name of the jar to be replaced
    redeployredeployTrue if the old and new jar should be undeployed and deployed according * to their respective {@link * org.postgresql.pljava.management.SQLDeploymentDescriptor deployment @@ -184,13 +184,13 @@ *
    SELECT sqlj.remove_jar(<jar_name>, <undeploy>); *
    *

    Parameters

    - *
    + *
    Parameters for sqlj.remove_jar
    * - * + * * * * - * + * * @@ -204,7 +204,7 @@ *
    SELECT sqlj.get_classpath(<schema>); *
    *

    Parameters

    - *
    Parameters for sqlj.remove_jar
    jar_namejar_nameThe name of the jar to be removed
    undeployundeployTrue if the jar should be undeployed according to its {@link * org.postgresql.pljava.management.SQLDeploymentDescriptor deployment * descriptor}, false otherwise
    + *
    Parameters for sqlj.get_classpath
    * * * @@ -219,7 +219,7 @@ *
    SELECT sqlj.set_classpath(<schema>, <classpath>); *
    *

    Parameters

    - *
    Parameters for sqlj.get_classpath
    schemaThe name of the schema
    + *
    Parameters for sqlj.set_classpath
    * * * @@ -236,7 +236,7 @@ *
    SELECT sqlj.add_type_mapping(<sqlTypeName>, <className>); *
    *

    Parameters

    - *
    Parameters for sqlj.set_classpath
    schemaThe name of the schema
    + *
    Parameters for sqlj.add_type_mapping
    * * *
    Parameters for sqlj.add_type_mapping
    sqlTypeNameThe name of the SQL type. The name can be qualified with a @@ -256,7 +256,7 @@ *
    SELECT sqlj.drop_type_mapping(<sqlTypeName>); *
    *

    Parameters

    - *
    + *
    Parameters for sqlj.drop_type_mapping
    * * *
    Parameters for sqlj.drop_type_mapping
    sqlTypeNameThe name of the SQL type. The name can be qualified with a @@ -275,7 +275,7 @@ * {@code SELECT sqlj.alias_java_language(, sandboxed => );} * *

    Parameters

    - *
    + *
    Parameters for sqlj.alias_java_language
    * * *
    Parameters for sqlj.alias_java_language
    aliasThe name desired for the language alias. Language names are not From a3ee259f9f93e5f8b3b684bb12d68feaaa98bf92 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Wed, 6 Sep 2023 22:40:24 -0400 Subject: [PATCH 14/25] Quiet warnings about casts of function types It is easy enough to stop casting _PgObject_pureVirtualCalled to incompatible function types, as it makes modern compilers suspicious, and was only done in three places anyway. --- pljava-so/src/main/c/PgObject.c | 7 +--- pljava-so/src/main/c/type/Type.c | 33 ++++++++++++++++--- .../src/main/include/pljava/PgObject_priv.h | 20 +++++------ 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/pljava-so/src/main/c/PgObject.c b/pljava-so/src/main/c/PgObject.c index c34159323..fbf311fc7 100644 --- a/pljava-so/src/main/c/PgObject.c +++ b/pljava-so/src/main/c/PgObject.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2023 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,11 +66,6 @@ const char* PgObjectClass_getName(PgObjectClass self) return self->name; } -void _PgObject_pureVirtualCalled(PgObject object) -{ - ereport(ERROR, (errmsg("Pure virtual method called"))); -} - char* PgObject_getClassName(jclass cls) { jstring jstr; diff --git a/pljava-so/src/main/c/type/Type.c b/pljava-so/src/main/c/type/Type.c index 188e86e78..d3dcc50a5 100644 --- a/pljava-so/src/main/c/type/Type.c +++ b/pljava-so/src/main/c/type/Type.c @@ -1029,6 +1029,31 @@ void Type_initialize(void) initializeTypeBridges(); } +static Type unimplementedTypeObtainer(Oid typeId); +static jvalue unimplementedDatumCoercer(Type, Datum); +static Datum unimplementedObjectCoercer(Type, jobject); + +static Type unimplementedTypeObtainer(Oid typeId) +{ + ereport(ERROR, + (errmsg("no type obtainer registered for type oid %ud", typeId))); + pg_unreachable(); +} + +static jvalue unimplementedDatumCoercer(Type t, Datum d) +{ + ereport(ERROR, + (errmsg("no datum coercer registered for type oid %ud", t->typeId))); + pg_unreachable(); +} + +static Datum unimplementedObjectCoercer(Type t, jobject o) +{ + ereport(ERROR, + (errmsg("no object coercer registered for type oid %ud", t->typeId))); + pg_unreachable(); +} + /* * Abstract Type constructor */ @@ -1047,8 +1072,8 @@ TypeClass TypeClass_alloc2( self->javaTypeName = ""; self->javaClass = 0; self->canReplaceType = _Type_canReplaceType; - self->coerceDatum = (DatumCoercer)_PgObject_pureVirtualCalled; - self->coerceObject = (ObjectCoercer)_PgObject_pureVirtualCalled; + self->coerceDatum = unimplementedDatumCoercer; + self->coerceObject = unimplementedObjectCoercer; self->createArrayType = _Type_createArrayType; self->invoke = _Type_invoke; self->getSRFCollector = _Type_getSRFCollector; @@ -1137,9 +1162,7 @@ static void _registerType( void Type_registerType(const char* javaTypeName, Type type) { - _registerType( - type->typeId, javaTypeName, type, - (TypeObtainer)_PgObject_pureVirtualCalled); + _registerType(type->typeId, javaTypeName, type, unimplementedTypeObtainer); } void Type_registerType2( diff --git a/pljava-so/src/main/include/pljava/PgObject_priv.h b/pljava-so/src/main/include/pljava/PgObject_priv.h index b179a3b84..4c116b202 100644 --- a/pljava-so/src/main/include/pljava/PgObject_priv.h +++ b/pljava-so/src/main/include/pljava/PgObject_priv.h @@ -1,10 +1,14 @@ /* - * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden - * Distributed under the terms shown in the file COPYRIGHT - * found in the root folder of this project or at - * http://eng.tada.se/osprojects/COPYRIGHT.html + * Copyright (c) 2004-2023 Tada AB and other contributors, as listed below. * - * @author Thomas Hallgren + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the The BSD 3-Clause License + * which accompanies this distribution, and is available at + * http://opensource.org/licenses/BSD-3-Clause + * + * Contributors: + * Tada AB + * Chapman Flack */ #ifndef __pljava_PgObject_priv_h #define __pljava_PgObject_priv_h @@ -54,12 +58,6 @@ struct PgObject_ PgObjectClass m_class; }; -/* - * Internal bogus. Someone forgot to replace a function - * pointer somewhere. - */ -extern void _PgObject_pureVirtualCalled(PgObject self); - /* * Throw an exception indicating that wanted member could not be * found. From 188b418a8a8fbec2a3008250ca97b1190837f180 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sun, 10 Sep 2023 19:36:14 -0400 Subject: [PATCH 15/25] Two straggling schema qualifications Puzzling how these were overlooked in a7ce56f. --- .../org/postgresql/pljava/jdbc/SPIDatabaseMetaData.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pljava/src/main/java/org/postgresql/pljava/jdbc/SPIDatabaseMetaData.java b/pljava/src/main/java/org/postgresql/pljava/jdbc/SPIDatabaseMetaData.java index 1b5de43d6..067bfa0fa 100644 --- a/pljava/src/main/java/org/postgresql/pljava/jdbc/SPIDatabaseMetaData.java +++ b/pljava/src/main/java/org/postgresql/pljava/jdbc/SPIDatabaseMetaData.java @@ -1574,7 +1574,11 @@ public java.sql.ResultSet getProcedureColumns(String catalog, // if we are returning a multi-column result. if(returnTypeType.equals("c")) { - String columnsql = "SELECT a.attname,a.atttypid FROM pg_catalog.pg_attribute a WHERE a.attrelid = ? ORDER BY a.attnum "; + String columnsql = + "SELECT a.attname,a.atttypid " + + "FROM pg_catalog.pg_attribute a " + + "WHERE a.attrelid OPERATOR(pg_catalog.=) ? " + + "ORDER BY a.attnum"; PreparedStatement stmt = m_connection.prepareStatement(columnsql); stmt.setObject(1, returnTypeRelid); ResultSet columnrs = stmt.executeQuery(columnsql); @@ -2158,7 +2162,7 @@ public java.sql.ResultSet getTablePrivileges(String catalog, String sql = "SELECT n.nspname,c.relname,u.usename,c.relacl " + " FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, pg_catalog.pg_user u " - + " WHERE c.relnamespace = n.oid " + + " WHERE c.relnamespace OPERATOR(pg_catalog.=) n.oid " + " AND u.usesysid OPERATOR(pg_catalog.=) c.relowner " + " AND c.relkind OPERATOR(pg_catalog.=) 'r' " + " AND " + resolveSchemaPatternCondition( From 4ee2a9d1cfd089f49767a21cfb070e42ef512317 Mon Sep 17 00:00:00 2001 From: Chapman Flack Date: Sat, 16 Sep 2023 22:47:10 -0400 Subject: [PATCH 16/25] Allow use of Node with either PGJDBC or pgjdbc-ng The two drivers use slightly different URL syntax, and different names for some properties (database.name vs. PGDBNAME, and application.name vs. ApplicationName matter here). Expose a new static s_urlForm and constants URL_FORM_PGJDBC and URL_FORM_PGJDBCNG (and URL_FORM_NONE if no recognized driver has been found) so a client can know what's been selected. To simply count the otherwise-unwanted rows of a ResultSet, pgjdbc-ng allows rs.last();rs.getRow(); but PGJDBC does not, at least under its default for ResultSet scrollability. The method voidResultSetDims gets a change here to not attempt to count the rows when called by peek(); instead, it just returns -1 for rows in that case, which will look odd but play well with both drivers. The PostgreSQL backend sends an interesting message in the case of function/procedure creation with types mentioned that are shells. The message has severity NOTICE but SQLState 42809 (ERRCODE_WRONG_OBJECT_TYPE). For some reason, pgjdbc-ng has not been delivering those, but PGJDBC does, and the heuristic of looking at the class digits to decide if it's ok or not would make the wrong call seeing class 42. Happily, PGJDBC exposes (by casting to PGJDBC-specific types) the severity tag from the backend. So that has to be done here, and done reflectively, to avoid a hard PGJDBC dependency. PGJDBC exposes the SEVERITY (S) tag, but not the SEVERITY_NONLOCALIZED (V) tag that was added in PG 10 (postgres/postgres@26fa446). The upshot is that the rule used here to recognize WARNING will fail if the backend is using a language where it's some other word. A new static method set_WARNING_localized can be used to set the correct tag (PERINGATAN in Indonesian, for example) so the classification will happen correctly for the language selected in the backend. For utility statements with no result, where in pgjdbc-ng there really is no result, in PGJDBC there is a zero row count, the same as for a DML statement that touched no rows. It'll take another commit to make the test state machines work either way. --- pljava-packaging/pom.xml | 17 ++ pljava-packaging/src/main/java/Node.java | 238 +++++++++++++++++++++-- 2 files changed, 235 insertions(+), 20 deletions(-) diff --git a/pljava-packaging/pom.xml b/pljava-packaging/pom.xml index b7262e705..ee19ad959 100644 --- a/pljava-packaging/pom.xml +++ b/pljava-packaging/pom.xml @@ -64,6 +64,23 @@ + + + pgjdbc + + + org.postgresql + postgresql + [42.6.0,) + + + + + Date: Tue, 19 Sep 2023 15:52:52 -0400 Subject: [PATCH 25/25] Fix a silly copy/pasto in the release notes well, it'll be fixed for the next release.... --- src/site/markdown/releasenotes.md.vm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/site/markdown/releasenotes.md.vm b/src/site/markdown/releasenotes.md.vm index 9e0330ef4..a8a1c46c6 100644 --- a/src/site/markdown/releasenotes.md.vm +++ b/src/site/markdown/releasenotes.md.vm @@ -95,6 +95,8 @@ $h3 Bugs fixed [adjsfs]: pljava-api/apidocs/org.postgresql.pljava/org/postgresql/pljava/Adjusting.XML.html#method.detail [egsfs]: https://github.com/tada/pljava/blob/V1_6_6/pljava-examples/src/main/java/org/postgresql/pljava/example/annotation/PassXML.java#L528 +$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 @@ -191,8 +193,6 @@ Tim Van Holder, `aadrian`, `sincatter`, `tayalrun1`. [versions]: build/versions.html [JDK-8309515]: https://bugs.openjdk.org/browse/JDK-8309515 -$h2 Earlier releases - $h2 PL/Java 1.6.4 This is the fourth minor update in the PL/Java 1.6 series. It is a minor