You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hugegraph.apache.org by vg...@apache.org on 2024/09/08 08:08:12 UTC
(incubator-hugegraph) branch father-sub-edge created (now 16a2b65a9)
This is an automated email from the ASF dual-hosted git repository.
vgalaxies pushed a change to branch father-sub-edge
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph.git
at 16a2b65a9 Merge branch 'master' into father-sub-edge
This branch includes the following new commits:
new 25010428c setup
new 16a2b65a9 Merge branch 'master' into father-sub-edge
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(incubator-hugegraph) 01/02: setup
Posted by vg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vgalaxies pushed a commit to branch father-sub-edge
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph.git
commit 25010428c47f453f2e3f0ae4f114b211b361bc88
Author: VGalaxies <vg...@apache.org>
AuthorDate: Sun Sep 8 16:05:36 2024 +0800
setup
---
.../org/apache/hugegraph/api/graph/EdgeAPI.java | 12 +-
.../apache/hugegraph/api/schema/EdgeLabelAPI.java | 29 ++
.../main/java/org/apache/hugegraph/HugeGraph.java | 19 +-
.../org/apache/hugegraph/backend/id/EdgeId.java | 68 +++--
.../org/apache/hugegraph/backend/query/Query.java | 4 +
.../backend/serializer/BinarySerializer.java | 29 +-
.../hugegraph/backend/serializer/BytesBuffer.java | 5 +-
.../backend/store/AbstractBackendStore.java | 67 +++++
.../hugegraph/backend/store/BackendStore.java | 6 +
.../backend/tx/GraphIndexTransaction.java | 12 +
.../hugegraph/backend/tx/GraphTransaction.java | 42 ++-
.../hugegraph/backend/tx/SchemaTransactionV2.java | 25 +-
.../hugegraph/io/GraphSONSchemaSerializer.java | 57 ++--
.../org/apache/hugegraph/schema/EdgeLabel.java | 178 ++++++++----
.../hugegraph/schema/builder/EdgeLabelBuilder.java | 198 ++++++++++---
.../org/apache/hugegraph/structure/HugeEdge.java | 38 ++-
.../org/apache/hugegraph/structure/HugeVertex.java | 2 +
.../hugegraph/type/define/EdgeLabelType.java | 8 -
.../org/apache/hugegraph/type/define/HugeKeys.java | 3 +
.../backend/store/hstore/HstoreStore.java | 318 +++++++++++----------
20 files changed, 785 insertions(+), 335 deletions(-)
diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java
index 25e8cacf0..6a289368e 100644
--- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java
+++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/graph/EdgeAPI.java
@@ -426,7 +426,15 @@ public class EdgeAPI extends BatchAPI {
private Id getEdgeId(HugeGraph g, JsonEdge newEdge) {
String sortKeys = "";
- Id labelId = g.edgeLabel(newEdge.label).id();
+ EdgeLabel edgeLabel = g.edgeLabel(newEdge.label);
+ E.checkArgument(!edgeLabel.edgeLabelType().parent(),
+ "The label of the created/updated edge is not allowed" +
+ " to be the parent type");
+ Id labelId = edgeLabel.id();
+ Id subLabelId = edgeLabel.id();
+ if (edgeLabel.edgeLabelType().sub()) {
+ labelId = edgeLabel.fatherId();
+ }
List<Id> sortKeyIds = g.edgeLabel(labelId).sortKeys();
if (!sortKeyIds.isEmpty()) {
List<Object> sortKeyValues = new ArrayList<>(sortKeyIds.size());
@@ -442,7 +450,7 @@ public class EdgeAPI extends BatchAPI {
sortKeys = ConditionQuery.concatValues(sortKeyValues);
}
EdgeId edgeId = new EdgeId(HugeVertex.getIdValue(newEdge.source),
- Directions.OUT, labelId, sortKeys,
+ Directions.OUT, labelId, subLabelId, sortKeys,
HugeVertex.getIdValue(newEdge.target));
if (newEdge.id != null) {
E.checkArgument(edgeId.asString().equals(newEdge.id),
diff --git a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java
index 97bad8c77..09eb93bd7 100644
--- a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java
+++ b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/schema/EdgeLabelAPI.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.hugegraph.HugeGraph;
@@ -32,6 +33,7 @@ import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.define.Checkable;
import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.schema.Userdata;
+import org.apache.hugegraph.type.define.EdgeLabelType;
import org.apache.hugegraph.type.define.Frequency;
import org.apache.hugegraph.type.define.GraphMode;
import org.apache.hugegraph.util.E;
@@ -183,10 +185,16 @@ public class EdgeLabelAPI extends API {
public long id;
@JsonProperty("name")
public String name;
+ @JsonProperty("edge_label_type")
+ public EdgeLabelType edgeLabelType;
+ @JsonProperty("parent_label")
+ public String fatherLabel;
@JsonProperty("source_label")
public String sourceLabel;
@JsonProperty("target_label")
public String targetLabel;
+ @JsonProperty("links")
+ public Set<Map<String, String>> links;
@JsonProperty("frequency")
public Frequency frequency;
@JsonProperty("properties")
@@ -223,12 +231,33 @@ public class EdgeLabelAPI extends API {
g, g.mode());
builder.id(this.id);
}
+ if (this.edgeLabelType == null) {
+ this.edgeLabelType = EdgeLabelType.NORMAL;
+ } else if (this.edgeLabelType.parent()) {
+ builder.asBase();
+ } else if (this.edgeLabelType.sub()) {
+ builder.withBase(this.fatherLabel);
+ } else {
+ E.checkArgument(this.edgeLabelType.normal(),
+ "Please enter a valid edge_label_type value " +
+ "in [NORMAL, PARENT, SUB]");
+ }
if (this.sourceLabel != null) {
builder.sourceLabel(this.sourceLabel);
}
if (this.targetLabel != null) {
builder.targetLabel(this.targetLabel);
}
+ if (this.links != null && !this.links.isEmpty()) {
+ for (Map<String, String> map : this.links) {
+ E.checkArgument(map.size() == 1,
+ "The map size must be 1, due to it is a " +
+ "pair");
+ Map.Entry<String, String> entry =
+ map.entrySet().iterator().next();
+ builder.link(entry.getKey(), entry.getValue());
+ }
+ }
if (this.frequency != null) {
builder.frequency(this.frequency);
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java
index ab460d495..5e09f34f7 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java
@@ -19,9 +19,12 @@ package org.apache.hugegraph;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hugegraph.auth.AuthManager;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.query.Query;
@@ -300,11 +303,25 @@ public interface HugeGraph extends Graph {
Id[] ids = new Id[edgeLabels.length];
for (int i = 0; i < edgeLabels.length; i++) {
EdgeLabel edgeLabel = this.edgeLabel(edgeLabels[i]);
- ids[i] = edgeLabel.id();
+ if (edgeLabel.hasFather()) {
+ ids[i] = edgeLabel.fatherId();
+ } else {
+ ids[i] = edgeLabel.id();
+ }
}
return ids;
}
+ default Set<Pair<String, String>> mapPairId2Name(
+ Set<Pair<Id, Id>> pairs) {
+ Set<Pair<String, String>> results = new HashSet<>(pairs.size());
+ for (Pair<Id, Id> pair : pairs) {
+ results.add(Pair.of(this.vertexLabel(pair.getLeft()).name(),
+ this.vertexLabel(pair.getRight()).name()));
+ }
+ return results;
+ }
+
default Id[] mapVlName2Id(String[] vertexLabels) {
Id[] ids = new Id[vertexLabels.length];
for (int i = 0; i < vertexLabels.length; i++) {
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java
index a9053e513..fe030a153 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/EdgeId.java
@@ -28,8 +28,13 @@ import org.apache.hugegraph.util.StringEncoding;
/**
* Class used to format and parse id of edge, the edge id consists of:
- * { source-vertex-id + edge-label + edge-name + target-vertex-id }
- * NOTE: if we use `entry.type()` which is IN or OUT as a part of id,
+ * EdgeId = { source-vertex-id > direction > parentEdgeLabelId > subEdgeLabelId
+ * > sortKeys > target-vertex-id }
+ * NOTE:
+ * <p>1. for edges with edgeLabelType = NORMAL: edgeLabelId = parentEdgeLabelId = subEdgeLabelId;
+ * for edges with edgeLabelType = PARENT: edgeLabelId = subEdgeLabelId, parentEdgeLabelId =
+ * edgeLabelId.fatherId
+ * <p>2.if we use `entry.type()` which is IN or OUT as a part of id,
* an edge's id will be different due to different directions (belongs
* to 2 owner vertex)
*/
@@ -39,6 +44,7 @@ public class EdgeId implements Id {
HugeKeys.OWNER_VERTEX,
HugeKeys.DIRECTION,
HugeKeys.LABEL,
+ HugeKeys.SUB_LABEL,
HugeKeys.SORT_VALUES,
HugeKeys.OTHER_VERTEX
};
@@ -46,6 +52,7 @@ public class EdgeId implements Id {
private final Id ownerVertexId;
private final Directions direction;
private final Id edgeLabelId;
+ private final Id subLabelId;
private final String sortValues;
private final Id otherVertexId;
@@ -53,22 +60,23 @@ public class EdgeId implements Id {
private String cache;
public EdgeId(HugeVertex ownerVertex, Directions direction,
- Id edgeLabelId, String sortValues, HugeVertex otherVertex) {
- this(ownerVertex.id(), direction, edgeLabelId,
+ Id edgeLabelId, Id subLabelId, String sortValues, HugeVertex otherVertex) {
+ this(ownerVertex.id(), direction, edgeLabelId, subLabelId,
sortValues, otherVertex.id());
}
- public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId,
+ public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, Id subLabelId,
String sortValues, Id otherVertexId) {
- this(ownerVertexId, direction, edgeLabelId,
+ this(ownerVertexId, direction, edgeLabelId, subLabelId,
sortValues, otherVertexId, false);
}
- public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId,
+ public EdgeId(Id ownerVertexId, Directions direction, Id edgeLabelId, Id subLabelId,
String sortValues, Id otherVertexId, boolean directed) {
this.ownerVertexId = ownerVertexId;
this.direction = direction;
this.edgeLabelId = edgeLabelId;
+ this.subLabelId = subLabelId;
this.sortValues = sortValues;
this.otherVertexId = otherVertexId;
this.directed = directed;
@@ -78,12 +86,12 @@ public class EdgeId implements Id {
@Watched
public EdgeId switchDirection() {
Directions direction = this.direction.opposite();
- return new EdgeId(this.otherVertexId, direction, this.edgeLabelId,
+ return new EdgeId(this.otherVertexId, direction, this.edgeLabelId, this.subLabelId,
this.sortValues, this.ownerVertexId, this.directed);
}
public EdgeId directed(boolean directed) {
- return new EdgeId(this.ownerVertexId, this.direction, this.edgeLabelId,
+ return new EdgeId(this.ownerVertexId, this.direction, this.edgeLabelId, this.subLabelId,
this.sortValues, this.otherVertexId, directed);
}
@@ -107,6 +115,10 @@ public class EdgeId implements Id {
return this.edgeLabelId;
}
+ public Id subLabelId() {
+ return this.subLabelId;
+ }
+
public Directions direction() {
return this.direction;
}
@@ -138,12 +150,14 @@ public class EdgeId implements Id {
IdUtil.writeString(this.ownerVertexId),
this.direction.type().string(),
IdUtil.writeLong(this.edgeLabelId),
+ IdUtil.writeLong(this.subLabelId),
this.sortValues,
IdUtil.writeString(this.otherVertexId));
} else {
this.cache = SplicingIdGenerator.concat(
IdUtil.writeString(this.sourceVertexId()),
IdUtil.writeLong(this.edgeLabelId),
+ IdUtil.writeLong(this.subLabelId),
this.sortValues,
IdUtil.writeString(this.targetVertexId()));
}
@@ -181,11 +195,13 @@ public class EdgeId implements Id {
return this.ownerVertexId.hashCode() ^
this.direction.hashCode() ^
this.edgeLabelId.hashCode() ^
+ this.subLabelId.hashCode() ^
this.sortValues.hashCode() ^
this.otherVertexId.hashCode();
} else {
return this.sourceVertexId().hashCode() ^
this.edgeLabelId.hashCode() ^
+ this.subLabelId.hashCode() ^
this.sortValues.hashCode() ^
this.targetVertexId().hashCode();
}
@@ -201,11 +217,13 @@ public class EdgeId implements Id {
return this.ownerVertexId.equals(other.ownerVertexId) &&
this.direction == other.direction &&
this.edgeLabelId.equals(other.edgeLabelId) &&
+ this.subLabelId.equals(other.subLabelId) &&
this.sortValues.equals(other.sortValues) &&
this.otherVertexId.equals(other.otherVertexId);
} else {
return this.sourceVertexId().equals(other.sourceVertexId()) &&
this.edgeLabelId.equals(other.edgeLabelId) &&
+ this.subLabelId.equals(other.subLabelId) &&
this.sortValues.equals(other.sortValues) &&
this.targetVertexId().equals(other.targetVertexId());
}
@@ -235,31 +253,33 @@ public class EdgeId implements Id {
public static EdgeId parse(String id, boolean returnNullIfError)
throws NotFoundException {
String[] idParts = SplicingIdGenerator.split(id);
- if (!(idParts.length == 4 || idParts.length == 5)) {
+ if (!(idParts.length == 5 || idParts.length == 6)) {
if (returnNullIfError) {
return null;
}
- throw new NotFoundException("Edge id must be formatted as 4~5 " +
+ throw new NotFoundException("Edge id must be formatted as 5~6 " +
"parts, but got %s parts: '%s'",
idParts.length, id);
}
try {
- if (idParts.length == 4) {
+ if (idParts.length == 5) {
Id ownerVertexId = IdUtil.readString(idParts[0]);
Id edgeLabelId = IdUtil.readLong(idParts[1]);
- String sortValues = idParts[2];
- Id otherVertexId = IdUtil.readString(idParts[3]);
- return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId,
+ Id subLabelId = IdUtil.readLong(idParts[2]);
+ String sortValues = idParts[3];
+ Id otherVertexId = IdUtil.readString(idParts[4]);
+ return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, subLabelId,
sortValues, otherVertexId);
} else {
- assert idParts.length == 5;
+ assert idParts.length == 6;
Id ownerVertexId = IdUtil.readString(idParts[0]);
HugeType direction = HugeType.fromString(idParts[1]);
Id edgeLabelId = IdUtil.readLong(idParts[2]);
- String sortValues = idParts[3];
- Id otherVertexId = IdUtil.readString(idParts[4]);
+ Id subLabelId = IdUtil.readLong(idParts[3]);
+ String sortValues = idParts[4];
+ Id otherVertexId = IdUtil.readString(idParts[5]);
return new EdgeId(ownerVertexId, Directions.convert(direction),
- edgeLabelId, sortValues, otherVertexId);
+ edgeLabelId, subLabelId, sortValues, otherVertexId);
}
} catch (Throwable e) {
if (returnNullIfError) {
@@ -272,12 +292,13 @@ public class EdgeId implements Id {
public static Id parseStoredString(String id) {
String[] idParts = split(id);
- E.checkArgument(idParts.length == 4, "Invalid id format: %s", id);
+ E.checkArgument(idParts.length == 5, "Invalid id format: %s", id);
Id ownerVertexId = IdUtil.readStoredString(idParts[0]);
Id edgeLabelId = IdGenerator.ofStoredString(idParts[1], IdType.LONG);
- String sortValues = idParts[2];
- Id otherVertexId = IdUtil.readStoredString(idParts[3]);
- return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId,
+ Id subLabelId = IdGenerator.ofStoredString(idParts[2], IdType.LONG);
+ String sortValues = idParts[3];
+ Id otherVertexId = IdUtil.readStoredString(idParts[4]);
+ return new EdgeId(ownerVertexId, Directions.OUT, edgeLabelId, subLabelId,
sortValues, otherVertexId);
}
@@ -286,6 +307,7 @@ public class EdgeId implements Id {
return SplicingIdGenerator.concat(
IdUtil.writeStoredString(eid.sourceVertexId()),
IdGenerator.asStoredString(eid.edgeLabelId()),
+ IdGenerator.asStoredString(eid.subLabelId()),
eid.sortValues(),
IdUtil.writeStoredString(eid.targetVertexId()));
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java
index 4d8e39ccb..3a024283f 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Query.java
@@ -139,6 +139,10 @@ public class Query implements Cloneable {
return this.originQuery;
}
+ public void setOriginQuery(Query query) {
+ this.originQuery = query;
+ }
+
public Query rootOriginQuery() {
Query root = this;
while (root.originQuery != null) {
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java
index 0dd4c9d3e..bb985cc43 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BinarySerializer.java
@@ -59,6 +59,7 @@ import org.apache.hugegraph.type.define.AggregateType;
import org.apache.hugegraph.type.define.Cardinality;
import org.apache.hugegraph.type.define.DataType;
import org.apache.hugegraph.type.define.Directions;
+import org.apache.hugegraph.type.define.EdgeLabelType;
import org.apache.hugegraph.type.define.Frequency;
import org.apache.hugegraph.type.define.HugeKeys;
import org.apache.hugegraph.type.define.IdStrategy;
@@ -73,6 +74,8 @@ import org.apache.hugegraph.util.NumericUtil;
import org.apache.hugegraph.util.StringEncoding;
import org.apache.tinkerpop.gremlin.structure.Edge;
+import static org.apache.hugegraph.schema.SchemaElement.UNDEF;
+
public class BinarySerializer extends AbstractSerializer {
/*
@@ -277,15 +280,27 @@ public class BinarySerializer extends AbstractSerializer {
}
byte type = buffer.read();
Id labelId = buffer.readId();
+ Id subLabelId = buffer.readId();
String sortValues = buffer.readStringWithEnding();
Id otherVertexId = buffer.readId();
boolean direction = EdgeId.isOutDirectionFromCode(type);
- EdgeLabel edgeLabel = graph.edgeLabelOrNone(labelId);
- // Construct edge
- HugeEdge edge = HugeEdge.constructEdge(vertex, direction, edgeLabel,
- sortValues, otherVertexId);
+ HugeEdge edge;
+ if (graph == null) { /* when calculation sinking */
+ EdgeLabel edgeLabel = new EdgeLabel(null, subLabelId, UNDEF);
+ if (subLabelId != labelId) {
+ edgeLabel.edgeLabelType(EdgeLabelType.SUB);
+ edgeLabel.fatherId(labelId);
+ }
+ edge = HugeEdge.constructEdgeWithoutGraph(vertex, direction, edgeLabel,
+ sortValues, otherVertexId);
+ } else {
+ EdgeLabel edgeLabel = graph.edgeLabelOrNone(subLabelId);
+
+ edge = HugeEdge.constructEdge(vertex, direction, edgeLabel,
+ sortValues, otherVertexId);
+ }
// Parse edge-id + edge-properties
buffer = BytesBuffer.wrap(col.value);
@@ -1104,8 +1119,7 @@ public class BinarySerializer extends AbstractSerializer {
public BinaryBackendEntry writeEdgeLabel(EdgeLabel schema) {
this.entry = newBackendEntry(schema);
writeString(HugeKeys.NAME, schema.name());
- writeId(HugeKeys.SOURCE_LABEL, schema.sourceLabel());
- writeId(HugeKeys.TARGET_LABEL, schema.targetLabel());
+ writeIds(HugeKeys.LINKS, schema.linksIds());
writeEnum(HugeKeys.FREQUENCY, schema.frequency());
writeIds(HugeKeys.PROPERTIES, schema.properties());
writeIds(HugeKeys.SORT_KEYS, schema.sortKeys());
@@ -1127,8 +1141,7 @@ public class BinarySerializer extends AbstractSerializer {
String name = readString(HugeKeys.NAME);
EdgeLabel edgeLabel = new EdgeLabel(graph, id, name);
- edgeLabel.sourceLabel(readId(HugeKeys.SOURCE_LABEL));
- edgeLabel.targetLabel(readId(HugeKeys.TARGET_LABEL));
+ edgeLabel.linksIds(readIds(HugeKeys.LINKS));
edgeLabel.frequency(readEnum(HugeKeys.FREQUENCY, Frequency.class));
edgeLabel.properties(readIds(HugeKeys.PROPERTIES));
edgeLabel.sortKeys(readIds(HugeKeys.SORT_KEYS));
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java
index c13d61108..2c890ebe4 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/serializer/BytesBuffer.java
@@ -697,11 +697,12 @@ public final class BytesBuffer extends OutputStream {
}
public BytesBuffer writeEdgeId(Id id) {
- // owner-vertex + dir + edge-label + sort-values + other-vertex
+ // owner-vertex + dir + edge-label + sub-edge-label + sort-values + other-vertex
EdgeId edge = (EdgeId) id;
this.writeId(edge.ownerVertexId());
this.write(edge.directionCode());
this.writeId(edge.edgeLabelId());
+ this.writeId(edge.subLabelId());
this.writeStringWithEnding(edge.sortValues());
this.writeId(edge.otherVertexId());
return this;
@@ -709,7 +710,7 @@ public final class BytesBuffer extends OutputStream {
public Id readEdgeId() {
return new EdgeId(this.readId(), EdgeId.directionFromCode(this.read()),
- this.readId(), this.readStringWithEnding(),
+ this.readId(), this.readId(), this.readStringWithEnding(),
this.readId());
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java
index 2ef9a6db7..adb3c8c40 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/AbstractBackendStore.java
@@ -17,8 +17,24 @@
package org.apache.hugegraph.backend.store;
+import org.apache.hugegraph.HugeGraph;
+import org.apache.hugegraph.backend.query.Condition;
+import org.apache.hugegraph.backend.query.ConditionQuery;
+import org.apache.hugegraph.backend.query.ConditionQueryFlatten;
+import org.apache.hugegraph.backend.query.Query;
import org.apache.hugegraph.exception.ConnectionException;
+import org.apache.hugegraph.iterator.ExtendableIterator;
+import org.apache.hugegraph.iterator.FlatMapperIterator;
import org.apache.hugegraph.type.HugeType;
+import org.apache.hugegraph.type.define.Directions;
+import org.apache.hugegraph.type.define.HugeKeys;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
public abstract class AbstractBackendStore<Session extends BackendSession>
implements BackendStore {
@@ -36,6 +52,57 @@ public abstract class AbstractBackendStore<Session extends BackendSession>
return this.dispatcher;
}
+ protected List<HugeType> getHugeTypes(Query sampleQuery) {
+ Set<HugeType> typeSet = new HashSet<>();
+ for (Condition c : sampleQuery.conditions()) {
+ if (c.isRelation() && c.isSysprop()) {
+ Condition.SyspropRelation sr = (Condition.SyspropRelation) c;
+ if (sr.relation() == Condition.RelationType.EQ) {
+ if (sr.key().equals(HugeKeys.DIRECTION)) {
+ typeSet.add(((Directions) sr.value()).type());
+ }
+ }
+ } else if (c.type() == Condition.ConditionType.OR && c.isSysprop()) {
+ for (Condition.Relation r : c.relations()) {
+ if (r.relation() == Condition.RelationType.EQ) {
+ if (r.key().equals(HugeKeys.DIRECTION)) {
+ typeSet.add(((Directions) r.value()).type());
+ }
+ }
+ }
+ }
+ }
+ return new ArrayList<>(typeSet);
+ }
+
+ @Override
+ public Iterator<Iterator<BackendEntry>> query(Iterator<Query> queries,
+ Function<Query, Query> queryWriter,
+ HugeGraph hugeGraph) {
+ List<Iterator<BackendEntry>> result = new ArrayList<>();
+
+ FlatMapperIterator<Query, BackendEntry> it =
+ new FlatMapperIterator<>(queries, query -> {
+ assert query instanceof ConditionQuery;
+ List<ConditionQuery> flattenQueryList =
+ ConditionQueryFlatten.flatten((ConditionQuery) query);
+
+ if (flattenQueryList.size() > 1) {
+ ExtendableIterator<BackendEntry> itExtend
+ = new ExtendableIterator<>();
+ flattenQueryList.forEach(cq -> {
+ Query cQuery = queryWriter.apply(cq);
+ itExtend.extend(this.query(cQuery));
+ });
+ return itExtend;
+ } else {
+ return this.query(queryWriter.apply(query));
+ }
+ });
+ result.add(it);
+ return result.iterator();
+ }
+
public void registerMetaHandler(String name, MetaHandler<Session> handler) {
this.dispatcher.registerMetaHandler(name, handler);
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java
index 5c05e37c5..8bd1bb294 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/BackendStore.java
@@ -19,7 +19,9 @@ package org.apache.hugegraph.backend.store;
import java.util.Iterator;
import java.util.Map;
+import java.util.function.Function;
+import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
import org.apache.hugegraph.backend.query.Query;
@@ -70,6 +72,10 @@ public interface BackendStore {
// Query data
Iterator<BackendEntry> query(Query query);
+ Iterator<Iterator<BackendEntry>> query(Iterator<Query> queries,
+ Function<Query, Query> queryWriter,
+ HugeGraph hugeGraph);
+
Number queryNumber(Query query);
// Transaction
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java
index 3905ebb0c..b7c0c3d7e 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java
@@ -67,6 +67,7 @@ import org.apache.hugegraph.iterator.Metadatable;
import org.apache.hugegraph.job.EphemeralJob;
import org.apache.hugegraph.job.system.DeleteExpiredJob;
import org.apache.hugegraph.perf.PerfUtil.Watched;
+import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.schema.IndexLabel;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.SchemaLabel;
@@ -147,6 +148,17 @@ public class GraphIndexTransaction extends AbstractTransaction {
} else {
this.doAppend(this.serializer.writeIndex(index));
}
+
+ if (element instanceof HugeEdge && ((EdgeLabel) label).hasFather()) {
+ HugeIndex fatherIndex = new HugeIndex(this.graph(), IndexLabel.label(element.type()));
+ fatherIndex.fieldValues(((EdgeLabel) label).fatherId());
+ fatherIndex.elementIds(element.id(), element.expiredTime());
+ if (removed) {
+ this.doEliminate(this.serializer.writeIndex(fatherIndex));
+ } else {
+ this.doAppend(this.serializer.writeIndex(fatherIndex));
+ }
+ }
}
@Watched(prefix = "index")
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java
index 10aa73f71..8ecfc2eed 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java
@@ -31,6 +31,8 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
+import com.google.common.collect.Iterators;
+
import org.apache.commons.collections.CollectionUtils;
import org.apache.hugegraph.HugeException;
import org.apache.hugegraph.HugeGraph;
@@ -1044,6 +1046,20 @@ public class GraphTransaction extends IndexableTransaction {
protected Iterator<HugeEdge> queryEdgesFromBackend(Query query) {
assert query.resultType().isEdge();
+ if (query instanceof ConditionQuery) {
+ ConditionQuery cq = (ConditionQuery) query;
+ Id label = cq.condition(HugeKeys.LABEL);
+ if (label != null &&
+ graph().edgeLabel(label).isFather() &&
+ cq.condition(HugeKeys.SUB_LABEL) == null &&
+ cq.condition(HugeKeys.OWNER_VERTEX) != null &&
+ cq.condition(HugeKeys.DIRECTION) != null &&
+ matchEdgeSortKeys(cq, false, this.graph())) {
+ return parentElQueryWithSortKeys(graph().edgeLabel(label), graph().edgeLabels(),
+ cq);
+ }
+ }
+
QueryResults<BackendEntry> results = this.query(query);
Iterator<BackendEntry> entries = results.iterator();
@@ -1070,6 +1086,26 @@ public class GraphTransaction extends IndexableTransaction {
return edges;
}
+ private Iterator<HugeEdge> parentElQueryWithSortKeys(EdgeLabel label,
+ Collection<EdgeLabel> allEls,
+ ConditionQuery cq) {
+ Iterator<HugeEdge> edges = null;
+ int count = 0;
+ for (EdgeLabel el : allEls) {
+ if (el.edgeLabelType().sub() && el.fatherId().equals(label.id())) {
+ ConditionQuery tempQuery = cq.copy();
+ tempQuery.eq(HugeKeys.SUB_LABEL, el.id());
+ count++;
+ if (count == 1) {
+ edges = this.queryEdgesFromBackend(tempQuery);
+ } else {
+ edges = Iterators.concat(edges, this.queryEdgesFromBackend(tempQuery));
+ }
+ }
+ }
+ return edges;
+ }
+
@Watched(prefix = "graph")
public <V> void addVertexProperty(HugeVertexProperty<V> prop) {
// NOTE: this method can also be used to update property
@@ -1522,7 +1558,8 @@ public class GraphTransaction extends IndexableTransaction {
query.optimized(OptimizedType.SORT_KEYS);
query = query.copy();
// Serialize sort-values
- List<Id> keys = this.graph().edgeLabel(label).sortKeys();
+ EdgeLabel el = this.graph().edgeLabel(label);
+ List<Id> keys = el.sortKeys();
List<Condition> conditions = GraphIndexTransaction
.constructShardConditions(query, keys, HugeKeys.SORT_VALUES);
query.query(conditions);
@@ -1532,6 +1569,9 @@ public class GraphTransaction extends IndexableTransaction {
*/
query.resetUserpropConditions();
+ if (query.condition(HugeKeys.SUB_LABEL) == null) {
+ query.eq(HugeKeys.SUB_LABEL, el.id());
+ }
LOG.debug("Query edges by sortKeys: {}", query);
return query;
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java
index 8bf0a68b2..903bfade6 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/SchemaTransactionV2.java
@@ -288,19 +288,18 @@ public class SchemaTransactionV2 implements ISchemaTransaction {
*/
LOG.debug("SchemaTransaction remove edge label '{}'", id);
EdgeLabel schema = this.getEdgeLabel(id);
- // TODO: uncomment later - sub edge labels
- //if (schema.edgeLabelType().parent()) {
- // List<EdgeLabel> edgeLabels = this.getEdgeLabels();
- // for (EdgeLabel edgeLabel : edgeLabels) {
- // if (edgeLabel.edgeLabelType().sub() &&
- // edgeLabel.fatherId() == id) {
- // throw new NotAllowException(
- // "Not allowed to remove a parent edge label: '%s' " +
- // "because the sub edge label '%s' is still existing",
- // schema.name(), edgeLabel.name());
- // }
- // }
- //}
+ if (schema.edgeLabelType().parent()) {
+ List<EdgeLabel> edgeLabels = this.getEdgeLabels();
+ for (EdgeLabel edgeLabel : edgeLabels) {
+ if (edgeLabel.edgeLabelType().sub() &&
+ edgeLabel.fatherId() == id) {
+ throw new NotAllowException(
+ "Not allowed to remove a parent edge label: '%s' " +
+ "because the sub edge label '%s' is still existing",
+ schema.name(), edgeLabel.name());
+ }
+ }
+ }
SchemaJob job = new EdgeLabelRemoveJob();
return asyncRun(this.graph(), schema, job);
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java
index b92d50653..31d197c09 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/io/GraphSONSchemaSerializer.java
@@ -20,12 +20,15 @@ package org.apache.hugegraph.io;
import java.util.LinkedHashMap;
import java.util.Map;
+import com.google.common.collect.ImmutableList;
+
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.schema.IndexLabel;
import org.apache.hugegraph.schema.PropertyKey;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.type.HugeType;
+import org.apache.hugegraph.type.define.EdgeLabelType;
import org.apache.hugegraph.type.define.HugeKeys;
public class GraphSONSchemaSerializer {
@@ -64,25 +67,43 @@ public class GraphSONSchemaSerializer {
Map<HugeKeys, Object> map = new LinkedHashMap<>();
map.put(HugeKeys.ID, edgeLabel.id().asLong());
map.put(HugeKeys.NAME, edgeLabel.name());
- map.put(HugeKeys.SOURCE_LABEL, edgeLabel.sourceLabelName());
- map.put(HugeKeys.TARGET_LABEL, edgeLabel.targetLabelName());
- map.put(HugeKeys.FREQUENCY, edgeLabel.frequency());
- map.put(HugeKeys.SORT_KEYS,
- graph.mapPkId2Name(edgeLabel.sortKeys()));
- map.put(HugeKeys.NULLABLE_KEYS,
- graph.mapPkId2Name(edgeLabel.nullableKeys()));
- map.put(HugeKeys.INDEX_LABELS,
- graph.mapIlId2Name(edgeLabel.indexLabels()));
- map.put(HugeKeys.PROPERTIES,
- graph.mapPkId2Name(edgeLabel.properties()));
- map.put(HugeKeys.STATUS, edgeLabel.status());
- map.put(HugeKeys.TTL, edgeLabel.ttl());
- String ttlStartTimeName = edgeLabel.ttlStartTimeName();
- if (ttlStartTimeName != null) {
- map.put(HugeKeys.TTL_START_TIME, ttlStartTimeName);
+ if (edgeLabel.isFather()) {
+ map.put(HugeKeys.EDGELABEL_TYPE, EdgeLabelType.PARENT);
+ if (edgeLabel.links().size() > 0) {
+ map.put(HugeKeys.LINKS,
+ graph.mapPairId2Name(edgeLabel.links()));
+ }
+ } else if (edgeLabel.hasFather()) {
+ map.put(HugeKeys.EDGELABEL_TYPE, EdgeLabelType.SUB);
+ map.put(HugeKeys.PARENT_LABEL,
+ graph.mapElId2Name(ImmutableList.of(edgeLabel.fatherId()))
+ .get(0));
+ } else {
+ map.put(HugeKeys.EDGELABEL_TYPE, edgeLabel.edgeLabelType());
}
- map.put(HugeKeys.ENABLE_LABEL_INDEX, edgeLabel.enableLabelIndex());
- map.put(HugeKeys.USER_DATA, edgeLabel.userdata());
+
+ if (!edgeLabel.isFather()) {
+ map.put(HugeKeys.LINKS,
+ graph.mapPairId2Name(edgeLabel.links()));
+ map.put(HugeKeys.FREQUENCY, edgeLabel.frequency());
+ map.put(HugeKeys.SORT_KEYS,
+ graph.mapPkId2Name(edgeLabel.sortKeys()));
+ map.put(HugeKeys.NULLABLE_KEYS,
+ graph.mapPkId2Name(edgeLabel.nullableKeys()));
+ map.put(HugeKeys.INDEX_LABELS,
+ graph.mapIlId2Name(edgeLabel.indexLabels()));
+ map.put(HugeKeys.PROPERTIES,
+ graph.mapPkId2Name(edgeLabel.properties()));
+ map.put(HugeKeys.STATUS, edgeLabel.status());
+ map.put(HugeKeys.TTL, edgeLabel.ttl());
+ String ttlStartTimeName = edgeLabel.ttlStartTimeName();
+ if (ttlStartTimeName != null) {
+ map.put(HugeKeys.TTL_START_TIME, ttlStartTimeName);
+ }
+ map.put(HugeKeys.ENABLE_LABEL_INDEX, edgeLabel.enableLabelIndex());
+ map.put(HugeKeys.USER_DATA, edgeLabel.userdata());
+ }
+
return map;
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java
index b9fac4643..8ce63ad96 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java
@@ -21,11 +21,13 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
@@ -43,11 +45,13 @@ public class EdgeLabel extends SchemaLabel {
public static final EdgeLabel NONE = new EdgeLabel(null, NONE_ID, UNDEF);
+ private Set<Pair<Id, Id>> links = new HashSet<>();
private Id sourceLabel = NONE_ID;
- private Id targetLabel = NONE_ID;
private Frequency frequency;
private List<Id> sortKeys;
- private EdgeLabelType edgeLabelType;
+
+ private EdgeLabelType edgeLabelType = EdgeLabelType.NORMAL;
+ private Id fatherId;
public EdgeLabel(final HugeGraph graph, Id id, String name) {
super(graph, id, name);
@@ -60,14 +64,34 @@ public class EdgeLabel extends SchemaLabel {
return HugeType.EDGE_LABEL;
}
- public Frequency frequency() {
- return this.frequency;
+ public boolean isFather() {
+ return this.edgeLabelType.parent();
}
public void edgeLabelType(EdgeLabelType type) {
this.edgeLabelType = type;
}
+ public EdgeLabelType edgeLabelType() {
+ return this.edgeLabelType;
+ }
+
+ public boolean hasFather() {
+ return this.edgeLabelType.sub();
+ }
+
+ public Id fatherId() {
+ return this.fatherId;
+ }
+
+ public void fatherId(Id fatherId) {
+ this.fatherId = fatherId;
+ }
+
+ public Frequency frequency() {
+ return this.frequency;
+ }
+
public void frequency(Frequency frequency) {
this.frequency = frequency;
}
@@ -78,53 +102,107 @@ public class EdgeLabel extends SchemaLabel {
}
public String sourceLabelName() {
- return this.graph.vertexLabelOrNone(this.sourceLabel).name();
+ E.checkState(this.links.size() == 1,
+ "Only edge label has single vertex label pair can call " +
+ "sourceLabelName(), but current edge label got %s",
+ this.links.size());
+ return this.graph.vertexLabelOrNone(this.links.iterator().next().getLeft()).name();
+ }
+
+ public List<Id> linksIds() {
+ List<Id> ids = new ArrayList<>(this.links.size() * 2);
+ for (Pair<Id, Id> link : this.links) {
+ ids.add(link.getLeft());
+ ids.add(link.getRight());
+ }
+ return ids;
+ }
+
+ public void linksIds(Id[] ids) {
+ this.links = new HashSet<>(ids.length / 2);
+ for (int i = 0; i < ids.length; i += 2) {
+ this.links.add(Pair.of(ids[i], ids[i + 1]));
+ }
}
public Id sourceLabel() {
- return this.sourceLabel;
+ if (links.size() == 1) {
+ return links.iterator().next().getLeft();
+ }
+ return NONE_ID;
}
public void sourceLabel(Id id) {
- E.checkArgument(this.sourceLabel == NONE_ID,
- "Not allowed to set source label multi times " +
- "of edge label '%s'", this.name());
+ E.checkArgument(this.links.isEmpty(),
+ "Not allowed add source label to an edge label which " +
+ "already has links");
this.sourceLabel = id;
}
public String targetLabelName() {
- return this.graph.vertexLabelOrNone(this.targetLabel).name();
+ E.checkState(this.links.size() == 1,
+ "Only edge label has single vertex label pair can call " +
+ "sourceLabelName(), but current edge label got %s",
+ this.links.size());
+ return this.graph.vertexLabelOrNone(this.links.iterator().next().getRight()).name();
}
public Id targetLabel() {
- return this.targetLabel;
+ if (links.size() == 1) {
+ return links.iterator().next().getRight();
+ }
+ return NONE_ID;
}
public void targetLabel(Id id) {
- E.checkArgument(this.targetLabel == NONE_ID,
- "Not allowed to set target label multi times " +
- "of edge label '%s'", this.name());
- this.targetLabel = id;
+ E.checkArgument(this.links.isEmpty(),
+ "Not allowed add source label to an edge label which " +
+ "already has links");
+ E.checkArgument(this.sourceLabel != NONE_ID,
+ "Not allowed add target label to an edge label which " +
+ "not has source label yet");
+ this.links.add(Pair.of(this.sourceLabel, id));
+ this.sourceLabel = NONE_ID;
}
public boolean linkWithLabel(Id id) {
- return this.sourceLabel.equals(id) || this.targetLabel.equals(id);
+ for (Pair<Id, Id> link : this.links) {
+ if (link.getLeft().equals(id) || link.getRight().equals(id)) {
+ return true;
+ }
+ }
+ return false;
}
public boolean linkWithVertexLabel(Id label, Directions dir) {
+ if (this.links.size() != 1) {
+ return false;
+ }
+ Id sourceLabel = this.links.iterator().next().getLeft();
+ Id targetLabel = this.links.iterator().next().getRight();
if (dir.equals(Directions.IN)) {
- return this.targetLabel.equals(label);
+ return targetLabel.equals(label);
} else if (dir.equals(Directions.OUT)) {
- return this.sourceLabel.equals(label);
+ return sourceLabel.equals(label);
} else if (dir.equals(Directions.BOTH)) {
- return this.targetLabel.equals(label) || this.sourceLabel.equals(label);
+ return targetLabel.equals(label) || sourceLabel.equals(label);
}
return false;
}
public boolean checkLinkEqual(Id sourceLabel, Id targetLabel) {
- return this.sourceLabel.equals(sourceLabel) &&
- this.targetLabel.equals(targetLabel);
+ return this.links.contains(Pair.of(sourceLabel, targetLabel));
+ }
+
+ public Set<Pair<Id, Id>> links() {
+ return this.links;
+ }
+
+ public void links(Pair<Id, Id> link) {
+ if (this.links == null) {
+ this.links = new HashSet<>();
+ }
+ this.links.add(link);
}
public boolean existSortKeys() {
@@ -160,6 +238,10 @@ public class EdgeLabel extends SchemaLabel {
Id rebuildIndex();
+ Builder asBase();
+
+ Builder withBase(String fatherLabel);
+
Builder link(String sourceLabel, String targetLabel);
Builder sourceLabel(String label);
@@ -221,13 +303,13 @@ public class EdgeLabel extends SchemaLabel {
map.put(P.SORT_KEYS, this.sortKeys);
}
- //map.put(P.EDGELABEL_TYPE, this.edgeLabelType);
- //if (this.fatherId() != null) {
- // map.put(P.FATHER_ID, this.fatherId().asString());
- //}
+ map.put(P.EDGELABEL_TYPE, this.edgeLabelType);
+ if (this.fatherId() != null) {
+ map.put(P.FATHER_ID, this.fatherId().asString());
+ }
map.put(P.ENABLE_LABEL_INDEX, this.enableLabelIndex());
map.put(P.TTL, String.valueOf(this.ttl()));
- //map.put(P.LINKS, this.links());
+ map.put(P.LINKS, this.links());
map.put(P.FREQUENCY, this.frequency().toString());
return super.asMap(map);
@@ -278,17 +360,17 @@ public class EdgeLabel extends SchemaLabel {
Long.parseLong((String) entry.getValue());
edgeLabel.ttlStartTime(IdGenerator.of(ttlStartTime));
break;
- //case P.LINKS:
- // // TODO: serialize and deserialize
- // List<Map> list = (List<Map>) entry.getValue();
- // for (Map m : list) {
- // for (Object key : m.keySet()) {
- // Id sid = IdGenerator.of(Long.parseLong((String) key));
- // Id tid = IdGenerator.of(Long.parseLong(String.valueOf(m.get(key))));
- // edgeLabel.links(Pair.of(sid, tid));
- // }
- // }
- // break;
+ case P.LINKS:
+ // TODO: serialize and deserialize
+ List<Map> list = (List<Map>) entry.getValue();
+ for (Map m : list) {
+ for (Object key : m.keySet()) {
+ Id sid = IdGenerator.of(Long.parseLong((String) key));
+ Id tid = IdGenerator.of(Long.parseLong(String.valueOf(m.get(key))));
+ edgeLabel.links(Pair.of(sid, tid));
+ }
+ }
+ break;
case P.SOURCE_LABEL:
long sourceLabel =
Long.parseLong((String) entry.getValue());
@@ -299,17 +381,17 @@ public class EdgeLabel extends SchemaLabel {
Long.parseLong((String) entry.getValue());
edgeLabel.targetLabel(IdGenerator.of(targetLabel));
break;
- //case P.FATHER_ID:
- // long fatherId =
- // Long.parseLong((String) entry.getValue());
- // edgeLabel.fatherId(IdGenerator.of(fatherId));
- // break;
- //case P.EDGELABEL_TYPE:
- // EdgeLabelType edgeLabelType =
- // EdgeLabelType.valueOf(
- // ((String) entry.getValue()).toUpperCase());
- // edgeLabel.edgeLabelType(edgeLabelType);
- // break;
+ case P.FATHER_ID:
+ long fatherId =
+ Long.parseLong((String) entry.getValue());
+ edgeLabel.fatherId(IdGenerator.of(fatherId));
+ break;
+ case P.EDGELABEL_TYPE:
+ EdgeLabelType edgeLabelType =
+ EdgeLabelType.valueOf(
+ ((String) entry.getValue()).toUpperCase());
+ edgeLabel.edgeLabelType(edgeLabelType);
+ break;
case P.FREQUENCY:
Frequency frequency =
Frequency.valueOf(((String) entry.getValue()).toUpperCase());
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java
index f7aa460e1..01047d6fa 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/builder/EdgeLabelBuilder.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
@@ -40,6 +41,7 @@ import org.apache.hugegraph.schema.Userdata;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.Action;
+import org.apache.hugegraph.type.define.EdgeLabelType;
import org.apache.hugegraph.type.define.Frequency;
import org.apache.hugegraph.util.CollectionUtil;
import org.apache.hugegraph.util.E;
@@ -51,8 +53,10 @@ public class EdgeLabelBuilder extends AbstractBuilder
private Id id;
private String name;
+ private Set<Pair<String, String>> links;
+ private EdgeLabelType edgeLabelType;
+ private String fatherLabel;
private String sourceLabel;
- private String targetLabel;
private Frequency frequency;
private Set<String> properties;
private List<String> sortKeys;
@@ -69,8 +73,9 @@ public class EdgeLabelBuilder extends AbstractBuilder
E.checkNotNull(name, "name");
this.id = null;
this.name = name;
- this.sourceLabel = null;
- this.targetLabel = null;
+ this.links = new HashSet<>();
+ this.edgeLabelType = EdgeLabelType.NORMAL;
+ this.fatherLabel = null;
this.frequency = Frequency.DEFAULT;
this.properties = new HashSet<>();
this.sortKeys = new ArrayList<>();
@@ -89,8 +94,11 @@ public class EdgeLabelBuilder extends AbstractBuilder
HugeGraph origin = copy.graph();
this.id = null;
this.name = copy.name();
- this.sourceLabel = copy.sourceLabelName();
- this.targetLabel = copy.targetLabelName();
+ this.links = mapPairId2Name(origin, copy.links());
+ this.edgeLabelType = copy.edgeLabelType();
+ if (copy.edgeLabelType().sub()) {
+ this.fatherLabel = mapElId2Name(origin, copy.fatherId());
+ }
this.frequency = copy.frequency();
this.properties = mapPkId2Name(origin, copy.properties());
this.sortKeys = mapPkId2Name(origin, copy.sortKeys());
@@ -108,8 +116,10 @@ public class EdgeLabelBuilder extends AbstractBuilder
this.id, this.name);
HugeGraph graph = this.graph();
EdgeLabel edgeLabel = new EdgeLabel(graph, id, this.name);
- edgeLabel.sourceLabel(graph.vertexLabel(this.sourceLabel).id());
- edgeLabel.targetLabel(graph.vertexLabel(this.targetLabel).id());
+ for (Pair<String, String> link : this.links) {
+ edgeLabel.links(Pair.of(graph.vertexLabel(link.getLeft()).id(),
+ graph.vertexLabel(link.getRight()).id()));
+ }
edgeLabel.frequency(this.frequency == Frequency.DEFAULT ?
Frequency.SINGLE : this.frequency);
edgeLabel.ttl(this.ttl);
@@ -132,9 +142,52 @@ public class EdgeLabelBuilder extends AbstractBuilder
edgeLabel.nullableKey(propertyKey.id());
}
edgeLabel.userdata(this.userdata);
+ if (this.edgeLabelType.sub()) {
+ edgeLabel.edgeLabelType(EdgeLabelType.SUB);
+ EdgeLabel fatherEl = graph.edgeLabel(this.fatherLabel);
+ edgeLabel.fatherId(fatherEl.id());
+ registerInfoToFatherEl(fatherEl, edgeLabel);
+ } else {
+ edgeLabel.edgeLabelType(this.edgeLabelType);
+ }
return edgeLabel;
}
+ private void registerInfoToFatherEl(EdgeLabel fatherEl, EdgeLabel subEl) {
+ HugeGraph graph = this.graph();
+ // When the new edge label is a subtype, register the links information
+ // of the sub edgelabel to the parent edge Label
+ for (Pair<String, String> link : this.links) {
+ fatherEl.links(Pair.of(this.graph().vertexLabel(link.getLeft()).id(),
+ graph.vertexLabel(link.getRight()).id()));
+ }
+
+ List<Id> fatherSortKeys = fatherEl.sortKeys();
+ List<Id> subSortKeys = subEl.sortKeys();
+ if (fatherSortKeys == null || fatherSortKeys.size() == 0) {
+ for (Id sortKey : subSortKeys) {
+ fatherEl.sortKeys(sortKey);
+ }
+ } else {
+ E.checkArgument(fatherSortKeys.size() == subSortKeys.size(),
+ "The sortKeys of each sub edgelabel need to be " +
+ "consistent. " + "Currently, the sortKeys of already exist edgelabel " +
+ "are " + "'%s', " + "and the sortKeys of newly added " +
+ "sub edgelabel are '%s'",
+ fatherSortKeys, subSortKeys);
+ for (int i = 0; i < fatherSortKeys.size(); i++) {
+ E.checkArgument(fatherSortKeys.get(i).equals(subSortKeys.get(i)),
+ "The sortKeys of each sub edgelabel need to be " +
+ "consistent. " +
+ "Currently, the sortKeys of already exist edgelabel " +
+ "are " + "'%s', " + "and the sortKeys of newly added " +
+ "sub edgelabel are '%s'",
+ fatherSortKeys, subSortKeys);
+ }
+ }
+ this.graph().updateEdgeLabel(fatherEl);
+ }
+
@Override
public EdgeLabel create() {
HugeType type = HugeType.EDGE_LABEL;
@@ -177,14 +230,12 @@ public class EdgeLabelBuilder extends AbstractBuilder
*/
private boolean hasSameProperties(EdgeLabel existedEdgeLabel) {
HugeGraph graph = this.graph();
- Id sourceId = graph.vertexLabel(this.sourceLabel).id();
- if (!existedEdgeLabel.sourceLabel().equals(sourceId)) {
- return false;
- }
-
- Id targetId = graph.vertexLabel(this.targetLabel).id();
- if (!existedEdgeLabel.targetLabel().equals(targetId)) {
- return false;
+ for (Pair<Id, Id> link : existedEdgeLabel.links()) {
+ String sourceName = graph.vertexLabel(link.getLeft()).name();
+ String targetName = graph.vertexLabel(link.getRight()).name();
+ if (!this.links.contains(Pair.of(sourceName, targetName))) {
+ return false;
+ }
}
if ((this.frequency == Frequency.DEFAULT &&
@@ -302,6 +353,28 @@ public class EdgeLabelBuilder extends AbstractBuilder
return this.graph().rebuildIndex(edgeLabel);
}
+ @Override
+ public EdgeLabel.Builder asBase() {
+ this.edgeLabelType = EdgeLabelType.PARENT;
+ return this;
+ }
+
+ @Override
+ public EdgeLabel.Builder withBase(String fatherLabel) {
+ // Check if fatherLabel is reasonable (if it exists or not)
+ E.checkArgumentNotNull(fatherLabel, "When creating a subtype edgeLabel, " +
+ "the edgeLabel name of the parent type edgeLabel must" +
+ " be entered");
+ EdgeLabel edgeLabel = this.edgeLabelOrNull(fatherLabel);
+ if (edgeLabel == null) {
+ throw new NotFoundException("Can't create subtype edge label '%s' " +
+ "since it's parent edge label doesn't exist", this.name);
+ }
+ this.edgeLabelType = EdgeLabelType.SUB;
+ this.fatherLabel = fatherLabel;
+ return this;
+ }
+
@Override
public EdgeLabelBuilder id(long id) {
E.checkArgument(id != 0L, "Not allowed to assign 0 as edge label id");
@@ -340,20 +413,32 @@ public class EdgeLabelBuilder extends AbstractBuilder
@Override
public EdgeLabelBuilder link(String sourceLabel, String targetLabel) {
- this.sourceLabel(sourceLabel);
- this.targetLabel(targetLabel);
+ if (this.links == null) {
+ this.links = new HashSet<>();
+ }
+ this.links.add(Pair.of(sourceLabel, targetLabel));
return this;
}
@Override
public EdgeLabelBuilder sourceLabel(String label) {
+ E.checkArgument(this.links.isEmpty(),
+ "Not allowed add source label to an edge label which " +
+ "already has links");
this.sourceLabel = label;
return this;
}
@Override
public EdgeLabelBuilder targetLabel(String label) {
- this.targetLabel = label;
+ E.checkArgument(this.links.isEmpty(),
+ "Not allowed add source label to an edge label which " +
+ "already has links");
+ E.checkArgument(this.sourceLabel != null,
+ "Not allowed add target label to an edge label which " +
+ "not has source label yet");
+ this.links.add(Pair.of(this.sourceLabel, label));
+ this.sourceLabel = null;
return this;
}
@@ -518,30 +603,38 @@ public class EdgeLabelBuilder extends AbstractBuilder
}
private void checkRelation() {
- String srcLabel = this.sourceLabel;
- String tgtLabel = this.targetLabel;
-
- E.checkArgument(srcLabel != null && tgtLabel != null,
- "Must set source and target label " +
- "for edge label '%s'", this.name);
-
- E.checkArgumentNotNull(this.vertexLabelOrNull(srcLabel),
- "Undefined source vertex label '%s' " +
- "in edge label '%s'", srcLabel, this.name);
- E.checkArgumentNotNull(this.vertexLabelOrNull(tgtLabel),
- "Undefined target vertex label '%s' " +
- "in edge label '%s'", tgtLabel, this.name);
+ if (this.edgeLabelType.parent()) {
+ E.checkArgument(this.links.isEmpty(),
+ "The links of the parent edge label must be empty");
+ } else {
+ E.checkArgument(!this.links.isEmpty(),
+ "The links of standard and subtype edge label " +
+ "can't be empty");
+ E.checkArgument(this.links.size() == 1,
+ "The links size of standard and subtype edge " +
+ "label must be 1");
+ for (Pair<String, String> link : this.links) {
+ String srcLabel = link.getLeft();
+ String tgtLabel = link.getRight();
+ E.checkArgument(srcLabel != null && tgtLabel != null,
+ "Must set source and target label " +
+ "for edge label '%s'", this.name);
+ E.checkArgumentNotNull(this.vertexLabelOrNull(srcLabel),
+ "Undefined source vertex label '%s' " +
+ "in edge label '%s'", srcLabel,
+ this.name);
+ E.checkArgumentNotNull(this.vertexLabelOrNull(tgtLabel),
+ "Undefined target vertex label '%s' " +
+ "in edge label '%s'", tgtLabel,
+ this.name);
+ }
+ }
}
private void checkStableVars() {
- if (this.sourceLabel != null) {
- throw new NotAllowException(
- "Not allowed to update source label " +
- "for edge label '%s', it must be null", this.name);
- }
- if (this.targetLabel != null) {
+ if (this.links != null && !this.links.isEmpty()) {
throw new NotAllowException(
- "Not allowed to update target label " +
+ "Not allowed to update source/target label " +
"for edge label '%s', it must be null", this.name);
}
if (this.frequency != Frequency.DEFAULT) {
@@ -569,15 +662,17 @@ public class EdgeLabelBuilder extends AbstractBuilder
"Can't set ttl start time if ttl is not set");
return;
}
- VertexLabel source = this.graph().vertexLabel(this.sourceLabel);
- VertexLabel target = this.graph().vertexLabel(this.targetLabel);
- E.checkArgument((source.ttl() == 0L || this.ttl <= source.ttl()) &&
- (target.ttl() == 0L || this.ttl <= target.ttl()),
- "The ttl(%s) of edge label '%s' should less than " +
- "ttl(%s) of source label '%s' and ttl(%s) of target " +
- "label '%s'", this.ttl, this.name,
- source.ttl(), this.sourceLabel,
- target.ttl(), this.targetLabel);
+ for (Pair<String, String> link : this.links) {
+ VertexLabel source = this.graph().vertexLabel(link.getLeft());
+ VertexLabel target = this.graph().vertexLabel(link.getRight());
+ E.checkArgument((source.ttl() == 0L || this.ttl <= source.ttl()) &&
+ (target.ttl() == 0L || this.ttl <= target.ttl()),
+ "The ttl(%s) of edge label '%s' should less than " +
+ "ttl(%s) of source label '%s' and ttl(%s) of target " +
+ "label '%s'", this.ttl, this.name,
+ source.ttl(), link.getLeft(),
+ target.ttl(), link.getRight());
+ }
if (this.ttlStartTime == null) {
return;
}
@@ -624,4 +719,13 @@ public class EdgeLabelBuilder extends AbstractBuilder
private static List<String> mapPkId2Name(HugeGraph graph, List<Id> ids) {
return graph.mapPkId2Name(ids);
}
+
+ private static String mapElId2Name(HugeGraph graph, Id fatherId) {
+ return graph.mapElId2Name(ImmutableList.of(fatherId)).get(0);
+ }
+
+ private static Set<Pair<String, String>> mapPairId2Name(HugeGraph graph,
+ Set<Pair<Id, Id>> pairs) {
+ return graph.mapPairId2Name(pairs);
+ }
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java
index f38c2b067..5bf7011a6 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeEdge.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.hugegraph.HugeException;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.id.EdgeId;
@@ -141,9 +142,18 @@ public class HugeEdge extends HugeElement implements Edge, Cloneable {
@Watched(prefix = "edge")
public void assignId() {
// Generate an id and assign
- this.id = new EdgeId(this.ownerVertex(), this.direction(),
- this.schemaLabel().id(), this.name(),
- this.otherVertex());
+ if (this.schemaLabel().hasFather()) {
+ this.id = new EdgeId(this.ownerVertex(), this.direction(),
+ this.schemaLabel().fatherId(),
+ this.schemaLabel().id(),
+ this.name(),
+ this.otherVertex());
+ } else {
+ this.id = new EdgeId(this.ownerVertex(), this.direction(),
+ this.schemaLabel().id(),
+ this.schemaLabel().id(),
+ this.name(), this.otherVertex());
+ }
if (this.fresh()) {
int len = this.id.length();
@@ -315,9 +325,15 @@ public class HugeEdge extends HugeElement implements Edge, Cloneable {
case OWNER_VERTEX:
return this.ownerVertex().id();
case LABEL:
- return this.schemaLabel().id();
+ if (this.schemaLabel().hasFather()) {
+ return this.schemaLabel().fatherId();
+ } else {
+ return this.schemaLabel().id();
+ }
case DIRECTION:
return this.direction();
+ case SUB_LABEL:
+ return this.schemaLabel().id();
case OTHER_VERTEX:
return this.otherVertex().id();
case SORT_VALUES:
@@ -363,11 +379,15 @@ public class HugeEdge extends HugeElement implements Edge, Cloneable {
public void vertices(HugeVertex owner, HugeVertex other) {
Id ownerLabel = owner.schemaLabel().id();
- if (ownerLabel.equals(this.label.sourceLabel())) {
- this.vertices(true, owner, other);
- } else {
- assert ownerLabel.equals(this.label.targetLabel());
- this.vertices(false, owner, other);
+ Id otherLabel = other.schemaLabel().id();
+ for (Pair<Id, Id> link : this.label.links()) {
+ if (ownerLabel.equals(link.getLeft()) &&
+ otherLabel.equals(link.getRight())) {
+ this.vertices(true, owner, other);
+ } else if (ownerLabel.equals(link.getRight()) &&
+ otherLabel.equals(link.getLeft())) {
+ this.vertices(false, owner, other);
+ }
}
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java
index 4726e88e5..389b0f0e8 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/structure/HugeVertex.java
@@ -303,6 +303,8 @@ public class HugeVertex extends HugeElement implements Vertex, Cloneable {
E.checkArgument(label != null && !label.isEmpty(),
"Edge label can't be null or empty");
EdgeLabel edgeLabel = this.graph().edgeLabel(label);
+ E.checkArgument(!edgeLabel.isFather(), "Adding an edge of parent type " +
+ "is not allowed");
// Check link
E.checkArgument(edgeLabel.checkLinkEqual(this.schemaLabel().id(),
vertex.schemaLabel().id()),
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java
index 912ed43d5..2857c6e3b 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/EdgeLabelType.java
@@ -19,14 +19,11 @@ package org.apache.hugegraph.type.define;
public enum EdgeLabelType implements SerialEnum {
-
NORMAL(1, "NORMAL"),
PARENT(2, "PARENT"),
SUB(3, "SUB"),
-
- GENERAL(4, "GENERAL"),
;
static {
@@ -62,9 +59,4 @@ public enum EdgeLabelType implements SerialEnum {
public boolean sub() {
return this == SUB;
}
-
- public boolean general() {
- return this == GENERAL;
- }
-
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java
index 5ffa3997f..0e3536b01 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/HugeKeys.java
@@ -48,6 +48,8 @@ public enum HugeKeys {
SORT_KEYS(84, "sort_keys"),
TTL(85, "ttl"),
TTL_START_TIME(86, "ttl_start_time"),
+ EDGELABEL_TYPE(87, "edgelabel_type"),
+ PARENT_LABEL(89, "parent_label"),
/* Column names of schema type (PropertyKey) */
DATA_TYPE(120, "data_type"),
@@ -77,6 +79,7 @@ public enum HugeKeys {
SORT_VALUES(206, "sort_values"),
PRIMARY_VALUES(207, "primary_values"),
EXPIRED_TIME(208, "expired_time"),
+ SUB_LABEL(211, "sub_label"),
PROPERTY_TYPE(249, "property_type"),
AGGREGATE_PROPERTIES(250, "aggregate_properties");
diff --git a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java
index 954fe3507..643909667 100644
--- a/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java
+++ b/hugegraph-server/hugegraph-hstore/src/main/java/org/apache/hugegraph/backend/store/hstore/HstoreStore.java
@@ -19,6 +19,7 @@ package org.apache.hugegraph.backend.store.hstore;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -29,12 +30,18 @@ import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import com.google.common.collect.Lists;
+
import org.apache.commons.collections.CollectionUtils;
+import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.id.IdGenerator;
+import org.apache.hugegraph.backend.query.ConditionQuery;
+import org.apache.hugegraph.backend.query.ConditionQueryFlatten;
import org.apache.hugegraph.backend.query.IdPrefixQuery;
import org.apache.hugegraph.backend.query.IdQuery;
import org.apache.hugegraph.backend.query.Query;
@@ -52,10 +59,12 @@ import org.apache.hugegraph.backend.store.hstore.HstoreSessions.Session;
import org.apache.hugegraph.config.CoreOptions;
import org.apache.hugegraph.config.HugeConfig;
import org.apache.hugegraph.iterator.CIter;
+import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.type.HugeTableType;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.Action;
import org.apache.hugegraph.type.define.GraphMode;
+import org.apache.hugegraph.type.define.HugeKeys;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import org.slf4j.Logger;
@@ -339,161 +348,160 @@ public abstract class HstoreStore extends AbstractBackendStore<Session> {
}
}
- // TODO: uncomment later - sub edge labels
- //@Override
- //public Iterator<Iterator<BackendEntry>> query(Iterator<Query> queries,
- // Function<Query, Query> queryWriter,
- // HugeGraph hugeGraph) {
- // if (queries == null || !queries.hasNext()) {
- // return Collections.emptyIterator();
- // }
- //
- // class QueryWrapper implements Iterator<IdPrefixQuery> {
- // Query first;
- // final Iterator<Query> queries;
- // Iterator<Id> subEls;
- // Query preQuery;
- // Iterator<IdPrefixQuery> queryListIterator;
- //
- // QueryWrapper(Iterator<Query> queries, Query first) {
- // this.queries = queries;
- // this.first = first;
- // }
- //
- // @Override
- // public boolean hasNext() {
- // return first != null || (this.subEls != null && this.subEls.hasNext())
- // || (queryListIterator != null && queryListIterator.hasNext()) ||
- // queries.hasNext();
- // }
- //
- // @Override
- // public IdPrefixQuery next() {
- // if (queryListIterator != null && queryListIterator.hasNext()) {
- // return queryListIterator.next();
- // }
- //
- // Query q;
- // if (first != null) {
- // q = first;
- // preQuery = q.copy();
- // first = null;
- // } else {
- // if (this.subEls == null || !this.subEls.hasNext()) {
- // q = queries.next();
- // preQuery = q.copy();
- // } else {
- // q = preQuery.copy();
- // }
- // }
- //
- // assert q instanceof ConditionQuery;
- // ConditionQuery cq = (ConditionQuery) q;
- // ConditionQuery originQuery = (ConditionQuery) q.copy();
- //
- // List<IdPrefixQuery> queryList = Lists.newArrayList();
- // if (hugeGraph != null) {
- // for (ConditionQuery conditionQuery :
- // ConditionQueryFlatten.flatten(cq)) {
- // Id label = conditionQuery.condition(HugeKeys.LABEL);
- // /* Parent type + sortKeys: g.V("V.id").outE("parentLabel").has
- // ("sortKey","value") converted to all subtypes + sortKeys */
- // if ((this.subEls == null ||
- // !this.subEls.hasNext()) && label != null &&
- // hugeGraph.edgeLabel(label).isFather() &&
- // conditionQuery.condition(HugeKeys.SUB_LABEL) ==
- // null &&
- // conditionQuery.condition(HugeKeys.OWNER_VERTEX) !=
- // null &&
- // conditionQuery.condition(HugeKeys.DIRECTION) !=
- // null &&
- // matchEdgeSortKeys(conditionQuery, false,
- // hugeGraph)) {
- // this.subEls =
- // getSubLabelsOfParentEl(
- // hugeGraph.edgeLabels(),
- // label);
- // }
- //
- // if (this.subEls != null &&
- // this.subEls.hasNext()) {
- // conditionQuery.eq(HugeKeys.SUB_LABEL,
- // subEls.next());
- // }
- //
- // HugeType hugeType = conditionQuery.resultType();
- // if (hugeType != null && hugeType.isEdge() &&
- // !conditionQuery.conditions().isEmpty()) {
- // IdPrefixQuery idPrefixQuery =
- // (IdPrefixQuery) queryWriter.apply(
- // conditionQuery);
- // idPrefixQuery.setOriginQuery(originQuery);
- // queryList.add(idPrefixQuery);
- // }
- // }
- //
- // queryListIterator = queryList.iterator();
- // if (queryListIterator.hasNext()) {
- // return queryListIterator.next();
- // }
- // }
- //
- // Id ownerId = cq.condition(HugeKeys.OWNER_VERTEX);
- // assert ownerId != null;
- // BytesBuffer buffer =
- // BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID);
- // buffer.writeId(ownerId);
- // return new IdPrefixQuery(cq, new BinaryBackendEntry.BinaryId(
- // buffer.bytes(), ownerId));
- // }
- //
- // private boolean matchEdgeSortKeys(ConditionQuery query,
- // boolean matchAll,
- // HugeGraph graph) {
- // assert query.resultType().isEdge();
- // Id label = query.condition(HugeKeys.LABEL);
- // if (label == null) {
- // return false;
- // }
- // List<Id> sortKeys = graph.edgeLabel(label).sortKeys();
- // if (sortKeys.isEmpty()) {
- // return false;
- // }
- // Set<Id> queryKeys = query.userpropKeys();
- // for (int i = sortKeys.size(); i > 0; i--) {
- // List<Id> subFields = sortKeys.subList(0, i);
- // if (queryKeys.containsAll(subFields)) {
- // if (queryKeys.size() == subFields.size() || !matchAll) {
- // /*
- // * Return true if:
- // * matchAll=true and all queryKeys are in sortKeys
- // * or
- // * partial queryKeys are in sortKeys
- // */
- // return true;
- // }
- // }
- // }
- // return false;
- // }
- // }
- // Query first = queries.next();
- // List<HugeType> typeList = getHugeTypes(first);
- // QueryWrapper idPrefixQueries = new QueryWrapper(queries, first);
- //
- // return query(typeList, idPrefixQueries);
- //}
-
- //private Iterator<Id> getSubLabelsOfParentEl(Collection<EdgeLabel> allEls,
- // Id label) {
- // List<Id> list = new ArrayList<>();
- // for (EdgeLabel el : allEls) {
- // if (el.edgeLabelType().sub() && el.fatherId().equals(label)) {
- // list.add(el.id());
- // }
- // }
- // return list.iterator();
- //}
+ @Override
+ public Iterator<Iterator<BackendEntry>> query(Iterator<Query> queries,
+ Function<Query, Query> queryWriter,
+ HugeGraph hugeGraph) {
+ if (queries == null || !queries.hasNext()) {
+ return Collections.emptyIterator();
+ }
+
+ class QueryWrapper implements Iterator<IdPrefixQuery> {
+ Query first;
+ final Iterator<Query> queries;
+ Iterator<Id> subEls;
+ Query preQuery;
+ Iterator<IdPrefixQuery> queryListIterator;
+
+ QueryWrapper(Iterator<Query> queries, Query first) {
+ this.queries = queries;
+ this.first = first;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return first != null || (this.subEls != null && this.subEls.hasNext())
+ || (queryListIterator != null && queryListIterator.hasNext()) ||
+ queries.hasNext();
+ }
+
+ @Override
+ public IdPrefixQuery next() {
+ if (queryListIterator != null && queryListIterator.hasNext()) {
+ return queryListIterator.next();
+ }
+
+ Query q;
+ if (first != null) {
+ q = first;
+ preQuery = q.copy();
+ first = null;
+ } else {
+ if (this.subEls == null || !this.subEls.hasNext()) {
+ q = queries.next();
+ preQuery = q.copy();
+ } else {
+ q = preQuery.copy();
+ }
+ }
+
+ assert q instanceof ConditionQuery;
+ ConditionQuery cq = (ConditionQuery) q;
+ ConditionQuery originQuery = (ConditionQuery) q.copy();
+
+ List<IdPrefixQuery> queryList = Lists.newArrayList();
+ if (hugeGraph != null) {
+ for (ConditionQuery conditionQuery :
+ ConditionQueryFlatten.flatten(cq)) {
+ Id label = conditionQuery.condition(HugeKeys.LABEL);
+ /* Parent type + sortKeys: g.V("V.id").outE("parentLabel")
+ .has("sortKey","value") converted to all subtypes + sortKeys */
+ if ((this.subEls == null ||
+ !this.subEls.hasNext()) && label != null &&
+ hugeGraph.edgeLabel(label).isFather() &&
+ conditionQuery.condition(HugeKeys.SUB_LABEL) ==
+ null &&
+ conditionQuery.condition(HugeKeys.OWNER_VERTEX) !=
+ null &&
+ conditionQuery.condition(HugeKeys.DIRECTION) !=
+ null &&
+ matchEdgeSortKeys(conditionQuery, false,
+ hugeGraph)) {
+ this.subEls =
+ getSubLabelsOfParentEl(
+ hugeGraph.edgeLabels(),
+ label);
+ }
+
+ if (this.subEls != null &&
+ this.subEls.hasNext()) {
+ conditionQuery.eq(HugeKeys.SUB_LABEL,
+ subEls.next());
+ }
+
+ HugeType hugeType = conditionQuery.resultType();
+ if (hugeType != null && hugeType.isEdge() &&
+ !conditionQuery.conditions().isEmpty()) {
+ IdPrefixQuery idPrefixQuery =
+ (IdPrefixQuery) queryWriter.apply(
+ conditionQuery);
+ idPrefixQuery.setOriginQuery(originQuery);
+ queryList.add(idPrefixQuery);
+ }
+ }
+
+ queryListIterator = queryList.iterator();
+ if (queryListIterator.hasNext()) {
+ return queryListIterator.next();
+ }
+ }
+
+ Id ownerId = cq.condition(HugeKeys.OWNER_VERTEX);
+ assert ownerId != null;
+ BytesBuffer buffer =
+ BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID);
+ buffer.writeId(ownerId);
+ return new IdPrefixQuery(cq, new BinaryBackendEntry.BinaryId(
+ buffer.bytes(), ownerId));
+ }
+
+ private boolean matchEdgeSortKeys(ConditionQuery query,
+ boolean matchAll,
+ HugeGraph graph) {
+ assert query.resultType().isEdge();
+ Id label = query.condition(HugeKeys.LABEL);
+ if (label == null) {
+ return false;
+ }
+ List<Id> sortKeys = graph.edgeLabel(label).sortKeys();
+ if (sortKeys.isEmpty()) {
+ return false;
+ }
+ Set<Id> queryKeys = query.userpropKeys();
+ for (int i = sortKeys.size(); i > 0; i--) {
+ List<Id> subFields = sortKeys.subList(0, i);
+ if (queryKeys.containsAll(subFields)) {
+ if (queryKeys.size() == subFields.size() || !matchAll) {
+ /*
+ * Return true if:
+ * matchAll=true and all queryKeys are in sortKeys
+ * or
+ * partial queryKeys are in sortKeys
+ */
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+ Query first = queries.next();
+ List<HugeType> typeList = getHugeTypes(first);
+ QueryWrapper idPrefixQueries = new QueryWrapper(queries, first);
+
+ return query(typeList, idPrefixQueries);
+ }
+
+ private Iterator<Id> getSubLabelsOfParentEl(Collection<EdgeLabel> allEls,
+ Id label) {
+ List<Id> list = new ArrayList<>();
+ for (EdgeLabel el : allEls) {
+ if (el.edgeLabelType().sub() && el.fatherId().equals(label)) {
+ list.add(el.id());
+ }
+ }
+ return list.iterator();
+ }
public List<CIter<BackendEntry>> query(List<HugeType> typeList,
List<IdPrefixQuery> queries) {
(incubator-hugegraph) 02/02: Merge branch 'master' into father-sub-edge
Posted by vg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vgalaxies pushed a commit to branch father-sub-edge
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph.git
commit 16a2b65a9692c3e330fa917209e18a9c314ed668
Merge: 25010428c a529c0257
Author: VGalaxies <vg...@apache.org>
AuthorDate: Sun Sep 8 16:07:40 2024 +0800
Merge branch 'master' into father-sub-edge
.github/workflows/commons-ci.yml | 4 ++--
hugegraph-commons/pom.xml | 2 +-
.../hugegraph-dist/src/assembly/travis/run-api-test-for-raft.sh | 2 +-
hugegraph-server/hugegraph-dist/src/assembly/travis/run-api-test.sh | 2 +-
hugegraph-server/hugegraph-dist/src/assembly/travis/run-core-test.sh | 2 +-
.../hugegraph-dist/src/assembly/travis/run-tinkerpop-test.sh | 4 ++--
hugegraph-server/hugegraph-dist/src/assembly/travis/run-unit-test.sh | 2 +-
7 files changed, 9 insertions(+), 9 deletions(-)