Search in sources :

Example 6 with SchemaTableTree

use of org.umlg.sqlg.sql.parse.SchemaTableTree in project sqlg by pietermartin.

the class SqlgVertexStep method constructQueryPerSchemaTable.

private void constructQueryPerSchemaTable() {
    for (SchemaTable schemaTable : this.heads.keySet()) {
        SchemaTableTree rootSchemaTableTree = parseForStrategy(schemaTable);
        // If the order is over multiple tables then the resultSet will be completely loaded into memory and then sorted.
        if (this.replacedStepTree.hasOrderBy()) {
            if (isForMultipleQueries() || !replacedStepTree.orderByIsOrder() || this.replacedStepTree.orderByHasSelectOneStepAndForLabelNotInTree()) {
                setEagerLoad(true);
                // Remove the dbComparators
                rootSchemaTableTree.removeDbComparators();
            } else {
                // This is only needed for test assertions at the moment.
                replacedStepTree.applyComparatorsOnDb();
            }
        }
        // range is always the last step as sqlg does not optimize beyond a range step.
        if (this.replacedStepTree.hasRange()) {
            if (this.replacedStepTree.hasOrderBy()) {
                this.replacedStepTree.doNotApplyRangeOnDb();
                setEagerLoad(true);
            } else {
                if (!isForMultipleQueries()) {
                    // In this case the range is only applied on the db.
                    this.replacedStepTree.doNotApplyInStep();
                }
            }
        }
        this.schemaTableElements.put(schemaTable, elements(schemaTable, rootSchemaTableTree));
    }
}
Also used : SchemaTableTree(org.umlg.sqlg.sql.parse.SchemaTableTree)

Example 7 with SchemaTableTree

use of org.umlg.sqlg.sql.parse.SchemaTableTree in project sqlg by pietermartin.

the class SqlDialect method drop.

/**
 * if the query traverses edges then the deletion logic is non trivial.
 * The edges can not be deleted upfront as then we will not be able to travers to the leaf vertices anymore
 * because the edges are no longer there to travers. In this case we need to drop foreign key constraint checking.
 * Delete the vertices and then the edges using the same query.
 * The edge query is the same as the vertex query with the last SchemaTableTree removed from the distinctQueryStack;
 *
 * @param sqlgGraph            The graph.
 * @param leafElementsToDelete The leaf elements of the query. eg. g.V().out().out() The last vertices returned by the gremlin query.
 * @param edgesToDelete
 * @param distinctQueryStack   The query's SchemaTableTree stack as constructed by parsing.
 * @return
 */
default List<Triple<SqlgSqlExecutor.DROP_QUERY, String, SchemaTable>> drop(SqlgGraph sqlgGraph, String leafElementsToDelete, Optional<String> edgesToDelete, LinkedList<SchemaTableTree> distinctQueryStack) {
    List<Triple<SqlgSqlExecutor.DROP_QUERY, String, SchemaTable>> sqls = new ArrayList<>();
    SchemaTableTree last = distinctQueryStack.getLast();
    SchemaTableTree lastEdge = null;
    // if the leaf elements are vertices then we need to delete its in and out edges.
    boolean isVertex = last.getSchemaTable().isVertexTable();
    VertexLabel lastVertexLabel = null;
    if (isVertex) {
        Optional<Schema> schemaOptional = sqlgGraph.getTopology().getSchema(last.getSchemaTable().getSchema());
        Preconditions.checkState(schemaOptional.isPresent(), "BUG: %s not found in the topology.", last.getSchemaTable().getSchema());
        Schema schema = schemaOptional.get();
        Optional<VertexLabel> vertexLabelOptional = schema.getVertexLabel(last.getSchemaTable().withOutPrefix().getTable());
        Preconditions.checkState(vertexLabelOptional.isPresent(), "BUG: %s not found in the topology.", last.getSchemaTable().withOutPrefix().getTable());
        lastVertexLabel = vertexLabelOptional.get();
    }
    boolean queryTraversesEdge = isVertex && (distinctQueryStack.size() > 1);
    EdgeLabel lastEdgeLabel = null;
    if (queryTraversesEdge) {
        lastEdge = distinctQueryStack.get(distinctQueryStack.size() - 2);
        Optional<Schema> edgeSchema = sqlgGraph.getTopology().getSchema(lastEdge.getSchemaTable().getSchema());
        Preconditions.checkState(edgeSchema.isPresent(), "BUG: %s not found in the topology.", lastEdge.getSchemaTable().getSchema());
        Optional<EdgeLabel> edgeLabelOptional = edgeSchema.get().getEdgeLabel(lastEdge.getSchemaTable().withOutPrefix().getTable());
        Preconditions.checkState(edgeLabelOptional.isPresent(), "BUG: %s not found in the topology.", lastEdge.getSchemaTable().getTable());
        lastEdgeLabel = edgeLabelOptional.get();
    }
    if (isVertex) {
        // First delete all edges except for this edge traversed to get to the vertices.
        StringBuilder sb;
        for (Map.Entry<String, EdgeLabel> edgeLabelEntry : lastVertexLabel.getOutEdgeLabels().entrySet()) {
            EdgeLabel edgeLabel = edgeLabelEntry.getValue();
            if (lastEdgeLabel == null || !edgeLabel.equals(lastEdgeLabel)) {
                // Delete
                sb = new StringBuilder();
                sb.append("DELETE FROM ");
                sb.append(maybeWrapInQoutes(edgeLabel.getSchema().getName()));
                sb.append(".");
                sb.append(maybeWrapInQoutes(Topology.EDGE_PREFIX + edgeLabel.getName()));
                sb.append("\nWHERE ");
                sb.append(maybeWrapInQoutes(lastVertexLabel.getSchema().getName() + "." + lastVertexLabel.getName() + Topology.OUT_VERTEX_COLUMN_END));
                sb.append(" IN\n\t(");
                sb.append(leafElementsToDelete);
                sb.append(")");
                sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.NORMAL, sb.toString(), SchemaTable.of(edgeLabel.getSchema().getName(), Topology.EDGE_PREFIX + edgeLabel.getName())));
            }
        }
        for (Map.Entry<String, EdgeLabel> edgeLabelEntry : lastVertexLabel.getInEdgeLabels().entrySet()) {
            EdgeLabel edgeLabel = edgeLabelEntry.getValue();
            if (lastEdgeLabel == null || !edgeLabel.equals(lastEdgeLabel)) {
                // Delete
                sb = new StringBuilder();
                sb.append("DELETE FROM ");
                sb.append(maybeWrapInQoutes(edgeLabel.getSchema().getName()));
                sb.append(".");
                sb.append(maybeWrapInQoutes(Topology.EDGE_PREFIX + edgeLabel.getName()));
                sb.append("\nWHERE ");
                sb.append(maybeWrapInQoutes(lastVertexLabel.getSchema().getName() + "." + lastVertexLabel.getName() + Topology.IN_VERTEX_COLUMN_END));
                sb.append(" IN\n\t(");
                sb.append(leafElementsToDelete);
                sb.append(")");
                sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.NORMAL, sb.toString(), SchemaTable.of(edgeLabel.getSchema().getName(), Topology.EDGE_PREFIX + edgeLabel.getName())));
            }
        }
    }
    // Need to defer foreign key constraint checks.
    if (queryTraversesEdge) {
        String edgeTableName = (maybeWrapInQoutes(lastEdge.getSchemaTable().getSchema())) + "." + maybeWrapInQoutes(lastEdge.getSchemaTable().getTable());
        sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.ALTER, this.sqlToTurnOffReferentialConstraintCheck(edgeTableName), lastEdge.getSchemaTable()));
    }
    // Delete the leaf vertices, if there are foreign keys then its been deferred.
    StringBuilder sb = new StringBuilder();
    sb.append("DELETE FROM ");
    sb.append(maybeWrapInQoutes(last.getSchemaTable().getSchema()));
    sb.append(".");
    sb.append(maybeWrapInQoutes(last.getSchemaTable().getTable()));
    sb.append("\nWHERE \"ID\" IN (\n\t");
    sb.append(leafElementsToDelete);
    sb.append(")");
    sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.NORMAL, sb.toString(), null));
    if (queryTraversesEdge) {
        sb = new StringBuilder();
        sb.append("DELETE FROM ");
        sb.append(maybeWrapInQoutes(lastEdge.getSchemaTable().getSchema()));
        sb.append(".");
        sb.append(maybeWrapInQoutes(lastEdge.getSchemaTable().getTable()));
        sb.append("\nWHERE \"ID\" IN (\n\t");
        sb.append(edgesToDelete.get());
        sb.append(")");
        sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.EDGE, sb.toString(), lastEdge.getSchemaTable()));
    }
    // Enable the foreign key constraint
    if (queryTraversesEdge) {
        String edgeTableName = (maybeWrapInQoutes(lastEdge.getSchemaTable().getSchema())) + "." + maybeWrapInQoutes(lastEdge.getSchemaTable().getTable());
        sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.ALTER, this.sqlToTurnOnReferentialConstraintCheck(edgeTableName), null));
    }
    return sqls;
}
Also used : Schema(org.umlg.sqlg.structure.topology.Schema) EdgeLabel(org.umlg.sqlg.structure.topology.EdgeLabel) Triple(org.apache.commons.lang3.tuple.Triple) SqlgSqlExecutor(org.umlg.sqlg.strategy.SqlgSqlExecutor) SchemaTableTree(org.umlg.sqlg.sql.parse.SchemaTableTree) VertexLabel(org.umlg.sqlg.structure.topology.VertexLabel)

Example 8 with SchemaTableTree

use of org.umlg.sqlg.sql.parse.SchemaTableTree in project sqlg by pietermartin.

the class SqlgGraphStep method doLast.

private Set<SchemaTableTree> doLast() {
    this.replacedStepTree.maybeAddLabelToLeafNodes();
    Set<SchemaTableTree> rootSchemaTableTrees = parseForStrategy();
    // If the order is over multiple tables then the resultSet will be completely loaded into memory and then sorted.
    if (this.replacedStepTree.hasOrderBy()) {
        if (isForMultipleQueries() || !this.replacedStepTree.orderByIsOrder()) {
            setEagerLoad(true);
            // Remove the dbComparators
            for (SchemaTableTree rootSchemaTableTree : rootSchemaTableTrees) {
                rootSchemaTableTree.removeDbComparators();
            }
        } else {
            // This is only needed for test assertions at the moment.
            this.replacedStepTree.applyComparatorsOnDb();
        }
    }
    // range is always the last step as sqlg does not optimize beyond a range step.
    if (this.replacedStepTree.hasRange()) {
        if (this.replacedStepTree.hasOrderBy()) {
            if (isForMultipleQueries()) {
                this.replacedStepTree.doNotApplyRangeOnDb();
                setEagerLoad(true);
            } else {
                this.replacedStepTree.doNotApplyInStep();
            }
        } else {
            if (!isForMultipleQueries()) {
                // In this case the range is only applied on the db.
                this.replacedStepTree.doNotApplyInStep();
            } else {
                this.replacedStepTree.doNotApplyRangeOnDb();
            }
        }
    }
    return rootSchemaTableTrees;
}
Also used : SchemaTableTree(org.umlg.sqlg.sql.parse.SchemaTableTree)

Example 9 with SchemaTableTree

use of org.umlg.sqlg.sql.parse.SchemaTableTree in project sqlg by pietermartin.

the class PostgresDialect method drop.

@Override
public List<Triple<SqlgSqlExecutor.DROP_QUERY, String, SchemaTable>> drop(SqlgGraph sqlgGraph, String leafElementsToDelete, Optional<String> edgesToDelete, LinkedList<SchemaTableTree> distinctQueryStack) {
    List<Triple<SqlgSqlExecutor.DROP_QUERY, String, SchemaTable>> sqls = new ArrayList<>();
    SchemaTableTree last = distinctQueryStack.getLast();
    SchemaTableTree lastEdge = null;
    // if the leaf elements are vertices then we need to delete its in and out edges.
    boolean isVertex = last.getSchemaTable().isVertexTable();
    VertexLabel lastVertexLabel = null;
    if (isVertex) {
        Optional<Schema> schemaOptional = sqlgGraph.getTopology().getSchema(last.getSchemaTable().getSchema());
        Preconditions.checkState(schemaOptional.isPresent(), "BUG: %s not found in the topology.", last.getSchemaTable().getSchema());
        Schema schema = schemaOptional.get();
        Optional<VertexLabel> vertexLabelOptional = schema.getVertexLabel(last.getSchemaTable().withOutPrefix().getTable());
        Preconditions.checkState(vertexLabelOptional.isPresent(), "BUG: %s not found in the topology.", last.getSchemaTable().withOutPrefix().getTable());
        lastVertexLabel = vertexLabelOptional.get();
    }
    boolean queryTraversesEdge = isVertex && (distinctQueryStack.size() > 1);
    EdgeLabel lastEdgeLabel = null;
    if (queryTraversesEdge) {
        lastEdge = distinctQueryStack.get(distinctQueryStack.size() - 2);
        Optional<Schema> edgeSchema = sqlgGraph.getTopology().getSchema(lastEdge.getSchemaTable().getSchema());
        Preconditions.checkState(edgeSchema.isPresent(), "BUG: %s not found in the topology.", lastEdge.getSchemaTable().getSchema());
        Optional<EdgeLabel> edgeLabelOptional = edgeSchema.get().getEdgeLabel(lastEdge.getSchemaTable().withOutPrefix().getTable());
        Preconditions.checkState(edgeLabelOptional.isPresent(), "BUG: %s not found in the topology.", lastEdge.getSchemaTable().getTable());
        lastEdgeLabel = edgeLabelOptional.get();
    }
    if (isVertex) {
        // First delete all edges except for this edge traversed to get to the vertices.
        StringBuilder sb;
        for (EdgeLabel edgeLabel : lastVertexLabel.getOutEdgeLabels().values()) {
            if (lastEdgeLabel == null || !edgeLabel.equals(lastEdgeLabel)) {
                // Delete
                sb = new StringBuilder();
                sb.append("WITH todelete AS (");
                sb.append(leafElementsToDelete);
                sb.append("\n)\nDELETE FROM ");
                sb.append(maybeWrapInQoutes(edgeLabel.getSchema().getName()));
                sb.append(".");
                sb.append(maybeWrapInQoutes(Topology.EDGE_PREFIX + edgeLabel.getName()));
                sb.append(" a USING todelete\nWHERE a.");
                sb.append(maybeWrapInQoutes(lastVertexLabel.getSchema().getName() + "." + lastVertexLabel.getName() + Topology.OUT_VERTEX_COLUMN_END));
                sb.append(" = todelete.");
                sb.append(maybeWrapInQoutes("alias1"));
                sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.NORMAL, sb.toString(), SchemaTable.of(edgeLabel.getSchema().getName(), Topology.EDGE_PREFIX + edgeLabel.getName())));
            }
        }
        for (EdgeLabel edgeLabel : lastVertexLabel.getInEdgeLabels().values()) {
            if (lastEdgeLabel == null || !edgeLabel.equals(lastEdgeLabel)) {
                // Delete
                sb = new StringBuilder();
                sb.append("WITH todelete AS (");
                sb.append(leafElementsToDelete);
                sb.append("\n)\nDELETE FROM ");
                sb.append(maybeWrapInQoutes(edgeLabel.getSchema().getName()));
                sb.append(".");
                sb.append(maybeWrapInQoutes(Topology.EDGE_PREFIX + edgeLabel.getName()));
                sb.append(" a USING todelete\nWHERE a.");
                sb.append(maybeWrapInQoutes(lastVertexLabel.getSchema().getName() + "." + lastVertexLabel.getName() + Topology.IN_VERTEX_COLUMN_END));
                sb.append(" = todelete.");
                sb.append(maybeWrapInQoutes("alias1"));
                sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.NORMAL, sb.toString(), SchemaTable.of(edgeLabel.getSchema().getName(), Topology.EDGE_PREFIX + edgeLabel.getName())));
            }
        }
    }
    // Need to defer foreign key constraint checks.
    if (queryTraversesEdge) {
        sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.ALTER, "SET CONSTRAINTS ALL DEFERRED", null));
    }
    // Delete the leaf vertices, if there are foreign keys then its been deferred.
    StringBuilder sb = new StringBuilder();
    sb.append("WITH todelete AS (");
    sb.append(leafElementsToDelete);
    sb.append("\n)\nDELETE FROM ");
    sb.append(maybeWrapInQoutes(last.getSchemaTable().getSchema()));
    sb.append(".");
    sb.append(maybeWrapInQoutes(last.getSchemaTable().getTable()));
    sb.append(" a USING todelete\nWHERE a.");
    sb.append(maybeWrapInQoutes("ID"));
    sb.append(" = todelete.");
    sb.append(maybeWrapInQoutes("alias1"));
    sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.NORMAL, sb.toString(), last.getSchemaTable()));
    if (queryTraversesEdge) {
        sb = new StringBuilder();
        sb.append("WITH todelete AS (");
        sb.append(edgesToDelete.get());
        sb.append("\n)\nDELETE FROM ");
        sb.append(maybeWrapInQoutes(lastEdge.getSchemaTable().getSchema()));
        sb.append(".");
        sb.append(maybeWrapInQoutes(lastEdge.getSchemaTable().getTable()));
        sb.append(" a USING todelete\nWHERE a.");
        sb.append(maybeWrapInQoutes("ID"));
        sb.append(" = todelete.");
        sb.append(maybeWrapInQoutes("alias1"));
        sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.EDGE, sb.toString(), lastEdge.getSchemaTable()));
    }
    // Enable the foreign key constraint
    if (queryTraversesEdge) {
        sqls.add(Triple.of(SqlgSqlExecutor.DROP_QUERY.ALTER, "SET CONSTRAINTS ALL IMMEDIATE", null));
    }
    return sqls;
}
Also used : Triple(org.apache.commons.lang3.tuple.Triple) SqlgSqlExecutor(org.umlg.sqlg.strategy.SqlgSqlExecutor) SchemaTableTree(org.umlg.sqlg.sql.parse.SchemaTableTree)

Example 10 with SchemaTableTree

use of org.umlg.sqlg.sql.parse.SchemaTableTree in project sqlg by pietermartin.

the class SqlgUtil method loadResultSetIntoResultIterator.

/**
 * @param sqlgGraph
 * @param resultSetMetaData
 * @param resultSet
 * @param rootSchemaTableTree
 * @param subQueryStacks
 * @param first
 * @param lastElementIdCountMap
 * @param forParent             Indicates that the gremlin query is for SqlgVertexStep. It is in the context of an incoming traverser, the parent.
 * @return A list of @{@link Emit}s that represent a single @{@link org.apache.tinkerpop.gremlin.process.traversal.Path}
 * @throws SQLException
 */
public static List<Emit<SqlgElement>> loadResultSetIntoResultIterator(SqlgGraph sqlgGraph, ResultSetMetaData resultSetMetaData, ResultSet resultSet, SchemaTableTree rootSchemaTableTree, List<LinkedList<SchemaTableTree>> subQueryStacks, boolean first, Map<String, Integer> lastElementIdCountMap, boolean forParent) throws SQLException {
    List<Emit<SqlgElement>> result = new ArrayList<>();
    if (resultSet.next()) {
        if (first) {
            for (LinkedList<SchemaTableTree> subQueryStack : subQueryStacks) {
                for (SchemaTableTree schemaTableTree : subQueryStack) {
                    schemaTableTree.clearColumnNamePropertyNameMap();
                }
            }
            populateIdCountMap(resultSetMetaData, rootSchemaTableTree, lastElementIdCountMap);
        }
        int subQueryDepth = 1;
        for (LinkedList<SchemaTableTree> subQueryStack : subQueryStacks) {
            List<Emit<SqlgElement>> labeledElements = SqlgUtil.loadLabeledElements(sqlgGraph, resultSet, subQueryStack, subQueryDepth == subQueryStacks.size(), lastElementIdCountMap, forParent);
            result.addAll(labeledElements);
            if (subQueryDepth == subQueryStacks.size()) {
                SchemaTableTree lastSchemaTableTree = subQueryStack.getLast();
                if (labeledElements.isEmpty()) {
                    SqlgElement e = SqlgUtil.loadElement(sqlgGraph, lastElementIdCountMap, resultSet, lastSchemaTableTree);
                    Emit<SqlgElement> emit;
                    if (!forParent) {
                        emit = new Emit<>(e, Collections.emptySet(), lastSchemaTableTree.getStepDepth(), lastSchemaTableTree.getSqlgComparatorHolder());
                    } else {
                        emit = new Emit<>(resultSet.getLong(1), e, Collections.emptySet(), lastSchemaTableTree.getStepDepth(), lastSchemaTableTree.getSqlgComparatorHolder());
                    }
                    if (lastSchemaTableTree.isLocalStep() && lastSchemaTableTree.isOptionalLeftJoin()) {
                        emit.setIncomingOnlyLocalOptionalStep(true);
                    }
                    result.add(emit);
                }
                if (lastSchemaTableTree.getReplacedStepDepth() == lastSchemaTableTree.getStepDepth() && lastSchemaTableTree.isEmit() && lastSchemaTableTree.isUntilFirst()) {
                    Emit<SqlgElement> repeatEmit = labeledElements.get(labeledElements.size() - 1);
                    repeatEmit.setRepeat(true);
                }
            }
            subQueryDepth++;
        }
    }
    return result;
}
Also used : Emit(org.umlg.sqlg.strategy.Emit) SchemaTableTree(org.umlg.sqlg.sql.parse.SchemaTableTree)

Aggregations

SchemaTableTree (org.umlg.sqlg.sql.parse.SchemaTableTree)11 Triple (org.apache.commons.lang3.tuple.Triple)4 SqlgSqlExecutor (org.umlg.sqlg.strategy.SqlgSqlExecutor)3 Emit (org.umlg.sqlg.strategy.Emit)2 LinkedList (java.util.LinkedList)1 ImmutablePair (org.apache.commons.lang3.tuple.ImmutablePair)1 Pair (org.apache.commons.lang3.tuple.Pair)1 HasContainer (org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer)1 AndOrHasContainer (org.umlg.sqlg.sql.parse.AndOrHasContainer)1 WhereClause (org.umlg.sqlg.sql.parse.WhereClause)1 SchemaTable (org.umlg.sqlg.structure.SchemaTable)1 EdgeLabel (org.umlg.sqlg.structure.topology.EdgeLabel)1 Schema (org.umlg.sqlg.structure.topology.Schema)1 VertexLabel (org.umlg.sqlg.structure.topology.VertexLabel)1