support bin serialization for cassandra (#680)

Change-Id: Ib4f48f3235ac9e5526c63c5617e3819ab4d29711
This commit is contained in:
Jermy Li 2019-09-17 11:14:30 +08:00 committed by Linary
parent 1208522699
commit efcd839ee2
51 changed files with 1803 additions and 674 deletions

View File

@ -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");
}
}

View File

@ -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) {

View File

@ -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";
}
}

View File

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

View File

@ -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

View File

@ -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)) {

View File

@ -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,

View File

@ -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();
}
}
}

View File

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

View File

@ -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 {

View File

@ -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

View File

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

View File

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

View File

@ -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) {

View File

@ -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

View File

@ -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");
}
}

View File

@ -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;
}

View File

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

View File

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

View File

@ -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";
}
}

View File

@ -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");
}
}

View File

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

View File

@ -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";
}
}

View File

@ -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");

View File

@ -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()));

View File

@ -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;
}
}

View File

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

View File

@ -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 {

View File

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

View File

@ -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 {

View File

@ -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 {

View File

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

View File

@ -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";
}
}

View File

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

View File

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

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -17,7 +17,7 @@
* under the License.
*/
package com.baidu.hugegraph.unit.core;
package com.baidu.hugegraph.unit.cassandra;
import java.util.Map;

View File

@ -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();
}

View File

@ -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"));

View File

@ -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;
}
}

View File

@ -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"));
}
}

View File

@ -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());
}
}

View File

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

View File

@ -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());
}
}

View File

@ -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;

View File

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

View File

@ -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();
});
}
}

View File

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

View File

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