forked from hugegraph/hugegraph
support bin serialization for cassandra (#680)
Change-Id: Ib4f48f3235ac9e5526c63c5617e3819ab4d29711
This commit is contained in:
parent
1208522699
commit
efcd839ee2
|
|
@ -19,11 +19,8 @@
|
|||
|
||||
package com.baidu.hugegraph.backend.store.cassandra;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.serializer.TableBackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
|
||||
public class CassandraBackendEntry extends TableBackendEntry {
|
||||
|
|
@ -43,41 +40,4 @@ public class CassandraBackendEntry extends TableBackendEntry {
|
|||
public CassandraBackendEntry(TableBackendEntry.Row row) {
|
||||
super(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("CassandraBackendEntry{%s, sub-rows: %s}",
|
||||
this.row().toString(),
|
||||
this.subRows().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int columnsSize() {
|
||||
throw new RuntimeException("Not supported by Cassandra");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BackendColumn> columns() {
|
||||
throw new RuntimeException("Not supported by Cassandra");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columns(Collection<BackendColumn> bytesColumns) {
|
||||
throw new RuntimeException("Not supported by Cassandra");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columns(BackendColumn... bytesColumns) {
|
||||
throw new RuntimeException("Not supported by Cassandra");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(BackendEntry other) {
|
||||
throw new RuntimeException("Not supported by Cassandra");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new RuntimeException("Not supported by Cassandra");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package com.baidu.hugegraph.backend.store.cassandra;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
|
@ -28,13 +29,17 @@ import java.util.Set;
|
|||
import com.baidu.hugegraph.backend.BackendException;
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.id.IdGenerator;
|
||||
import com.baidu.hugegraph.backend.id.IdUtil;
|
||||
import com.baidu.hugegraph.backend.serializer.BytesBuffer;
|
||||
import com.baidu.hugegraph.backend.serializer.TableBackendEntry;
|
||||
import com.baidu.hugegraph.backend.serializer.TableSerializer;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry;
|
||||
import com.baidu.hugegraph.schema.PropertyKey;
|
||||
import com.baidu.hugegraph.schema.SchemaElement;
|
||||
import com.baidu.hugegraph.structure.HugeElement;
|
||||
import com.baidu.hugegraph.structure.HugeProperty;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
import com.baidu.hugegraph.type.define.DataType;
|
||||
import com.baidu.hugegraph.type.define.HugeKeys;
|
||||
import com.baidu.hugegraph.util.InsertionOrderUtil;
|
||||
import com.baidu.hugegraph.util.JsonUtil;
|
||||
|
|
@ -62,7 +67,7 @@ public class CassandraSerializer extends TableSerializer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> parseIndexElemIds(TableBackendEntry entry) {
|
||||
protected Set<Object> parseIndexElemIds(TableBackendEntry entry) {
|
||||
return ImmutableSet.of(entry.column(HugeKeys.ELEMENT_IDS));
|
||||
}
|
||||
|
||||
|
|
@ -110,9 +115,7 @@ public class CassandraSerializer extends TableSerializer {
|
|||
} else {
|
||||
// Format properties
|
||||
for (HugeProperty<?> prop : element.getProperties().values()) {
|
||||
row.column(HugeKeys.PROPERTIES,
|
||||
prop.propertyKey().id().asLong(),
|
||||
JsonUtil.toJson(prop.value()));
|
||||
this.formatProperty(prop, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -120,13 +123,52 @@ public class CassandraSerializer extends TableSerializer {
|
|||
@Override
|
||||
protected void parseProperties(HugeElement element,
|
||||
TableBackendEntry.Row row) {
|
||||
Map<Number, String> props = row.column(HugeKeys.PROPERTIES);
|
||||
for (Map.Entry<Number, String> prop : props.entrySet()) {
|
||||
Id pkeyId = toId(prop.getKey());
|
||||
Map<Number, Object> props = row.column(HugeKeys.PROPERTIES);
|
||||
for (Map.Entry<Number, Object> prop : props.entrySet()) {
|
||||
Id pkeyId = this.toId(prop.getKey());
|
||||
this.parseProperty(pkeyId, prop.getValue(), element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object writeProperty(HugeProperty<?> property) {
|
||||
BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_PROPERTY);
|
||||
buffer.writeProperty(property.propertyKey(), property.value());
|
||||
buffer.flip();
|
||||
return buffer.asByteBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object writeProperty(Object value) {
|
||||
/*
|
||||
* Since we can't know the type of the property value in some scenarios,
|
||||
* so need to construct a fake property key to serialize to reuse code.
|
||||
*/
|
||||
PropertyKey pkey = new PropertyKey(null, IdGenerator.of(0L), "fake");
|
||||
pkey.dataType(DataType.fromClass(value.getClass()));
|
||||
BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_PROPERTY);
|
||||
buffer.writeProperty(pkey, value);
|
||||
buffer.flip();
|
||||
return buffer.asByteBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T readProperty(PropertyKey pkey, Object value) {
|
||||
BytesBuffer buffer = BytesBuffer.wrap((ByteBuffer) value);
|
||||
return (T) buffer.readProperty(pkey);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object writeId(Id id) {
|
||||
return IdUtil.writeBinString(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Id readId(Object id) {
|
||||
return IdUtil.readBinString(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeUserdata(SchemaElement schema,
|
||||
TableBackendEntry entry) {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ public class CassandraStoreProvider extends AbstractBackendStoreProvider {
|
|||
* also split range table to rangeInt, rangeFloat,
|
||||
* rangeLong and rangeDouble
|
||||
* [1.5] #633: support unique index
|
||||
* [1.6] #661 & #680: support bin serialization for cassandra
|
||||
*/
|
||||
return "1.5";
|
||||
return "1.6";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ public abstract class CassandraTable
|
|||
rs.extend(this.results2Entries(query, results));
|
||||
}
|
||||
} catch (DriverException e) {
|
||||
LOG.debug("Failed to query [{}], detail statement: {}",
|
||||
query, selections, e);
|
||||
throw new BackendException("Failed to query [%s]", e, query);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,12 +52,15 @@ public class CassandraTables {
|
|||
public static final String LABEL_INDEX = "label_index";
|
||||
public static final String NAME_INDEX = "name_index";
|
||||
|
||||
private static final DataType DATATYPE_PK = DataType.cint();
|
||||
private static final DataType DATATYPE_SL = DataType.cint(); // VL/EL
|
||||
private static final DataType DATATYPE_IL = DataType.cint();
|
||||
private static final DataType TYPE_PK = DataType.cint();
|
||||
private static final DataType TYPE_SL = DataType.cint(); // VL/EL
|
||||
private static final DataType TYPE_IL = DataType.cint();
|
||||
|
||||
private static final DataType DATATYPE_UD = DataType.map(DataType.text(),
|
||||
DataType.text());
|
||||
private static final DataType TYPE_UD = DataType.map(DataType.text(),
|
||||
DataType.text());
|
||||
|
||||
private static final DataType TYPE_ID = DataType.blob();
|
||||
private static final DataType TYPE_PROP = DataType.blob();
|
||||
|
||||
private static final int COMMIT_DELETE_BATCH = 1000;
|
||||
|
||||
|
|
@ -116,19 +119,19 @@ public class CassandraTables {
|
|||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.ID, DATATYPE_SL
|
||||
HugeKeys.ID, TYPE_SL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of();
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap
|
||||
.<HugeKeys, DataType>builder()
|
||||
.put(HugeKeys.NAME, DataType.text())
|
||||
.put(HugeKeys.ID_STRATEGY, DataType.tinyint())
|
||||
.put(HugeKeys.PRIMARY_KEYS, DataType.list(DATATYPE_PK))
|
||||
.put(HugeKeys.NULLABLE_KEYS, DataType.set(DATATYPE_PK))
|
||||
.put(HugeKeys.INDEX_LABELS, DataType.set(DATATYPE_IL))
|
||||
.put(HugeKeys.PROPERTIES, DataType.set(DATATYPE_PK))
|
||||
.put(HugeKeys.PRIMARY_KEYS, DataType.list(TYPE_PK))
|
||||
.put(HugeKeys.NULLABLE_KEYS, DataType.set(TYPE_PK))
|
||||
.put(HugeKeys.INDEX_LABELS, DataType.set(TYPE_IL))
|
||||
.put(HugeKeys.PROPERTIES, DataType.set(TYPE_PK))
|
||||
.put(HugeKeys.ENABLE_LABEL_INDEX, DataType.cboolean())
|
||||
.put(HugeKeys.USER_DATA, DATATYPE_UD)
|
||||
.put(HugeKeys.USER_DATA, TYPE_UD)
|
||||
.put(HugeKeys.STATUS, DataType.tinyint())
|
||||
.build();
|
||||
|
||||
|
|
@ -148,21 +151,21 @@ public class CassandraTables {
|
|||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.ID, DATATYPE_SL
|
||||
HugeKeys.ID, TYPE_SL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of();
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap
|
||||
.<HugeKeys, DataType>builder()
|
||||
.put(HugeKeys.NAME, DataType.text())
|
||||
.put(HugeKeys.FREQUENCY, DataType.tinyint())
|
||||
.put(HugeKeys.SOURCE_LABEL, DATATYPE_SL)
|
||||
.put(HugeKeys.TARGET_LABEL, DATATYPE_SL)
|
||||
.put(HugeKeys.SORT_KEYS, DataType.list(DATATYPE_PK))
|
||||
.put(HugeKeys.NULLABLE_KEYS, DataType.set(DATATYPE_PK))
|
||||
.put(HugeKeys.INDEX_LABELS, DataType.set(DATATYPE_IL))
|
||||
.put(HugeKeys.PROPERTIES, DataType.set(DATATYPE_PK))
|
||||
.put(HugeKeys.SOURCE_LABEL, TYPE_SL)
|
||||
.put(HugeKeys.TARGET_LABEL, TYPE_SL)
|
||||
.put(HugeKeys.SORT_KEYS, DataType.list(TYPE_PK))
|
||||
.put(HugeKeys.NULLABLE_KEYS, DataType.set(TYPE_PK))
|
||||
.put(HugeKeys.INDEX_LABELS, DataType.set(TYPE_IL))
|
||||
.put(HugeKeys.PROPERTIES, DataType.set(TYPE_PK))
|
||||
.put(HugeKeys.ENABLE_LABEL_INDEX, DataType.cboolean())
|
||||
.put(HugeKeys.USER_DATA, DATATYPE_UD)
|
||||
.put(HugeKeys.USER_DATA, TYPE_UD)
|
||||
.put(HugeKeys.STATUS, DataType.tinyint())
|
||||
.build();
|
||||
|
||||
|
|
@ -190,8 +193,8 @@ public class CassandraTables {
|
|||
.put(HugeKeys.NAME, DataType.text())
|
||||
.put(HugeKeys.DATA_TYPE, DataType.tinyint())
|
||||
.put(HugeKeys.CARDINALITY, DataType.tinyint())
|
||||
.put(HugeKeys.PROPERTIES, DataType.set(DATATYPE_PK))
|
||||
.put(HugeKeys.USER_DATA, DATATYPE_UD)
|
||||
.put(HugeKeys.PROPERTIES, DataType.set(TYPE_PK))
|
||||
.put(HugeKeys.USER_DATA, TYPE_UD)
|
||||
.put(HugeKeys.STATUS, DataType.tinyint())
|
||||
.build();
|
||||
|
||||
|
|
@ -211,16 +214,16 @@ public class CassandraTables {
|
|||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.ID, DATATYPE_IL
|
||||
HugeKeys.ID, TYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of();
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap
|
||||
.<HugeKeys, DataType>builder()
|
||||
.put(HugeKeys.NAME, DataType.text())
|
||||
.put(HugeKeys.BASE_TYPE, DataType.tinyint())
|
||||
.put(HugeKeys.BASE_VALUE, DATATYPE_SL)
|
||||
.put(HugeKeys.BASE_VALUE, TYPE_SL)
|
||||
.put(HugeKeys.INDEX_TYPE, DataType.tinyint())
|
||||
.put(HugeKeys.FIELDS, DataType.list(DATATYPE_PK))
|
||||
.put(HugeKeys.FIELDS, DataType.list(TYPE_PK))
|
||||
.put(HugeKeys.STATUS, DataType.tinyint())
|
||||
.build();
|
||||
|
||||
|
|
@ -240,13 +243,12 @@ public class CassandraTables {
|
|||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.ID, DataType.text()
|
||||
HugeKeys.ID, TYPE_ID
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of();
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of(
|
||||
HugeKeys.LABEL, DATATYPE_SL,
|
||||
HugeKeys.PROPERTIES, DataType.map(DATATYPE_PK,
|
||||
DataType.text())
|
||||
HugeKeys.LABEL, TYPE_SL,
|
||||
HugeKeys.PROPERTIES, DataType.map(TYPE_PK, TYPE_PROP)
|
||||
);
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
|
|
@ -304,17 +306,16 @@ public class CassandraTables {
|
|||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.OWNER_VERTEX, DataType.text()
|
||||
HugeKeys.OWNER_VERTEX, TYPE_ID
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.DIRECTION, DataType.tinyint(),
|
||||
HugeKeys.LABEL, DATATYPE_SL,
|
||||
HugeKeys.LABEL, TYPE_SL,
|
||||
HugeKeys.SORT_VALUES, DataType.text(),
|
||||
HugeKeys.OTHER_VERTEX, DataType.text()
|
||||
HugeKeys.OTHER_VERTEX, TYPE_ID
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of(
|
||||
HugeKeys.PROPERTIES, DataType.map(DATATYPE_PK,
|
||||
DataType.text())
|
||||
HugeKeys.PROPERTIES, DataType.map(TYPE_PK, TYPE_PROP)
|
||||
);
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
|
|
@ -341,7 +342,9 @@ public class CassandraTables {
|
|||
@Override
|
||||
protected List<Object> idColumnValue(Id id) {
|
||||
EdgeId edgeId;
|
||||
if (!(id instanceof EdgeId)) {
|
||||
if (id instanceof EdgeId) {
|
||||
edgeId = (EdgeId) id;
|
||||
} else {
|
||||
String[] idParts = EdgeId.split(id);
|
||||
if (idParts.length == 1) {
|
||||
// Delete edge by label
|
||||
|
|
@ -349,8 +352,6 @@ public class CassandraTables {
|
|||
}
|
||||
id = IdUtil.readString(id.asString());
|
||||
edgeId = EdgeId.parse(id.asString());
|
||||
} else {
|
||||
edgeId = (EdgeId) id;
|
||||
}
|
||||
|
||||
E.checkState(edgeId.direction() == this.direction,
|
||||
|
|
@ -361,12 +362,13 @@ public class CassandraTables {
|
|||
}
|
||||
|
||||
protected final List<Object> idColumnValue(EdgeId edgeId) {
|
||||
// TODO: move to Serializer
|
||||
List<Object> list = new ArrayList<>(5);
|
||||
list.add(IdUtil.writeStoredString(edgeId.ownerVertexId()));
|
||||
list.add(edgeId.direction().code());
|
||||
list.add(IdUtil.writeBinString(edgeId.ownerVertexId()));
|
||||
list.add(edgeId.directionCode());
|
||||
list.add(edgeId.edgeLabelId().asLong());
|
||||
list.add(edgeId.sortValues());
|
||||
list.add(IdUtil.writeStoredString(edgeId.otherVertexId()));
|
||||
list.add(IdUtil.writeBinString(edgeId.otherVertexId()));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -417,11 +419,11 @@ public class CassandraTables {
|
|||
for (Iterator<Row> it = rs.iterator(); it.hasNext();) {
|
||||
Row row = it.next();
|
||||
// Delete OUT edges from edges_out table
|
||||
String ownerVertex = row.get(OWNER_VERTEX, String.class);
|
||||
Object ownerVertex = row.getObject(OWNER_VERTEX);
|
||||
session.add(buildDelete(label, ownerVertex, Directions.OUT));
|
||||
|
||||
// Delete IN edges from edges_in table
|
||||
String otherVertex = row.get(OTHER_VERTEX, String.class);
|
||||
Object otherVertex = row.getObject(OTHER_VERTEX);
|
||||
session.add(buildDelete(label, otherVertex, Directions.IN));
|
||||
|
||||
count += 2;
|
||||
|
|
@ -432,11 +434,12 @@ public class CassandraTables {
|
|||
}
|
||||
}
|
||||
|
||||
private Delete buildDelete(Id label, String ownerVertex,
|
||||
private Delete buildDelete(Id label, Object ownerVertex,
|
||||
Directions direction) {
|
||||
Delete delete = QueryBuilder.delete().from(edgesTable(direction));
|
||||
delete.where(formatEQ(HugeKeys.OWNER_VERTEX, ownerVertex));
|
||||
delete.where(formatEQ(HugeKeys.DIRECTION, direction.code()));
|
||||
delete.where(formatEQ(HugeKeys.DIRECTION,
|
||||
EdgeId.directionToCode(direction)));
|
||||
delete.where(formatEQ(HugeKeys.LABEL, label.asLong()));
|
||||
return delete;
|
||||
}
|
||||
|
|
@ -455,9 +458,8 @@ public class CassandraTables {
|
|||
"The next entry must be EDGE");
|
||||
|
||||
if (current != null) {
|
||||
Id nextVertexId = IdGenerator.of(
|
||||
next.<String>column(HugeKeys.OWNER_VERTEX));
|
||||
if (current.id().equals(nextVertexId)) {
|
||||
Object nextVertexId = next.column(HugeKeys.OWNER_VERTEX);
|
||||
if (current.id().equals(IdGenerator.of(nextVertexId))) {
|
||||
current.subRow(next.row());
|
||||
return current;
|
||||
}
|
||||
|
|
@ -468,7 +470,7 @@ public class CassandraTables {
|
|||
|
||||
private CassandraBackendEntry wrapByVertex(CassandraBackendEntry edge) {
|
||||
assert edge.type().isEdge();
|
||||
String ownerVertex = edge.column(HugeKeys.OWNER_VERTEX);
|
||||
Object ownerVertex = edge.column(HugeKeys.OWNER_VERTEX);
|
||||
E.checkState(ownerVertex != null, "Invalid backend entry");
|
||||
Id vertexId = IdGenerator.of(ownerVertex);
|
||||
CassandraBackendEntry vertex = new CassandraBackendEntry(
|
||||
|
|
@ -513,8 +515,8 @@ public class CassandraTables {
|
|||
HugeKeys.FIELD_VALUES, DataType.text()
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL,
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
HugeKeys.INDEX_LABEL_ID, TYPE_IL,
|
||||
HugeKeys.ELEMENT_IDS, TYPE_ID
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
|
|
@ -643,17 +645,21 @@ public class CassandraTables {
|
|||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL
|
||||
HugeKeys.INDEX_LABEL_ID, TYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.FIELD_VALUES, DataType.decimal(),
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
HugeKeys.FIELD_VALUES, this.fieldValuesType(),
|
||||
HugeKeys.ELEMENT_IDS, TYPE_ID
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
}
|
||||
|
||||
protected DataType fieldValuesType() {
|
||||
return DataType.decimal();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<HugeKeys> idColumnName() {
|
||||
return ImmutableList.of(HugeKeys.INDEX_LABEL_ID,
|
||||
|
|
@ -717,17 +723,8 @@ public class CassandraTables {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.FIELD_VALUES, DataType.cint(),
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
protected DataType fieldValuesType() {
|
||||
return DataType.cint();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -740,17 +737,8 @@ public class CassandraTables {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.FIELD_VALUES, DataType.cfloat(),
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
protected DataType fieldValuesType() {
|
||||
return DataType.cfloat();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -763,17 +751,9 @@ public class CassandraTables {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.FIELD_VALUES, DataType.bigint(),
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
protected DataType fieldValuesType() {
|
||||
// TODO: DataType.varint()
|
||||
return DataType.bigint();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -786,17 +766,8 @@ public class CassandraTables {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.FIELD_VALUES, DataType.cdouble(),
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
protected DataType fieldValuesType() {
|
||||
return DataType.cdouble();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -809,17 +780,8 @@ public class CassandraTables {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init(CassandraSessionPool.Session session) {
|
||||
ImmutableMap<HugeKeys, DataType> pkeys = ImmutableMap.of(
|
||||
HugeKeys.INDEX_LABEL_ID, DATATYPE_IL
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> ckeys = ImmutableMap.of(
|
||||
HugeKeys.FIELD_VALUES, DataType.text(),
|
||||
HugeKeys.ELEMENT_IDS, DataType.text()
|
||||
);
|
||||
ImmutableMap<HugeKeys, DataType> columns = ImmutableMap.of();
|
||||
|
||||
this.createTable(session, pkeys, ckeys, columns);
|
||||
protected DataType fieldValuesType() {
|
||||
return DataType.text();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@ public class EdgeId implements Id {
|
|||
return this.direction;
|
||||
}
|
||||
|
||||
public byte directionCode() {
|
||||
return directionToCode(this.direction);
|
||||
}
|
||||
|
||||
public String sortValues() {
|
||||
return this.sortValues;
|
||||
}
|
||||
|
|
@ -190,6 +194,14 @@ public class EdgeId implements Id {
|
|||
return this.asString();
|
||||
}
|
||||
|
||||
public static byte directionToCode(Directions direction) {
|
||||
return direction.type().code();
|
||||
}
|
||||
|
||||
public static Directions directionFromCode(byte code) {
|
||||
return Directions.convert(HugeType.fromCode(code));
|
||||
}
|
||||
|
||||
public static EdgeId parse(String id) throws NotFoundException {
|
||||
String[] idParts = split(id);
|
||||
if (!(idParts.length == 4 || idParts.length == 5)) {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ public interface Id extends Comparable<Id> {
|
|||
return this.type() == IdType.STRING;
|
||||
}
|
||||
|
||||
public default boolean edge() {
|
||||
return this.type() == IdType.EDGE;
|
||||
}
|
||||
|
||||
public enum IdType {
|
||||
|
||||
UNKNOWN,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
package com.baidu.hugegraph.backend.id;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id.IdType;
|
||||
|
|
@ -51,6 +52,19 @@ public abstract class IdGenerator {
|
|||
return new LongId(id);
|
||||
}
|
||||
|
||||
public static Id of(Object id) {
|
||||
if (id instanceof Id) {
|
||||
return (Id) id;
|
||||
} else if (id instanceof String) {
|
||||
return of((String) id);
|
||||
} else if (id instanceof Number) {
|
||||
return of(((Number) id).longValue());
|
||||
} else if (id instanceof UUID) {
|
||||
return of((UUID) id);
|
||||
}
|
||||
return new ObjectId(id);
|
||||
}
|
||||
|
||||
public final static Id of(byte[] bytes, IdType type) {
|
||||
switch (type) {
|
||||
case LONG:
|
||||
|
|
@ -91,24 +105,6 @@ public abstract class IdGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a string id
|
||||
* @param id original string id value
|
||||
* @return wrapped id object
|
||||
*/
|
||||
public final Id generate(String id) {
|
||||
return of(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a long id
|
||||
* @param id original long id value
|
||||
* @return wrapped id object
|
||||
*/
|
||||
public final Id generate(long id) {
|
||||
return of(id);
|
||||
}
|
||||
|
||||
/****************************** id defines ******************************/
|
||||
|
||||
public static final class StringId implements Id {
|
||||
|
|
@ -364,4 +360,70 @@ public abstract class IdGenerator {
|
|||
return this.uuid.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is just used by backend store for wrapper object as Id
|
||||
*/
|
||||
private static final class ObjectId implements Id {
|
||||
|
||||
private final Object object;
|
||||
|
||||
public ObjectId(Object object) {
|
||||
E.checkNotNull(object, "object");
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdType type() {
|
||||
return IdType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asObject() {
|
||||
return this.object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] asBytes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Id o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.object.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ObjectId)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.object, ((ObjectId) other).object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.object.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@
|
|||
|
||||
package com.baidu.hugegraph.backend.id;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id.IdType;
|
||||
import com.baidu.hugegraph.backend.serializer.BytesBuffer;
|
||||
|
||||
public final class IdUtil {
|
||||
|
||||
|
|
@ -44,36 +47,48 @@ public final class IdUtil {
|
|||
|
||||
public static Id readStoredString(String id) {
|
||||
IdType type = IdType.valueOfPrefix(id);
|
||||
id = id.substring(1);
|
||||
String idContent = id.substring(1);
|
||||
switch (type) {
|
||||
case LONG:
|
||||
case STRING:
|
||||
case UUID:
|
||||
return IdGenerator.ofStoredString(id, type);
|
||||
return IdGenerator.ofStoredString(idContent, type);
|
||||
case EDGE:
|
||||
return EdgeId.parseStoredString(id);
|
||||
return EdgeId.parseStoredString(idContent);
|
||||
default:
|
||||
throw new AssertionError("Invalid id type " + type);
|
||||
throw new IllegalArgumentException("Invalid id: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object writeBinString(Id id) {
|
||||
int len = id.edge() ? BytesBuffer.BUF_EDGE_ID : id.length() + 1;
|
||||
BytesBuffer buffer = BytesBuffer.allocate(len).writeId(id);
|
||||
buffer.flip();
|
||||
return buffer.asByteBuffer();
|
||||
}
|
||||
|
||||
public static Id readBinString(Object id) {
|
||||
BytesBuffer buffer = BytesBuffer.wrap((ByteBuffer) id);
|
||||
return buffer.readId();
|
||||
}
|
||||
|
||||
public static String writeString(Id id) {
|
||||
return "" + id.type().prefix() + id.asObject();
|
||||
}
|
||||
|
||||
public static Id readString(String id) {
|
||||
IdType type = IdType.valueOfPrefix(id);
|
||||
id = id.substring(1);
|
||||
String idContent = id.substring(1);
|
||||
switch (type) {
|
||||
case LONG:
|
||||
return IdGenerator.of(Long.parseLong(id));
|
||||
return IdGenerator.of(Long.parseLong(idContent));
|
||||
case STRING:
|
||||
case UUID:
|
||||
return IdGenerator.of(id, type == IdType.UUID);
|
||||
return IdGenerator.of(idContent, type == IdType.UUID);
|
||||
case EDGE:
|
||||
return EdgeId.parse(id);
|
||||
return EdgeId.parse(idContent);
|
||||
default:
|
||||
throw new AssertionError("Invalid id type " + type);
|
||||
throw new IllegalArgumentException("Invalid id: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public class SnowflakeIdGenerator extends IdGenerator {
|
|||
if (this.idWorker == null) {
|
||||
throw new HugeException("Please initialize before using");
|
||||
}
|
||||
Id id = this.generate(this.idWorker.nextId());
|
||||
Id id = of(this.idWorker.nextId());
|
||||
if (!this.forceString) {
|
||||
return id;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public class BinaryBackendEntry implements BackendEntry {
|
|||
if (this.columns.size() > 1) {
|
||||
Collections.sort(this.columns);
|
||||
}
|
||||
return Collections.unmodifiableCollection(this.columns);
|
||||
return Collections.unmodifiableList(this.columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -180,7 +180,7 @@ public class BinaryBackendEntry implements BackendEntry {
|
|||
|
||||
@Override
|
||||
public Object asObject() {
|
||||
return this.asBytes();
|
||||
return ByteBuffer.wrap(this.bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ package com.baidu.hugegraph.backend.serializer;
|
|||
import org.apache.commons.lang.NotImplementedException;
|
||||
|
||||
import com.baidu.hugegraph.HugeGraph;
|
||||
import com.baidu.hugegraph.backend.id.EdgeId;
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry.BackendColumn;
|
||||
import com.baidu.hugegraph.schema.VertexLabel;
|
||||
import com.baidu.hugegraph.structure.HugeVertex;
|
||||
import com.baidu.hugegraph.structure.HugeVertexProperty;
|
||||
import com.baidu.hugegraph.util.Bytes;
|
||||
|
||||
public class BinaryInlineSerializer extends BinarySerializer {
|
||||
|
||||
|
|
@ -67,17 +67,18 @@ public class BinaryInlineSerializer extends BinarySerializer {
|
|||
|
||||
// Parse id
|
||||
Id id = entry.id().origin();
|
||||
HugeVertex vertex = new HugeVertex(graph, id, VertexLabel.NONE);
|
||||
Id vid = id.edge() ? ((EdgeId) id).ownerVertexId() : id;
|
||||
HugeVertex vertex = new HugeVertex(graph, vid, VertexLabel.NONE);
|
||||
|
||||
// Parse all properties and edges of a Vertex
|
||||
for (BackendColumn col : entry.columns()) {
|
||||
if (Bytes.equals(entry.id().asBytes(), col.name)) {
|
||||
if (id.edge()) {
|
||||
// Parse vertex edges
|
||||
this.parseColumn(col, vertex);
|
||||
} else {
|
||||
// Parse vertex properties
|
||||
assert entry.columnsSize() == 1 : entry.columnsSize();
|
||||
this.parseVertex(col.value, vertex);
|
||||
} else {
|
||||
// Parse vertex edges
|
||||
this.parseColumn(col, vertex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import com.baidu.hugegraph.backend.BackendException;
|
|||
import com.baidu.hugegraph.backend.id.EdgeId;
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.id.IdGenerator;
|
||||
import com.baidu.hugegraph.backend.id.IdUtil;
|
||||
import com.baidu.hugegraph.backend.page.PageState;
|
||||
import com.baidu.hugegraph.backend.query.Condition;
|
||||
import com.baidu.hugegraph.backend.query.Condition.RangeConditions;
|
||||
|
|
@ -162,7 +161,7 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
}
|
||||
|
||||
protected BackendColumn formatProperty(HugeProperty<?> prop) {
|
||||
BytesBuffer buffer = BytesBuffer.allocate(64);
|
||||
BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_PROPERTY);
|
||||
buffer.writeProperty(prop.propertyKey(), prop.value());
|
||||
return BackendColumn.of(this.formatPropertyName(prop), buffer.bytes());
|
||||
}
|
||||
|
|
@ -212,16 +211,8 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
|
||||
protected byte[] formatEdgeName(HugeEdge edge) {
|
||||
// owner-vertex + dir + edge-label + sort-values + other-vertex
|
||||
|
||||
BytesBuffer buffer = BytesBuffer.allocate(256);
|
||||
|
||||
buffer.writeId(edge.ownerVertex().id());
|
||||
buffer.write(edge.type().code());
|
||||
buffer.writeId(edge.schemaLabel().id());
|
||||
buffer.writeStringWithEnding(edge.name());
|
||||
buffer.writeId(edge.otherVertex().id());
|
||||
|
||||
return buffer.bytes();
|
||||
return BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID)
|
||||
.writeEdgeId(edge.id()).bytes();
|
||||
}
|
||||
|
||||
protected byte[] formatEdgeValue(HugeEdge edge) {
|
||||
|
|
@ -340,13 +331,13 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
if (!type.isNumericIndex() && indexIdLengthExceedLimit(indexId)) {
|
||||
indexId = index.hashId();
|
||||
}
|
||||
String elemId = IdUtil.writeStoredString(index.elementId());
|
||||
Id elemId = index.elementId();
|
||||
int idLen = 1 + elemId.length() + 1 + indexId.length();
|
||||
buffer = BytesBuffer.allocate(idLen);
|
||||
// Write index-id
|
||||
buffer.writeIndexId(indexId, type);
|
||||
// Write element-id
|
||||
buffer.writeString(elemId);
|
||||
buffer.writeId(elemId);
|
||||
}
|
||||
|
||||
return buffer.bytes();
|
||||
|
|
@ -363,8 +354,7 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
if (this.indexWithIdPrefix) {
|
||||
buffer.readIndexId(index.type());
|
||||
}
|
||||
String elemId = buffer.readString();
|
||||
index.elementIds(IdUtil.readStoredString(elemId));
|
||||
index.elementIds(buffer.readId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +426,7 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public HugeEdge readEdge(HugeGraph graph, BackendEntry entry) {
|
||||
public HugeEdge readEdge(HugeGraph graph, BackendEntry bytesEntry) {
|
||||
throw new NotImplementedException("Unsupported readEdge()");
|
||||
}
|
||||
|
||||
|
|
@ -568,7 +558,7 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
|
||||
private Query writeQueryEdgePrefixCondition(ConditionQuery cq) {
|
||||
int count = 0;
|
||||
BytesBuffer buffer = BytesBuffer.allocate(64);
|
||||
BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID);
|
||||
for (HugeKeys key : EdgeId.KEYS) {
|
||||
Object value = cq.condition(key);
|
||||
|
||||
|
|
@ -737,13 +727,8 @@ public class BinarySerializer extends AbstractSerializer {
|
|||
} else {
|
||||
edgeId = EdgeId.parse(id.asString());
|
||||
}
|
||||
BytesBuffer buffer = BytesBuffer.allocate(256);
|
||||
buffer.writeId(edgeId.ownerVertexId());
|
||||
buffer.write(edgeId.direction().type().code());
|
||||
buffer.writeId(edgeId.edgeLabelId());
|
||||
buffer.writeStringWithEnding(edgeId.sortValues());
|
||||
buffer.writeId(edgeId.otherVertexId());
|
||||
|
||||
BytesBuffer buffer = BytesBuffer.allocate(BytesBuffer.BUF_EDGE_ID)
|
||||
.writeEdgeId(edgeId);
|
||||
return new BinaryId(buffer.bytes(), id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.Collection;
|
|||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.EdgeId;
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.id.Id.IdType;
|
||||
import com.baidu.hugegraph.backend.id.IdGenerator;
|
||||
|
|
@ -68,6 +69,9 @@ public final class BytesBuffer {
|
|||
public static final int DEFAULT_CAPACITY = 64;
|
||||
public static final int MAX_BUFFER_CAPACITY = 128 * 1024 * 1024; // 128M
|
||||
|
||||
public static final int BUF_EDGE_ID = 128;
|
||||
public static final int BUF_PROPERTY = 64;
|
||||
|
||||
private ByteBuffer buffer;
|
||||
|
||||
public BytesBuffer() {
|
||||
|
|
@ -90,6 +94,10 @@ public final class BytesBuffer {
|
|||
return new BytesBuffer(capacity);
|
||||
}
|
||||
|
||||
public static BytesBuffer wrap(ByteBuffer buffer) {
|
||||
return new BytesBuffer(buffer);
|
||||
}
|
||||
|
||||
public static BytesBuffer wrap(byte[] array) {
|
||||
return new BytesBuffer(ByteBuffer.wrap(array));
|
||||
}
|
||||
|
|
@ -500,38 +508,47 @@ public final class BytesBuffer {
|
|||
}
|
||||
|
||||
public BytesBuffer writeId(Id id, boolean big) {
|
||||
if (id.number()) {
|
||||
// Number Id
|
||||
long value = id.asLong();
|
||||
this.writeNumber(value);
|
||||
} else if (id.uuid()) {
|
||||
// UUID Id
|
||||
byte[] bytes = id.asBytes();
|
||||
assert bytes.length == Id.UUID_LENGTH;
|
||||
this.writeUInt8(0x7f); // 0b01111111 means UUID
|
||||
this.write(bytes);
|
||||
} else {
|
||||
// String Id
|
||||
byte[] bytes = id.asBytes();
|
||||
int len = bytes.length;
|
||||
E.checkArgument(len > 0, "Can't write empty id");
|
||||
if (!big) {
|
||||
E.checkArgument(len <= ID_LEN_MAX,
|
||||
"Id max length is %s, but got %s {%s}",
|
||||
ID_LEN_MAX, len, id);
|
||||
len -= 1; // mapping [1, 128] to [0, 127]
|
||||
this.writeUInt8(len | 0x80);
|
||||
} else {
|
||||
E.checkArgument(len <= BIG_ID_LEN_MAX,
|
||||
"Big id max length is %s, but got %s {%s}",
|
||||
BIG_ID_LEN_MAX, len, id);
|
||||
len -= 1;
|
||||
int high = len >> 8;
|
||||
int low = len & 0xff;
|
||||
this.writeUInt8(high | 0x80);
|
||||
this.writeUInt8(low);
|
||||
}
|
||||
this.write(bytes);
|
||||
switch (id.type()) {
|
||||
case LONG:
|
||||
// Number Id
|
||||
long value = id.asLong();
|
||||
this.writeNumber(value);
|
||||
break;
|
||||
case UUID:
|
||||
// UUID Id
|
||||
byte[] bytes = id.asBytes();
|
||||
assert bytes.length == Id.UUID_LENGTH;
|
||||
this.writeUInt8(0x7f); // 0b01111111 means UUID
|
||||
this.write(bytes);
|
||||
break;
|
||||
case EDGE:
|
||||
// Edge Id
|
||||
this.writeUInt8(0x7e); // 0b01111110 means EdgeId
|
||||
this.writeEdgeId(id);
|
||||
break;
|
||||
default:
|
||||
// String Id
|
||||
bytes = id.asBytes();
|
||||
int len = bytes.length;
|
||||
E.checkArgument(len > 0, "Can't write empty id");
|
||||
if (!big) {
|
||||
E.checkArgument(len <= ID_LEN_MAX,
|
||||
"Id max length is %s, but got %s {%s}",
|
||||
ID_LEN_MAX, len, id);
|
||||
len -= 1; // mapping [1, 128] to [0, 127]
|
||||
this.writeUInt8(len | 0x80);
|
||||
} else {
|
||||
E.checkArgument(len <= BIG_ID_LEN_MAX,
|
||||
"Big id max length is %s, but got %s {%s}",
|
||||
BIG_ID_LEN_MAX, len, id);
|
||||
len -= 1;
|
||||
int high = len >> 8;
|
||||
int low = len & 0xff;
|
||||
this.writeUInt8(high | 0x80);
|
||||
this.writeUInt8(low);
|
||||
}
|
||||
this.write(bytes);
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
@ -544,12 +561,16 @@ public final class BytesBuffer {
|
|||
byte b = this.read();
|
||||
boolean number = (b & 0x80) == 0;
|
||||
if (number) {
|
||||
// UUID Id
|
||||
if (b == 0x7f) {
|
||||
// UUID Id
|
||||
return IdGenerator.of(this.read(Id.UUID_LENGTH), IdType.UUID);
|
||||
} else if (b == 0x7e) {
|
||||
// Edge Id
|
||||
return this.readEdgeId();
|
||||
} else {
|
||||
// Number Id
|
||||
return IdGenerator.of(this.readNumber(b));
|
||||
}
|
||||
// Number Id
|
||||
return IdGenerator.of(this.readNumber(b));
|
||||
} else {
|
||||
// String Id
|
||||
int len = b & ID_LEN_MASK;
|
||||
|
|
@ -564,6 +585,22 @@ public final class BytesBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
public BytesBuffer writeEdgeId(Id id) {
|
||||
EdgeId edge = (EdgeId) id;
|
||||
this.writeId(edge.ownerVertexId());
|
||||
this.write(edge.directionCode());
|
||||
this.writeId(edge.edgeLabelId());
|
||||
this.writeStringWithEnding(edge.sortValues());
|
||||
this.writeId(edge.otherVertexId());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Id readEdgeId() {
|
||||
return new EdgeId(this.readId(), EdgeId.directionFromCode(this.read()),
|
||||
this.readId(), this.readStringWithEnding(),
|
||||
this.readId());
|
||||
}
|
||||
|
||||
public BytesBuffer writeIndexId(Id id, HugeType type) {
|
||||
return this.writeIndexId(id, type, true);
|
||||
}
|
||||
|
|
@ -642,6 +679,7 @@ public final class BytesBuffer {
|
|||
* 0b 0111 0000 X X X X X X X X [-2^64, -1]
|
||||
*
|
||||
* NOTE: 0b 0111 1111 is used by 128 bits UUID
|
||||
* 0b 0111 1110 is used by EdgeId
|
||||
*/
|
||||
int positive = val >= 0 ? 0x08 : 0x00;
|
||||
if (~0x7ffL <= val && val <= 0x7ffL) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class SerializerFactory {
|
|||
|
||||
Class<? extends AbstractSerializer> clazz = serializers.get(name);
|
||||
if (clazz == null) {
|
||||
throw new BackendException("Not exists serializer: %s", name);
|
||||
throw new BackendException("Not exists serializer: '%s'", name);
|
||||
}
|
||||
|
||||
assert AbstractSerializer.class.isAssignableFrom(clazz);
|
||||
|
|
@ -62,13 +62,13 @@ public class SerializerFactory {
|
|||
try {
|
||||
clazz = classLoader.loadClass(classPath);
|
||||
} catch (Exception e) {
|
||||
throw new BackendException(e);
|
||||
throw new BackendException("Invalid class: '%s'", e, classPath);
|
||||
}
|
||||
|
||||
// Check subclass
|
||||
if (!AbstractSerializer.class.isAssignableFrom(clazz)) {
|
||||
throw new BackendException("Class '%s' is not a subclass of " +
|
||||
"class AbstractSerializer", classPath);
|
||||
throw new BackendException("Class is not a subclass of class " +
|
||||
"AbstractSerializer: '%s'", classPath);
|
||||
}
|
||||
|
||||
// Check exists
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
|
|
@ -82,11 +84,17 @@ public class TableBackendEntry implements BackendEntry {
|
|||
this.column(key, value);
|
||||
break;
|
||||
case SET:
|
||||
this.columns.putIfAbsent(key, new LinkedHashSet<>());
|
||||
// Avoid creating new Set when the key exists
|
||||
if (!this.columns.containsKey(key)) {
|
||||
this.columns.putIfAbsent(key, new LinkedHashSet<>());
|
||||
}
|
||||
this.<Set<T>>column(key).add(value);
|
||||
break;
|
||||
case LIST:
|
||||
this.columns.putIfAbsent(key, new LinkedList<>());
|
||||
// Avoid creating new List when the key exists
|
||||
if (!this.columns.containsKey(key)) {
|
||||
this.columns.putIfAbsent(key, new LinkedList<>());
|
||||
}
|
||||
this.<List<T>>column(key).add(value);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -95,7 +103,9 @@ public class TableBackendEntry implements BackendEntry {
|
|||
}
|
||||
|
||||
public <T> void column(HugeKeys key, Object name, T value) {
|
||||
this.columns.putIfAbsent(key, new ConcurrentHashMap<>());
|
||||
if (!this.columns.containsKey(key)) {
|
||||
this.columns.putIfAbsent(key, new ConcurrentHashMap<>());
|
||||
}
|
||||
this.<Map<Object, T>>column(key).put(name, value);
|
||||
}
|
||||
|
||||
|
|
@ -206,31 +216,31 @@ public class TableBackendEntry implements BackendEntry {
|
|||
|
||||
@Override
|
||||
public int columnsSize() {
|
||||
throw new RuntimeException("Not supported by table backend");
|
||||
throw new NotImplementedException("Not supported by table backend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BackendEntry.BackendColumn> columns() {
|
||||
throw new RuntimeException("Not supported by table backend");
|
||||
throw new NotImplementedException("Not supported by table backend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columns(Collection<BackendEntry.BackendColumn> bytesColumns) {
|
||||
throw new RuntimeException("Not supported by table backend");
|
||||
throw new NotImplementedException("Not supported by table backend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columns(BackendEntry.BackendColumn... bytesColumns) {
|
||||
throw new RuntimeException("Not supported by table backend");
|
||||
throw new NotImplementedException("Not supported by table backend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(BackendEntry other) {
|
||||
throw new RuntimeException("Not supported by table backend");
|
||||
throw new NotImplementedException("Not supported by table backend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new RuntimeException("Not supported by table backend");
|
||||
throw new NotImplementedException("Not supported by table backend");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,18 +84,18 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
@Override
|
||||
protected abstract TableBackendEntry convertEntry(BackendEntry backendEntry);
|
||||
|
||||
protected void formatProperty(HugeProperty<?> prop,
|
||||
protected void formatProperty(HugeProperty<?> property,
|
||||
TableBackendEntry.Row row) {
|
||||
long pkid = prop.propertyKey().id().asLong();
|
||||
row.column(HugeKeys.PROPERTIES, pkid, JsonUtil.toJson(prop.value()));
|
||||
long pkid = property.propertyKey().id().asLong();
|
||||
row.column(HugeKeys.PROPERTIES, pkid, this.writeProperty(property));
|
||||
}
|
||||
|
||||
protected void parseProperty(Id key, String colValue, HugeElement owner) {
|
||||
// Get PropertyKey by PropertyKey name
|
||||
protected void parseProperty(Id key, Object colValue, HugeElement owner) {
|
||||
// Get PropertyKey by PropertyKey id
|
||||
PropertyKey pkey = owner.graph().propertyKey(key);
|
||||
|
||||
// Parse value
|
||||
Object value = JsonUtil.fromJson(colValue, pkey.implementClazz());
|
||||
Object value = this.readProperty(pkey, colValue);
|
||||
|
||||
// Set properties of vertex/edge
|
||||
if (pkey.cardinality() == Cardinality.SINGLE) {
|
||||
|
|
@ -103,27 +103,44 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
} else {
|
||||
if (!(value instanceof Collection)) {
|
||||
throw new BackendException(
|
||||
"Invalid value of non-single property: %s",
|
||||
value);
|
||||
}
|
||||
for (Object v : (Collection<?>) value) {
|
||||
v = JsonUtil.castNumber(v, pkey.dataType().clazz());
|
||||
owner.addProperty(pkey, v);
|
||||
"Invalid value of non-single property: %s", value);
|
||||
}
|
||||
owner.addProperty(pkey, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object writeProperty(HugeProperty<?> property) {
|
||||
return this.writeProperty(property.value());
|
||||
}
|
||||
|
||||
protected Object writeProperty(Object value) {
|
||||
return JsonUtil.toJson(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T readProperty(PropertyKey pkey, Object value) {
|
||||
Class<T> clazz = (Class<T>) pkey.implementClazz();
|
||||
T result = JsonUtil.fromJson(value.toString(), clazz);
|
||||
if (pkey.cardinality() != Cardinality.SINGLE) {
|
||||
Collection<?> values = (Collection<?>) result;
|
||||
List<Object> newValues = new ArrayList<>(values.size());
|
||||
for (Object v : values) {
|
||||
newValues.add(JsonUtil.castNumber(v, pkey.dataType().clazz()));
|
||||
}
|
||||
result = (T) newValues;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected TableBackendEntry.Row formatEdge(HugeEdge edge) {
|
||||
EdgeId id = edge.idWithDirection();
|
||||
TableBackendEntry.Row row = new TableBackendEntry.Row(edge.type(), id);
|
||||
// Id: ownerVertex + direction + edge-label + sortValues + otherVertex
|
||||
row.column(HugeKeys.OWNER_VERTEX,
|
||||
IdUtil.writeStoredString(id.ownerVertexId()));
|
||||
row.column(HugeKeys.DIRECTION, id.direction().code());
|
||||
row.column(HugeKeys.OWNER_VERTEX, this.writeId(id.ownerVertexId()));
|
||||
row.column(HugeKeys.DIRECTION, id.directionCode());
|
||||
row.column(HugeKeys.LABEL, id.edgeLabelId().asLong());
|
||||
row.column(HugeKeys.SORT_VALUES, id.sortValues());
|
||||
row.column(HugeKeys.OTHER_VERTEX,
|
||||
IdUtil.writeStoredString(id.otherVertexId()));
|
||||
row.column(HugeKeys.OTHER_VERTEX, this.writeId(id.otherVertexId()));
|
||||
|
||||
this.formatProperties(edge, row);
|
||||
return row;
|
||||
|
|
@ -138,16 +155,15 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
*/
|
||||
protected HugeEdge parseEdge(TableBackendEntry.Row row,
|
||||
HugeVertex vertex, HugeGraph graph) {
|
||||
String ownerVertexId = row.column(HugeKeys.OWNER_VERTEX);
|
||||
Object ownerVertexId = row.column(HugeKeys.OWNER_VERTEX);
|
||||
Number dir = row.column(HugeKeys.DIRECTION);
|
||||
Directions direction = SerialEnum.fromCode(Directions.class,
|
||||
dir.byteValue());
|
||||
Directions direction = EdgeId.directionFromCode(dir.byteValue());
|
||||
Number label = row.column(HugeKeys.LABEL);
|
||||
String sortValues = row.column(HugeKeys.SORT_VALUES);
|
||||
String otherVertexId = row.column(HugeKeys.OTHER_VERTEX);
|
||||
Object otherVertexId = row.column(HugeKeys.OTHER_VERTEX);
|
||||
|
||||
if (vertex == null) {
|
||||
Id ownerId = IdUtil.readStoredString(ownerVertexId);
|
||||
Id ownerId = this.readId(ownerVertexId);
|
||||
vertex = new HugeVertex(graph, ownerId, null);
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +171,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
VertexLabel srcLabel = graph.vertexLabel(edgeLabel.sourceLabel());
|
||||
VertexLabel tgtLabel = graph.vertexLabel(edgeLabel.targetLabel());
|
||||
|
||||
Id otherId = IdUtil.readStoredString(otherVertexId);
|
||||
Id otherId = this.readId(otherVertexId);
|
||||
boolean isOutEdge = direction == Directions.OUT;
|
||||
HugeVertex otherVertex;
|
||||
if (isOutEdge) {
|
||||
|
|
@ -190,7 +206,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
@Override
|
||||
public BackendEntry writeVertex(HugeVertex vertex) {
|
||||
TableBackendEntry entry = newBackendEntry(vertex);
|
||||
entry.column(HugeKeys.ID, IdUtil.writeStoredString(vertex.id()));
|
||||
entry.column(HugeKeys.ID, this.writeId(vertex.id()));
|
||||
entry.column(HugeKeys.LABEL, vertex.schemaLabel().id().asLong());
|
||||
// Add all properties of a Vertex
|
||||
this.formatProperties(vertex, entry.row());
|
||||
|
|
@ -202,7 +218,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
HugeVertex vertex = prop.element();
|
||||
TableBackendEntry entry = newBackendEntry(vertex);
|
||||
entry.subId(IdGenerator.of(prop.key()));
|
||||
entry.column(HugeKeys.ID, IdUtil.writeStoredString(vertex.id()));
|
||||
entry.column(HugeKeys.ID, this.writeId(vertex.id()));
|
||||
entry.column(HugeKeys.LABEL, vertex.schemaLabel().id().asLong());
|
||||
|
||||
this.formatProperty(prop, entry.row());
|
||||
|
|
@ -219,7 +235,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
TableBackendEntry entry = this.convertEntry(backendEntry);
|
||||
assert entry.type().isVertex();
|
||||
|
||||
Id id = IdUtil.readStoredString(entry.column(HugeKeys.ID));
|
||||
Id id = this.readId(entry.column(HugeKeys.ID));
|
||||
Number label = entry.column(HugeKeys.LABEL);
|
||||
|
||||
VertexLabel vertexLabel = VertexLabel.NONE;
|
||||
|
|
@ -248,13 +264,11 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
EdgeId id = edge.idWithDirection();
|
||||
TableBackendEntry.Row row = new TableBackendEntry.Row(edge.type(), id);
|
||||
// Id: ownerVertex + direction + edge-label + sortValues + otherVertex
|
||||
row.column(HugeKeys.OWNER_VERTEX,
|
||||
IdUtil.writeStoredString(id.ownerVertexId()));
|
||||
row.column(HugeKeys.DIRECTION, id.direction().code());
|
||||
row.column(HugeKeys.OWNER_VERTEX, this.writeId(id.ownerVertexId()));
|
||||
row.column(HugeKeys.DIRECTION, id.directionCode());
|
||||
row.column(HugeKeys.LABEL, id.edgeLabelId().asLong());
|
||||
row.column(HugeKeys.SORT_VALUES, id.sortValues());
|
||||
row.column(HugeKeys.OTHER_VERTEX,
|
||||
IdUtil.writeStoredString(id.otherVertexId()));
|
||||
row.column(HugeKeys.OTHER_VERTEX, this.writeId(id.otherVertexId()));
|
||||
// Format edge property
|
||||
this.formatProperty(prop, row);
|
||||
|
||||
|
|
@ -286,8 +300,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
} else {
|
||||
entry.column(HugeKeys.FIELD_VALUES, index.fieldValues());
|
||||
entry.column(HugeKeys.INDEX_LABEL_ID, index.indexLabel().longId());
|
||||
entry.column(HugeKeys.ELEMENT_IDS,
|
||||
IdUtil.writeStoredString(index.elementId()));
|
||||
entry.column(HugeKeys.ELEMENT_IDS, this.writeId(index.elementId()));
|
||||
entry.subId(index.elementId());
|
||||
}
|
||||
return entry;
|
||||
|
|
@ -305,13 +318,13 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
|
||||
Object indexValues = entry.column(HugeKeys.FIELD_VALUES);
|
||||
Number indexLabelId = entry.column(HugeKeys.INDEX_LABEL_ID);
|
||||
Set<String> elemIds = this.parseIndexElemIds(entry);
|
||||
Set<Object> elemIds = this.parseIndexElemIds(entry);
|
||||
|
||||
IndexLabel indexLabel = graph.indexLabel(this.toId(indexLabelId));
|
||||
HugeIndex index = new HugeIndex(indexLabel);
|
||||
index.fieldValues(indexValues);
|
||||
for (String elemId : elemIds) {
|
||||
index.elementIds(IdUtil.readStoredString(elemId));
|
||||
for (Object elemId : elemIds) {
|
||||
index.elementIds(this.readId(elemId));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
|
@ -328,7 +341,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
id = EdgeId.parse(id.asString());
|
||||
}
|
||||
} else if (type.isGraph()) {
|
||||
id = IdGenerator.of(IdUtil.writeStoredString(id));
|
||||
id = IdGenerator.of(this.writeId(id));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
|
@ -342,14 +355,13 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
if (r.key() == HugeKeys.OWNER_VERTEX ||
|
||||
r.key() == HugeKeys.OTHER_VERTEX) {
|
||||
// Serialize vertex id
|
||||
String id = IdUtil.writeStoredString((Id) value);
|
||||
r.serialValue(this.escapeString(id));
|
||||
r.serialValue(this.writeId((Id) value));
|
||||
} else {
|
||||
// Serialize label id
|
||||
r.serialValue(((Id) value).asObject());
|
||||
}
|
||||
} else if (value instanceof Directions) {
|
||||
r.serialValue(((Directions) value).code());
|
||||
r.serialValue(((Directions) value).type().code());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
@ -377,7 +389,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
|
||||
if (query.resultType().isGraph() &&
|
||||
r.relation() == Condition.RelationType.CONTAINS_VALUE) {
|
||||
r.serialValue(JsonUtil.toJson(r.serialValue()));
|
||||
r.serialValue(this.writeProperty(r.serialValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -587,7 +599,7 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
|
||||
protected abstract Object toLongList(Collection<Id> ids);
|
||||
|
||||
protected abstract Set<String> parseIndexElemIds(TableBackendEntry entry);
|
||||
protected abstract Set<Object> parseIndexElemIds(TableBackendEntry entry);
|
||||
|
||||
protected abstract void formatProperties(HugeElement element,
|
||||
TableBackendEntry.Row row);
|
||||
|
|
@ -595,17 +607,18 @@ public abstract class TableSerializer extends AbstractSerializer {
|
|||
protected abstract void parseProperties(HugeElement element,
|
||||
TableBackendEntry.Row row);
|
||||
|
||||
protected Object writeId(Id id) {
|
||||
return IdUtil.writeStoredString(id);
|
||||
}
|
||||
|
||||
protected Id readId(Object id) {
|
||||
return IdUtil.readStoredString(id.toString());
|
||||
}
|
||||
|
||||
protected Object serializeValue(Object value) {
|
||||
if (value instanceof Id) {
|
||||
value = ((Id) value).asObject();
|
||||
}
|
||||
if (value instanceof String) {
|
||||
value = this.escapeString((String) value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected String escapeString(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,4 +170,8 @@ public enum HugeType implements SerialEnum {
|
|||
public static HugeType fromString(String type) {
|
||||
return ALL_NAME.get(type);
|
||||
}
|
||||
|
||||
public static HugeType fromCode(byte code) {
|
||||
return SerialEnum.fromCode(HugeType.class, code);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ package com.baidu.hugegraph.type.define;
|
|||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.baidu.hugegraph.HugeException;
|
||||
import com.baidu.hugegraph.util.DateUtil;
|
||||
|
||||
public enum DataType implements SerialEnum {
|
||||
|
|
@ -161,4 +162,13 @@ public enum DataType implements SerialEnum {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DataType fromClass(Class<?> clazz) {
|
||||
for (DataType type : DataType.values()) {
|
||||
if (type.clazz() == clazz) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new HugeException("Unknow clazz '%s' for DataType", clazz);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ public class HbaseStoreProvider extends AbstractBackendStoreProvider {
|
|||
* also split range table to rangeInt, rangeFloat,
|
||||
* rangeLong and rangeDouble
|
||||
* [1.5] #633: support unique index
|
||||
* [1.6] #680: update index element-id to bin format
|
||||
*/
|
||||
return "1.5";
|
||||
return "1.6";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,8 @@
|
|||
|
||||
package com.baidu.hugegraph.backend.store.mysql;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.serializer.TableBackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
|
||||
public class MysqlBackendEntry extends TableBackendEntry {
|
||||
|
|
@ -43,41 +40,4 @@ public class MysqlBackendEntry extends TableBackendEntry {
|
|||
public MysqlBackendEntry(TableBackendEntry.Row row) {
|
||||
super(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MysqlBackendEntry{%s, sub-rows: %s}",
|
||||
this.row().toString(),
|
||||
this.subRows().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int columnsSize() {
|
||||
throw new RuntimeException("Not supported by MySQL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BackendColumn> columns() {
|
||||
throw new RuntimeException("Not supported by MySQL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columns(Collection<BackendColumn> bytesColumns) {
|
||||
throw new RuntimeException("Not supported by MySQL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columns(BackendColumn... bytesColumns) {
|
||||
throw new RuntimeException("Not supported by MySQL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(BackendEntry other) {
|
||||
throw new RuntimeException("Not supported by MySQL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new RuntimeException("Not supported by MySQL");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ public class MysqlSerializer extends TableSerializer {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> parseIndexElemIds(TableBackendEntry entry) {
|
||||
Set<String> elemIds = InsertionOrderUtil.newSet();
|
||||
protected Set<Object> parseIndexElemIds(TableBackendEntry entry) {
|
||||
Set<Object> elemIds = InsertionOrderUtil.newSet();
|
||||
elemIds.add(entry.column(HugeKeys.ELEMENT_IDS));
|
||||
for (TableBackendEntry.Row row : entry.subRows()) {
|
||||
elemIds.add(row.column(HugeKeys.ELEMENT_IDS));
|
||||
|
|
@ -162,9 +162,4 @@ public class MysqlSerializer extends TableSerializer {
|
|||
schema.userdata(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String escapeString(String value) {
|
||||
return MysqlUtil.escapeString(value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ public class MysqlStoreProvider extends AbstractBackendStoreProvider {
|
|||
* also split range table to rangeInt, rangeFloat,
|
||||
* rangeLong and rangeDouble
|
||||
* [1.4] #633: support unique index
|
||||
* [1.5] #661: reduce the storage of vertex/edge id
|
||||
*/
|
||||
return "1.4";
|
||||
return "1.5";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ import com.baidu.hugegraph.backend.store.TableDefine;
|
|||
import com.baidu.hugegraph.backend.store.mysql.MysqlEntryIterator.PagePosition;
|
||||
import com.baidu.hugegraph.backend.store.mysql.MysqlSessions.Session;
|
||||
import com.baidu.hugegraph.exception.NotFoundException;
|
||||
import com.baidu.hugegraph.exception.NotSupportException;
|
||||
import com.baidu.hugegraph.iterator.ExtendableIterator;
|
||||
import com.baidu.hugegraph.type.define.HugeKeys;
|
||||
import com.baidu.hugegraph.util.Log;
|
||||
|
|
@ -195,8 +194,8 @@ public abstract class MysqlTable
|
|||
delete.append("DELETE FROM ").append(this.table());
|
||||
this.appendPartition(delete);
|
||||
|
||||
WhereBuilder where = new WhereBuilder();
|
||||
where.and(formatKeys(idNames), "?");
|
||||
WhereBuilder where = this.newWhereBuilder();
|
||||
where.and(formatKeys(idNames), "=");
|
||||
delete.append(where.build());
|
||||
|
||||
this.deleteTemplate = delete.toString();
|
||||
|
|
@ -381,7 +380,7 @@ public abstract class MysqlTable
|
|||
values.add(objects.get(0));
|
||||
}
|
||||
|
||||
WhereBuilder where = new WhereBuilder();
|
||||
WhereBuilder where = this.newWhereBuilder();
|
||||
where.in(formatKey(nameParts.get(0)), values);
|
||||
select.append(where.build());
|
||||
return ImmutableList.of(select);
|
||||
|
|
@ -402,7 +401,7 @@ public abstract class MysqlTable
|
|||
* NOTE: concat with AND relation, like:
|
||||
* "pk = id and ck1 = v1 and ck2 = v2"
|
||||
*/
|
||||
WhereBuilder where = new WhereBuilder();
|
||||
WhereBuilder where = this.newWhereBuilder();
|
||||
where.and(formatKeys(nameParts), objects);
|
||||
|
||||
idSelection.append(where.build());
|
||||
|
|
@ -419,7 +418,7 @@ public abstract class MysqlTable
|
|||
for (Condition condition : conditions) {
|
||||
clauses.add(this.condition2Sql(condition));
|
||||
}
|
||||
WhereBuilder where = new WhereBuilder();
|
||||
WhereBuilder where = this.newWhereBuilder();
|
||||
where.and(clauses);
|
||||
select.append(where.build());
|
||||
return ImmutableList.of(select);
|
||||
|
|
@ -450,40 +449,17 @@ public abstract class MysqlTable
|
|||
String key = relation.serialKey().toString();
|
||||
Object value = relation.serialValue();
|
||||
|
||||
StringBuilder sql = new StringBuilder(32);
|
||||
sql.append(key);
|
||||
switch (relation.relation()) {
|
||||
case EQ:
|
||||
sql.append(" = ").append(value);
|
||||
break;
|
||||
case NEQ:
|
||||
sql.append(" != ").append(value);
|
||||
break;
|
||||
case GT:
|
||||
sql.append(" > ").append(value);
|
||||
break;
|
||||
case GTE:
|
||||
sql.append(" >= ").append(value);
|
||||
break;
|
||||
case LT:
|
||||
sql.append(" < ").append(value);
|
||||
break;
|
||||
case LTE:
|
||||
sql.append(" <= ").append(value);
|
||||
break;
|
||||
case IN:
|
||||
sql.append(" IN (");
|
||||
String values = Strings.join((List<?>) value, ',');
|
||||
sql.append(values);
|
||||
sql.append(")");
|
||||
break;
|
||||
case CONTAINS_VALUE:
|
||||
case CONTAINS_KEY:
|
||||
case SCAN:
|
||||
default:
|
||||
throw new NotSupportException("relation '%s'", relation);
|
||||
}
|
||||
return sql;
|
||||
WhereBuilder sql = this.newWhereBuilder(false);
|
||||
sql.relation(key, relation.relation(), value);
|
||||
return sql.build();
|
||||
}
|
||||
|
||||
protected WhereBuilder newWhereBuilder() {
|
||||
return this.newWhereBuilder(true);
|
||||
}
|
||||
|
||||
protected WhereBuilder newWhereBuilder(boolean startWithWhere) {
|
||||
return new WhereBuilder(startWithWhere);
|
||||
}
|
||||
|
||||
protected void wrapOrderBy(StringBuilder select, Query query) {
|
||||
|
|
@ -526,7 +502,7 @@ public abstract class MysqlTable
|
|||
|
||||
// Need add `where` to `select` when query is IdQuery
|
||||
boolean startWithWhere = query.conditions().isEmpty();
|
||||
WhereBuilder where = new WhereBuilder(startWithWhere);
|
||||
WhereBuilder where = this.newWhereBuilder(startWithWhere);
|
||||
where.gte(formatKeys(idColumnNames), values);
|
||||
if (!startWithWhere) {
|
||||
select.append(" AND");
|
||||
|
|
|
|||
|
|
@ -287,7 +287,9 @@ public class MysqlTables {
|
|||
@Override
|
||||
public List<Object> idColumnValue(Id id) {
|
||||
EdgeId edgeId;
|
||||
if (!(id instanceof EdgeId)) {
|
||||
if (id instanceof EdgeId) {
|
||||
edgeId = (EdgeId) id;
|
||||
} else {
|
||||
String[] idParts = EdgeId.split(id);
|
||||
if (idParts.length == 1) {
|
||||
// Delete edge by label
|
||||
|
|
@ -295,8 +297,6 @@ public class MysqlTables {
|
|||
}
|
||||
id = IdUtil.readString(id.asString());
|
||||
edgeId = EdgeId.parse(id.asString());
|
||||
} else {
|
||||
edgeId = (EdgeId) id;
|
||||
}
|
||||
|
||||
E.checkState(edgeId.direction() == this.direction,
|
||||
|
|
@ -305,7 +305,7 @@ public class MysqlTables {
|
|||
|
||||
List<Object> list = new ArrayList<>(5);
|
||||
list.add(IdUtil.writeStoredString(edgeId.ownerVertexId()));
|
||||
list.add(edgeId.direction().code());
|
||||
list.add(edgeId.directionCode());
|
||||
list.add(edgeId.edgeLabelId().asLong());
|
||||
list.add(edgeId.sortValues());
|
||||
list.add(IdUtil.writeStoredString(edgeId.otherVertexId()));
|
||||
|
|
|
|||
|
|
@ -21,94 +21,111 @@ package com.baidu.hugegraph.backend.store.mysql;
|
|||
|
||||
public class MysqlUtil {
|
||||
|
||||
public static String escapeAndWrapString(String value) {
|
||||
return escapeString(value, true);
|
||||
}
|
||||
|
||||
public static String escapeString(String value) {
|
||||
return escapeString(value, false);
|
||||
}
|
||||
|
||||
private static String escapeString(String value, boolean wrap) {
|
||||
int length = value.length();
|
||||
if (!isEscapeNeededForString(value, length)) {
|
||||
if (!wrap) {
|
||||
return value;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(length + 2);
|
||||
buf.append('\'').append(value).append('\'');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder((int) (length * 1.1D));
|
||||
buf.append('\'');
|
||||
StringBuilder buffer = new StringBuilder((int) (length * 1.1d));
|
||||
|
||||
if (wrap) {
|
||||
buffer.append('\'');
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
char c = value.charAt(i);
|
||||
switch (c) {
|
||||
case '\u0000':
|
||||
buf.append('\\');
|
||||
buf.append('0');
|
||||
buffer.append('\\');
|
||||
buffer.append('0');
|
||||
break;
|
||||
case '\n':
|
||||
buf.append('\\');
|
||||
buf.append('n');
|
||||
buffer.append('\\');
|
||||
buffer.append('n');
|
||||
break;
|
||||
case '\r':
|
||||
buf.append('\\');
|
||||
buf.append('r');
|
||||
buffer.append('\\');
|
||||
buffer.append('r');
|
||||
break;
|
||||
case '\u001a':
|
||||
buf.append('\\');
|
||||
buf.append('Z');
|
||||
buffer.append('\\');
|
||||
buffer.append('Z');
|
||||
break;
|
||||
case '"':
|
||||
/*
|
||||
* Doesn't need to add '\', because we wrap string with "'"
|
||||
* Assume that we don't use Ansi Mode
|
||||
*/
|
||||
buf.append('"');
|
||||
buffer.append('"');
|
||||
break;
|
||||
case '\'':
|
||||
buf.append('\\');
|
||||
buf.append('\'');
|
||||
buffer.append('\\');
|
||||
buffer.append('\'');
|
||||
break;
|
||||
case '\\':
|
||||
buf.append('\\');
|
||||
buf.append('\\');
|
||||
buffer.append('\\');
|
||||
buffer.append('\\');
|
||||
break;
|
||||
default:
|
||||
buf.append(c);
|
||||
buffer.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf.append('\'');
|
||||
return buf.toString();
|
||||
if (wrap) {
|
||||
buffer.append('\'');
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public static boolean isEscapeNeededForString(String sql, int length) {
|
||||
boolean needsHesqlEscape = false;
|
||||
boolean needsEscape = false;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
char c = sql.charAt(i);
|
||||
switch (c) {
|
||||
case '\u0000':
|
||||
needsHesqlEscape = true;
|
||||
needsEscape = true;
|
||||
break;
|
||||
case '\n':
|
||||
needsHesqlEscape = true;
|
||||
needsEscape = true;
|
||||
break;
|
||||
case '\r':
|
||||
needsHesqlEscape = true;
|
||||
needsEscape = true;
|
||||
break;
|
||||
case '\u001a':
|
||||
needsHesqlEscape = true;
|
||||
needsEscape = true;
|
||||
break;
|
||||
case '\'':
|
||||
needsHesqlEscape = true;
|
||||
needsEscape = true;
|
||||
break;
|
||||
case '\\':
|
||||
needsHesqlEscape = true;
|
||||
needsEscape = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (needsHesqlEscape) {
|
||||
if (needsEscape) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return needsHesqlEscape;
|
||||
return needsEscape;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ package com.baidu.hugegraph.backend.store.mysql;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.baidu.hugegraph.backend.query.Condition.RelationType;
|
||||
import com.baidu.hugegraph.exception.NotSupportException;
|
||||
import com.baidu.hugegraph.util.E;
|
||||
|
||||
public class WhereBuilder {
|
||||
|
|
@ -39,30 +41,72 @@ public class WhereBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat as: key1 = value and key2 = value...
|
||||
* @param keys the keys to be concatted with value
|
||||
* @param value the value to be concatted with every key
|
||||
*/
|
||||
public void and(List<String> keys, String value) {
|
||||
this.and(keys, " = ", value);
|
||||
public WhereBuilder relation(String key, RelationType type, Object value) {
|
||||
String operator = null;
|
||||
switch (type) {
|
||||
case EQ:
|
||||
operator = "=";
|
||||
break;
|
||||
case NEQ:
|
||||
operator = "!=";
|
||||
break;
|
||||
case GT:
|
||||
operator = ">";
|
||||
break;
|
||||
case GTE:
|
||||
operator = ">=";
|
||||
break;
|
||||
case LT:
|
||||
operator = "<";
|
||||
break;
|
||||
case LTE:
|
||||
operator = "<=";
|
||||
break;
|
||||
case IN:
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> values = (List<Object>) value;
|
||||
this.in(key, values);
|
||||
break;
|
||||
case CONTAINS_VALUE:
|
||||
case CONTAINS_KEY:
|
||||
case SCAN:
|
||||
default:
|
||||
throw new NotSupportException("relation '%s'", type);
|
||||
}
|
||||
if (operator != null) {
|
||||
this.builder.append(key);
|
||||
this.builder.append(operator);
|
||||
this.builder.append(wrapStringIfNeeded(value));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat as: key1 op value and key2 op value...
|
||||
* Concat as: cond1 and cond2...
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public WhereBuilder and() {
|
||||
this.builder.append(" AND ");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat as: key1 op ? and key2 op ?...
|
||||
* @param keys the keys to be concatted with value
|
||||
* @param operator the operator to link every key and value pair
|
||||
* @param value the value to be concatted with every key
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void and(List<String> keys, String operator, String value) {
|
||||
public WhereBuilder and(List<String> keys, String operator) {
|
||||
for (int i = 0, n = keys.size(); i < n; i++) {
|
||||
this.builder.append(keys.get(i));
|
||||
this.builder.append(operator);
|
||||
this.builder.append(value);
|
||||
this.builder.append("?");
|
||||
if (i != n - 1) {
|
||||
this.builder.append(" AND ");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,9 +115,10 @@ public class WhereBuilder {
|
|||
* same index
|
||||
* @param values the values to be concatted with every keys according to
|
||||
* the same index
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void and(List<String> keys, List<Object> values) {
|
||||
this.and(keys, " = ", values);
|
||||
public WhereBuilder and(List<String> keys, List<Object> values) {
|
||||
return this.and(keys, "=", values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -83,8 +128,11 @@ public class WhereBuilder {
|
|||
* @param operator the operator to link every key and value pair
|
||||
* @param values the values to be concatted with every keys according to
|
||||
* the same index
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void and(List<String> keys, String operator, List<Object> values) {
|
||||
public WhereBuilder and(List<String> keys,
|
||||
String operator,
|
||||
List<Object> values) {
|
||||
E.checkArgument(keys.size() == values.size(),
|
||||
"The size of keys '%s' is not equal with " +
|
||||
"values size '%s'",
|
||||
|
|
@ -93,16 +141,12 @@ public class WhereBuilder {
|
|||
for (int i = 0, n = keys.size(); i < n; i++) {
|
||||
this.builder.append(keys.get(i));
|
||||
this.builder.append(operator);
|
||||
Object value = values.get(i);
|
||||
if (value instanceof String) {
|
||||
this.builder.append(MysqlUtil.escapeString((String) value));
|
||||
} else {
|
||||
this.builder.append(value);
|
||||
}
|
||||
this.builder.append(wrapStringIfNeeded(values.get(i)));
|
||||
if (i != n - 1) {
|
||||
this.builder.append(" AND ");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,10 +157,11 @@ public class WhereBuilder {
|
|||
* according to the same index
|
||||
* @param values the values to be concatted with every keys according to
|
||||
* the same index
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void and(List<String> keys,
|
||||
List<String> operators,
|
||||
List<Object> values) {
|
||||
public WhereBuilder and(List<String> keys,
|
||||
List<String> operators,
|
||||
List<Object> values) {
|
||||
E.checkArgument(keys.size() == operators.size(),
|
||||
"The size of keys '%s' is not equal with " +
|
||||
"operators size '%s'",
|
||||
|
|
@ -129,23 +174,20 @@ public class WhereBuilder {
|
|||
for (int i = 0, n = keys.size(); i < n; i++) {
|
||||
this.builder.append(keys.get(i));
|
||||
this.builder.append(operators.get(i));
|
||||
Object value = values.get(i);
|
||||
if (value instanceof String) {
|
||||
this.builder.append(MysqlUtil.escapeString((String) value));
|
||||
} else {
|
||||
this.builder.append(value);
|
||||
}
|
||||
this.builder.append(wrapStringIfNeeded(values.get(i)));
|
||||
if (i != n - 1) {
|
||||
this.builder.append(" AND ");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat as: clause1 and clause2...
|
||||
* @param clauses the clauses to be concatted with 'AND' operator
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void and(List<StringBuilder> clauses) {
|
||||
public WhereBuilder and(List<StringBuilder> clauses) {
|
||||
E.checkArgument(clauses != null && !clauses.isEmpty(),
|
||||
"The clauses can't be empty");
|
||||
|
||||
|
|
@ -157,35 +199,34 @@ public class WhereBuilder {
|
|||
this.builder.append(" AND ");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat as: key in (value1, value2...)
|
||||
* @param key the key to be concatted with 'IN' operator
|
||||
* @param values the values to be concated with ',' and wappred by '()'
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void in(String key, List<Object> values) {
|
||||
public WhereBuilder in(String key, List<Object> values) {
|
||||
this.builder.append(key).append(" IN (");
|
||||
for (int i = 0, n = values.size(); i < n; i++) {
|
||||
Object value = values.get(i);
|
||||
if (value instanceof String) {
|
||||
this.builder.append(MysqlUtil.escapeString((String) value));
|
||||
} else {
|
||||
this.builder.append(value);
|
||||
}
|
||||
this.builder.append(wrapStringIfNeeded(values.get(i)));
|
||||
if (i != n - 1) {
|
||||
this.builder.append(", ");
|
||||
}
|
||||
}
|
||||
this.builder.append(")");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat as: (key1, key2...keyn) {@code >=} (val1, val2...valn)
|
||||
* @param keys the keys to be concatted with {@code >=} operator
|
||||
* @param values the values to be concatted with {@code >=} operator
|
||||
* @return WhereBuilder
|
||||
*/
|
||||
public void gte(List<String> keys, List<Object> values) {
|
||||
public WhereBuilder gte(List<String> keys, List<Object> values) {
|
||||
E.checkArgument(keys.size() == values.size(),
|
||||
"The size of keys '%s' is not equal with " +
|
||||
"values size '%s'",
|
||||
|
|
@ -199,25 +240,33 @@ public class WhereBuilder {
|
|||
}
|
||||
this.builder.append(") >= (");
|
||||
for (int i = 0, n = values.size(); i < n; i++) {
|
||||
Object value = values.get(i);
|
||||
if (value instanceof String) {
|
||||
this.builder.append(MysqlUtil.escapeString((String) value));
|
||||
} else {
|
||||
this.builder.append(value);
|
||||
}
|
||||
this.builder.append(wrapStringIfNeeded(values.get(i)));
|
||||
if (i != n - 1) {
|
||||
this.builder.append(", ");
|
||||
}
|
||||
}
|
||||
this.builder.append(")");
|
||||
return this;
|
||||
}
|
||||
|
||||
public String build() {
|
||||
return this.builder.toString();
|
||||
public StringBuilder build() {
|
||||
return this.builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.builder.toString();
|
||||
}
|
||||
|
||||
protected String wrapStringIfNeeded(Object value) {
|
||||
if (value instanceof String) {
|
||||
return this.escapeAndWrapString((String) value);
|
||||
} else {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected String escapeAndWrapString(String value) {
|
||||
return MysqlUtil.escapeAndWrapString(value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,9 @@ public class PaloStoreProvider extends MysqlStoreProvider {
|
|||
* also split range table to rangeInt, rangeFloat,
|
||||
* rangeLong and rangeDouble
|
||||
* [1.4] #633: support unique index
|
||||
* [1.5] #661: reduce the storage of vertex/edge id
|
||||
*/
|
||||
return "1.4";
|
||||
return "1.5";
|
||||
}
|
||||
|
||||
public static class PaloSchemaStore extends PaloStore {
|
||||
|
|
|
|||
|
|
@ -52,12 +52,4 @@ public class PostgresqlSerializer extends MysqlSerializer {
|
|||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String escapeString(String value) {
|
||||
if (value.equals("\u0000")) {
|
||||
return "\'\'";
|
||||
}
|
||||
return PostgresqlSessions.escapeString(value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public class PostgresqlSessions extends MysqlSessions {
|
|||
public boolean existsDatabase() {
|
||||
String statement = String.format(
|
||||
"SELECT datname FROM pg_catalog.pg_database " +
|
||||
"WHERE datname = %s;", this.escapedDatabase());
|
||||
"WHERE datname = '%s';", this.escapedDatabase());
|
||||
try (Connection conn = this.openWithoutDB(0)) {
|
||||
ResultSet result = conn.createStatement().executeQuery(statement);
|
||||
return result.next();
|
||||
|
|
@ -101,7 +101,7 @@ public class PostgresqlSessions extends MysqlSessions {
|
|||
" FROM pg_stat_activity " +
|
||||
" WHERE pg_stat_activity.datname = %s;" +
|
||||
"DROP DATABASE IF EXISTS %s;",
|
||||
database, escapeString(database), database);
|
||||
database, escapeAndWrapString(database), database);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -110,7 +110,7 @@ public class PostgresqlSessions extends MysqlSessions {
|
|||
return new URIBuilder().addParameter("loggerLevel", "OFF");
|
||||
}
|
||||
|
||||
public static String escapeString(String value) {
|
||||
public static String escapeAndWrapString(String value) {
|
||||
StringBuilder builder = new StringBuilder(8 + value.length());
|
||||
builder.append('\'');
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -58,8 +58,9 @@ public class PostgresqlStoreProvider extends MysqlStoreProvider {
|
|||
* also split range table to rangeInt, rangeFloat,
|
||||
* rangeLong and rangeDouble
|
||||
* [1.2] #633: support unique index
|
||||
* [1.3] #661: reduce the storage of vertex/edge id
|
||||
*/
|
||||
return "1.2";
|
||||
return "1.3";
|
||||
}
|
||||
|
||||
public static class PostgresqlSchemaStore extends PostgresqlStore {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@ import java.util.List;
|
|||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
import com.baidu.hugegraph.backend.store.mysql.MysqlBackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.mysql.MysqlTable;
|
||||
import com.baidu.hugegraph.backend.store.mysql.MysqlSessions.Session;
|
||||
import com.baidu.hugegraph.backend.store.mysql.MysqlTable;
|
||||
import com.baidu.hugegraph.backend.store.mysql.WhereBuilder;
|
||||
import com.baidu.hugegraph.type.define.HugeKeys;
|
||||
|
||||
public abstract class PostgresqlTable extends MysqlTable {
|
||||
|
|
@ -38,10 +39,12 @@ public abstract class PostgresqlTable extends MysqlTable {
|
|||
super(table);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildDropTemplate() {
|
||||
return String.format("DROP TABLE IF EXISTS %s CASCADE;", this.table());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildTruncateTemplate() {
|
||||
return String.format("TRUNCATE TABLE %s CASCADE;", this.table());
|
||||
}
|
||||
|
|
@ -112,6 +115,7 @@ public abstract class PostgresqlTable extends MysqlTable {
|
|||
}
|
||||
|
||||
// Set order-by to keep results order consistence for PostgreSQL result
|
||||
@Override
|
||||
protected String orderByKeys() {
|
||||
if (this.orderByKeys != null) {
|
||||
return this.orderByKeys;
|
||||
|
|
@ -130,4 +134,24 @@ public abstract class PostgresqlTable extends MysqlTable {
|
|||
this.orderByKeys = select.toString();
|
||||
return this.orderByKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WhereBuilder newWhereBuilder(boolean startWithWhere) {
|
||||
return new PgWhereBuilder(startWithWhere);
|
||||
}
|
||||
|
||||
private static class PgWhereBuilder extends WhereBuilder {
|
||||
|
||||
public PgWhereBuilder(boolean startWithWhere) {
|
||||
super(startWithWhere);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String escapeAndWrapString(String value) {
|
||||
if (value.equals("\u0000")) {
|
||||
return "\'\'";
|
||||
}
|
||||
return PostgresqlSessions.escapeAndWrapString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ public class RocksDBStoreProvider extends AbstractBackendStoreProvider {
|
|||
* also split range table to rangeInt, rangeFloat,
|
||||
* rangeLong and rangeDouble
|
||||
* [1.4] #633: support unique index
|
||||
* [1.5] #680: update index element-id to bin format
|
||||
*/
|
||||
return "1.4";
|
||||
return "1.5";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.baidu.hugegraph.schema.EdgeLabel;
|
|||
import com.baidu.hugegraph.schema.SchemaManager;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.type.define.Frequency;
|
||||
import com.baidu.hugegraph.util.Events;
|
||||
|
||||
public class EdgeLabelCoreTest extends SchemaCoreTest {
|
||||
|
||||
|
|
@ -46,15 +47,13 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
EdgeLabel look = schema.edgeLabel("look").multiTimes()
|
||||
.properties("time")
|
||||
.link("person", "book")
|
||||
.sortKeys("time")
|
||||
.create();
|
||||
.properties("time")
|
||||
.link("person", "book")
|
||||
.sortKeys("time")
|
||||
.create();
|
||||
|
||||
Assert.assertNotNull(look);
|
||||
Assert.assertEquals("look", look.name());
|
||||
|
|
@ -114,13 +113,11 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
EdgeLabel look = schema.edgeLabel("look").properties("time")
|
||||
.link("person", "book")
|
||||
.create();
|
||||
.link("person", "book")
|
||||
.create();
|
||||
|
||||
Assert.assertNotNull(look);
|
||||
Assert.assertEquals("look", look.name());
|
||||
|
|
@ -140,13 +137,11 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
EdgeLabel look = schema.edgeLabel("look").singleTime()
|
||||
.link("person", "book")
|
||||
.create();
|
||||
.link("person", "book")
|
||||
.create();
|
||||
|
||||
Assert.assertNotNull(look);
|
||||
Assert.assertEquals("look", look.name());
|
||||
|
|
@ -161,12 +156,6 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
public void testAddEdgeLabelWithoutLink() {
|
||||
super.initPropertyKeys();
|
||||
SchemaManager schema = graph().schema();
|
||||
schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> {
|
||||
schema.edgeLabel("look").multiTimes()
|
||||
|
|
@ -184,7 +173,7 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> {
|
||||
|
|
@ -198,11 +187,7 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
public void testAddEdgeLabelWithNotExistVertexLabel() {
|
||||
super.initPropertyKeys();
|
||||
SchemaManager schema = graph().schema();
|
||||
schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
|
||||
Assert.assertThrows(IllegalArgumentException.class, () -> {
|
||||
|
|
@ -303,8 +288,6 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
EdgeLabel look = schema.edgeLabel("look")
|
||||
|
|
@ -409,6 +392,89 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddEdgeLabelWithEnableLabelIndex() {
|
||||
super.initPropertyKeys();
|
||||
SchemaManager schema = graph().schema();
|
||||
|
||||
schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.create();
|
||||
|
||||
schema.vertexLabel("book")
|
||||
.properties("name")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
|
||||
EdgeLabel write = schema.edgeLabel("write").link("person", "book")
|
||||
.properties("time", "weight")
|
||||
.enableLabelIndex(true)
|
||||
.create();
|
||||
Assert.assertEquals(true, write.enableLabelIndex());
|
||||
|
||||
Vertex marko = graph().addVertex(T.label, "person", "name", "marko",
|
||||
"age", 22);
|
||||
Vertex java = graph().addVertex(T.label, "book",
|
||||
"name", "java in action");
|
||||
Vertex hadoop = graph().addVertex(T.label, "book",
|
||||
"name", "hadoop mapreduce");
|
||||
|
||||
marko.addEdge("write", java, "time", "2016-12-12", "weight", 0.3);
|
||||
marko.addEdge("write", hadoop, "time", "2014-2-28", "weight", 0.5);
|
||||
graph().tx().commit();
|
||||
|
||||
List<Edge> edges = graph().traversal().E().hasLabel("write").toList();
|
||||
Assert.assertEquals(2, edges.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddEdgeLabelWithDisableeLabelIndex() {
|
||||
super.initPropertyKeys();
|
||||
HugeGraph graph = graph();
|
||||
SchemaManager schema = graph.schema();
|
||||
|
||||
schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.create();
|
||||
|
||||
schema.vertexLabel("book")
|
||||
.properties("name")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
|
||||
EdgeLabel write = schema.edgeLabel("write").link("person", "book")
|
||||
.properties("time", "weight")
|
||||
.enableLabelIndex(false)
|
||||
.create();
|
||||
Assert.assertEquals(false, write.enableLabelIndex());
|
||||
|
||||
Vertex marko = graph.addVertex(T.label, "person", "name", "marko",
|
||||
"age", 22);
|
||||
Vertex java = graph.addVertex(T.label, "book",
|
||||
"name", "java in action");
|
||||
Vertex hadoop = graph.addVertex(T.label, "book",
|
||||
"name", "hadoop mapreduce");
|
||||
|
||||
marko.addEdge("write", java, "time", "2016-12-12", "weight", 0.3);
|
||||
marko.addEdge("write", hadoop, "time", "2014-2-28", "weight", 0.5);
|
||||
graph.tx().commit();
|
||||
|
||||
BackendFeatures features = graph.graphTransaction().store().features();
|
||||
if (!features.supportsQueryByLabel()) {
|
||||
Assert.assertThrows(NoIndexException.class, () -> {
|
||||
graph.traversal().E().hasLabel("write").toList();
|
||||
});
|
||||
} else {
|
||||
List<Edge> edges = graph.traversal().E().hasLabel("write")
|
||||
.toList();
|
||||
Assert.assertEquals(2, edges.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendEdgeLabelWithUndefinedNullableKeys() {
|
||||
super.initPropertyKeys();
|
||||
|
|
@ -731,7 +797,7 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
graph().tx().commit();
|
||||
|
||||
List<Edge> edges = graph().traversal().E().hasLabel("write")
|
||||
.has("weight", 0.5).toList();
|
||||
.has("weight", 0.5).toList();
|
||||
Assert.assertNotNull(edges);
|
||||
Assert.assertEquals(1, edges.size());
|
||||
|
||||
|
|
@ -786,7 +852,7 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
graph().tx().commit();
|
||||
|
||||
List<Edge> edges = graph().traversal().E().hasLabel("write")
|
||||
.has("time", "2016-12-12").toList();
|
||||
.has("time", "2016-12-12").toList();
|
||||
Assert.assertNotNull(edges);
|
||||
Assert.assertEquals(1, edges.size());
|
||||
|
||||
|
|
@ -974,85 +1040,41 @@ public class EdgeLabelCoreTest extends SchemaCoreTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddEdgeLabelWithEnableLabelIndex() {
|
||||
public void testListEdgeLabels() {
|
||||
super.initPropertyKeys();
|
||||
SchemaManager schema = graph().schema();
|
||||
|
||||
schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.create();
|
||||
|
||||
schema.vertexLabel("book")
|
||||
.properties("name")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
|
||||
EdgeLabel write = schema.edgeLabel("write").link("person", "book")
|
||||
.properties("time", "weight")
|
||||
.enableLabelIndex(true)
|
||||
schema.vertexLabel("author").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
schema.vertexLabel("book").properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
EdgeLabel look = schema.edgeLabel("look").multiTimes()
|
||||
.properties("time")
|
||||
.link("person", "book")
|
||||
.sortKeys("time")
|
||||
.create();
|
||||
EdgeLabel write = schema.edgeLabel("write").multiTimes()
|
||||
.properties("time")
|
||||
.link("author", "book")
|
||||
.sortKeys("time")
|
||||
.create();
|
||||
Assert.assertEquals(true, write.enableLabelIndex());
|
||||
|
||||
Vertex marko = graph().addVertex(T.label, "person", "name", "marko",
|
||||
"age", 22);
|
||||
Vertex java = graph().addVertex(T.label, "book",
|
||||
"name", "java in action");
|
||||
Vertex hadoop = graph().addVertex(T.label, "book",
|
||||
"name", "hadoop mapreduce");
|
||||
List<EdgeLabel> edgeLabels = schema.getEdgeLabels();
|
||||
Assert.assertEquals(2, edgeLabels.size());
|
||||
Assert.assertTrue(edgeLabels.contains(look));
|
||||
Assert.assertTrue(edgeLabels.contains(write));
|
||||
|
||||
marko.addEdge("write", java, "time", "2016-12-12", "weight", 0.3);
|
||||
marko.addEdge("write", hadoop, "time", "2014-2-28", "weight", 0.5);
|
||||
graph().tx().commit();
|
||||
// clear cache
|
||||
graph().schemaEventHub().call(Events.CACHE, "clear", null);
|
||||
|
||||
List<Edge> edges = graph().traversal().E().hasLabel("write").toList();
|
||||
Assert.assertEquals(2, edges.size());
|
||||
}
|
||||
Assert.assertEquals(look, schema.getEdgeLabel("look"));
|
||||
|
||||
@Test
|
||||
public void testAddEdgeLabelWithDisableeLabelIndex() {
|
||||
super.initPropertyKeys();
|
||||
HugeGraph graph = graph();
|
||||
SchemaManager schema = graph.schema();
|
||||
|
||||
schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.create();
|
||||
|
||||
schema.vertexLabel("book")
|
||||
.properties("name")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
|
||||
EdgeLabel write = schema.edgeLabel("write").link("person", "book")
|
||||
.properties("time", "weight")
|
||||
.enableLabelIndex(false)
|
||||
.create();
|
||||
Assert.assertEquals(false, write.enableLabelIndex());
|
||||
|
||||
Vertex marko = graph.addVertex(T.label, "person", "name", "marko",
|
||||
"age", 22);
|
||||
Vertex java = graph.addVertex(T.label, "book",
|
||||
"name", "java in action");
|
||||
Vertex hadoop = graph.addVertex(T.label, "book",
|
||||
"name", "hadoop mapreduce");
|
||||
|
||||
marko.addEdge("write", java, "time", "2016-12-12", "weight", 0.3);
|
||||
marko.addEdge("write", hadoop, "time", "2014-2-28", "weight", 0.5);
|
||||
graph.tx().commit();
|
||||
|
||||
BackendFeatures features = graph.graphTransaction().store().features();
|
||||
if (!features.supportsQueryByLabel()) {
|
||||
Assert.assertThrows(NoIndexException.class, () -> {
|
||||
graph.traversal().E().hasLabel("write").toList();
|
||||
});
|
||||
} else {
|
||||
List<Edge> edges = graph.traversal().E().hasLabel("write")
|
||||
.toList();
|
||||
Assert.assertEquals(2, edges.size());
|
||||
}
|
||||
edgeLabels = schema.getEdgeLabels();
|
||||
Assert.assertEquals(2, edgeLabels.size());
|
||||
Assert.assertTrue(edgeLabels.contains(look));
|
||||
Assert.assertTrue(edgeLabels.contains(write));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import com.baidu.hugegraph.schema.SchemaManager;
|
|||
import com.baidu.hugegraph.schema.VertexLabel;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.type.define.IdStrategy;
|
||||
import com.baidu.hugegraph.util.Events;
|
||||
|
||||
public class VertexLabelCoreTest extends SchemaCoreTest {
|
||||
|
||||
|
|
@ -45,9 +46,9 @@ public class VertexLabelCoreTest extends SchemaCoreTest {
|
|||
SchemaManager schema = graph().schema();
|
||||
|
||||
VertexLabel person = schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.create();
|
||||
|
||||
Assert.assertNotNull(person);
|
||||
Assert.assertEquals("person", person.name());
|
||||
|
|
@ -505,6 +506,59 @@ public class VertexLabelCoreTest extends SchemaCoreTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddVertexLabelWithEnableLabelIndex() {
|
||||
super.initPropertyKeys();
|
||||
SchemaManager schema = graph().schema();
|
||||
|
||||
VertexLabel person = schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.enableLabelIndex(true)
|
||||
.create();
|
||||
Assert.assertEquals(true, person.enableLabelIndex());
|
||||
|
||||
graph().addVertex(T.label, "person", "name", "marko", "age", 18);
|
||||
graph().addVertex(T.label, "person", "name", "josh", "age", 20);
|
||||
graph().tx().commit();
|
||||
|
||||
List<Vertex> persons = graph().traversal().V()
|
||||
.hasLabel("person").toList();
|
||||
Assert.assertEquals(2, persons.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddVertexLabelWithDisableLabelIndex() {
|
||||
super.initPropertyKeys();
|
||||
HugeGraph graph = graph();
|
||||
SchemaManager schema = graph.schema();
|
||||
|
||||
VertexLabel person = schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.enableLabelIndex(false)
|
||||
.create();
|
||||
Assert.assertEquals(false, person.enableLabelIndex());
|
||||
|
||||
graph.addVertex(T.label, "person", "name", "marko", "age", 18);
|
||||
graph.addVertex(T.label, "person", "name", "josh", "age", 20);
|
||||
graph().tx().commit();
|
||||
|
||||
List<Vertex> persons;
|
||||
|
||||
BackendFeatures features = graph.graphTransaction().store().features();
|
||||
if (!features.supportsQueryByLabel()) {
|
||||
Assert.assertThrows(NoIndexException.class, () -> {
|
||||
graph.traversal().V().hasLabel("person").toList();
|
||||
});
|
||||
} else {
|
||||
persons = graph.traversal().V().hasLabel("person").toList();
|
||||
Assert.assertEquals(2, persons.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendVertexLabelWithUndefinedNullableKeys() {
|
||||
super.initPropertyKeys();
|
||||
|
|
@ -879,55 +933,35 @@ public class VertexLabelCoreTest extends SchemaCoreTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testAddVertexLabelWithEnableLabelIndex() {
|
||||
public void testListVertexLabels() {
|
||||
super.initPropertyKeys();
|
||||
SchemaManager schema = graph().schema();
|
||||
|
||||
VertexLabel person = schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.enableLabelIndex(true)
|
||||
.create();
|
||||
Assert.assertEquals(true, person.enableLabelIndex());
|
||||
VertexLabel author = schema.vertexLabel("author")
|
||||
.properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
VertexLabel book = schema.vertexLabel("book")
|
||||
.properties("id", "name")
|
||||
.primaryKeys("id").create();
|
||||
|
||||
graph().addVertex(T.label, "person", "name", "marko", "age", 18);
|
||||
graph().addVertex(T.label, "person", "name", "josh", "age", 20);
|
||||
graph().tx().commit();
|
||||
List<VertexLabel> vertexLabels = schema.getVertexLabels();
|
||||
Assert.assertEquals(3, vertexLabels.size());
|
||||
Assert.assertTrue(vertexLabels.contains(person));
|
||||
Assert.assertTrue(vertexLabels.contains(author));
|
||||
Assert.assertTrue(vertexLabels.contains(book));
|
||||
|
||||
List<Vertex> persons = graph().traversal().V()
|
||||
.hasLabel("person").toList();
|
||||
Assert.assertEquals(2, persons.size());
|
||||
}
|
||||
// clear cache
|
||||
graph().schemaEventHub().call(Events.CACHE, "clear", null);
|
||||
|
||||
@Test
|
||||
public void testAddVertexLabelWithDisableLabelIndex() {
|
||||
super.initPropertyKeys();
|
||||
HugeGraph graph = graph();
|
||||
SchemaManager schema = graph.schema();
|
||||
Assert.assertEquals(person, schema.getVertexLabel("person"));
|
||||
|
||||
VertexLabel person = schema.vertexLabel("person")
|
||||
.properties("name", "age", "city")
|
||||
.primaryKeys("name")
|
||||
.nullableKeys("city")
|
||||
.enableLabelIndex(false)
|
||||
.create();
|
||||
Assert.assertEquals(false, person.enableLabelIndex());
|
||||
|
||||
graph.addVertex(T.label, "person", "name", "marko", "age", 18);
|
||||
graph.addVertex(T.label, "person", "name", "josh", "age", 20);
|
||||
graph().tx().commit();
|
||||
|
||||
List<Vertex> persons;
|
||||
|
||||
BackendFeatures features = graph.graphTransaction().store().features();
|
||||
if (!features.supportsQueryByLabel()) {
|
||||
Assert.assertThrows(NoIndexException.class, () -> {
|
||||
graph.traversal().V().hasLabel("person").toList();
|
||||
});
|
||||
} else {
|
||||
persons = graph.traversal().V().hasLabel("person").toList();
|
||||
Assert.assertEquals(2, persons.size());
|
||||
}
|
||||
vertexLabels = schema.getVertexLabels();
|
||||
Assert.assertEquals(3, vertexLabels.size());
|
||||
Assert.assertTrue(vertexLabels.contains(person));
|
||||
Assert.assertTrue(vertexLabels.contains(author));
|
||||
Assert.assertTrue(vertexLabels.contains(book));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class FakeObjects {
|
|||
private Map<String, Object> values;
|
||||
|
||||
public FakeEdge(String label, Vertex outVertex, Vertex inVertex,
|
||||
Object... keyValues) {
|
||||
Object... keyValues) {
|
||||
this.label = label;
|
||||
this.outVertex = outVertex;
|
||||
this.inVertex = inVertex;
|
||||
|
|
|
|||
|
|
@ -20,18 +20,24 @@
|
|||
package com.baidu.hugegraph.unit;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.configuration.Configuration;
|
||||
import org.apache.commons.configuration.PropertiesConfiguration;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.baidu.hugegraph.HugeGraph;
|
||||
import com.baidu.hugegraph.backend.id.EdgeId;
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.id.IdGenerator;
|
||||
import com.baidu.hugegraph.config.HugeConfig;
|
||||
import com.baidu.hugegraph.schema.EdgeLabel;
|
||||
import com.baidu.hugegraph.schema.IndexLabel;
|
||||
import com.baidu.hugegraph.schema.PropertyKey;
|
||||
import com.baidu.hugegraph.schema.VertexLabel;
|
||||
import com.baidu.hugegraph.structure.HugeEdge;
|
||||
import com.baidu.hugegraph.structure.HugeVertex;
|
||||
import com.baidu.hugegraph.testutil.Whitebox;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
import com.baidu.hugegraph.type.define.Cardinality;
|
||||
import com.baidu.hugegraph.type.define.DataType;
|
||||
|
|
@ -78,6 +84,8 @@ public final class FakeObjects {
|
|||
PropertyKey schema = new PropertyKey(this.graph, id, name);
|
||||
schema.dataType(dataType);
|
||||
schema.cardinality(cardinality);
|
||||
|
||||
Mockito.when(this.graph.propertyKey(id)).thenReturn(schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +95,8 @@ public final class FakeObjects {
|
|||
VertexLabel schema = new VertexLabel(this.graph, id, name);
|
||||
schema.idStrategy(idStrategy);
|
||||
schema.properties(properties);
|
||||
|
||||
Mockito.when(this.graph.vertexLabel(id)).thenReturn(schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +108,8 @@ public final class FakeObjects {
|
|||
schema.sourceLabel(sourceLabel);
|
||||
schema.targetLabel(targetLabel);
|
||||
schema.properties(properties);
|
||||
|
||||
Mockito.when(this.graph.edgeLabel(id)).thenReturn(schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +121,51 @@ public final class FakeObjects {
|
|||
schema.baseValue(baseValue);
|
||||
schema.indexType(indexType);
|
||||
schema.indexFields(fields);
|
||||
|
||||
Mockito.when(this.graph.indexLabel(id)).thenReturn(schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
public HugeEdge newEdge(long sourceVertexId, long targetVertexId) {
|
||||
PropertyKey name = this.newPropertyKey(IdGenerator.of(1), "name");
|
||||
PropertyKey age = this.newPropertyKey(IdGenerator.of(2), "age",
|
||||
DataType.INT,
|
||||
Cardinality.SINGLE);
|
||||
PropertyKey city = this.newPropertyKey(IdGenerator.of(3), "city");
|
||||
PropertyKey date = this.newPropertyKey(IdGenerator.of(4), "date",
|
||||
DataType.DATE);
|
||||
PropertyKey weight = this.newPropertyKey(IdGenerator.of(5),
|
||||
"weight", DataType.DOUBLE);
|
||||
|
||||
VertexLabel vl = this.newVertexLabel(IdGenerator.of(1), "person",
|
||||
IdStrategy.CUSTOMIZE_NUMBER,
|
||||
name.id(), age.id(), city.id());
|
||||
|
||||
EdgeLabel el = this.newEdgeLabel(IdGenerator.of(1), "knows",
|
||||
Frequency.SINGLE, vl.id(), vl.id(),
|
||||
date.id(), weight.id());
|
||||
|
||||
HugeVertex source = new HugeVertex(this.graph(),
|
||||
IdGenerator.of(sourceVertexId), vl);
|
||||
source.addProperty(name, "tom");
|
||||
source.addProperty(age, 18);
|
||||
source.addProperty(city, "Beijing");
|
||||
|
||||
HugeVertex target = new HugeVertex(this.graph(),
|
||||
IdGenerator.of(targetVertexId), vl);
|
||||
target.addProperty(name, "cat");
|
||||
target.addProperty(age, 20);
|
||||
target.addProperty(city, "Shanghai");
|
||||
|
||||
Id id = EdgeId.parse("L123456>1>>L987654");
|
||||
HugeEdge edge = new HugeEdge(this.graph(), id, el);
|
||||
|
||||
Whitebox.setInternalState(edge, "sourceVertex", source);
|
||||
Whitebox.setInternalState(edge, "targetVertex", target);
|
||||
edge.assignId();
|
||||
edge.addProperty(date, new Date());
|
||||
edge.addProperty(weight, 0.75);
|
||||
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,24 +26,31 @@ import com.baidu.hugegraph.unit.cache.CacheManagerTest;
|
|||
import com.baidu.hugegraph.unit.cache.CachedGraphTransactionTest;
|
||||
import com.baidu.hugegraph.unit.cache.CachedSchemaTransactionTest;
|
||||
import com.baidu.hugegraph.unit.cache.RamCacheTest;
|
||||
import com.baidu.hugegraph.unit.cassandra.CassandraTest;
|
||||
import com.baidu.hugegraph.unit.core.AnalyzerTest;
|
||||
import com.baidu.hugegraph.unit.core.BackendMutationTest;
|
||||
import com.baidu.hugegraph.unit.core.BytesBufferTest;
|
||||
import com.baidu.hugegraph.unit.core.CassandraTest;
|
||||
import com.baidu.hugegraph.unit.core.ConditionQueryFlattenTest;
|
||||
import com.baidu.hugegraph.unit.core.ConditionTest;
|
||||
import com.baidu.hugegraph.unit.core.DataTypeTest;
|
||||
import com.baidu.hugegraph.unit.core.DirectionsTest;
|
||||
import com.baidu.hugegraph.unit.core.EdgeIdTest;
|
||||
import com.baidu.hugegraph.unit.core.ExceptionTest;
|
||||
import com.baidu.hugegraph.unit.core.IdTest;
|
||||
import com.baidu.hugegraph.unit.core.LocksTableTest;
|
||||
import com.baidu.hugegraph.unit.core.QueryTest;
|
||||
import com.baidu.hugegraph.unit.core.SecurityManagerTest;
|
||||
import com.baidu.hugegraph.unit.core.SerialEnumTest;
|
||||
import com.baidu.hugegraph.unit.id.IdTest;
|
||||
import com.baidu.hugegraph.unit.id.IdUtilTest;
|
||||
import com.baidu.hugegraph.unit.mysql.MysqlUtilTest;
|
||||
import com.baidu.hugegraph.unit.mysql.WhereBuilderTest;
|
||||
import com.baidu.hugegraph.unit.rocksdb.RocksDBCountersTest;
|
||||
import com.baidu.hugegraph.unit.rocksdb.RocksDBSessionsTest;
|
||||
import com.baidu.hugegraph.unit.util.IdUtilTest;
|
||||
import com.baidu.hugegraph.unit.serializer.BinaryBackendEntryTest;
|
||||
import com.baidu.hugegraph.unit.serializer.BinaryInlineSerializerTest;
|
||||
import com.baidu.hugegraph.unit.serializer.BytesBufferTest;
|
||||
import com.baidu.hugegraph.unit.serializer.SerializerFactoryTest;
|
||||
import com.baidu.hugegraph.unit.serializer.TableBackendEntryTest;
|
||||
import com.baidu.hugegraph.unit.serializer.TextBackendEntryTest;
|
||||
import com.baidu.hugegraph.unit.util.JsonUtilTest;
|
||||
import com.baidu.hugegraph.unit.util.StringEncodingTest;
|
||||
import com.baidu.hugegraph.unit.util.VersionTest;
|
||||
|
|
@ -61,10 +68,13 @@ import com.baidu.hugegraph.unit.util.VersionTest;
|
|||
DirectionsTest.class,
|
||||
SerialEnumTest.class,
|
||||
|
||||
/* id */
|
||||
IdTest.class,
|
||||
IdUtilTest.class,
|
||||
|
||||
/* core */
|
||||
LocksTableTest.class,
|
||||
AnalyzerTest.class,
|
||||
IdTest.class,
|
||||
EdgeIdTest.class,
|
||||
BackendMutationTest.class,
|
||||
ConditionTest.class,
|
||||
|
|
@ -72,11 +82,22 @@ import com.baidu.hugegraph.unit.util.VersionTest;
|
|||
QueryTest.class,
|
||||
SecurityManagerTest.class,
|
||||
ExceptionTest.class,
|
||||
|
||||
/* serializer */
|
||||
BytesBufferTest.class,
|
||||
SerializerFactoryTest.class,
|
||||
TextBackendEntryTest.class,
|
||||
TableBackendEntryTest.class,
|
||||
BinaryBackendEntryTest.class,
|
||||
BinaryInlineSerializerTest.class,
|
||||
|
||||
/* cassandra */
|
||||
CassandraTest.class,
|
||||
|
||||
/* mysql */
|
||||
MysqlUtilTest.class,
|
||||
WhereBuilderTest.class,
|
||||
|
||||
/* rocksdb */
|
||||
RocksDBSessionsTest.class,
|
||||
RocksDBCountersTest.class,
|
||||
|
|
@ -84,7 +105,6 @@ import com.baidu.hugegraph.unit.util.VersionTest;
|
|||
/* utils */
|
||||
VersionTest.class,
|
||||
JsonUtilTest.class,
|
||||
IdUtilTest.class,
|
||||
StringEncodingTest.class
|
||||
})
|
||||
public class UnitTestSuite {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.core;
|
||||
package com.baidu.hugegraph.unit.cassandra;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -293,9 +293,9 @@ public class SecurityManagerTest {
|
|||
.job(new GremlinAPI.GremlinJob());
|
||||
HugeTask<?> task = builder.schedule();
|
||||
try {
|
||||
graph.taskScheduler().waitUntilTaskCompleted(task.id(), 5);
|
||||
graph.taskScheduler().waitUntilTaskCompleted(task.id(), 10);
|
||||
} catch (TimeoutException e) {
|
||||
throw new HugeException("Wait task %s timeout", e, task);
|
||||
throw new HugeException("Wait for task timeout: %s", e, task);
|
||||
}
|
||||
return task.result();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.core;
|
||||
package com.baidu.hugegraph.unit.id;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
|
|
@ -34,16 +35,6 @@ import com.google.common.primitives.Bytes;
|
|||
|
||||
public class IdTest extends BaseUnitTest {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// pass
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
// pass
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringId() {
|
||||
Id id = IdGenerator.of("test-id");
|
||||
|
|
@ -144,6 +135,79 @@ public class IdTest extends BaseUnitTest {
|
|||
"g14RU5KBSVeGkc95JY6Q6w==", IdType.UUID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectId() {
|
||||
Object object = ByteBuffer.wrap(new byte[]{1, 2});
|
||||
Object object2 = ByteBuffer.wrap(new byte[]{2, 2});
|
||||
Id id = IdGenerator.of(object);
|
||||
Assert.assertEquals(IdType.UNKNOWN, id.type());
|
||||
Assert.assertEquals(object, id.asObject());
|
||||
Assert.assertEquals(object.hashCode(), id.hashCode());
|
||||
Assert.assertEquals(object.toString(), id.toString());
|
||||
Assert.assertTrue(id.equals(IdGenerator.of(object)));
|
||||
Assert.assertFalse(id.equals(IdGenerator.of(object2)));
|
||||
Assert.assertFalse(id.equals(object));
|
||||
|
||||
Assert.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
id.asString();
|
||||
});
|
||||
Assert.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
id.asLong();
|
||||
});
|
||||
Assert.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
id.asBytes();
|
||||
});
|
||||
Assert.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
id.compareTo(id);
|
||||
});
|
||||
Assert.assertThrows(UnsupportedOperationException.class, () -> {
|
||||
id.length();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOfObjectId() {
|
||||
Object any1 = 123;
|
||||
Id id1 = IdGenerator.of(any1);
|
||||
Assert.assertEquals(IdType.LONG, id1.type());
|
||||
Assert.assertEquals(123L, id1.asObject());
|
||||
|
||||
Object any2 = 123L;
|
||||
Id id2 = IdGenerator.of(any2);
|
||||
Assert.assertEquals(id1, id2);
|
||||
|
||||
Object any3 = "123";
|
||||
Id id3 = IdGenerator.of(any3);
|
||||
Assert.assertEquals(IdType.STRING, id3.type());
|
||||
Assert.assertEquals("123", id3.asObject());
|
||||
|
||||
Object any4 = "12" + "3";
|
||||
Id id4 = IdGenerator.of(any4);
|
||||
Assert.assertEquals(id3, id4);
|
||||
|
||||
Object any5 = UUID.randomUUID();
|
||||
Id id5 = IdGenerator.of(any5);
|
||||
Assert.assertEquals(IdType.UUID, id5.type());
|
||||
Assert.assertEquals(any5, id5.asObject());
|
||||
|
||||
Object any6 = UUID.fromString(any5.toString());
|
||||
Id id6 = IdGenerator.of(any6);
|
||||
Assert.assertEquals(id5, id6);
|
||||
|
||||
Object any7 = ByteBuffer.wrap(new byte[]{1, 2});
|
||||
Id id7 = IdGenerator.of(any7);
|
||||
Assert.assertEquals(IdType.UNKNOWN, id7.type());
|
||||
Assert.assertEquals(ByteBuffer.wrap(new byte[]{1, 2}), id7.asObject());
|
||||
|
||||
Object any8 = ByteBuffer.wrap(new byte[]{1, 2});
|
||||
Id id8 = IdGenerator.of(any8);
|
||||
Assert.assertEquals(id7, id8);
|
||||
|
||||
Object any9 = id1;
|
||||
Id id9 = IdGenerator.of(any9);
|
||||
Assert.assertEquals(any9, id9);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdType() {
|
||||
Assert.assertEquals(IdType.LONG, IdType.valueOfPrefix("L"));
|
||||
|
|
@ -17,7 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.util;
|
||||
package com.baidu.hugegraph.unit.id;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
|
@ -53,6 +55,35 @@ public class IdUtilTest {
|
|||
Assert.assertEquals(id, IdUtil.readString("ES1111>2222>3>L4444"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteReadBinString() {
|
||||
Id id = IdGenerator.of(123);
|
||||
ByteBuffer bytes = ByteBuffer.wrap(genBytes("087b"));
|
||||
Assert.assertEquals(bytes, IdUtil.writeBinString(id));
|
||||
Assert.assertEquals(id, IdUtil.readBinString(bytes));
|
||||
|
||||
id = IdGenerator.of("123");
|
||||
bytes = ByteBuffer.wrap(genBytes("82313233"));
|
||||
Assert.assertEquals(bytes, IdUtil.writeBinString(id));
|
||||
Assert.assertEquals(id, IdUtil.readBinString(bytes));
|
||||
|
||||
String uuid = "835e1153-9281-4957-8691-cf79258e90eb";
|
||||
id = IdGenerator.of(uuid, true);
|
||||
bytes = ByteBuffer.wrap(genBytes("7f835e1153928149578691cf79258e90eb"));
|
||||
Assert.assertEquals(bytes, IdUtil.writeBinString(id));
|
||||
Assert.assertEquals(id, IdUtil.readBinString(bytes));
|
||||
|
||||
id = EdgeId.parse("S1>2>3>L4");
|
||||
bytes = ByteBuffer.wrap(genBytes("7e803182080233ff0804"));
|
||||
Assert.assertEquals(bytes, IdUtil.writeBinString(id));
|
||||
Assert.assertEquals(id, IdUtil.readBinString(bytes));
|
||||
|
||||
id = EdgeId.parse("S1111>2222>3>L4444");
|
||||
bytes = ByteBuffer.wrap(genBytes("7e8331313131821808ae33ff18115c"));
|
||||
Assert.assertEquals(bytes, IdUtil.writeBinString(id));
|
||||
Assert.assertEquals(id, IdUtil.readBinString(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteReadStoredString() {
|
||||
Id id = IdGenerator.of(123);
|
||||
|
|
@ -106,4 +137,14 @@ public class IdUtilTest {
|
|||
Assert.assertEquals(1, IdUtil.unescape("", "", "").length);
|
||||
Assert.assertEquals(1, IdUtil.unescape("foo", "bar", "baz").length);
|
||||
}
|
||||
|
||||
private byte[] genBytes(String string) {
|
||||
int size = string.length() / 2;
|
||||
byte[] bytes = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
String b = string.substring(i * 2, i * 2 + 2);
|
||||
bytes[i] = Integer.valueOf(b, 16).byteValue();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.mysql;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.store.mysql.MysqlUtil;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
|
||||
public class MysqlUtilTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testEscapeString() {
|
||||
Assert.assertEquals("abc", MysqlUtil.escapeString("abc"));
|
||||
Assert.assertEquals("abc\"", MysqlUtil.escapeString("abc\""));
|
||||
|
||||
Assert.assertEquals("can\\'t", MysqlUtil.escapeString("can't"));
|
||||
Assert.assertEquals("abc\\n", MysqlUtil.escapeString("abc\n"));
|
||||
Assert.assertEquals("abc\\r", MysqlUtil.escapeString("abc\r"));
|
||||
Assert.assertEquals("abc\\\\", MysqlUtil.escapeString("abc\\"));
|
||||
Assert.assertEquals("abc\\0", MysqlUtil.escapeString("abc\u0000"));
|
||||
Assert.assertEquals("abc\\Z", MysqlUtil.escapeString("abc\u001a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEscapeAndWrapString() {
|
||||
Assert.assertEquals("'abc'", MysqlUtil.escapeAndWrapString("abc"));
|
||||
Assert.assertEquals("'abc\"'", MysqlUtil.escapeAndWrapString("abc\""));
|
||||
Assert.assertEquals("''", MysqlUtil.escapeAndWrapString(""));
|
||||
|
||||
Assert.assertEquals("'can\\'t'",
|
||||
MysqlUtil.escapeAndWrapString("can't"));
|
||||
Assert.assertEquals("'abc\\n'",
|
||||
MysqlUtil.escapeAndWrapString("abc\n"));
|
||||
Assert.assertEquals("'abc\\r'",
|
||||
MysqlUtil.escapeAndWrapString("abc\r"));
|
||||
Assert.assertEquals("'abc\\\\'",
|
||||
MysqlUtil.escapeAndWrapString("abc\\"));
|
||||
Assert.assertEquals("'abc\\0'",
|
||||
MysqlUtil.escapeAndWrapString("abc\u0000"));
|
||||
Assert.assertEquals("'abc\\Z'",
|
||||
MysqlUtil.escapeAndWrapString("abc\u001a"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.mysql;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.query.Condition.RelationType;
|
||||
import com.baidu.hugegraph.backend.store.mysql.WhereBuilder;
|
||||
import com.baidu.hugegraph.exception.NotSupportException;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class WhereBuilderTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testRelation() {
|
||||
WhereBuilder where = new WhereBuilder();
|
||||
where.relation("key1", RelationType.EQ, "value1");
|
||||
Assert.assertEquals(" WHERE key1='value1'", where.build().toString());
|
||||
Assert.assertEquals(" WHERE key1='value1'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.EQ, "value1");
|
||||
Assert.assertEquals(" key1='value1'", where.build().toString());
|
||||
Assert.assertEquals(" key1='value1'", where.toString());
|
||||
|
||||
where.and().relation("key2", RelationType.EQ, "value2");
|
||||
Assert.assertEquals(" key1='value1' AND key2='value2'",
|
||||
where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.NEQ, "value1");
|
||||
Assert.assertEquals(" key1!='value1'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.GT, "value1");
|
||||
Assert.assertEquals(" key1>'value1'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.GTE, "value1");
|
||||
Assert.assertEquals(" key1>='value1'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.LT, "value1");
|
||||
Assert.assertEquals(" key1<'value1'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.LTE, "value1");
|
||||
Assert.assertEquals(" key1<='value1'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.relation("key1", RelationType.IN, ImmutableList.of("v1", "v2"));
|
||||
Assert.assertEquals(" key1 IN ('v1', 'v2')", where.toString());
|
||||
|
||||
Assert.assertThrows(NotSupportException.class, () -> {
|
||||
new WhereBuilder().relation("k", RelationType.CONTAINS_KEY, "v");
|
||||
});
|
||||
Assert.assertThrows(NotSupportException.class, () -> {
|
||||
new WhereBuilder().relation("k", RelationType.CONTAINS_VALUE, "v");
|
||||
});
|
||||
Assert.assertThrows(NotSupportException.class, () -> {
|
||||
new WhereBuilder().relation("k", RelationType.NOT_IN, "v");
|
||||
});
|
||||
Assert.assertThrows(NotSupportException.class, () -> {
|
||||
new WhereBuilder().relation("k", RelationType.TEXT_CONTAINS, "v");
|
||||
});
|
||||
Assert.assertThrows(NotSupportException.class, () -> {
|
||||
new WhereBuilder().relation("k", RelationType.SCAN, "v");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnd() {
|
||||
WhereBuilder where = new WhereBuilder(false);
|
||||
where.and(ImmutableList.of("k1", "k2"), ImmutableList.of("v1", "v2"));
|
||||
Assert.assertEquals(" k1='v1' AND k2='v2'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.and(ImmutableList.of("k1", "k2"), "!=",
|
||||
ImmutableList.of("v1", "v2"));
|
||||
Assert.assertEquals(" k1!='v1' AND k2!='v2'", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.and(ImmutableList.of("k1", "k2", "k3"),
|
||||
ImmutableList.of("=", "!=", ">"),
|
||||
ImmutableList.of("v1", "v2", 3));
|
||||
Assert.assertEquals(" k1='v1' AND k2!='v2' AND k3>3", where.toString());
|
||||
|
||||
where = new WhereBuilder(false);
|
||||
where.and(ImmutableList.of("k1", "k2"), "=");
|
||||
Assert.assertEquals(" k1=? AND k2=?", where.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIn() {
|
||||
WhereBuilder where = new WhereBuilder(false);
|
||||
where.in("key", ImmutableList.of("v1", "v2", "v3"));
|
||||
Assert.assertEquals(" key IN ('v1', 'v2', 'v3')", where.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGt() {
|
||||
WhereBuilder where = new WhereBuilder(false);
|
||||
where.gte(ImmutableList.of("k1", "k2"), ImmutableList.of("v1", "v2"));
|
||||
Assert.assertEquals(" (k1, k2) >= ('v1', 'v2')", where.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.serializer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.serializer.BinaryBackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry.BackendColumn;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class BinaryBackendEntryTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testColumns() {
|
||||
BinaryBackendEntry entry = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BackendColumn col = BackendColumn.of(new byte[]{1, 2},
|
||||
new byte[]{3, 4});
|
||||
|
||||
entry.columns(ImmutableList.of(col));
|
||||
Assert.assertEquals(1, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(col), entry.columns());
|
||||
|
||||
entry.columns(ImmutableList.of(col, col));
|
||||
Assert.assertEquals(3, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(col, col, col), entry.columns());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() {
|
||||
BinaryBackendEntry entry = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BackendColumn col = BackendColumn.of(new byte[]{1, 2},
|
||||
new byte[]{3, 4});
|
||||
|
||||
entry.column(col);
|
||||
Assert.assertEquals(1, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(col), entry.columns());
|
||||
|
||||
entry.clear();
|
||||
Assert.assertEquals(0, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(), entry.columns());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMerge() {
|
||||
BinaryBackendEntry entry = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BinaryBackendEntry entry2 = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{2, 2});
|
||||
BackendColumn col = BackendColumn.of(new byte[]{1, 2},
|
||||
new byte[]{3, 4});
|
||||
BackendColumn col2 = BackendColumn.of(new byte[]{5, 6},
|
||||
new byte[]{7, 8});
|
||||
|
||||
entry.column(col);
|
||||
entry2.column(col2);
|
||||
Assert.assertEquals(1, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(col), entry.columns());
|
||||
|
||||
entry.merge(entry2);
|
||||
Assert.assertEquals(2, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(col, col2), entry.columns());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
BinaryBackendEntry entry = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BinaryBackendEntry entry2 = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{2, 2});
|
||||
BinaryBackendEntry entry3 = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BinaryBackendEntry entry4 = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BinaryBackendEntry entry5 = new BinaryBackendEntry(HugeType.VERTEX,
|
||||
new byte[]{1, 2});
|
||||
BackendColumn col = BackendColumn.of(new byte[]{1, 2},
|
||||
new byte[]{3, 4});
|
||||
BackendColumn col2 = BackendColumn.of(new byte[]{5, 6},
|
||||
new byte[]{7, 8});
|
||||
|
||||
entry.column(col);
|
||||
entry2.column(col2);
|
||||
entry3.column(col2);
|
||||
entry4.column(col);
|
||||
entry4.column(col2);
|
||||
entry5.column(col);
|
||||
|
||||
Assert.assertNotEquals(entry, entry2);
|
||||
Assert.assertNotEquals(entry, entry3);
|
||||
Assert.assertNotEquals(entry, entry4);
|
||||
Assert.assertEquals(entry, entry5);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.serializer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.serializer.BinaryInlineSerializer;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry;
|
||||
import com.baidu.hugegraph.structure.HugeEdge;
|
||||
import com.baidu.hugegraph.structure.HugeVertex;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.testutil.Whitebox;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
import com.baidu.hugegraph.unit.FakeObjects;
|
||||
|
||||
public class BinaryInlineSerializerTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testVertex() {
|
||||
BinaryInlineSerializer ser = new BinaryInlineSerializer();
|
||||
HugeEdge edge = new FakeObjects().newEdge(123, 456);
|
||||
|
||||
BackendEntry entry1 = ser.writeVertex(edge.sourceVertex());
|
||||
HugeVertex vertex1 = ser.readVertex(edge.graph(), entry1);
|
||||
Assert.assertEquals(edge.sourceVertex(), vertex1);
|
||||
Assert.assertEquals(edge.sourceVertex().getProperties(),
|
||||
vertex1.getProperties());
|
||||
|
||||
BackendEntry entry2 = ser.writeVertex(edge.targetVertex());
|
||||
HugeVertex vertex2 = ser.readVertex(edge.graph(), entry2);
|
||||
Assert.assertEquals(edge.targetVertex(), vertex2);
|
||||
Assert.assertEquals(edge.targetVertex().getProperties(),
|
||||
vertex2.getProperties());
|
||||
|
||||
Whitebox.setInternalState(vertex2, "removed", true);
|
||||
Assert.assertTrue(vertex2.removed());
|
||||
BackendEntry entry3 = ser.writeVertex(vertex2);
|
||||
Assert.assertEquals(0, entry3.columnsSize());
|
||||
|
||||
Assert.assertNull(ser.readVertex(edge.graph(), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEdge() {
|
||||
BinaryInlineSerializer ser = new BinaryInlineSerializer();
|
||||
|
||||
FakeObjects objects = new FakeObjects();
|
||||
HugeEdge edge1 = objects.newEdge(123, 456);
|
||||
HugeEdge edge2 = objects.newEdge(147, 789);
|
||||
|
||||
BackendEntry entry1 = ser.writeEdge(edge1);
|
||||
HugeVertex vertex1 = ser.readVertex(edge1.graph(), entry1);
|
||||
Assert.assertEquals(1, vertex1.getEdges().size());
|
||||
HugeEdge edge = vertex1.getEdges().iterator().next();
|
||||
Assert.assertEquals(edge1, edge);
|
||||
Assert.assertEquals(edge1.getProperties(), edge.getProperties());
|
||||
|
||||
BackendEntry entry2 = ser.writeEdge(edge2);
|
||||
HugeVertex vertex2 = ser.readVertex(edge1.graph(), entry2);
|
||||
Assert.assertEquals(1, vertex2.getEdges().size());
|
||||
edge = vertex2.getEdges().iterator().next();
|
||||
Assert.assertEquals(edge2, edge);
|
||||
Assert.assertEquals(edge2.getProperties(), edge.getProperties());
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.core;
|
||||
package com.baidu.hugegraph.unit.serializer;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.serializer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.BackendException;
|
||||
import com.baidu.hugegraph.backend.serializer.AbstractSerializer;
|
||||
import com.baidu.hugegraph.backend.serializer.BinaryInlineSerializer;
|
||||
import com.baidu.hugegraph.backend.serializer.BinarySerializer;
|
||||
import com.baidu.hugegraph.backend.serializer.SerializerFactory;
|
||||
import com.baidu.hugegraph.backend.serializer.TextSerializer;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
|
||||
public class SerializerFactoryTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testSerializer() {
|
||||
AbstractSerializer serializer = SerializerFactory.serializer("text");
|
||||
Assert.assertEquals(TextSerializer.class, serializer.getClass());
|
||||
|
||||
serializer = SerializerFactory.serializer("binary");
|
||||
Assert.assertEquals(BinarySerializer.class, serializer.getClass());
|
||||
|
||||
serializer = SerializerFactory.serializer("binaryinline");
|
||||
Assert.assertEquals(BinaryInlineSerializer.class,
|
||||
serializer.getClass());
|
||||
|
||||
Assert.assertThrows(BackendException.class, () -> {
|
||||
SerializerFactory.serializer("invalid");
|
||||
}, e -> {
|
||||
Assert.assertTrue(e.getMessage().contains(
|
||||
"Not exists serializer:"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegister() {
|
||||
SerializerFactory.register("fake", FakeSerializer.class.getName());
|
||||
Assert.assertEquals(FakeSerializer.class,
|
||||
SerializerFactory.serializer("fake").getClass());
|
||||
|
||||
Assert.assertThrows(BackendException.class, () -> {
|
||||
// exist
|
||||
SerializerFactory.register("fake", FakeSerializer.class.getName());
|
||||
}, e -> {
|
||||
Assert.assertTrue(e.getMessage().contains("Exists serializer:"));
|
||||
});
|
||||
|
||||
Assert.assertThrows(BackendException.class, () -> {
|
||||
// invalid class
|
||||
SerializerFactory.register("fake", "com.baidu.hugegraph.Invalid");
|
||||
}, e -> {
|
||||
Assert.assertTrue(e.getMessage().contains("Invalid class:"));
|
||||
});
|
||||
|
||||
Assert.assertThrows(BackendException.class, () -> {
|
||||
// subclass
|
||||
SerializerFactory.register("fake", "com.baidu.hugegraph.HugeGraph");
|
||||
}, e -> {
|
||||
Assert.assertTrue(e.getMessage().contains(
|
||||
"Class is not a subclass of class"));
|
||||
});
|
||||
}
|
||||
|
||||
public static class FakeSerializer extends BinarySerializer {
|
||||
|
||||
public FakeSerializer() {
|
||||
super(true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.serializer;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.Id;
|
||||
import com.baidu.hugegraph.backend.id.IdGenerator;
|
||||
import com.baidu.hugegraph.backend.serializer.TableBackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry.BackendColumn;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
import com.baidu.hugegraph.type.define.Cardinality;
|
||||
import com.baidu.hugegraph.type.define.HugeKeys;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class TableBackendEntryTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testType() {
|
||||
Id id = IdGenerator.of(1L);
|
||||
TableBackendEntry entry = new TableBackendEntry(id);
|
||||
Assert.assertNull(entry.type());
|
||||
Assert.assertEquals(id, entry.id());
|
||||
|
||||
entry.type(HugeType.VERTEX);
|
||||
Assert.assertEquals(HugeType.VERTEX, entry.type());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testId() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
Assert.assertNull(entry.id());
|
||||
|
||||
Id id = IdGenerator.of(1L);
|
||||
entry.id(id);
|
||||
Assert.assertEquals(HugeType.VERTEX, entry.type());
|
||||
Assert.assertEquals(id, entry.id());
|
||||
|
||||
Assert.assertNull(entry.subId());
|
||||
entry.subId(id);
|
||||
Assert.assertEquals(id, entry.subId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfChanged() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
Assert.assertTrue(entry.selfChanged());
|
||||
|
||||
entry.selfChanged(false);
|
||||
Assert.assertFalse(entry.selfChanged());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumn() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1L));
|
||||
entry.column(HugeKeys.ID, "v1");
|
||||
Assert.assertEquals("v1", entry.column(HugeKeys.ID));
|
||||
Assert.assertEquals("TableBackendEntry{Row{type=VERTEX, id=1, " +
|
||||
"columns={ID=v1}}, sub-rows: []}",
|
||||
entry.toString());
|
||||
|
||||
entry.column(HugeKeys.ID, "v2");
|
||||
Assert.assertEquals("v2", entry.column(HugeKeys.ID));
|
||||
Assert.assertEquals("TableBackendEntry{Row{type=VERTEX, id=1, " +
|
||||
"columns={ID=v2}}, sub-rows: []}",
|
||||
entry.toString());
|
||||
|
||||
entry.column(HugeKeys.NAME, "tom");
|
||||
Assert.assertEquals("tom", entry.column(HugeKeys.NAME));
|
||||
Assert.assertEquals("v2", entry.column(HugeKeys.ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumnOfMap() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
entry.column(HugeKeys.PROPERTIES, "k1", "v1");
|
||||
Assert.assertEquals(ImmutableMap.of("k1", "v1"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "k2", "v2");
|
||||
Assert.assertEquals(ImmutableMap.of("k1", "v1", "k2", "v2"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "k3", "v3");
|
||||
Assert.assertEquals(ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "k1", "v0");
|
||||
Assert.assertEquals(ImmutableMap.of("k1", "v0", "k2", "v2", "k3", "v3"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumnWithCardinalitySingle() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
entry.column(HugeKeys.ID, "v1", Cardinality.SINGLE);
|
||||
Assert.assertEquals("v1", entry.column(HugeKeys.ID));
|
||||
|
||||
entry.column(HugeKeys.ID, "v2", Cardinality.SINGLE);
|
||||
Assert.assertEquals("v2", entry.column(HugeKeys.ID));
|
||||
|
||||
Assert.assertThrows(ClassCastException.class, () -> {
|
||||
entry.column(HugeKeys.ID, "v3", Cardinality.SET);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumnWithCardinalityList() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
entry.column(HugeKeys.PROPERTIES, "v1", Cardinality.LIST);
|
||||
Assert.assertEquals(ImmutableList.of("v1"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "v2", Cardinality.LIST);
|
||||
Assert.assertEquals(ImmutableList.of("v1", "v2"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "v3", Cardinality.LIST);
|
||||
Assert.assertEquals(ImmutableList.of("v1", "v2", "v3"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "v2", Cardinality.LIST);
|
||||
Assert.assertEquals(ImmutableList.of("v1", "v2", "v3", "v2"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumnWithCardinalitySet() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
entry.column(HugeKeys.PROPERTIES, "v1", Cardinality.SET);
|
||||
Assert.assertEquals(ImmutableSet.of("v1"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "v2", Cardinality.SET);
|
||||
Assert.assertEquals(ImmutableSet.of("v1", "v2"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "v3", Cardinality.SET);
|
||||
Assert.assertEquals(ImmutableSet.of("v1", "v2", "v3"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
|
||||
entry.column(HugeKeys.PROPERTIES, "v2", Cardinality.SET);
|
||||
Assert.assertEquals(ImmutableSet.of("v1", "v2", "v3"),
|
||||
entry.column(HugeKeys.PROPERTIES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotImplemented() {
|
||||
TableBackendEntry entry = new TableBackendEntry(HugeType.VERTEX);
|
||||
BackendColumn col = BackendColumn.of(new byte[]{1}, new byte[]{12});
|
||||
|
||||
Assert.assertThrows(NotImplementedException.class, () -> {
|
||||
entry.columnsSize();
|
||||
});
|
||||
Assert.assertThrows(NotImplementedException.class, () -> {
|
||||
entry.columns();
|
||||
});
|
||||
Assert.assertThrows(NotImplementedException.class, () -> {
|
||||
entry.columns(ImmutableList.of(col));
|
||||
});
|
||||
Assert.assertThrows(NotImplementedException.class, () -> {
|
||||
entry.columns(col);
|
||||
});
|
||||
Assert.assertThrows(NotImplementedException.class, () -> {
|
||||
entry.merge(entry);
|
||||
});
|
||||
Assert.assertThrows(NotImplementedException.class, () -> {
|
||||
entry.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright 2017 HugeGraph Authors
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with this
|
||||
* work for additional information regarding copyright ownership. The ASF
|
||||
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.baidu.hugegraph.unit.serializer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baidu.hugegraph.backend.id.IdGenerator;
|
||||
import com.baidu.hugegraph.backend.serializer.TextBackendEntry;
|
||||
import com.baidu.hugegraph.backend.store.BackendEntry.BackendColumn;
|
||||
import com.baidu.hugegraph.testutil.Assert;
|
||||
import com.baidu.hugegraph.type.HugeType;
|
||||
import com.baidu.hugegraph.type.define.HugeKeys;
|
||||
import com.baidu.hugegraph.unit.BaseUnitTest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class TextBackendEntryTest extends BaseUnitTest {
|
||||
|
||||
@Test
|
||||
public void testColumns() {
|
||||
TextBackendEntry entry = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1));
|
||||
entry.column(HugeKeys.ID, "1");
|
||||
entry.column(HugeKeys.NAME, "tom");
|
||||
|
||||
BackendColumn col1 = BackendColumn.of(new byte[]{'i', 'd'},
|
||||
new byte[]{'1'});
|
||||
BackendColumn col2 = BackendColumn.of(new byte[]{'n', 'a', 'm', 'e'},
|
||||
new byte[]{'t', 'o', 'm'});
|
||||
|
||||
Assert.assertEquals(2, entry.columnsSize());
|
||||
Assert.assertEquals(ImmutableList.of(col1, col2),
|
||||
entry.columns());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopy() {
|
||||
TextBackendEntry entry = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1));
|
||||
entry.column(HugeKeys.ID, "1");
|
||||
entry.column(HugeKeys.NAME, "tom");
|
||||
Assert.assertEquals(2, entry.columnsSize());
|
||||
|
||||
TextBackendEntry entry2 = entry.copy();
|
||||
Assert.assertEquals(2, entry2.columnsSize());
|
||||
Assert.assertEquals("1", entry2.column(HugeKeys.ID));
|
||||
Assert.assertEquals("tom", entry2.column(HugeKeys.NAME));
|
||||
|
||||
entry2.clear();
|
||||
Assert.assertEquals(0, entry2.columnsSize());
|
||||
|
||||
Assert.assertEquals(2, entry.columnsSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
TextBackendEntry entry = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1));
|
||||
TextBackendEntry entry2 = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(2));
|
||||
TextBackendEntry entry3 = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1));
|
||||
TextBackendEntry entry4 = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1));
|
||||
TextBackendEntry entry5 = new TextBackendEntry(HugeType.VERTEX,
|
||||
IdGenerator.of(1));
|
||||
entry.column(HugeKeys.NAME, "tom");
|
||||
entry2.column(HugeKeys.NAME, "tom");
|
||||
entry3.column(HugeKeys.NAME, "tom2");
|
||||
entry4.column(HugeKeys.NAME, "tom");
|
||||
entry4.column(HugeKeys.LABEL, "person");
|
||||
entry5.column(HugeKeys.NAME, "tom");
|
||||
|
||||
Assert.assertNotEquals(entry, entry2);
|
||||
Assert.assertNotEquals(entry, entry3);
|
||||
Assert.assertNotEquals(entry, entry4);
|
||||
Assert.assertNotEquals(entry4, entry);
|
||||
Assert.assertEquals(entry, entry5);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.apache.tinkerpop.shaded.jackson.core.type.TypeReference;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
|
@ -59,16 +57,6 @@ import com.google.common.collect.ImmutableMap;
|
|||
|
||||
public class JsonUtilTest extends BaseUnitTest {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// pass
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
// pass
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializeStringId() {
|
||||
Id id = IdGenerator.of("123456");
|
||||
|
|
@ -295,7 +283,7 @@ public class JsonUtilTest extends BaseUnitTest {
|
|||
@Test
|
||||
public void testDeserializeList() {
|
||||
String json = "[\"1\", \"2\", \"3\"]";
|
||||
TypeReference typeRef = new TypeReference<List<Integer>>() {};
|
||||
TypeReference<?> typeRef = new TypeReference<List<Integer>>() {};
|
||||
Assert.assertEquals(ImmutableList.of(1, 2, 3),
|
||||
JsonUtil.fromJson(json, typeRef));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue