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));
}
}
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;
}
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;
}
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;
}
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;
}
Aggregations