diff --git a/CI/common b/CI/common index 08df17edc..28947da5c 100644 --- a/CI/common +++ b/CI/common @@ -147,6 +147,12 @@ if ( 24 <= jFeatureVersion ) { serverOptions.put("pljava.allow_unenforced_udt", "on"); } +String pgConfigVersion = Node.getPgConfigProperty("--version"); + +Map clusterOptions = + Pattern.compile("\\b9\\.[56]").matcher(pgConfigVersion).find() ? + Map.of("--auth-host", "md5") : Map.of(); + Node n1 = Node.get_new_node("TestNode1"); if ( s_isWindows ) diff --git a/CI/integration b/CI/integration index 7690cd8e2..c191cdc26 100644 --- a/CI/integration +++ b/CI/integration @@ -32,7 +32,7 @@ /open CI/common try ( - AutoCloseable t1 = n1.initialized_cluster(tweaks); + AutoCloseable t1 = n1.initialized_cluster(clusterOptions, tweaks); AutoCloseable t2 = n1.started_server(serverOptions, tweaks); ) { diff --git a/pljava-packaging/src/main/java/Node.java b/pljava-packaging/src/main/java/Node.java index cabed18ea..073b4b901 100644 --- a/pljava-packaging/src/main/java/Node.java +++ b/pljava-packaging/src/main/java/Node.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2024 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2026 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,6 +30,9 @@ * For "Node" behavior: */ +import java.io.InterruptedIOException; +import java.io.IOException; + import static java.lang.ProcessBuilder.Redirect.INHERIT; import java.lang.reflect.InvocationHandler; // flexible SAM allowing exceptions import java.lang.reflect.UndeclaredThrowableException; @@ -155,13 +158,13 @@ public class Node extends JarX { private Matcher m_prefix; private int m_fsepLength; - private String m_lineSep; private boolean m_dryrun = false; private static Node s_jarxHelper = new Node(null, 0, null, null); private static boolean s_jarProcessed = false; private static String s_examplesJar; private static String s_sharedObject; + private static String s_lineSep = getProperty("line.separator"); /** * Performs an ordinary installation, using {@code pg_config} or the @@ -205,7 +208,6 @@ public void prepareResolver(String v) throws Exception { m_prefix = compile("^pljava/([^/]+dir)(?![^/])").matcher(""); m_fsepLength = getProperty("file.separator").length(); - m_lineSep = getProperty("line.separator"); } /** @@ -227,42 +229,7 @@ public String resolve(String storedPath, String platformPath) String replacement = getProperty(propkey); if ( null == replacement ) { - String pgc = getProperty("pgconfig", "pg_config"); - ProcessBuilder pb = new ProcessBuilder(pgc, "--"+key); - pb.redirectError(ProcessBuilder.Redirect.INHERIT); - Process proc = pb.start(); - byte[] output; - try ( InputStream instream = proc.getInputStream() ) - { - proc.getOutputStream().close(); - output = instream.readAllBytes(); - } - finally - { - int status = proc.waitFor(); - if ( 0 != status ) - { - System.err.println( - "ERROR: pg_config status is "+status); - System.exit(1); - } - } - /* - * pg_config output is the saved value followed by one \n only. - * However, on Windows, the C library treats stdout as text mode - * by default, and pg_config does nothing to change that, so the - * single \n written by pg_config gets turned to \r\n before it - * arrives here. The earlier use of the trim() method papered - * over the problem, but trim() can remove too much. Simply have - * to assume that the string will end with line.separator, and - * remove that. - */ - replacement = defaultCharset().newDecoder() - .decode(ByteBuffer.wrap(output, 0, output.length)) - .toString(); - assert replacement.endsWith(m_lineSep); - replacement = replacement.substring(0, - replacement.length() - m_lineSep.length()); + replacement = getPgConfigProperty("--"+key); setProperty(propkey, replacement); } int plen = m_fsepLength - 1; /* original separator had length 1 */ @@ -288,6 +255,64 @@ else if ( storedPath.matches( * of this class that is acting as a "Node" rather than as the JarX helper. */ + /** + * Returns the output, decoded using default platform charset, of the + * {@code pg_config} command executed with the single supplied argument. + *

+ * If multiple versions of {@code pg_config} are available or + * {@code pg_config} is not present on the path, the system property + * {@code pgconfig} should be set as an absolute path to the desired + * executable. + *

+ * For example, {@code getPgConfigProperty("--version")} can be used if + * version information is needed early for selecting options to pass to + * {@code init} or {@code initialized_cluster}. + * + * @see #init(Map,UnaryOperator) init + * + * @param pgConfigArgument argument to be passed to the command + * @return output of the input command executed with the input argument + * @throws IOException if unable to read output of the command + * @throws InterruptedException if command does not complete successfully + */ + public static String getPgConfigProperty(String pgConfigArgument) + throws IOException, InterruptedException + { + String pgc = getProperty("pgconfig", "pg_config"); + ProcessBuilder pb = new ProcessBuilder(pgc, pgConfigArgument); + pb.redirectError(INHERIT); + Process proc = pb.start(); + byte[] output; + try ( InputStream instream = proc.getInputStream() ) + { + proc.getOutputStream().close(); + output = instream.readAllBytes(); + } + finally + { + int status = proc.waitFor(); + if ( 0 != status ) + throw new InterruptedIOException( + "pg_config has exited with status " + status); + } + /* + * pg_config output is the saved value followed by one \n only. + * However, on Windows, the C library treats stdout as text mode + * by default, and pg_config does nothing to change that, so the + * single \n written by pg_config gets turned to \r\n before it + * arrives here. The earlier use of the trim() method papered + * over the problem, but trim() can remove too much. Simply have + * to assume that the string will end with line.separator, and + * remove that. + */ + String replacement = defaultCharset().newDecoder() + .decode(ByteBuffer.wrap(output, 0, output.length)) + .toString(); + assert replacement.endsWith(s_lineSep); + return replacement.substring(0, + replacement.length() - s_lineSep.length()); + } + /** * True if the platform is determined to be Windows. *

@@ -792,20 +817,38 @@ public void init(UnaryOperator tweaks) throws Exception * and tweaks to be applied to the {@code ProcessBuilder} * before it is started. *

- * By default, {@code postgres} will be the name of the superuser, UTF-8 - * will be the encoding, {@code auth-local} will be {@code peer} and - * {@code auth-host} will be {@code md5}. The initialization will skip - * {@code fsync} for speed rather than safety (if something goes wrong, just - * {@code clean_node()} and start over). + * When any of the following is not present in suppliedOptions, + * it will default as follows: {@code postgres} will be the name of + * the superuser, UTF-8 will be the encoding, {@code auth-local} will be + * {@code peer}, and {@code auth-host} will be an authentication method + * using passwords (see below). + *

+ * The initialization will, by default, skip {@code fsync} for speed rather + * than safety (if something goes wrong, just {@code clean_node()} and + * start over). *

* The {@code initdb} that will be run is the one in the {@code bindir} * reported by {@code pg_config} (or set by {@code -Dpgconfig.bindir}). + *

+ * Password authentication methods: Early versions of + * this class defaulted to {@code md5}, which has been deprecated. As of + * this writing, the default is now {@code scram-sha-256}, which became + * available in PostgreSQL 10. If this class is used in automated testing + * of PL/Java support for earlier PostgreSQL releases, the script will need + * to pass something like {@code Map.of("--auth-host", "md5")} with + * suppliedOptions. A script that needs to make that decision can + * use {@code getPgConfigProperty("--version")} to retrieve a version string + * before calling this method (and, therefore, before a data directory has + * been populated with a {@code PG_VERSION} file). * @param suppliedOptions a Map where each key is an option to initdb * (for example, --encoding), and the value corresponds. * @param tweaks a lambda applicable to the {@code ProcessBuilder} to * further configure it. On Windows, the tweaks will be applied ahead of * transformation of the arguments by * {@link #forWindowsCRuntime forWindowsCRuntime}. + * + * @see #initialized_cluster(Map,UnaryOperator) initialized_cluster + * @see #getPgConfigProperty getPgConfigProperty */ public void init( Map suppliedOptions, @@ -840,7 +883,7 @@ public void init( options.putIfAbsent("--encoding", "utf-8"); options.putIfAbsent("--pwfile", pwfile.toString()); options.putIfAbsent("--auth-local", "peer"); - options.putIfAbsent("--auth-host", "md5"); + options.putIfAbsent("--auth-host", "scram-sha-256"); options.putIfAbsent("-N", null); String[] args = diff --git a/pljava-so/src/main/c/Backend.c b/pljava-so/src/main/c/Backend.c index 8e4cf71d0..35e0846b5 100644 --- a/pljava-so/src/main/c/Backend.c +++ b/pljava-so/src/main/c/Backend.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2025 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -195,9 +195,9 @@ static void reLogWithChangedLevel(int); #endif #ifdef USE_PLJAVA_SIGHANDLERS -static void pljavaStatementCancelHandler(int); -static void pljavaDieHandler(int); -static void pljavaQuickDieHandler(int); +static void pljavaStatementCancelHandler(SIGNAL_ARGS); +static void pljavaDieHandler(SIGNAL_ARGS); +static void pljavaQuickDieHandler(SIGNAL_ARGS); #endif enum initstage @@ -950,7 +950,7 @@ static void reLogWithChangedLevel(int level) FreeErrorData(edata); } -void _PG_init() +void _PG_init(void) { char *sep; @@ -1122,7 +1122,7 @@ static const char DEATH_HINT[] = static void onJVMExitOrAbort(void); -static void JNICALL my_abort() +static void JNICALL my_abort(void) { onJVMExitOrAbort(); ereport(FATAL, ( @@ -1147,7 +1147,7 @@ static void JNICALL my_exit(jint code) )); } -static void onJVMExitOrAbort() +static void onJVMExitOrAbort(void) { /* * We will later hit the proc_exit handler, which will try to destroy the @@ -1363,7 +1363,7 @@ static char* getModulePath(const char* prefix) #ifdef USE_PLJAVA_SIGHANDLERS -static void pljavaStatementCancelHandler(int signum) +static void pljavaStatementCancelHandler(SIGNAL_ARGS) { if(!proc_exit_inprogress) { @@ -1376,7 +1376,7 @@ static void pljavaStatementCancelHandler(int signum) } } -static void pljavaDieHandler(int signum) +static void pljavaDieHandler(SIGNAL_ARGS) { if(!proc_exit_inprogress) { @@ -1389,7 +1389,7 @@ static void pljavaDieHandler(int signum) } } -static void pljavaQuickDieHandler(int signum) +static void pljavaQuickDieHandler(SIGNAL_ARGS) { /* Just die. No ereporting here since we don't know what thread this is. */ @@ -1397,7 +1397,7 @@ static void pljavaQuickDieHandler(int signum) } static sigjmp_buf recoverBuf; -static void terminationTimeoutHandler() +static void terminationTimeoutHandler(void) { kill(MyProcPid, SIGQUIT); diff --git a/pljava-so/src/main/c/Exception.c b/pljava-so/src/main/c/Exception.c index 2c7c862e8..01053c22b 100644 --- a/pljava-so/src/main/c/Exception.c +++ b/pljava-so/src/main/c/Exception.c @@ -170,7 +170,7 @@ void Exception_throwSPI(const char* function, int errCode) SPI_result_code_string(errCode)); } -void Exception_throw_unhandled() +void Exception_throw_unhandled(void) { jobject ex; PG_TRY(); diff --git a/pljava-so/src/main/c/InstallHelper.c b/pljava-so/src/main/c/InstallHelper.c index 488ee0a66..b3b817ee7 100644 --- a/pljava-so/src/main/c/InstallHelper.c +++ b/pljava-so/src/main/c/InstallHelper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2024 Tada AB and other contributors, as listed below. + * Copyright (c) 2015-2026 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 @@ -77,7 +77,7 @@ static bool extensionExNihilo = false; static void checkLoadPath(void); static void getExtensionLoadPath(void); -static char *origUserName(); +static char *origUserName(void); char const *pljavaLoadPath = NULL; @@ -87,12 +87,12 @@ Oid pljavaTrustedOid = InvalidOid; Oid pljavaUntrustedOid = InvalidOid; -bool pljavaViableXact() +bool pljavaViableXact(void) { return IsTransactionState() && 'E' != TransactionBlockStatusCode(); } -char *pljavaDbName() +char *pljavaDbName(void) { if ( AmAutoVacuumWorkerProcess() || AmBackgroundWorkerProcess() ) { @@ -112,7 +112,7 @@ char *pljavaDbName() return MyProcPort->database_name; } -static char *origUserName() +static char *origUserName(void) { if ( AmAutoVacuumWorkerProcess() || AmBackgroundWorkerProcess() ) { @@ -129,7 +129,7 @@ static char *origUserName() return MyProcPort->user_name; } -char const *pljavaClusterName() +char const *pljavaClusterName(void) { /* * In PostgreSQL of at least 9.5, there's always one (even if it is an empty @@ -165,7 +165,7 @@ 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() +static void checkLoadPath(void) { List *l; Node *ut; @@ -216,7 +216,7 @@ static void checkLoadPath() (char const *)MemoryContextStrdup(TopMemoryContext, ls->filename); } -static void getExtensionLoadPath() +static void getExtensionLoadPath(void) { MemoryContext curr; Datum dtm; @@ -356,7 +356,7 @@ char *pljavaFnOidToLibPath(Oid fnOid, char **langName, bool *trusted) return probinstring; } -bool InstallHelper_shouldDeferInit() +bool InstallHelper_shouldDeferInit(void) { if ( AmAutoVacuumWorkerProcess() || AmBackgroundWorkerProcess() ) return true; @@ -434,13 +434,13 @@ char const *InstallHelper_defaultModulePath(char *pathbuf, char pathsep) return pathbuf; } -void InstallHelper_earlyHello() +void InstallHelper_earlyHello(void) { elog(DEBUG2, "pljava-so-" SO_VERSION_STRING " built for (" PG_VERSION_STR ")"); } -char *InstallHelper_hello() +char *InstallHelper_hello(void) { char pathbuf[MAXPGPATH]; Invocation ctx; @@ -521,7 +521,7 @@ char *InstallHelper_hello() return greetingC; } -void InstallHelper_groundwork() +void InstallHelper_groundwork(void) { Invocation ctx; bool snapshot_set = false; @@ -567,7 +567,7 @@ void InstallHelper_groundwork() PG_END_TRY(); } -void InstallHelper_initialize() +void InstallHelper_initialize(void) { s_InstallHelper_class = (jclass)JNI_newGlobalRef(PgObject_getJavaClass( "org/postgresql/pljava/internal/InstallHelper")); diff --git a/pljava-so/src/main/c/JNICalls.c b/pljava-so/src/main/c/JNICalls.c index 230fb3736..4872e128b 100644 --- a/pljava-so/src/main/c/JNICalls.c +++ b/pljava-so/src/main/c/JNICalls.c @@ -22,6 +22,10 @@ #include "pljava/type/ErrorData.h" #include "pljava/type/String.h" +#if 190000 <= PG_VERSION_NUM +#include /* for MyBackendType */ +#endif + static JNIEnv* jniEnv; jint (JNICALL *pljava_createvm)(JavaVM **, void **, void *); @@ -205,11 +209,13 @@ static void elogExceptionMessage(JNIEnv* env, jthrowable exh, int logLevel) static void printStacktrace(JNIEnv* env, jobject exh, int elevel) { -#if 100002<=PG_VERSION_NUM || \ +#if 190000<=PG_VERSION_NUM + if (elevel>=log_min_messages[MyBackendType] || elevel>=client_min_messages) +#elif 100002<=PG_VERSION_NUM || \ 90607<=PG_VERSION_NUM && PG_VERSION_NUM<100000 || \ 90511<=PG_VERSION_NUM && PG_VERSION_NUM< 90600 || \ ! defined(_MSC_VER) - if(elevel >= log_min_messages || elevel >= client_min_messages) + if (elevel >= log_min_messages || elevel >= client_min_messages) #else /* This is gross, but only happens as often as an exception escapes Java * code to be rethrown. There is some renewed interest on pgsql-hackers to @@ -1709,7 +1715,7 @@ static void _heavyUpdater(jobject loader) END_JAVA } -void _heavyRestorer() +void _heavyRestorer(void) { jobject thread; jobject value; @@ -1746,7 +1752,7 @@ static void _lightUpdater(jobject loader) END_JAVA } -void _lightRestorer() +void _lightRestorer(void) { jobject value; @@ -1764,6 +1770,6 @@ static void _noopUpdater(jobject loader) { } -void _noopRestorer() +void _noopRestorer(void) { } diff --git a/pljava-so/src/main/c/type/Array.c b/pljava-so/src/main/c/type/Array.c index b2e654482..d72bd7d8f 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-2023 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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,17 +14,17 @@ #include "pljava/type/Array.h" #include "pljava/Invocation.h" -void arraySetNull(bits8* bitmap, int offset, bool flag) +void arraySetNull(uint8* bitmap, int offset, bool flag) { if(bitmap != 0) { int bitmask = 1 << (offset % 8); bitmap += offset / 8; - *bitmap = (bits8)(flag? *bitmap & ~bitmask : *bitmap | bitmask); + *bitmap = (uint8)(flag? *bitmap & ~bitmask : *bitmap | bitmask); } } -bool arrayIsNull(const bits8* bitmap, int offset) +bool arrayIsNull(const uint8* bitmap, int offset) { return bitmap == 0 ? false : !(bitmap[offset / 8] & (1 << (offset % 8))); } @@ -47,7 +47,7 @@ ArrayType* createArrayType(jsize nElems, size_t elemSize, Oid elemType, bool wit nBytes += ARR_OVERHEAD_NONULLS(1); } v = (ArrayType*)palloc0(nBytes); - AssertVariableIsOfType(v->dataoffset, int32); + StaticAssertVariableIsOfType(v->dataoffset, int32); v->dataoffset = (int32)dataoffset; MemoryContextSwitchTo(currCtx); @@ -71,7 +71,7 @@ static jvalue _Array_coerceDatum(Type self, Datum arg) jsize nElems = (jsize)ArrayGetNItems(ARR_NDIM(v), ARR_DIMS(v)); jobjectArray objArray = JNI_newObjectArray(nElems, Type_getJavaClass(elemType), 0); const char* values = ARR_DATA_PTR(v); - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); for(idx = 0; idx < nElems; ++idx) { diff --git a/pljava-so/src/main/c/type/Boolean.c b/pljava-so/src/main/c/type/Boolean.c index fc93ac145..971f2e9e4 100644 --- a/pljava-so/src/main/c/type/Boolean.c +++ b/pljava-so/src/main/c/type/Boolean.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -47,7 +47,7 @@ static jvalue _booleanArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jboolean* values = (jboolean*)ARR_DATA_PTR(v); jboolean* elems = JNI_getBooleanArrayElements(booleanArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/Byte.c b/pljava-so/src/main/c/type/Byte.c index ec8fb21e5..287479060 100644 --- a/pljava-so/src/main/c/type/Byte.c +++ b/pljava-so/src/main/c/type/Byte.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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,7 +51,7 @@ static jvalue _byteArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jbyte* values = (jbyte*)ARR_DATA_PTR(v); jbyte* elems = JNI_getByteArrayElements(byteArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/Double.c b/pljava-so/src/main/c/type/Double.c index 241ba15b5..e2cc08a56 100644 --- a/pljava-so/src/main/c/type/Double.c +++ b/pljava-so/src/main/c/type/Double.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -54,7 +54,7 @@ static jvalue _doubleArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jdouble* values = (jdouble*)ARR_DATA_PTR(v); jdouble* elems = JNI_getDoubleArrayElements(doubleArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/Float.c b/pljava-so/src/main/c/type/Float.c index f853097f5..76a106065 100644 --- a/pljava-so/src/main/c/type/Float.c +++ b/pljava-so/src/main/c/type/Float.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -54,7 +54,7 @@ static jvalue _floatArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jfloat* values = (jfloat*)ARR_DATA_PTR(v); jfloat* elems = JNI_getFloatArrayElements(floatArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/Integer.c b/pljava-so/src/main/c/type/Integer.c index fde680b57..e364ef685 100644 --- a/pljava-so/src/main/c/type/Integer.c +++ b/pljava-so/src/main/c/type/Integer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -47,7 +47,7 @@ static jvalue _intArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jint* values = (jint*)ARR_DATA_PTR(v); jint* elems = JNI_getIntArrayElements(intArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/Long.c b/pljava-so/src/main/c/type/Long.c index 45c9ef377..b2d889016 100644 --- a/pljava-so/src/main/c/type/Long.c +++ b/pljava-so/src/main/c/type/Long.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -54,7 +54,7 @@ static jvalue _longArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jlong* values = (jlong*)ARR_DATA_PTR(v); jlong* elems = JNI_getLongArrayElements(longArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/Short.c b/pljava-so/src/main/c/type/Short.c index 88a6d9ae8..091351d6e 100644 --- a/pljava-so/src/main/c/type/Short.c +++ b/pljava-so/src/main/c/type/Short.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2020 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -47,7 +47,7 @@ static jvalue _shortArray_coerceDatum(Type self, Datum arg) { jsize idx; jboolean isCopy = JNI_FALSE; - bits8* nullBitMap = ARR_NULLBITMAP(v); + uint8* nullBitMap = ARR_NULLBITMAP(v); jshort* values = (jshort*)ARR_DATA_PTR(v); jshort* elems = JNI_getShortArrayElements(shortArray, &isCopy); for(idx = 0; idx < nElems; ++idx) diff --git a/pljava-so/src/main/c/type/String.c b/pljava-so/src/main/c/type/String.c index 8b4623942..d2649a86b 100644 --- a/pljava-so/src/main/c/type/String.c +++ b/pljava-so/src/main/c/type/String.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2023 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -390,7 +390,7 @@ void String_initialize(void) Type_registerType2(VARCHAROID, "java.lang.String", String_obtain); } -static void String_initialize_codec() +static void String_initialize_codec(void) { /* * Wondering why this function doesn't bother deleting its many local refs? diff --git a/pljava-so/src/main/c/type/Type.c b/pljava-so/src/main/c/type/Type.c index d3dcc50a5..228c2d0ad 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-2023 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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,6 +30,10 @@ #include "pljava/HashMap.h" #include "pljava/SPI.h" +#if PG_VERSION_NUM < 190000 +#define DomainHasConstraints(typid, volflag) DomainHasConstraints(typid) +#endif + #if PG_VERSION_NUM < 110000 static Oid BOOLARRAYOID; static Oid CHARARRAYOID; @@ -244,7 +248,8 @@ static Type _getCoerce(Type self, Type other, Oid fromOid, Oid toOid, * Binary compatible type. No need for a special coercer. * Unless ... it's a domain .... */ - if ( ! IsBinaryCoercible(fromOid, toOid) && DomainHasConstraints(toOid)) + if ( ! IsBinaryCoercible(fromOid, toOid) + && DomainHasConstraints(toOid, NULL) ) elog(WARNING, "disregarding domain constraints of (regtype) %d", toOid); return self; @@ -881,7 +886,7 @@ static void addTypeBridge(jclass c, jmethodID m, char const *cName, Oid oid) JNI_deleteLocalRef(jcn); } -static void initializeTypeBridges() +static void initializeTypeBridges(void) { jclass cls; jmethodID ofClass; diff --git a/pljava-so/src/main/include/pljava/pljava.h b/pljava-so/src/main/include/pljava/pljava.h index 9a95a0b72..c0996fa6f 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-2025 Tada AB and other contributors, as listed below. + * Copyright (c) 2004-2026 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 @@ -40,15 +40,17 @@ extern int vsnprintf(char* buf, size_t count, const char* format, va_list arg); #include /* - * AssertVariableIsOfType appeared in PG9.3. Can test for the macro directly. - * Likewise for StaticAssertStmt. + * StaticAssertVariableIsOfType first appeared, differently named, in PG9.3. + * Can test for the macro directly. Likewise for the macro flavor. */ -#ifndef AssertVariableIsOfType -#define AssertVariableIsOfType(varname, typename) +#ifndef StaticAssertVariableIsOfType +#define StaticAssertVariableIsOfType(varname, typename) \ + AssertVariableIsOfType(varname, typename) #endif -#ifndef StaticAssertStmt -#define StaticAssertStmt(condition, errmessage) +#ifndef StaticAssertVariableIsOfTypeMacro +#define StaticAssertVariableIsOfTypeMacro(varname, typename) \ + AssertVariableIsOfTypeMacro(varname, typename) #endif /* @@ -159,7 +161,7 @@ PointerGetJLong(const void *X) } #define JLongGet(T, X) \ - (AssertVariableIsOfTypeMacro(X, jlong), (T)(uintptr_t)(X)) + (StaticAssertVariableIsOfTypeMacro(X, jlong), (T)(uintptr_t)(X)) struct Invocation_; typedef struct Invocation_ Invocation; diff --git a/pljava-so/src/main/include/pljava/type/Array.h b/pljava-so/src/main/include/pljava/type/Array.h index a9079203a..46946b112 100644 --- a/pljava-so/src/main/include/pljava/type/Array.h +++ b/pljava-so/src/main/include/pljava/type/Array.h @@ -1,8 +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-2026 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 + * which accompanies this distribution, and is available at + * http://opensource.org/licenses/BSD-3-Clause + * + * Contributors: + * Tada AB + * Chapman Flack */ #ifndef __pljava_type_Array_h #define __pljava_type_Array_h @@ -23,8 +29,8 @@ extern "C" { ***********************************************************************/ extern ArrayType* createArrayType(jsize nElems, size_t elemSize, Oid elemType, bool withNulls); -extern void arraySetNull(bits8* bitmap, int offset, bool flag); -extern bool arrayIsNull(const bits8* bitmap, int offset); +extern void arraySetNull(uint8* bitmap, int offset, bool flag); +extern bool arrayIsNull(const uint8* bitmap, int offset); extern Type Array_fromOid(Oid typeId, Type elementType); extern Type Array_fromOid2(Oid typeId, Type elementType, DatumCoercer coerceDatum, ObjectCoercer coerceObject);