All Downloads are FREE. Search and download functionalities are using the official Maven repository.

apoc.systemdb.SystemDb Maven / Gradle / Ivy

package apoc.systemdb;

import apoc.ApocConfig;
import apoc.Extended;
import apoc.result.RowResult;
import apoc.result.VirtualNode;
import apoc.result.VirtualRelationship;
import apoc.util.Util;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;
import org.neo4j.internal.helpers.collection.Iterables;
import org.neo4j.internal.kernel.api.procs.ProcedureCallContext;
import org.neo4j.internal.kernel.api.security.SecurityContext;
import org.neo4j.kernel.impl.coreapi.TransactionImpl;
import org.neo4j.procedure.Context;
import org.neo4j.procedure.Name;
import org.neo4j.procedure.Procedure;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Extended
public class SystemDb {

    @Context
    public ApocConfig apocConfig;

    @Context
    public SecurityContext securityContext;

    @Context
    public ProcedureCallContext callContext;

    public static class NodesAndRelationshipsResult {
        public List nodes;
        public List relationships;

        public NodesAndRelationshipsResult(List nodes, List relationships) {
            this.nodes = nodes;
            this.relationships = relationships;
        }
    }

    @Procedure
    public Stream graph() {
        Util.checkAdmin(securityContext, callContext,"apoc.systemdb.graph");
        return withSystemDbTransaction(tx -> {
            Map virtualNodes = new HashMap<>();
            for (Node node: tx.getAllNodes())  {
                virtualNodes.put(-node.getId(), new VirtualNode(-node.getId(), Iterables.asArray(Label.class, node.getLabels()), node.getAllProperties()));
            }

            List relationships = tx.getAllRelationships().stream().map(rel -> new VirtualRelationship(
                    -rel.getId(),
                    virtualNodes.get(-rel.getStartNodeId()),
                    virtualNodes.get(-rel.getEndNodeId()),
                    rel.getType(),
                    rel.getAllProperties())).collect(Collectors.toList()
            );
            return Stream.of(new NodesAndRelationshipsResult(Iterables.asList(virtualNodes.values()), relationships) );
        });
    }

    @Procedure
    public Stream execute(@Name("DDL commands, either a string or a list of strings") Object ddlStringOrList, @Name(value="params", defaultValue = "{}") Map params) {
        Util.checkAdmin(securityContext, callContext, "apoc.systemdb.execute");

        List commands;
        if (ddlStringOrList instanceof String) {
            commands = Collections.singletonList((String)ddlStringOrList);
        } else if (ddlStringOrList instanceof List) {
            commands = (List) ddlStringOrList;
        } else {
            throw new IllegalArgumentException("don't know how to handle " + ddlStringOrList + ". Supply either a string or a list of strings");
        }

        Transaction tx = apocConfig.getSystemDb().beginTx();  // we can't use try-with-resources otherwise tx gets closed too early
        return commands.stream().flatMap(command -> tx.execute(command, params).stream().map(RowResult::new)).onClose(() -> {
            boolean isOpen = ((TransactionImpl) tx).isOpen(); // no other way to check if a tx is still open
            if (isOpen) {
                tx.commit();
            }
            tx.close();
        });
    }

    private  T withSystemDbTransaction(Function function) {
        try (Transaction tx = apocConfig.getSystemDb().beginTx()) {
            T result = function.apply(tx);
            tx.commit();
            return result;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy