Search in sources :

Example 6 with CallableUserFunction

use of org.neo4j.kernel.api.procedure.CallableUserFunction in project neo4j by neo4j.

the class ProcedureCompilationTest method shouldHandleNulls.

@Test
void shouldHandleNulls() throws ProcedureException {
    // Given
    UserFunctionSignature signature = functionSignature("test", "foo").in("b", NTBoolean).out(NTFloat).build();
    // When
    CallableUserFunction nullyMethod = compileFunction(signature, emptyList(), method("nullyMethod", Boolean.class));
    // Then
    assertEquals(Values.NO_VALUE, nullyMethod.apply(ctx, new AnyValue[] { TRUE }));
    assertEquals(PI, nullyMethod.apply(ctx, new AnyValue[] { Values.NO_VALUE }));
}
Also used : CallableUserFunction(org.neo4j.kernel.api.procedure.CallableUserFunction) AnyValue(org.neo4j.values.AnyValue) UserFunctionSignature(org.neo4j.internal.kernel.api.procs.UserFunctionSignature) NTBoolean(org.neo4j.internal.kernel.api.procs.Neo4jTypes.NTBoolean) Test(org.junit.jupiter.api.Test)

Example 7 with CallableUserFunction

use of org.neo4j.kernel.api.procedure.CallableUserFunction in project neo4j by neo4j.

the class ProcedureCompilationTest method shouldHandleNumberOutput.

@Test
void shouldHandleNumberOutput() throws ProcedureException {
    // Given
    UserFunctionSignature signature = functionSignature("test", "foo").in("numbers", NTList(NTNumber)).out(NTNumber).build();
    // When
    CallableUserFunction sumMethod = compileFunction(signature, emptyList(), method("sum", List.class));
    // Then
    assertEquals(longValue(3), sumMethod.apply(ctx, new AnyValue[] { list(longValue(1), longValue(2)) }));
}
Also used : CallableUserFunction(org.neo4j.kernel.api.procedure.CallableUserFunction) AnyValue(org.neo4j.values.AnyValue) Collections.singletonList(java.util.Collections.singletonList) Arrays.asList(java.util.Arrays.asList) Collections.emptyList(java.util.Collections.emptyList) List(java.util.List) NTList(org.neo4j.internal.kernel.api.procs.Neo4jTypes.NTList) UserFunctionSignature(org.neo4j.internal.kernel.api.procs.UserFunctionSignature) Test(org.junit.jupiter.api.Test)

Example 8 with CallableUserFunction

use of org.neo4j.kernel.api.procedure.CallableUserFunction in project neo4j by neo4j.

the class ProcedureCompilationTest method shouldExposeUserFunctionSignature.

@Test
void shouldExposeUserFunctionSignature() throws ProcedureException {
    // Given
    UserFunctionSignature signature = functionSignature("test", "foo").out(NTInteger).build();
    // When
    CallableUserFunction function = compileFunction(signature, emptyList(), method("longMethod"));
    // Then
    assertEquals(function.signature(), signature);
}
Also used : CallableUserFunction(org.neo4j.kernel.api.procedure.CallableUserFunction) UserFunctionSignature(org.neo4j.internal.kernel.api.procs.UserFunctionSignature) Test(org.junit.jupiter.api.Test)

Example 9 with CallableUserFunction

use of org.neo4j.kernel.api.procedure.CallableUserFunction in project neo4j by neo4j.

the class ProcedureCompilation method compileFunction.

/**
 * Generates code for a user-defined function.
 * <p>
 * Given a user-defined function defined by
 *
 * <pre>
 *     class MyClass {
 *       {@literal @}Context
 *        public Log log;
 *
 *       {@literal @}UserFunction
 *        public double addPi(long value) {
 *            return value + Math.PI;
 *        }
 *     }
 * </pre>
 * <p>
 * we will generate something like
 *
 * <pre>
 *     class GeneratedAddPi implements CallableUserFunction {
 *         public static UserFunctionSignature SIGNATURE;
 *         public static FieldSetter SETTER_0;
 *
 *         public AnyValue apply(Context ctx, AnyValue[] input) {
 *              try {
 *                  MyClass userClass = new MyClass();
 *                  userClass.log = (Log) SETTER_0.get(ctx);
 *                  return Values.doubleValue(userClass.addPi( ((NumberValue) input[0]).longValue() );
 *              } catch (Throwable T) {
 *                  throw new ProcedureException([appropriate error msg], T);
 *              }
 *         }
 *
 *         public UserFunctionSignature signature() {return SIGNATURE;}
 *     }
 * </pre>
 * <p>
 * where the static fields are set once during loading via reflection.
 *
 * @param signature the signature of the user-defined function
 * @param fieldSetters the fields to set before each call.
 * @param methodToCall the method to call
 * @return a CallableUserFunction delegating to the underlying user-defined function.
 * @throws ProcedureException if something went wrong when compiling the user-defined function.
 */
static CallableUserFunction compileFunction(UserFunctionSignature signature, List<FieldSetter> fieldSetters, Method methodToCall) throws ProcedureException {
    ClassHandle handle;
    try {
        CodeGenerator codeGenerator = codeGenerator();
        try (ClassGenerator generator = codeGenerator.generateClass(PACKAGE, className(signature), CallableUserFunction.class)) {
            // static fields
            FieldReference signatureField = generator.publicStaticField(typeReference(UserFunctionSignature.class), SIGNATURE_NAME);
            List<FieldReference> fieldsToSet = createContextSetters(fieldSetters, generator);
            // CallableUserFunction::apply
            try (CodeBlock method = generator.generate(USER_FUNCTION)) {
                method.tryCatch(body -> functionBody(body, fieldSetters, fieldsToSet, methodToCall), onError -> onError(onError, format("function `%s`", signature.name())), param(Throwable.class, "T"));
            }
            // CallableUserFunction::signature
            try (CodeBlock method = generator.generateMethod(UserFunctionSignature.class, "signature")) {
                method.returns(getStatic(signatureField));
            }
            handle = generator.handle();
        }
        Class<?> clazz = handle.loadClass();
        // set all static fields
        setAllStaticFields(signature, fieldSetters, methodToCall, clazz);
        return (CallableUserFunction) clazz.getConstructor().newInstance();
    } catch (Throwable e) {
        throw new ProcedureException(Status.Procedure.ProcedureRegistrationFailed, e, "Failed to compile function defined in `%s`: %s", methodToCall.getDeclaringClass().getSimpleName(), e.getMessage());
    }
}
Also used : CallableUserFunction(org.neo4j.kernel.api.procedure.CallableUserFunction) ClassGenerator(org.neo4j.codegen.ClassGenerator) FieldReference(org.neo4j.codegen.FieldReference) CodeBlock(org.neo4j.codegen.CodeBlock) CodeGenerator(org.neo4j.codegen.CodeGenerator) ProcedureException(org.neo4j.internal.kernel.api.exceptions.ProcedureException) UserFunctionSignature(org.neo4j.internal.kernel.api.procs.UserFunctionSignature) ClassHandle(org.neo4j.codegen.ClassHandle)

Example 10 with CallableUserFunction

use of org.neo4j.kernel.api.procedure.CallableUserFunction in project neo4j by neo4j.

the class GlobalProceduresRegistry method start.

@Override
public void start() throws Exception {
    ProcedureJarLoader loader = new ProcedureJarLoader(compiler, log);
    ProcedureJarLoader.Callables callables = loader.loadProceduresFromDir(proceduresDirectory);
    for (CallableProcedure procedure : callables.procedures()) {
        register(procedure);
    }
    for (CallableUserFunction function : callables.functions()) {
        register(function);
    }
    for (CallableUserAggregationFunction function : callables.aggregationFunctions()) {
        register(function);
    }
    // And register built-in procedures
    builtin.accept(this);
}
Also used : CallableUserFunction(org.neo4j.kernel.api.procedure.CallableUserFunction) CallableUserAggregationFunction(org.neo4j.kernel.api.procedure.CallableUserAggregationFunction) CallableProcedure(org.neo4j.kernel.api.procedure.CallableProcedure)

Aggregations

CallableUserFunction (org.neo4j.kernel.api.procedure.CallableUserFunction)28 Test (org.junit.jupiter.api.Test)23 UserFunctionSignature (org.neo4j.internal.kernel.api.procs.UserFunctionSignature)14 AnyValue (org.neo4j.values.AnyValue)10 ProcedureException (org.neo4j.internal.kernel.api.exceptions.ProcedureException)5 Log (org.neo4j.logging.Log)5 NullLog (org.neo4j.logging.NullLog)4 Collections.emptyList (java.util.Collections.emptyList)3 List (java.util.List)3 Method (java.lang.reflect.Method)2 Arrays.asList (java.util.Arrays.asList)2 Collections.singletonList (java.util.Collections.singletonList)2 FieldSignature (org.neo4j.internal.kernel.api.procs.FieldSignature)2 NTList (org.neo4j.internal.kernel.api.procs.Neo4jTypes.NTList)2 QualifiedName (org.neo4j.internal.kernel.api.procs.QualifiedName)2 ComponentInjectionException (org.neo4j.kernel.api.exceptions.ComponentInjectionException)2 CallableProcedure (org.neo4j.kernel.api.procedure.CallableProcedure)2 CallableUserAggregationFunction (org.neo4j.kernel.api.procedure.CallableUserAggregationFunction)2 FailedLoadFunction (org.neo4j.kernel.api.procedure.FailedLoadFunction)2 UserFunction (org.neo4j.procedure.UserFunction)2