use of org.neo4j.internal.kernel.api.procs.ProcedureSignature in project neo4j by neo4j.
the class ProcedureSignatureTest method shouldHonorVoidInEquals.
@Test
void shouldHonorVoidInEquals() {
ProcedureSignature sig1 = procedureSignature("foo").in("a", Neo4jTypes.NTAny).build();
ProcedureSignature sig2 = procedureSignature("foo").in("a", Neo4jTypes.NTAny).out(ProcedureSignature.VOID).build();
ProcedureSignature sig2clone = procedureSignature("foo").in("a", Neo4jTypes.NTAny).out(ProcedureSignature.VOID).build();
assertEquals(sig2, sig2clone);
assertNotEquals(sig1, sig2);
}
use of org.neo4j.internal.kernel.api.procs.ProcedureSignature in project neo4j by neo4j.
the class ProcedureCompilation method compileProcedure.
/**
* Generates code for a user-defined procedure.
* <p>
* Given a user-defined function defined by
*
* <pre>
* class MyClass {
* {@literal @}Context
* public Log log;
*
* {@literal @}Procedure
* public Stream<MyOut> myStream(long value) {
* ...
* }
* }
* </pre>
* <p>
* we will generate something like
*
* <pre>
* class GeneratedMyStream implements CallableProcedure {
* public static ProcedureSignature SIGNATURE;
* public static FieldSetter SETTER_0;
*
* RawIterator<AnyValue[], ProcedureException> apply( Context ctx, AnyValue[] in, ResourceTracker tracker ) throws ProcedureException {
* try {
* MyClass userClass = new MyClass();
* userClass.log = (Log) SETTER_0.get(ctx);
* Stream<MyOut> fromUser = userClass.myStream(((NumberValue) input[0]).longValue() );
* return new GeneratedIterator(fromUser, tracker, SIGNATURE);
* } catch (Throwable T) {
* throw new ProcedureException([appropriate error msg], T);
* }
* }
*
* public ProcedureSignature signature() {return SIGNATURE;}
* }
* </pre>
* <p>
* where the static fields are set once during loading via reflection and where the <tt>GeneratedIterator</tt>
* implements the appropriate mapping from user-types Object[] to AnyValue[].
*
* @param signature the signature of the procedure
* @param fieldSetters the fields to set before each call.
* @param methodToCall the method to call
* @return a CallableProcedure delegating to the underlying procedure method.
* @throws ProcedureException if something went wrong when compiling the user-defined function.
*/
static CallableProcedure compileProcedure(ProcedureSignature signature, List<FieldSetter> fieldSetters, Method methodToCall) throws ProcedureException {
ClassHandle handle;
try {
CodeGenerator codeGenerator = codeGenerator();
Class<?> iterator = generateIterator(codeGenerator, procedureType(methodToCall));
try (ClassGenerator generator = codeGenerator.generateClass(PACKAGE, className(signature), CallableProcedure.class)) {
// static fields
FieldReference signatureField = generator.publicStaticField(typeReference(ProcedureSignature.class), SIGNATURE_NAME);
List<FieldReference> fieldsToSet = createContextSetters(fieldSetters, generator);
// CallableProcedure::apply
try (CodeBlock method = generator.generate(USER_PROCEDURE)) {
method.tryCatch(body -> procedureBody(body, fieldSetters, fieldsToSet, signatureField, methodToCall, iterator), onError -> onError(onError, format("procedure `%s`", signature.name())), param(Throwable.class, "T"));
}
// CallableUserFunction::signature
try (CodeBlock method = generator.generateMethod(ProcedureSignature.class, "signature")) {
method.returns(getStatic(signatureField));
}
handle = generator.handle();
}
Class<?> clazz = handle.loadClass();
// set all static fields
setAllStaticFields(signature, fieldSetters, methodToCall, clazz);
return (CallableProcedure) clazz.getConstructor().newInstance();
} catch (Throwable e) {
throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, e, "Failed to compile procedure defined in `%s`: %s", methodToCall.getDeclaringClass().getSimpleName(), e.getMessage());
}
}
use of org.neo4j.internal.kernel.api.procs.ProcedureSignature in project neo4j by neo4j.
the class ProcedureCompiler method compileProcedure.
private CallableProcedure compileProcedure(Class<?> procDefinition, Method method, String warning, boolean fullAccess, QualifiedName procName) throws ProcedureException {
List<FieldSignature> inputSignature = inputSignatureDeterminer.signatureFor(method);
List<FieldSignature> outputSignature = outputSignatureCompiler.fieldSignatures(method);
String description = description(method);
Procedure procedure = method.getAnnotation(Procedure.class);
Mode mode = procedure.mode();
boolean admin = method.isAnnotationPresent(Admin.class);
boolean systemProcedure = method.isAnnotationPresent(SystemProcedure.class);
boolean allowExpiredCredentials = systemProcedure ? method.getAnnotation(SystemProcedure.class).allowExpiredCredentials() : false;
boolean internal = method.isAnnotationPresent(Internal.class);
String deprecated = deprecated(method, procedure::deprecatedBy, "Use of @Procedure(deprecatedBy) without @Deprecated in " + procName);
List<FieldSetter> setters = allFieldInjections.setters(procDefinition);
if (!fullAccess && !config.fullAccessFor(procName.toString())) {
try {
setters = safeFieldInjections.setters(procDefinition);
} catch (ComponentInjectionException e) {
description = describeAndLogLoadFailure(procName);
ProcedureSignature signature = new ProcedureSignature(procName, inputSignature, outputSignature, Mode.DEFAULT, admin, null, new String[0], description, warning, procedure.eager(), false, systemProcedure, internal, allowExpiredCredentials);
return new FailedLoadProcedure(signature);
}
}
ProcedureSignature signature = new ProcedureSignature(procName, inputSignature, outputSignature, mode, admin, deprecated, config.rolesFor(procName.toString()), description, warning, procedure.eager(), false, systemProcedure, internal, allowExpiredCredentials);
return ProcedureCompilation.compileProcedure(signature, setters, method);
}
use of org.neo4j.internal.kernel.api.procs.ProcedureSignature in project neo4j by neo4j.
the class ProcedureRegistry method register.
/**
* Register a new procedure.
*
* @param proc the procedure.
*/
public void register(CallableProcedure proc, boolean overrideCurrentImplementation) throws ProcedureException {
ProcedureSignature signature = proc.signature();
QualifiedName name = signature.name();
String descriptiveName = signature.toString();
validateSignature(descriptiveName, signature.inputSignature(), "input");
validateSignature(descriptiveName, signature.outputSignature(), "output");
if (!signature.isVoid() && signature.outputSignature().isEmpty()) {
throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Procedures with zero output fields must be declared as VOID");
}
CallableProcedure oldImplementation = procedures.get(name);
if (oldImplementation == null) {
procedures.put(name, proc, signature.caseInsensitive());
} else {
if (overrideCurrentImplementation) {
procedures.put(name, proc, signature.caseInsensitive());
} else {
throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, "Unable to register procedure, because the name `%s` is already in use.", name);
}
}
}
use of org.neo4j.internal.kernel.api.procs.ProcedureSignature in project neo4j by neo4j.
the class ProceduresKernelIT method shouldGetBuiltInProcedureByName.
@Test
void shouldGetBuiltInProcedureByName() throws Throwable {
// When
ProcedureSignature found = procs().procedureGet(procedureName("db", "labels")).signature();
// Then
assertThat(found).isEqualTo(procedureSignature(procedureName("db", "labels")).out("label", NTString).build());
commit();
}
Aggregations