From 1208bb59c2fdd031a770ac07f12acf14a0bb04d5 Mon Sep 17 00:00:00 2001 From: Paul Horn Date: Thu, 29 Aug 2024 14:16:58 +0200 Subject: [PATCH 1/2] 5.24 compatibility --- .../neo4j/gds/compat/_522/Neo4jProxyImpl.java | 88 +++++++++++++++++++ .../neo4j/gds/compat/_523/Neo4jProxyImpl.java | 88 +++++++++++++++++++ .../5.24/neo4j-kernel-adapter/build.gradle | 3 + .../neo4j/gds/compat/_524/Neo4jProxyImpl.java | 88 +++++++++++++++++++ .../gds/compat/CompatCallableProcedure.java | 5 +- .../org/neo4j/gds/compat/Neo4jProxyApi.java | 30 +++++++ .../java/org/neo4j/gds/compat/ProxyUtil.java | 2 +- .../gds/compat/CallableProcedureImpl.java | 52 ----------- .../gds/compat/GraphDatabaseApiProxy.java | 22 ++--- .../java/org/neo4j/gds/compat/Neo4jProxy.java | 38 +++++++- .../gds/core/loading/ValueConverter.java | 10 ++- .../neo4j/gds/utils/Neo4jValueConversion.java | 26 +++--- .../gds/projection/AlphaGraphAggregator.java | 5 +- .../neo4j/gds/projection/GraphAggregator.java | 5 +- .../projection/ProductGraphAggregator.java | 5 +- .../neo4j/gds/projection/ValueMapWrapper.java | 3 +- .../CypherLoadingUtils.java | 8 +- .../CypherRecordLoader.java | 5 +- .../ErrorCachingQuerySubscriber.java | 10 +-- .../gds/values/CypherNodeLabelTokens.java | 5 +- .../java/org/neo4j/gds/gdl/GdlFactory.java | 7 +- 21 files changed, 387 insertions(+), 118 deletions(-) delete mode 100644 compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CallableProcedureImpl.java rename {neo4j-adapter => compatibility/common/neo4j-kernel-adapter}/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java (93%) diff --git a/compatibility/5.22/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_522/Neo4jProxyImpl.java b/compatibility/5.22/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_522/Neo4jProxyImpl.java index af44c3aa3b9..31a3f111d3f 100644 --- a/compatibility/5.22/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_522/Neo4jProxyImpl.java +++ b/compatibility/5.22/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_522/Neo4jProxyImpl.java @@ -19,7 +19,12 @@ */ package org.neo4j.gds.compat._522; +import org.neo4j.collection.RawIterator; import org.neo4j.configuration.Config; +import org.neo4j.dbms.api.DatabaseNotFoundException; +import org.neo4j.exceptions.KernelException; +import org.neo4j.gds.annotation.SuppressForbidden; +import org.neo4j.gds.compat.CompatCallableProcedure; import org.neo4j.gds.compat.Neo4jProxyApi; import org.neo4j.gds.compat.batchimport.BatchImporter; import org.neo4j.gds.compat.batchimport.ExecutionMonitor; @@ -28,14 +33,25 @@ import org.neo4j.gds.compat.batchimport.input.Collector; import org.neo4j.gds.compat.batchimport.input.Estimates; import org.neo4j.gds.compat.batchimport.input.ReadableGroups; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.procs.ProcedureSignature; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.layout.DatabaseLayout; +import org.neo4j.kernel.api.ResourceMonitor; +import org.neo4j.kernel.api.exceptions.Status; +import org.neo4j.kernel.api.procedure.CallableProcedure; +import org.neo4j.kernel.api.procedure.Context; +import org.neo4j.kernel.impl.query.QueryExecutionKernelException; import org.neo4j.logging.internal.LogService; import org.neo4j.scheduler.JobScheduler; +import org.neo4j.values.AnyValue; +import org.neo4j.values.SequenceValue; import java.io.OutputStream; import java.util.function.LongConsumer; +import static org.neo4j.internal.helpers.collection.Iterators.asRawIterator; + public final class Neo4jProxyImpl implements Neo4jProxyApi { @Override @@ -141,4 +157,76 @@ public Estimates knownEstimates( numberOfNodeLabels ); } + + @Override + public void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException { + if (e.status() == Status.Procedure.ProcedureRegistrationFailed && e.getMessage().contains("already in use")) { + return; + } + throw e; + } + + @Override + public CallableProcedure callableProcedure(CompatCallableProcedure procedure) { + @SuppressForbidden(reason = "This is the compat API") + final class CallableProcedureImpl implements CallableProcedure { + private final CompatCallableProcedure procedure; + + private CallableProcedureImpl(CompatCallableProcedure procedure) { + this.procedure = procedure; + } + + @Override + public ProcedureSignature signature() { + return this.procedure.signature(); + } + + @Override + public RawIterator apply( + Context ctx, + AnyValue[] input, + ResourceMonitor resourceMonitor + ) throws ProcedureException { + return asRawIterator(this.procedure.apply(ctx, input)); + } + } + + return new CallableProcedureImpl(procedure); + } + + @Override + public int sequenceSizeAsInt(SequenceValue sequenceValue) { + return sequenceValue.length(); + } + + @Override + public RuntimeException queryExceptionAsRuntimeException(Throwable throwable) { + if (throwable instanceof RuntimeException) { + return (RuntimeException) throwable; + } else if (throwable instanceof QueryExecutionKernelException) { + return ((QueryExecutionKernelException) throwable).asUserException(); + } else { + return new RuntimeException(throwable); + } + } + + @Override + public ProcedureException procedureCallFailed(String message, Object... args) { + return new ProcedureException(Status.Procedure.ProcedureCallFailed, message, args); + } + + @Override + public ProcedureException procedureCallFailed(Throwable reason, String message, Object... args) { + return new ProcedureException(Status.Procedure.ProcedureCallFailed, reason, message, args); + } + + @Override + public String exceptionMessage(Throwable e) { + return e.getMessage(); + } + + @Override + public DatabaseNotFoundException databaseNotFoundException(String message) { + throw new DatabaseNotFoundException(message); + } } diff --git a/compatibility/5.23/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_523/Neo4jProxyImpl.java b/compatibility/5.23/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_523/Neo4jProxyImpl.java index 98a3b39db54..ff40252bf87 100644 --- a/compatibility/5.23/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_523/Neo4jProxyImpl.java +++ b/compatibility/5.23/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_523/Neo4jProxyImpl.java @@ -19,7 +19,12 @@ */ package org.neo4j.gds.compat._523; +import org.neo4j.collection.RawIterator; import org.neo4j.configuration.Config; +import org.neo4j.dbms.api.DatabaseNotFoundException; +import org.neo4j.exceptions.KernelException; +import org.neo4j.gds.annotation.SuppressForbidden; +import org.neo4j.gds.compat.CompatCallableProcedure; import org.neo4j.gds.compat.Neo4jProxyApi; import org.neo4j.gds.compat.batchimport.BatchImporter; import org.neo4j.gds.compat.batchimport.ExecutionMonitor; @@ -28,14 +33,25 @@ import org.neo4j.gds.compat.batchimport.input.Collector; import org.neo4j.gds.compat.batchimport.input.Estimates; import org.neo4j.gds.compat.batchimport.input.ReadableGroups; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.procs.ProcedureSignature; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.layout.DatabaseLayout; +import org.neo4j.kernel.api.ResourceMonitor; +import org.neo4j.kernel.api.exceptions.Status; +import org.neo4j.kernel.api.procedure.CallableProcedure; +import org.neo4j.kernel.api.procedure.Context; +import org.neo4j.kernel.impl.query.QueryExecutionKernelException; import org.neo4j.logging.internal.LogService; import org.neo4j.scheduler.JobScheduler; +import org.neo4j.values.AnyValue; +import org.neo4j.values.SequenceValue; import java.io.OutputStream; import java.util.function.LongConsumer; +import static org.neo4j.internal.helpers.collection.Iterators.asRawIterator; + public final class Neo4jProxyImpl implements Neo4jProxyApi { @Override @@ -141,4 +157,76 @@ public Estimates knownEstimates( numberOfNodeLabels ); } + + @Override + public void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException { + if (e.status() == Status.Procedure.ProcedureRegistrationFailed && e.getMessage().contains("already in use")) { + return; + } + throw e; + } + + @Override + public CallableProcedure callableProcedure(CompatCallableProcedure procedure) { + @SuppressForbidden(reason = "This is the compat API") + final class CallableProcedureImpl implements CallableProcedure { + private final CompatCallableProcedure procedure; + + private CallableProcedureImpl(CompatCallableProcedure procedure) { + this.procedure = procedure; + } + + @Override + public ProcedureSignature signature() { + return this.procedure.signature(); + } + + @Override + public RawIterator apply( + Context ctx, + AnyValue[] input, + ResourceMonitor resourceMonitor + ) throws ProcedureException { + return asRawIterator(this.procedure.apply(ctx, input)); + } + } + + return new CallableProcedureImpl(procedure); + } + + @Override + public int sequenceSizeAsInt(SequenceValue sequenceValue) { + return sequenceValue.length(); + } + + @Override + public RuntimeException queryExceptionAsRuntimeException(Throwable throwable) { + if (throwable instanceof RuntimeException) { + return (RuntimeException) throwable; + } else if (throwable instanceof QueryExecutionKernelException) { + return ((QueryExecutionKernelException) throwable).asUserException(); + } else { + return new RuntimeException(throwable); + } + } + + @Override + public ProcedureException procedureCallFailed(String message, Object... args) { + return new ProcedureException(Status.Procedure.ProcedureCallFailed, message, args); + } + + @Override + public ProcedureException procedureCallFailed(Throwable reason, String message, Object... args) { + return new ProcedureException(Status.Procedure.ProcedureCallFailed, reason, message, args); + } + + @Override + public String exceptionMessage(Throwable e) { + return e.getMessage(); + } + + @Override + public DatabaseNotFoundException databaseNotFoundException(String message) { + throw new DatabaseNotFoundException(message); + } } diff --git a/compatibility/5.24/neo4j-kernel-adapter/build.gradle b/compatibility/5.24/neo4j-kernel-adapter/build.gradle index 41f862f160a..5838683dc95 100644 --- a/compatibility/5.24/neo4j-kernel-adapter/build.gradle +++ b/compatibility/5.24/neo4j-kernel-adapter/build.gradle @@ -20,6 +20,9 @@ dependencies { compileOnly(group: 'org.neo4j', name: 'neo4j-import-api', version: neos.'5.24') { transitive = false } + compileOnly(group: 'org.neo4j', name: 'neo4j-gql-status', version: neos.'5.24') { + transitive = false + } implementation project(':neo4j-kernel-adapter-api') } diff --git a/compatibility/5.24/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_524/Neo4jProxyImpl.java b/compatibility/5.24/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_524/Neo4jProxyImpl.java index af35943228e..bd9d3b04e32 100644 --- a/compatibility/5.24/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_524/Neo4jProxyImpl.java +++ b/compatibility/5.24/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/_524/Neo4jProxyImpl.java @@ -19,7 +19,12 @@ */ package org.neo4j.gds.compat._524; +import org.neo4j.collection.ResourceRawIterator; import org.neo4j.configuration.Config; +import org.neo4j.dbms.api.DatabaseNotFoundException; +import org.neo4j.exceptions.KernelException; +import org.neo4j.gds.annotation.SuppressForbidden; +import org.neo4j.gds.compat.CompatCallableProcedure; import org.neo4j.gds.compat.Neo4jProxyApi; import org.neo4j.gds.compat.batchimport.BatchImporter; import org.neo4j.gds.compat.batchimport.ExecutionMonitor; @@ -28,14 +33,25 @@ import org.neo4j.gds.compat.batchimport.input.Collector; import org.neo4j.gds.compat.batchimport.input.Estimates; import org.neo4j.gds.compat.batchimport.input.ReadableGroups; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.procs.ProcedureSignature; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.layout.DatabaseLayout; +import org.neo4j.kernel.api.ResourceMonitor; +import org.neo4j.kernel.api.exceptions.Status; +import org.neo4j.kernel.api.procedure.CallableProcedure; +import org.neo4j.kernel.api.procedure.Context; +import org.neo4j.kernel.impl.query.QueryExecutionKernelException; import org.neo4j.logging.internal.LogService; import org.neo4j.scheduler.JobScheduler; +import org.neo4j.values.AnyValue; +import org.neo4j.values.SequenceValue; import java.io.OutputStream; import java.util.function.LongConsumer; +import static org.neo4j.internal.helpers.collection.Iterators.asRawIterator; + public final class Neo4jProxyImpl implements Neo4jProxyApi { @Override @@ -141,4 +157,76 @@ public Estimates knownEstimates( numberOfNodeLabels ); } + + @Override + public void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException { + if (e.status() == Status.Procedure.ProcedureRegistrationFailed && e.getMessage().contains("already in use")) { + return; + } + throw e; + } + + @Override + public CallableProcedure callableProcedure(CompatCallableProcedure procedure) { + @SuppressForbidden(reason = "This is the compat API") + final class CallableProcedureImpl implements CallableProcedure { + private final CompatCallableProcedure procedure; + + private CallableProcedureImpl(CompatCallableProcedure procedure) { + this.procedure = procedure; + } + + @Override + public ProcedureSignature signature() { + return this.procedure.signature(); + } + + @Override + public ResourceRawIterator apply( + Context context, + AnyValue[] anyValues, + ResourceMonitor resourceMonitor + ) throws ProcedureException { + return asRawIterator(this.procedure.apply(context, anyValues)); + } + } + + return new CallableProcedureImpl(procedure); + } + + @Override + public int sequenceSizeAsInt(SequenceValue sequenceValue) { + return sequenceValue.intSize(); + } + + @Override + public RuntimeException queryExceptionAsRuntimeException(Throwable throwable) { + if (throwable instanceof RuntimeException) { + return (RuntimeException) throwable; + } else if (throwable instanceof QueryExecutionKernelException) { + return ((QueryExecutionKernelException) throwable).asUserException(); + } else { + return new RuntimeException(throwable); + } + } + + @Override + public ProcedureException procedureCallFailed(String message, Object... args) { + return new ProcedureException(Status.Procedure.ProcedureCallFailed, message, args); + } + + @Override + public ProcedureException procedureCallFailed(Throwable reason, String message, Object... args) { + return new ProcedureException(Status.Procedure.ProcedureCallFailed, reason, message, args); + } + + @Override + public String exceptionMessage(Throwable e) { + return e.getMessage(); + } + + @Override + public DatabaseNotFoundException databaseNotFoundException(String message) { + throw new DatabaseNotFoundException(message); + } } diff --git a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CompatCallableProcedure.java b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CompatCallableProcedure.java index 97e67c52337..59560dc5130 100644 --- a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CompatCallableProcedure.java +++ b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CompatCallableProcedure.java @@ -19,14 +19,15 @@ */ package org.neo4j.gds.compat; -import org.neo4j.collection.RawIterator; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.internal.kernel.api.procs.ProcedureSignature; import org.neo4j.kernel.api.procedure.Context; import org.neo4j.values.AnyValue; +import java.util.stream.Stream; + public interface CompatCallableProcedure { ProcedureSignature signature(); - RawIterator apply(Context ctx, AnyValue[] input) throws ProcedureException; + Stream apply(Context ctx, AnyValue[] input) throws ProcedureException; } diff --git a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java index 28a36a18116..07aeb343424 100644 --- a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java +++ b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java @@ -19,7 +19,10 @@ */ package org.neo4j.gds.compat; +import org.intellij.lang.annotations.PrintFormat; import org.neo4j.configuration.Config; +import org.neo4j.dbms.api.DatabaseNotFoundException; +import org.neo4j.exceptions.KernelException; import org.neo4j.gds.compat.batchimport.BatchImporter; import org.neo4j.gds.compat.batchimport.ExecutionMonitor; import org.neo4j.gds.compat.batchimport.ImportConfig; @@ -27,10 +30,13 @@ import org.neo4j.gds.compat.batchimport.input.Collector; import org.neo4j.gds.compat.batchimport.input.Estimates; import org.neo4j.gds.compat.batchimport.input.ReadableGroups; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.layout.DatabaseLayout; +import org.neo4j.kernel.api.procedure.CallableProcedure; import org.neo4j.logging.internal.LogService; import org.neo4j.scheduler.JobScheduler; +import org.neo4j.values.SequenceValue; import java.io.OutputStream; import java.util.function.LongConsumer; @@ -95,4 +101,28 @@ Estimates knownEstimates( long sizeOfRelationshipProperties, long numberOfNodeLabels ); + + @CompatSince(minor = 24) + void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException; + + @CompatSince(minor = 24) + CallableProcedure callableProcedure(CompatCallableProcedure procedure); + + @CompatSince(minor = 24) + int sequenceSizeAsInt(SequenceValue sequenceValue); + + @CompatSince(minor = 24) + RuntimeException queryExceptionAsRuntimeException(Throwable e); + + @CompatSince(minor = 24) + ProcedureException procedureCallFailed(@PrintFormat String message, Object... args); + + @CompatSince(minor = 24) + ProcedureException procedureCallFailed(Throwable reason, @PrintFormat String message, Object... args); + + @CompatSince(minor = 24) + String exceptionMessage(Throwable e); + + @CompatSince(minor = 24) + DatabaseNotFoundException databaseNotFoundException(String message); } diff --git a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/ProxyUtil.java b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/ProxyUtil.java index d28812c8351..843ef9b49e2 100644 --- a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/ProxyUtil.java +++ b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/ProxyUtil.java @@ -173,7 +173,7 @@ private static > ProxyInfoempty() diff --git a/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CallableProcedureImpl.java b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CallableProcedureImpl.java deleted file mode 100644 index b456449a596..00000000000 --- a/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/CallableProcedureImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.gds.compat; - -import org.neo4j.collection.RawIterator; -import org.neo4j.gds.annotation.SuppressForbidden; -import org.neo4j.internal.kernel.api.exceptions.ProcedureException; -import org.neo4j.internal.kernel.api.procs.ProcedureSignature; -import org.neo4j.kernel.api.ResourceMonitor; -import org.neo4j.kernel.api.procedure.CallableProcedure; -import org.neo4j.kernel.api.procedure.Context; -import org.neo4j.values.AnyValue; - -@SuppressForbidden(reason = "This is the compat API") -final class CallableProcedureImpl implements CallableProcedure { - private final CompatCallableProcedure procedure; - - CallableProcedureImpl(CompatCallableProcedure procedure) { - this.procedure = procedure; - } - - @Override - public ProcedureSignature signature() { - return this.procedure.signature(); - } - - @Override - public RawIterator apply( - Context ctx, - AnyValue[] input, - ResourceMonitor resourceMonitor - ) throws ProcedureException { - return this.procedure.apply(ctx, input); - } -} diff --git a/neo4j-adapter/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java similarity index 93% rename from neo4j-adapter/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java rename to compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java index 44ca2759486..ea819e1c94d 100644 --- a/neo4j-adapter/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java +++ b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/GraphDatabaseApiProxy.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.TestOnly; import org.neo4j.common.DependencyResolver; import org.neo4j.exceptions.KernelException; -import org.neo4j.gds.annotation.ValueClass; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.NotFoundException; @@ -32,7 +31,6 @@ import org.neo4j.internal.kernel.api.security.LoginContext; import org.neo4j.io.layout.DatabaseLayout; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.procedure.CallableProcedure; import org.neo4j.kernel.api.procedure.CallableUserAggregationFunction; import org.neo4j.kernel.api.procedure.CallableUserFunction; @@ -221,19 +219,14 @@ public static InternalTransaction beginTransaction(GraphDatabaseService db, Logi @TestOnly public static Transactions newKernelTransaction(GraphDatabaseService db) { Transaction tx = db.beginTx(); - return ImmutableTransactions.of(tx, kernelTransaction(tx)); + return new Transactions(tx, kernelTransaction(tx)); } - @ValueClass - public interface Transactions extends AutoCloseable { - Transaction tx(); - - KernelTransaction ktx(); - + public record Transactions(Transaction tx, KernelTransaction ktx) implements AutoCloseable { @Override - default void close() { - tx().commit(); - tx().close(); + public void close() { + this.tx.commit(); + this.tx.close(); } } @@ -246,9 +239,6 @@ private GraphDatabaseApiProxy() { } private static void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException { - if (e.status() == Status.Procedure.ProcedureRegistrationFailed && e.getMessage().contains("already in use")) { - return; - } - throw e; + Neo4jProxy.rethrowUnlessDuplicateRegistration(e); } } diff --git a/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java index 128e4816402..898ee45a672 100644 --- a/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java +++ b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java @@ -19,6 +19,7 @@ */ package org.neo4j.gds.compat; +import org.intellij.lang.annotations.PrintFormat; import org.jetbrains.annotations.TestOnly; import org.neo4j.common.DependencyResolver; import org.neo4j.configuration.BootloaderSettings; @@ -28,6 +29,8 @@ import org.neo4j.configuration.connectors.ConnectorPortRegister; import org.neo4j.configuration.connectors.ConnectorType; import org.neo4j.configuration.helpers.DatabaseNameValidator; +import org.neo4j.dbms.api.DatabaseNotFoundException; +import org.neo4j.exceptions.KernelException; import org.neo4j.gds.annotation.SuppressForbidden; import org.neo4j.gds.compat.batchimport.BatchImporter; import org.neo4j.gds.compat.batchimport.ExecutionMonitor; @@ -83,6 +86,7 @@ import org.neo4j.storageengine.api.PropertySelection; import org.neo4j.storageengine.api.Reference; import org.neo4j.storageengine.api.StorageEngineFactory; +import org.neo4j.values.SequenceValue; import org.neo4j.values.storable.TextArray; import org.neo4j.values.virtual.MapValue; import org.neo4j.values.virtual.NodeValue; @@ -532,7 +536,35 @@ public static SslPolicyLoader createSllPolicyLoader( @SuppressForbidden(reason = "This is the compat API") public static CallableProcedure callableProcedure(CompatCallableProcedure procedure) { - return new CallableProcedureImpl(procedure); + return IMPL.callableProcedure(procedure); + } + + public static int sequenceSizeAsInt(SequenceValue listValue) { + return IMPL.sequenceSizeAsInt(listValue); + } + + public static RuntimeException queryExceptionAsRuntimeException(Throwable e) { + return IMPL.queryExceptionAsRuntimeException(e); + } + + public static ProcedureException procedureCallFailed(@PrintFormat String message, Object... args) { + return IMPL.procedureCallFailed(message, args); + } + + public static ProcedureException procedureCallFailed( + Throwable reason, + @PrintFormat String message, + Object... args + ) { + return IMPL.procedureCallFailed(reason, message, args); + } + + public static DatabaseNotFoundException databaseNotFoundException(String message) { + return IMPL.databaseNotFoundException(message); + } + + public static String exceptionMessage(Throwable e) { + return IMPL.exceptionMessage(e); } public static long transactionId(KernelTransactionHandle kernelTransactionHandle) { @@ -572,6 +604,10 @@ public static void registerCloseableResource( transaction.resourceMonitor().registerCloseableResource(autoCloseable); } + static void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException { + IMPL.rethrowUnlessDuplicateRegistration(e); + } + private Neo4jProxy() { throw new UnsupportedOperationException("No instances"); } diff --git a/core/src/main/java/org/neo4j/gds/core/loading/ValueConverter.java b/core/src/main/java/org/neo4j/gds/core/loading/ValueConverter.java index a1c385f2584..26218bb3c27 100644 --- a/core/src/main/java/org/neo4j/gds/core/loading/ValueConverter.java +++ b/core/src/main/java/org/neo4j/gds/core/loading/ValueConverter.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.neo4j.gds.api.nodeproperties.ValueType; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.ArrayValue; import org.neo4j.values.storable.DoubleArray; @@ -105,17 +106,18 @@ private static ArrayValue castToNumericArrayOrFail(ListValue listValue) { var firstValue = listValue.head(); try { + int size = Neo4jProxy.sequenceSizeAsInt(listValue); if (firstValue instanceof LongValue) { - var longArray = new long[listValue.size()]; + var longArray = new long[size]; var iterator = listValue.iterator(); - for (int i = 0; i < listValue.size() && iterator.hasNext(); i++) { + for (int i = 0; i < size && iterator.hasNext(); i++) { longArray[i] = ((LongValue) iterator.next()).longValue(); } return Values.longArray(longArray); } else if (firstValue instanceof DoubleValue) { - var doubleArray = new double[listValue.size()]; + var doubleArray = new double[size]; var iterator = listValue.iterator(); - for (int i = 0; i < listValue.size() && iterator.hasNext(); i++) { + for (int i = 0; i < size && iterator.hasNext(); i++) { doubleArray[i] = ((DoubleValue) iterator.next()).doubleValue(); } return Values.doubleArray(doubleArray); diff --git a/core/src/main/java/org/neo4j/gds/utils/Neo4jValueConversion.java b/core/src/main/java/org/neo4j/gds/utils/Neo4jValueConversion.java index 8937f4f8b8c..143ac7f79a4 100644 --- a/core/src/main/java/org/neo4j/gds/utils/Neo4jValueConversion.java +++ b/core/src/main/java/org/neo4j/gds/utils/Neo4jValueConversion.java @@ -19,6 +19,7 @@ */ package org.neo4j.gds.utils; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.values.storable.ByteArray; import org.neo4j.values.storable.DoubleArray; import org.neo4j.values.storable.FloatArray; @@ -98,12 +99,13 @@ public static float[] getFloatArray(Value value) { } private static double[] integralToDoubleArray(IntegralArray intArray) { - var result = new double[intArray.length()]; + var length = Neo4jProxy.sequenceSizeAsInt(intArray); + var result = new double[length]; IntToLongFunction longValueProvider = resolvelongValueProvider(intArray); try { - for (int idx = 0; idx < intArray.length(); idx++) { + for (int idx = 0; idx < length; idx++) { result[idx] = exactLongToDouble(longValueProvider.applyAsLong(idx)); } } catch (UnsupportedOperationException e) { @@ -114,9 +116,10 @@ private static double[] integralToDoubleArray(IntegralArray intArray) { } private static double[] floatToDoubleArray(FloatArray floatArray) { - var result = new double[floatArray.length()]; + var length = Neo4jProxy.sequenceSizeAsInt(floatArray); + var result = new double[length]; - for (int idx = 0; idx < floatArray.length(); idx++) { + for (int idx = 0; idx < length; idx++) { result[idx] = floatArray.doubleValue(idx); } @@ -124,10 +127,11 @@ private static double[] floatToDoubleArray(FloatArray floatArray) { } private static float[] doubleToFloatArray(DoubleArray doubleArray) { - var result = new float[doubleArray.length()]; + var length = Neo4jProxy.sequenceSizeAsInt(doubleArray); + var result = new float[length]; try { - for (int idx = 0; idx < doubleArray.length(); idx++) { + for (int idx = 0; idx < length; idx++) { result[idx] = notOverflowingDoubleToFloat(doubleArray.doubleValue(idx)); } } catch (UnsupportedOperationException e) { @@ -138,12 +142,13 @@ private static float[] doubleToFloatArray(DoubleArray doubleArray) { } private static float[] longToFloatArray(IntegralArray integralArray) { - var result = new float[integralArray.length()]; + var length = Neo4jProxy.sequenceSizeAsInt(integralArray); + var result = new float[length]; IntToLongFunction longValueProvider = resolvelongValueProvider(integralArray); try { - for (int idx = 0; idx < integralArray.length(); idx++) { + for (int idx = 0; idx < length; idx++) { result[idx] = exactLongToFloat(longValueProvider.applyAsLong(idx)); } } catch (UnsupportedOperationException e) { @@ -172,10 +177,11 @@ private static IntToLongFunction resolvelongValueProvider(IntegralArray integral } private static long[] floatToLongArray(FloatingPointArray floatArray) { - var result = new long[floatArray.length()]; + var length = Neo4jProxy.sequenceSizeAsInt(floatArray); + var result = new long[length]; try { - for (int idx = 0; idx < floatArray.length(); idx++) { + for (int idx = 0; idx < length; idx++) { result[idx] = exactDoubleToLong(floatArray.doubleValue(idx)); } } catch (UnsupportedOperationException e) { diff --git a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/AlphaGraphAggregator.java b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/AlphaGraphAggregator.java index 94737a42d62..42bf6e7da3f 100644 --- a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/AlphaGraphAggregator.java +++ b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/AlphaGraphAggregator.java @@ -20,10 +20,10 @@ package org.neo4j.gds.projection; import org.neo4j.gds.api.DatabaseId; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.loading.Capabilities.WriteMode; import org.neo4j.gds.metrics.projections.ProjectionMetricsService; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; -import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.NoValue; import org.neo4j.values.storable.TextValue; @@ -60,8 +60,7 @@ public void update(AnyValue[] input) throws ProcedureException { NoValue.NO_VALUE ); } catch (Exception e) { - throw new ProcedureException( - Status.Procedure.ProcedureCallFailed, + throw Neo4jProxy.procedureCallFailed( e, "Failed to invoke function `%s`: Caused by: %s", AlphaCypherAggregation.FUNCTION_NAME, diff --git a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/GraphAggregator.java b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/GraphAggregator.java index 71f6f2c4d2d..85018679e21 100644 --- a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/GraphAggregator.java +++ b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/GraphAggregator.java @@ -27,6 +27,7 @@ import org.neo4j.gds.api.DatabaseInfo.DatabaseLocation; import org.neo4j.gds.api.ImmutableDatabaseInfo; import org.neo4j.gds.api.PropertyState; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.ConfigKeyValidation; import org.neo4j.gds.core.CypherMapAccess; import org.neo4j.gds.core.concurrency.Concurrency; @@ -42,7 +43,6 @@ import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.internal.kernel.api.procs.UserAggregationReducer; import org.neo4j.internal.kernel.api.procs.UserAggregationUpdater; -import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.impl.util.ValueUtils; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.NoValue; @@ -255,8 +255,7 @@ public AnyValue result() throws ProcedureException { result = buildGraph(); } catch (Exception e) { projectionMetric.failed(e); - throw new ProcedureException( - Status.Procedure.ProcedureCallFailed, + throw Neo4jProxy.procedureCallFailed( e, "Failed to invoke function `%s`: Caused by: %s", CypherAggregation.FUNCTION_NAME, diff --git a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ProductGraphAggregator.java b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ProductGraphAggregator.java index 477711a9ae3..5b9c3212b3d 100644 --- a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ProductGraphAggregator.java +++ b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ProductGraphAggregator.java @@ -20,10 +20,10 @@ package org.neo4j.gds.projection; import org.neo4j.gds.api.DatabaseId; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.loading.Capabilities.WriteMode; import org.neo4j.gds.metrics.projections.ProjectionMetricsService; import org.neo4j.internal.kernel.api.exceptions.ProcedureException; -import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.TextValue; @@ -53,8 +53,7 @@ public void update(AnyValue[] input) throws ProcedureException { input[5] ); } catch (Exception e) { - throw new ProcedureException( - Status.Procedure.ProcedureCallFailed, + throw Neo4jProxy.procedureCallFailed( e, "Failed to invoke function `%s`: Caused by: %s", CypherAggregation.FUNCTION_NAME, diff --git a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ValueMapWrapper.java b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ValueMapWrapper.java index 11ecb99312a..db353b8ad31 100644 --- a/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ValueMapWrapper.java +++ b/cypher-aggregation/src/main/java/org/neo4j/gds/projection/ValueMapWrapper.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.CypherMapAccess; import org.neo4j.values.AnyValue; import org.neo4j.values.SequenceValue; @@ -163,7 +164,7 @@ public T mapTextArray(TextArray value) { @Override public T mapSequence(SequenceValue value) { if (List.class.isAssignableFrom(expectedType)) { - var length = value.length(); + var length = Neo4jProxy.sequenceSizeAsInt(value); var list = new ArrayList<>(length); for (var i = 0; i < length; i++) { list.add(value.value(i).map(AsJavaObject.instance())); diff --git a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherLoadingUtils.java b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherLoadingUtils.java index e63c79644f0..d620650e14a 100644 --- a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherLoadingUtils.java +++ b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherLoadingUtils.java @@ -19,7 +19,7 @@ */ package org.neo4j.gds.legacycypherprojection; -import org.neo4j.kernel.impl.query.QueryExecutionKernelException; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.kernel.impl.query.QuerySubscription; public final class CypherLoadingUtils { @@ -27,12 +27,8 @@ public final class CypherLoadingUtils { public static void consume(QuerySubscription execution) { try { execution.consumeAll(); - } catch (RuntimeException e) { - throw e; - } catch (QueryExecutionKernelException e) { - throw e.asUserException(); } catch (Exception e) { - throw new RuntimeException(e); + throw Neo4jProxy.queryExceptionAsRuntimeException(e); } } diff --git a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherRecordLoader.java b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherRecordLoader.java index fb8f5f2e3e7..d207c9dd43c 100644 --- a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherRecordLoader.java +++ b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/CypherRecordLoader.java @@ -29,7 +29,6 @@ import org.neo4j.kernel.impl.query.Neo4jTransactionalContextFactory; import org.neo4j.kernel.impl.query.QueryExecution; import org.neo4j.kernel.impl.query.QueryExecutionEngine; -import org.neo4j.kernel.impl.query.QueryExecutionKernelException; import org.neo4j.kernel.impl.query.QuerySubscriber; import org.neo4j.kernel.impl.query.TransactionalContextFactory; import org.neo4j.kernel.impl.util.ValueUtils; @@ -162,8 +161,8 @@ private static QueryExecution runQueryWithoutClosingTheResult( var context = Neo4jProxy.newQueryContext(contextFactory, tx, query, convertedParams); try { return executionEngine.executeQuery(query, convertedParams, context, false, subscriber); - } catch (QueryExecutionKernelException e) { - throw e.asUserException(); + } catch (Exception e) { + throw Neo4jProxy.queryExceptionAsRuntimeException(e); } } diff --git a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/ErrorCachingQuerySubscriber.java b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/ErrorCachingQuerySubscriber.java index 727043dc830..224df7d3baf 100644 --- a/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/ErrorCachingQuerySubscriber.java +++ b/legacy-cypher-projection/src/main/java/org/neo4j/gds/legacycypherprojection/ErrorCachingQuerySubscriber.java @@ -20,8 +20,8 @@ package org.neo4j.gds.legacycypherprojection; import org.jetbrains.annotations.Nullable; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.graphdb.QueryStatistics; -import org.neo4j.kernel.impl.query.QueryExecutionKernelException; import org.neo4j.kernel.impl.query.QuerySubscriber; import org.neo4j.values.AnyValue; @@ -37,13 +37,7 @@ public Optional error() { } public void onError(Throwable throwable) { - if (throwable instanceof RuntimeException) { - this.error = (RuntimeException) throwable; - } else if (throwable instanceof QueryExecutionKernelException) { - this.error = ((QueryExecutionKernelException) throwable).asUserException(); - } else { - this.error = new RuntimeException(throwable); - } + this.error = Neo4jProxy.queryExceptionAsRuntimeException(throwable); } public static final class DoNothingSubscriber extends ErrorCachingQuerySubscriber { diff --git a/neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java b/neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java index 98aac9d6edc..b7c61d5cdc3 100644 --- a/neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java +++ b/neo4j-values/src/main/java/org/neo4j/gds/values/CypherNodeLabelTokens.java @@ -22,6 +22,7 @@ import org.eclipse.collections.api.block.function.primitive.ObjectIntToObjectFunction; import org.jetbrains.annotations.NotNull; import org.neo4j.gds.NodeLabel; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.loading.construction.NodeLabelToken; import org.neo4j.gds.core.loading.construction.NodeLabelTokens; import org.neo4j.values.SequenceValue; @@ -58,7 +59,7 @@ private Sequence(T sequence, ObjectIntToObjectFunction toString) { @Override public int size() { - return sequence.length(); + return Neo4jProxy.sequenceSizeAsInt(sequence); } @Override @@ -68,7 +69,7 @@ public int size() { @Override public String[] getStrings() { - var result = new String[sequence.length()]; + var result = new String[size()]; Arrays.setAll(result, i -> toString.valueOf(sequence, i)); return result; } diff --git a/test-utils/src/main/java/org/neo4j/gds/gdl/GdlFactory.java b/test-utils/src/main/java/org/neo4j/gds/gdl/GdlFactory.java index b5db357b4bf..51c3407136d 100644 --- a/test-utils/src/main/java/org/neo4j/gds/gdl/GdlFactory.java +++ b/test-utils/src/main/java/org/neo4j/gds/gdl/GdlFactory.java @@ -35,6 +35,7 @@ import org.neo4j.gds.api.schema.Direction; import org.neo4j.gds.api.schema.MutableGraphSchema; import org.neo4j.gds.api.schema.MutableRelationshipSchema; +import org.neo4j.gds.compat.Neo4jProxy; import org.neo4j.gds.core.DimensionsMap; import org.neo4j.gds.core.GraphDimensions; import org.neo4j.gds.core.ImmutableGraphDimensions; @@ -52,10 +53,10 @@ import org.neo4j.gds.core.loading.construction.NodeLabelTokens; import org.neo4j.gds.core.loading.construction.PropertyValues; import org.neo4j.gds.core.loading.construction.RelationshipsBuilder; -import org.neo4j.gds.mem.MemoryEstimation; -import org.neo4j.gds.mem.MemoryEstimations; import org.neo4j.gds.core.utils.progress.tasks.ProgressTracker; import org.neo4j.gds.extension.GdlSupportPerMethodExtension; +import org.neo4j.gds.mem.MemoryEstimation; +import org.neo4j.gds.mem.MemoryEstimations; import org.neo4j.values.storable.ArrayValue; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.Values; @@ -422,7 +423,7 @@ static GraphDimensions of(GDLHandler gdlHandler) { var array = convertListProperty(((List) propertyValue)); nodePropertyDimensions.put( propertyKey, - Optional.of(((ArrayValue) Values.of(array)).length()) + Optional.of(Neo4jProxy.sequenceSizeAsInt((ArrayValue) Values.of(array))) ); } else { nodePropertyDimensions.put(propertyKey, Optional.of(1)); From 260d013735e59b5c2e252abedf0b24a83c66b5c6 Mon Sep 17 00:00:00 2001 From: Paul Horn Date: Thu, 29 Aug 2024 15:26:11 +0200 Subject: [PATCH 2/2] Add a comment about the need for compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Sören Reichardt --- .../org/neo4j/gds/compat/Neo4jProxyApi.java | 36 +++++++++++++++++++ .../java/org/neo4j/gds/compat/Neo4jProxy.java | 36 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java index 07aeb343424..b6d005a63b3 100644 --- a/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java +++ b/compatibility/api/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxyApi.java @@ -102,6 +102,12 @@ Estimates knownEstimates( long numberOfNodeLabels ); + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ @CompatSince(minor = 24) void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException; @@ -111,18 +117,48 @@ Estimates knownEstimates( @CompatSince(minor = 24) int sequenceSizeAsInt(SequenceValue sequenceValue); + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ @CompatSince(minor = 24) RuntimeException queryExceptionAsRuntimeException(Throwable e); + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ @CompatSince(minor = 24) ProcedureException procedureCallFailed(@PrintFormat String message, Object... args); + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ @CompatSince(minor = 24) ProcedureException procedureCallFailed(Throwable reason, @PrintFormat String message, Object... args); + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ @CompatSince(minor = 24) String exceptionMessage(Throwable e); + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ @CompatSince(minor = 24) DatabaseNotFoundException databaseNotFoundException(String message); } diff --git a/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java index 898ee45a672..e454fd96f2a 100644 --- a/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java +++ b/compatibility/common/neo4j-kernel-adapter/src/main/java/org/neo4j/gds/compat/Neo4jProxy.java @@ -543,14 +543,32 @@ public static int sequenceSizeAsInt(SequenceValue listValue) { return IMPL.sequenceSizeAsInt(listValue); } + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ public static RuntimeException queryExceptionAsRuntimeException(Throwable e) { return IMPL.queryExceptionAsRuntimeException(e); } + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ public static ProcedureException procedureCallFailed(@PrintFormat String message, Object... args) { return IMPL.procedureCallFailed(message, args); } + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ public static ProcedureException procedureCallFailed( Throwable reason, @PrintFormat String message, @@ -559,10 +577,22 @@ public static ProcedureException procedureCallFailed( return IMPL.procedureCallFailed(reason, message, args); } + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ public static DatabaseNotFoundException databaseNotFoundException(String message) { return IMPL.databaseNotFoundException(message); } + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ public static String exceptionMessage(Throwable e) { return IMPL.exceptionMessage(e); } @@ -604,6 +634,12 @@ public static void registerCloseableResource( transaction.resourceMonitor().registerCloseableResource(autoCloseable); } + /** + * The implementations of this method should look identical and are source-compatible. + * However, Since 5.24, Neo4j exceptions implement `HasGqlStatusInfo`, which requires + * a new module dependency that doesn't exist in versions before 5.24. + * In order to access any methods on exceptions, we need to do so behind the compat layer. + */ static void rethrowUnlessDuplicateRegistration(ProcedureException e) throws KernelException { IMPL.rethrowUnlessDuplicateRegistration(e); }