diff --git a/community/kernel-api/pom.xml b/community/kernel-api/pom.xml index 695cd4c36855d..7f01f933d9771 100644 --- a/community/kernel-api/pom.xml +++ b/community/kernel-api/pom.xml @@ -64,6 +64,11 @@ the relevant Commercial Agreement. neo4j-graphdb-api ${project.version} + + org.neo4j + neo4j-procedure-api + ${project.version} + org.neo4j neo4j-common diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Procedures.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Procedures.java new file mode 100644 index 0000000000000..a9fe518c9d16b --- /dev/null +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Procedures.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.internal.kernel.api; + +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.procs.QualifiedName; +import org.neo4j.internal.kernel.api.procs.UserAggregator; +import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; +import org.neo4j.internal.kernel.api.security.AccessMode; +import org.neo4j.values.AnyValue; + +public interface Procedures +{ + UserFunctionHandle functionGet( QualifiedName name ); + + UserFunctionHandle aggregationFunctionGet( QualifiedName name ); + + /** Invoke a read-only function by name + * @param id the id of the function. + * @param arguments the function arguments. + * @throws ProcedureException if there was an exception thrown during function execution. + */ + AnyValue functionCall( int id, AnyValue[] arguments ) throws ProcedureException; + + /** Invoke a read-only function by name, and set the transaction's access mode to + * {@link AccessMode.Static#READ READ} for the duration of the function execution. + * @param id the id of the function. + * @param arguments the function arguments. + * @throws ProcedureException if there was an exception thrown during function execution. + */ + AnyValue functionCallOverride( int id, AnyValue[] arguments ) throws ProcedureException; + + /** + * Create a read-only aggregation function by name + * @param id the id of the function + * @return the aggregation function + * @throws ProcedureException + */ + UserAggregator aggregationFunction( int id ) throws ProcedureException; + + /** Invoke a read-only aggregation function by name, and set the transaction's access mode to + * {@link AccessMode.Static#READ READ} for the duration of the function execution. + * @param id the id of the function. + * @throws ProcedureException if there was an exception thrown during function execution. + */ + UserAggregator aggregationFunctionOverride( int id ) throws ProcedureException; + +} diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java index e726521048d1d..87529462d7509 100644 --- a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java @@ -20,6 +20,8 @@ package org.neo4j.internal.kernel.api; import org.neo4j.internal.kernel.api.exceptions.KernelException; +import org.neo4j.internal.kernel.api.procs.QualifiedName; +import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; /** * Defines the graph read operations of the Kernel. diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Transaction.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Transaction.java index 77a62a2439190..1e0aed1daea24 100644 --- a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Transaction.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Transaction.java @@ -122,4 +122,6 @@ enum Type * @return The cursor factory */ CursorFactory cursors(); + + Procedures procedures(); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/ProcedureException.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/exceptions/ProcedureException.java similarity index 92% rename from community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/ProcedureException.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/exceptions/ProcedureException.java index 22aae4057eb09..aa4366a239be6 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/ProcedureException.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/exceptions/ProcedureException.java @@ -17,9 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.api.exceptions; +package org.neo4j.internal.kernel.api.exceptions; -import org.neo4j.internal.kernel.api.exceptions.KernelException; +import org.neo4j.kernel.api.exceptions.Status; public class ProcedureException extends KernelException { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/DefaultParameterValue.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/DefaultParameterValue.java similarity index 87% rename from community/kernel/src/main/java/org/neo4j/kernel/impl/proc/DefaultParameterValue.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/DefaultParameterValue.java index a2800757b0fd4..9349192e342cc 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/DefaultParameterValue.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/DefaultParameterValue.java @@ -17,13 +17,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.impl.proc; +package org.neo4j.internal.kernel.api.procs; import java.util.List; import java.util.Map; -import org.neo4j.kernel.api.proc.Neo4jTypes; - public class DefaultParameterValue { private final Object value; @@ -50,27 +48,27 @@ public static DefaultParameterValue ntString( String value ) return new DefaultParameterValue( value, Neo4jTypes.NTString ); } - static DefaultParameterValue ntInteger( long value ) + public static DefaultParameterValue ntInteger( long value ) { return new DefaultParameterValue( value, Neo4jTypes.NTInteger ); } - static DefaultParameterValue ntFloat( double value ) + public static DefaultParameterValue ntFloat( double value ) { return new DefaultParameterValue( value, Neo4jTypes.NTFloat ); } - static DefaultParameterValue ntBoolean( boolean value ) + public static DefaultParameterValue ntBoolean( boolean value ) { return new DefaultParameterValue( value, Neo4jTypes.NTBoolean ); } - static DefaultParameterValue ntMap( Map value ) + public static DefaultParameterValue ntMap( Map value ) { return new DefaultParameterValue( value, Neo4jTypes.NTMap ); } - static DefaultParameterValue ntList( List value, Neo4jTypes.AnyType inner ) + public static DefaultParameterValue ntList( List value, Neo4jTypes.AnyType inner ) { return new DefaultParameterValue( value, Neo4jTypes.NTList( inner ) ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/FieldSignature.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/FieldSignature.java similarity index 97% rename from community/kernel/src/main/java/org/neo4j/kernel/api/proc/FieldSignature.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/FieldSignature.java index 2a3a993d66f53..4f8b20fa8c5ac 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/FieldSignature.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/FieldSignature.java @@ -17,13 +17,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.api.proc; +package org.neo4j.internal.kernel.api.procs; import java.util.Objects; import java.util.Optional; -import org.neo4j.kernel.impl.proc.DefaultParameterValue; - import static java.util.Objects.requireNonNull; /** Represents a type and a name for a field in a record, used to define input and output record signatures. */ diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/Neo4jTypes.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/Neo4jTypes.java similarity index 99% rename from community/kernel/src/main/java/org/neo4j/kernel/api/proc/Neo4jTypes.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/Neo4jTypes.java index 7555340c7ae0a..cbc094b6fc6f5 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/Neo4jTypes.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/Neo4jTypes.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.api.proc; +package org.neo4j.internal.kernel.api.procs; /** * See also type_system.txt in the cypher code base, this is a mapping of that type system definition diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/ProcedureSignature.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/ProcedureSignature.java similarity index 87% rename from community/kernel/src/main/java/org/neo4j/kernel/api/proc/ProcedureSignature.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/ProcedureSignature.java index ded745bf7fd1b..065d1ba00f9d2 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/ProcedureSignature.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/ProcedureSignature.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.api.proc; +package org.neo4j.internal.kernel.api.procs; import java.util.ArrayList; import java.util.Arrays; @@ -26,9 +26,7 @@ import java.util.Optional; import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.api.proc.Neo4jTypes.AnyType; import org.neo4j.procedure.Mode; - import static java.util.Collections.unmodifiableList; /** @@ -43,19 +41,19 @@ public class ProcedureSignature private final List inputSignature; private final List outputSignature; private final Mode mode; - private final Optional deprecated; + private final String deprecated; private final String[] allowed; - private final Optional description; - private final Optional warning; + private final String description; + private final String warning; public ProcedureSignature( QualifiedName name, List inputSignature, List outputSignature, Mode mode, - Optional deprecated, + String deprecated, String[] allowed, - Optional description, - Optional warning ) + String description, + String warning ) { this.name = name; this.inputSignature = unmodifiableList( inputSignature ); @@ -79,7 +77,7 @@ public Mode mode() public Optional deprecated() { - return deprecated; + return Optional.ofNullable( deprecated ); } public String[] allowed() @@ -104,12 +102,12 @@ public boolean isVoid() public Optional description() { - return description; + return Optional.ofNullable( description ); } public Optional warning() { - return warning; + return Optional.ofNullable( warning ); } @Override @@ -156,10 +154,10 @@ public static class Builder private final List inputSignature = new LinkedList<>(); private List outputSignature = new LinkedList<>(); private Mode mode = Mode.READ; - private Optional deprecated = Optional.empty(); + private String deprecated; private String[] allowed = new String[0]; - private Optional description = Optional.empty(); - private Optional warning = Optional.empty(); + private String description; + private String warning; public Builder( String[] namespace, String name ) { @@ -174,25 +172,25 @@ public Builder mode( Mode mode ) public Builder description( String description ) { - this.description = Optional.of( description ); + this.description = description; return this; } public Builder deprecatedBy( String deprecated ) { - this.deprecated = Optional.of( deprecated ); + this.deprecated = deprecated; return this; } /** Define an input field */ - public Builder in( String name, AnyType type ) + public Builder in( String name, Neo4jTypes.AnyType type ) { inputSignature.add( FieldSignature.inputField( name, type ) ); return this; } /** Define an output field */ - public Builder out( String name, AnyType type ) + public Builder out( String name, Neo4jTypes.AnyType type ) { outputSignature.add( FieldSignature.outputField( name, type ) ); return this; @@ -212,7 +210,7 @@ public Builder allowed( String[] allowed ) public Builder warning( String warning ) { - this.warning = Optional.of( warning ); + this.warning = warning; return this; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/QualifiedName.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/QualifiedName.java similarity index 98% rename from community/kernel/src/main/java/org/neo4j/kernel/api/proc/QualifiedName.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/QualifiedName.java index 15460ca0b7624..c0d5a4e227287 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/QualifiedName.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/QualifiedName.java @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.api.proc; +package org.neo4j.internal.kernel.api.procs; import java.util.Arrays; import java.util.List; diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserAggregator.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserAggregator.java new file mode 100644 index 0000000000000..59177073c88ca --- /dev/null +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserAggregator.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.internal.kernel.api.procs; + +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; + +public interface UserAggregator +{ + void update( Object[] input ) throws ProcedureException; + + Object result() throws ProcedureException; +} diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserFunctionHandle.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserFunctionHandle.java new file mode 100644 index 0000000000000..d475bb343a151 --- /dev/null +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserFunctionHandle.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.internal.kernel.api.procs; + + +public class UserFunctionHandle +{ + private final UserFunctionSignature signature; + private final int id; + + public UserFunctionHandle( UserFunctionSignature signature, int id ) + { + this.signature = signature; + this.id = id; + } + + public UserFunctionSignature signature() + { + return signature; + } + + public int id() + { + return id; + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/UserFunctionSignature.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserFunctionSignature.java similarity index 88% rename from community/kernel/src/main/java/org/neo4j/kernel/api/proc/UserFunctionSignature.java rename to community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserFunctionSignature.java index 40d31aaa3524e..392bae9614cc5 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/proc/UserFunctionSignature.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/procs/UserFunctionSignature.java @@ -17,7 +17,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.neo4j.kernel.api.proc; +package org.neo4j.internal.kernel.api.procs; + import java.util.Arrays; import java.util.LinkedList; @@ -25,7 +26,6 @@ import java.util.Optional; import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.api.proc.Neo4jTypes.AnyType; import static java.util.Collections.unmodifiableList; @@ -33,21 +33,21 @@ * This describes the signature of a function, made up of its namespace, name, and input/output description. * Function uniqueness is currently *only* on the namespace/name level - no function overloading allowed (yet). */ -public class UserFunctionSignature +public final class UserFunctionSignature { private final QualifiedName name; private final List inputSignature; private final Neo4jTypes.AnyType type; private final String[] allowed; - private final Optional deprecated; - private final Optional description; + private final String deprecated; + private final String description; public UserFunctionSignature( QualifiedName name, List inputSignature, Neo4jTypes.AnyType type, - Optional deprecated, + String deprecated, String[] allowed, - Optional description ) + String description ) { this.name = name; this.inputSignature = unmodifiableList( inputSignature ); @@ -64,7 +64,7 @@ public QualifiedName name() public Optional deprecated() { - return deprecated; + return Optional.ofNullable( deprecated ); } public List inputSignature() @@ -79,7 +79,7 @@ public Neo4jTypes.AnyType outputType() public Optional description() { - return description; + return Optional.ofNullable( description ); } public String[] allowed() @@ -123,8 +123,8 @@ public static class Builder private final List inputSignature = new LinkedList<>(); private Neo4jTypes.AnyType outputType; private String[] allowed = new String[0]; - private Optional deprecated = Optional.empty(); - private Optional description = Optional.empty(); + private String deprecated; + private String description; public Builder( String[] namespace, String name ) { @@ -133,25 +133,25 @@ public Builder( String[] namespace, String name ) public Builder description( String description ) { - this.description = Optional.of( description ); + this.description = description; return this; } public Builder deprecatedBy( String deprecated ) { - this.deprecated = Optional.of( deprecated ); + this.deprecated = deprecated; return this; } /** Define an input field */ - public Builder in( String name, AnyType type ) + public Builder in( String name, Neo4jTypes.AnyType type ) { inputSignature.add( FieldSignature.inputField( name, type ) ); return this; } /** Define an output field */ - public Builder out( AnyType type ) + public Builder out( Neo4jTypes.AnyType type ) { outputType = type; return this; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/dbms/DbmsOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/api/dbms/DbmsOperations.java index 3596f58cb497a..f91334728b707 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/dbms/DbmsOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/dbms/DbmsOperations.java @@ -20,10 +20,10 @@ package org.neo4j.kernel.api.dbms; import org.neo4j.collection.RawIterator; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.procs.QualifiedName; import org.neo4j.kernel.api.InwardKernel; import org.neo4j.kernel.api.ResourceTracker; -import org.neo4j.kernel.api.exceptions.ProcedureException; -import org.neo4j.kernel.api.proc.QualifiedName; import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.values.AnyValue; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureHolder.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureHolder.java new file mode 100644 index 0000000000000..1dd6b63407a48 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureHolder.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.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.kernel.impl.proc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.neo4j.internal.kernel.api.procs.QualifiedName; + +/** + * Simple in memory store for procedures. + * + * Should only be accessed from a single thread + * @param the type to be stored + */ +class ProcedureHolder +{ + private final Map nameToId = new HashMap<>(); + private final ArrayList store = new ArrayList<>(); + + T get( QualifiedName name ) + { + Integer id = nameToId.get( name ); + if ( id == null ) + { + return null; + } + return store.get( id ); + } + + T get( int id ) + { + return store.get( id ); + } + + void put( QualifiedName name, T item ) + { + int id = store.size(); + store.add( item ); + nameToId.put( name, id ); + } + + int idOf( QualifiedName name ) + { + return nameToId.get( name ); + } + + List all() + { + return Collections.unmodifiableList( store ); + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureRegistry.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureRegistry.java index 21e28349fec80..5c139d959bddd 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureRegistry.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureRegistry.java @@ -19,34 +19,34 @@ */ package org.neo4j.kernel.impl.proc; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.neo4j.collection.RawIterator; +import org.neo4j.internal.kernel.api.procs.UserAggregator; +import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; import org.neo4j.kernel.api.ResourceTracker; -import org.neo4j.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.proc.CallableProcedure; import org.neo4j.kernel.api.proc.CallableUserAggregationFunction; import org.neo4j.kernel.api.proc.CallableUserFunction; import org.neo4j.kernel.api.proc.Context; -import org.neo4j.kernel.api.proc.FieldSignature; -import org.neo4j.kernel.api.proc.ProcedureSignature; -import org.neo4j.kernel.api.proc.QualifiedName; -import org.neo4j.kernel.api.proc.UserFunctionSignature; +import org.neo4j.internal.kernel.api.procs.FieldSignature; +import org.neo4j.internal.kernel.api.procs.ProcedureSignature; +import org.neo4j.internal.kernel.api.procs.QualifiedName; +import org.neo4j.internal.kernel.api.procs.UserFunctionSignature; import org.neo4j.values.AnyValue; public class ProcedureRegistry { - private final Map procedures = new HashMap<>(); - private final Map functions = new HashMap<>(); - private final Map aggregationFunctions = new HashMap<>(); + + private final ProcedureHolder procedures = new ProcedureHolder<>(); + private final ProcedureHolder functions = new ProcedureHolder<>(); + private final ProcedureHolder aggregationFunctions = new ProcedureHolder<>(); /** * Register a new procedure. @@ -172,24 +172,24 @@ public ProcedureSignature procedure( QualifiedName name ) throws ProcedureExcept return proc.signature(); } - public Optional function( QualifiedName name ) + public UserFunctionHandle function( QualifiedName name ) { CallableUserFunction func = functions.get( name ); if ( func == null ) { - return Optional.empty(); + return null; } - return Optional.of( func.signature() ); + return new UserFunctionHandle( func.signature(), functions.idOf( name) ); } - public Optional aggregationFunction( QualifiedName name ) + public UserFunctionHandle aggregationFunction( QualifiedName name ) { CallableUserAggregationFunction func = aggregationFunctions.get( name ); if ( func == null ) { - return Optional.empty(); + return null; } - return Optional.of( func.signature() ); + return new UserFunctionHandle( func.signature(), aggregationFunctions.idOf( name) ); } public RawIterator callProcedure( Context ctx, QualifiedName name, Object[] input, ResourceTracker resourceTracker ) @@ -207,20 +207,34 @@ public AnyValue callFunction( Context ctx, QualifiedName name, AnyValue[] input throws ProcedureException { CallableUserFunction func = functions.get( name ); + return func.apply( ctx, input ); + } + + public AnyValue callFunction( Context ctx, int functionId, AnyValue[] input ) + throws ProcedureException + { + CallableUserFunction func = functions.get( functionId ); + return func.apply( ctx, input ); + } + + public UserAggregator createAggregationFunction( Context ctx, QualifiedName name ) + throws ProcedureException + { + CallableUserAggregationFunction func = aggregationFunctions.get( name ); if ( func == null ) { throw noSuchFunction( name ); } - return func.apply( ctx, input ); + return func.create(ctx); } - public CallableUserAggregationFunction.Aggregator createAggregationFunction( Context ctx, QualifiedName name ) + public UserAggregator createAggregationFunction( Context ctx, int id ) throws ProcedureException { - CallableUserAggregationFunction func = aggregationFunctions.get( name ); + CallableUserAggregationFunction func = aggregationFunctions.get( id ); if ( func == null ) { - throw noSuchFunction( name ); + throw noSuchFunction( id ); } return func.create(ctx); } @@ -241,15 +255,21 @@ private ProcedureException noSuchFunction( QualifiedName name ) "function is properly deployed.", name ); } + private ProcedureException noSuchFunction( int id ) + { + return new ProcedureException( Status.Procedure.ProcedureNotFound, + "There is no function with the internal id `%d` registered for this database instance.", id ); + } + public Set getAllProcedures() { - return procedures.values().stream().map( CallableProcedure::signature ).collect( Collectors.toSet()); + return procedures.all().stream().map( CallableProcedure::signature ).collect( Collectors.toSet()); } public Set getAllFunctions() { - return Stream.concat(functions.values().stream().map( CallableUserFunction::signature ), - aggregationFunctions.values().stream().map( CallableUserAggregationFunction::signature )) + return Stream.concat(functions.all().stream().map( CallableUserFunction::signature ), + aggregationFunctions.all().stream().map( CallableUserAggregationFunction::signature )) .collect( Collectors.toSet() ); } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/Procedures.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/Procedures.java index 0b32f38c29875..2c1b4f36da71d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/Procedures.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/Procedures.java @@ -26,16 +26,18 @@ import org.neo4j.collection.RawIterator; import org.neo4j.function.ThrowingConsumer; import org.neo4j.internal.kernel.api.exceptions.KernelException; +import org.neo4j.internal.kernel.api.procs.UserAggregator; +import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; import org.neo4j.kernel.api.ResourceTracker; -import org.neo4j.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.proc.CallableProcedure; import org.neo4j.kernel.api.proc.CallableUserAggregationFunction; import org.neo4j.kernel.api.proc.CallableUserFunction; import org.neo4j.kernel.api.proc.Context; -import org.neo4j.kernel.api.proc.Neo4jTypes; -import org.neo4j.kernel.api.proc.ProcedureSignature; -import org.neo4j.kernel.api.proc.QualifiedName; -import org.neo4j.kernel.api.proc.UserFunctionSignature; +import org.neo4j.internal.kernel.api.procs.Neo4jTypes; +import org.neo4j.internal.kernel.api.procs.ProcedureSignature; +import org.neo4j.internal.kernel.api.procs.QualifiedName; +import org.neo4j.internal.kernel.api.procs.UserFunctionSignature; import org.neo4j.kernel.builtinprocs.SpecialBuiltInProcedures; import org.neo4j.kernel.impl.core.EmbeddedProxySPI; import org.neo4j.kernel.lifecycle.LifecycleAdapter; @@ -152,7 +154,7 @@ public void registerProcedure( Class proc ) throws KernelException */ public void registerProcedure( Class proc, boolean overrideCurrentImplementation ) throws KernelException { - registerProcedure( proc, overrideCurrentImplementation, Optional.empty() ); + registerProcedure( proc, overrideCurrentImplementation, null ); } /** @@ -162,13 +164,6 @@ public void registerProcedure( Class proc, boolean overrideCurrentImplementat * @param warning the warning the procedure should generate when called */ public void registerProcedure( Class proc, boolean overrideCurrentImplementation, String warning ) throws KernelException - { - registerProcedure( proc, overrideCurrentImplementation, Optional.of( warning ) ); - } - - private void registerProcedure( Class proc, boolean overrideCurrentImplementation, Optional warning ) - throws - KernelException { for ( CallableProcedure procedure : compiler.compileProcedure( proc, warning, true ) ) { @@ -263,12 +258,12 @@ public ProcedureSignature procedure( QualifiedName name ) throws ProcedureExcept return registry.procedure( name ); } - public Optional function( QualifiedName name ) + public UserFunctionHandle function( QualifiedName name ) { return registry.function( name ); } - public Optional aggregationFunction( QualifiedName name ) + public UserFunctionHandle aggregationFunction( QualifiedName name ) { return registry.aggregationFunction( name ); } @@ -294,11 +289,21 @@ public AnyValue callFunction( Context ctx, QualifiedName name, AnyValue[] input return registry.callFunction( ctx, name, input ); } - public CallableUserAggregationFunction.Aggregator createAggregationFunction( Context ctx, QualifiedName name ) throws ProcedureException + public AnyValue callFunction( Context ctx, int id, AnyValue[] input ) throws ProcedureException + { + return registry.callFunction( ctx, id, input ); + } + + public UserAggregator createAggregationFunction( Context ctx, QualifiedName name ) throws ProcedureException { return registry.createAggregationFunction( ctx, name ); } + public UserAggregator createAggregationFunction( Context ctx, int id ) throws ProcedureException + { + return registry.createAggregationFunction( ctx, id ); + } + public ValueMapper valueMapper() { return typeMappers; diff --git a/community/security/src/test/java/org/neo4j/server/security/auth/AuthProceduresTest.java b/community/security/src/test/java/org/neo4j/server/security/auth/AuthProceduresTest.java index 7b0b22c82a54e..4aebe2ac2aa54 100644 --- a/community/security/src/test/java/org/neo4j/server/security/auth/AuthProceduresTest.java +++ b/community/security/src/test/java/org/neo4j/server/security/auth/AuthProceduresTest.java @@ -27,11 +27,12 @@ import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.kernel.api.ResourceTracker; import org.neo4j.kernel.api.StubResourceManager; -import org.neo4j.kernel.api.exceptions.ProcedureException; +import org.neo4j.internal.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.security.AnonymousContext; import org.neo4j.kernel.impl.api.integrationtest.KernelIntegrationTest; -import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureName; +import static org.mockito.Mockito.mock; +import static org.neo4j.internal.kernel.api.procs.ProcedureSignature.procedureName; public class AuthProceduresTest extends KernelIntegrationTest {