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

apoc.model.Model Maven / Gradle / Ivy

package apoc.model;

import apoc.Extended;
import apoc.load.util.LoadJdbcConfig;
import apoc.result.VirtualNode;
import org.neo4j.graphdb.*;
import org.neo4j.procedure.Procedure;
import org.neo4j.procedure.*;
import schemacrawler.schema.*;
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
import schemacrawler.schemacrawler.SchemaCrawlerOptionsBuilder;
import schemacrawler.schemacrawler.SchemaInfoLevelBuilder;
import schemacrawler.utility.SchemaCrawlerUtility;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import static apoc.load.util.JdbcUtil.getConnection;
import static apoc.load.util.JdbcUtil.getUrlOrKey;
import static apoc.util.Util.map;

@Extended
public class Model {

    @Context
    public Transaction tx;

    private Node createNode(String label, String name, boolean virtual) {
        if (virtual) {
            return new VirtualNode(new Label[]{Label.label(label)}, map("name", name));
        } else {
            Node node = tx.createNode();
            node.addLabel(Label.label(label));
            node.setProperty("name", name);
            return node;
        }
    }

    public static class DatabaseModel {
        public final List nodes = new ArrayList<>();
        public final List relationships = new ArrayList<>();

        public Node add(Node node) {
            nodes.add(node);
            return node;
        }

        public Relationship add(Relationship relationship) {
            this.relationships.add(relationship);
            return relationship;
        }
    }

    @Procedure(mode = Mode.WRITE)
    @Description("apoc.model.jdbc('key or url', {schema:'', write: , filters: { tables:[], views: [], columns: []}) YIELD nodes, relationships - load schema from relational database")
    public Stream jdbc(@Name("jdbc") String urlOrKey, @Name(value = "config",defaultValue = "{}") Map config) throws Exception {
        String url = getUrlOrKey(urlOrKey);

        SchemaCrawlerOptionsBuilder optionsBuilder = SchemaCrawlerOptionsBuilder.builder()
                .withSchemaInfoLevel(SchemaInfoLevelBuilder.standard());
        SchemaCrawlerOptions options = optionsBuilder.toOptions();

        Catalog catalog = SchemaCrawlerUtility.getCatalog(getConnection(url, new LoadJdbcConfig(config)),
                options);

        DatabaseModel databaseModel = new DatabaseModel();

        ModelConfig modelConfig = new ModelConfig(config != null ? config : Collections.emptyMap());
        boolean virtual = !modelConfig.isWrite();

        for (final Schema schema : catalog.getSchemas()) {
            if (!modelConfig.getSchema().equalsIgnoreCase(schema.getFullName())) {
                continue;
            }
            Node schemaNode = databaseModel.add(createNode("Schema", schema.getFullName(),virtual));

            for (final Table table : catalog.getTables(schema)) {
                boolean isView = table instanceof View;
                List patterns = isView ? modelConfig.getViews() : modelConfig.getTables();
                boolean matchTableView = patterns.isEmpty()
                        ? true : patterns.stream().anyMatch(p -> table.getName().matches(p));
                if (!matchTableView) {
                    continue;
                }
                Node tableNode = databaseModel.add(createNode("Table", table.getName(),virtual));
                databaseModel.add(tableNode.createRelationshipTo(schemaNode, RelationshipType.withName("IN_SCHEMA")));
                if (isView) tableNode.addLabel(Label.label("View"));

                for (final Column column : table.getColumns()) {
                    boolean matchColumn = modelConfig.getColumns().isEmpty() ?
                            true : modelConfig.getColumns().stream().anyMatch(p -> column.getName().matches(p));
                    if (!matchColumn) {
                        continue;
                    }
                    Node columnNode = databaseModel.add(createNode("Column", column.getName(), virtual));
                    columnNode.setProperty("type", column.getColumnDataType().getDatabaseSpecificTypeName());
                    databaseModel.add(columnNode.createRelationshipTo(tableNode, RelationshipType.withName("IN_TABLE")));
                    if (column.isPartOfPrimaryKey()) columnNode.addLabel(Label.label("PrimaryKey"));
                    if (column.isPartOfForeignKey()) columnNode.addLabel(Label.label("ForeignKey"));
                    if (column.isPartOfUniqueIndex()) columnNode.setProperty("unique", true);
                }
            }
        }
        return Stream.of(databaseModel);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy