Search in sources :

Example 6 with CallableProcedure

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

the class ProcedureWithArgumentsTest method shouldRunSimpleProcedure.

@Test
void shouldRunSimpleProcedure() throws Throwable {
    // Given
    CallableProcedure procedure = compile(ClassWithProcedureWithSimpleArgs.class).get(0);
    // When
    RawIterator<AnyValue[], ProcedureException> out = procedure.apply(prepareContext(), new AnyValue[] { stringValue("Pontus"), longValue(35L) }, EMPTY_RESOURCE_TRACKER);
    // Then
    List<AnyValue[]> collect = asList(out);
    assertThat(collect.get(0)[0]).isEqualTo(stringValue("Pontus is 35 years old."));
}
Also used : CallableProcedure(org.neo4j.kernel.api.procedure.CallableProcedure) ProcedureException(org.neo4j.internal.kernel.api.exceptions.ProcedureException) Test(org.junit.jupiter.api.Test)

Example 7 with CallableProcedure

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

the class ResourceInjectionTest method shouldCompileAndRunUnsafeProcedureUnsafeMode.

@Test
void shouldCompileAndRunUnsafeProcedureUnsafeMode() throws Throwable {
    // Given
    CallableProcedure proc = compiler.compileProcedure(ProcedureWithUnsafeAPI.class, null, true).get(0);
    // Then
    List<AnyValue[]> out = Iterators.asList(proc.apply(prepareContext(), new AnyValue[0], EMPTY_RESOURCE_TRACKER));
    // Then
    assertThat(out.get(0)).isEqualTo(new AnyValue[] { stringValue("Morpheus") });
    assertThat(out.get(1)).isEqualTo(new AnyValue[] { stringValue("Trinity") });
    assertThat(out.get(2)).isEqualTo(new AnyValue[] { stringValue("Neo") });
    assertThat(out.get(3)).isEqualTo(new AnyValue[] { stringValue("Emil") });
}
Also used : AnyValue(org.neo4j.values.AnyValue) CallableProcedure(org.neo4j.kernel.api.procedure.CallableProcedure) Test(org.junit.jupiter.api.Test)

Example 8 with CallableProcedure

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

the class ResourceInjectionTest method shouldCompileAndRunProcedure.

@Test
void shouldCompileAndRunProcedure() throws Throwable {
    // Given
    CallableProcedure proc = compiler.compileProcedure(ProcedureWithInjectedAPI.class, null, true).get(0);
    // Then
    List<AnyValue[]> out = Iterators.asList(proc.apply(prepareContext(), new AnyValue[0], EMPTY_RESOURCE_TRACKER));
    // Then
    assertThat(out.get(0)).isEqualTo(new AnyValue[] { stringValue("Bonnie") });
    assertThat(out.get(1)).isEqualTo(new AnyValue[] { stringValue("Clyde") });
}
Also used : AnyValue(org.neo4j.values.AnyValue) CallableProcedure(org.neo4j.kernel.api.procedure.CallableProcedure) Test(org.junit.jupiter.api.Test)

Example 9 with CallableProcedure

use of org.neo4j.kernel.api.procedure.CallableProcedure 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());
    }
}
Also used : ProcedureSignature(org.neo4j.internal.kernel.api.procs.ProcedureSignature) ClassGenerator(org.neo4j.codegen.ClassGenerator) FieldReference(org.neo4j.codegen.FieldReference) CodeBlock(org.neo4j.codegen.CodeBlock) CallableProcedure(org.neo4j.kernel.api.procedure.CallableProcedure) CodeGenerator(org.neo4j.codegen.CodeGenerator) ProcedureException(org.neo4j.internal.kernel.api.exceptions.ProcedureException) ClassHandle(org.neo4j.codegen.ClassHandle)

Example 10 with CallableProcedure

use of org.neo4j.kernel.api.procedure.CallableProcedure 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

CallableProcedure (org.neo4j.kernel.api.procedure.CallableProcedure)35 Test (org.junit.jupiter.api.Test)29 ProcedureException (org.neo4j.internal.kernel.api.exceptions.ProcedureException)16 ProcedureSignature (org.neo4j.internal.kernel.api.procs.ProcedureSignature)13 Log (org.neo4j.logging.Log)7 AnyValue (org.neo4j.values.AnyValue)7 NullLog (org.neo4j.logging.NullLog)6 URL (java.net.URL)4 FieldSignature (org.neo4j.internal.kernel.api.procs.FieldSignature)2 QualifiedName (org.neo4j.internal.kernel.api.procs.QualifiedName)2 ComponentInjectionException (org.neo4j.kernel.api.exceptions.ComponentInjectionException)2 CallableUserAggregationFunction (org.neo4j.kernel.api.procedure.CallableUserAggregationFunction)2 CallableUserFunction (org.neo4j.kernel.api.procedure.CallableUserFunction)2 FailedLoadProcedure (org.neo4j.kernel.api.procedure.FailedLoadProcedure)2 SystemProcedure (org.neo4j.kernel.api.procedure.SystemProcedure)2 Mode (org.neo4j.procedure.Mode)2 Procedure (org.neo4j.procedure.Procedure)2 Constructor (java.lang.reflect.Constructor)1 Method (java.lang.reflect.Method)1 Modifier.isPublic (java.lang.reflect.Modifier.isPublic)1