From c8aa20a8106c2fac1b243913f3ef3591b0eb4c88 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Thu, 30 Dec 2021 13:38:42 +0800 Subject: [PATCH] support dauration data type --- .../client/graph/data/DurationWrapper.java | 78 +++++++ .../client/graph/data/ValueWrapper.java | 150 +++++++++---- .../client/storage/data/BaseTableRow.java | 5 + .../nebula/client/graph/data/TestData.java | 197 ++++++++++-------- .../client/graph/data/TestDataFromServer.java | 29 ++- 5 files changed, 327 insertions(+), 132 deletions(-) create mode 100644 client/src/main/java/com/vesoft/nebula/client/graph/data/DurationWrapper.java diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/data/DurationWrapper.java b/client/src/main/java/com/vesoft/nebula/client/graph/data/DurationWrapper.java new file mode 100644 index 000000000..256048926 --- /dev/null +++ b/client/src/main/java/com/vesoft/nebula/client/graph/data/DurationWrapper.java @@ -0,0 +1,78 @@ +/* Copyright (c) 2021 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License. + */ + +package com.vesoft.nebula.client.graph.data; + +import com.vesoft.nebula.Duration; +import java.util.Objects; + +public class DurationWrapper extends BaseDataObject { + private final Duration duration; + + /** + * DurationWrapper is a wrapper for the duration type of nebula-graph + */ + public DurationWrapper(Duration duration) { + this.duration = duration; + } + + /** + * @return utc duration seconds + */ + public long getSeconds() { + return duration.seconds; + } + + /** + * @retrun utc duration microseconds + */ + public int getMicroseconds() { + return duration.microseconds; + } + + /** + * @return utc duration months + */ + public int getMonths() { + return duration.months; + } + + /** + * @return the duration string + */ + public String getDurationString() { + return String.format("duration({months:%d, seconds:%d, microseconds:%d})", + getMonths(), getSeconds(), getMicroseconds()); + } + + + @Override + public String toString() { + long year = duration.seconds / (60 * 60 * 24); + long remainSeconds = duration.seconds - (year) * (60 * 60 * 24); + return String.format("P%dM%dDT%sS", + duration.months, year, remainSeconds + duration.microseconds / 1000000.0); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DurationWrapper that = (DurationWrapper) o; + return duration.months == that.getMonths() + && duration.seconds == that.getSeconds() + && duration.microseconds == that.getMicroseconds(); + } + + @Override + public int hashCode() { + return Objects.hash(duration); + } + +} diff --git a/client/src/main/java/com/vesoft/nebula/client/graph/data/ValueWrapper.java b/client/src/main/java/com/vesoft/nebula/client/graph/data/ValueWrapper.java index 600f66e9e..9858d4564 100644 --- a/client/src/main/java/com/vesoft/nebula/client/graph/data/ValueWrapper.java +++ b/client/src/main/java/com/vesoft/nebula/client/graph/data/ValueWrapper.java @@ -37,15 +37,24 @@ public int getNullType() { @Override public String toString() { switch (nullType) { - case __NULL__: return "NULL"; - case NaN: return "NaN"; - case BAD_DATA: return "BAD_DATA"; - case BAD_TYPE: return "BAD_TYPE"; - case ERR_OVERFLOW: return "ERR_OVERFLOW"; - case UNKNOWN_PROP: return "UNKNOWN_PROP"; - case DIV_BY_ZERO: return "DIV_BY_ZERO"; - case OUT_OF_RANGE: return "OUT_OF_RANGE"; - default: return "Unknown type: " + nullType; + case __NULL__: + return "NULL"; + case NaN: + return "NaN"; + case BAD_DATA: + return "BAD_DATA"; + case BAD_TYPE: + return "BAD_TYPE"; + case ERR_OVERFLOW: + return "ERR_OVERFLOW"; + case UNKNOWN_PROP: + return "UNKNOWN_PROP"; + case DIV_BY_ZERO: + return "DIV_BY_ZERO"; + case OUT_OF_RANGE: + return "OUT_OF_RANGE"; + default: + return "Unknown type: " + nullType; } } } @@ -88,13 +97,15 @@ private String descType() { return "DATASET"; case Value.GGVAL: return "GEOGRAPHY"; + case Value.DUVAL: + return "DURATION"; default: throw new IllegalArgumentException("Unknown field id " + value.getSetField()); } } /** - * @param value the Value get from service + * @param value the Value get from service * @param decodeType the decodeType get from the service to decode the byte array, * but now the service no return the decodeType, so use the utf-8 */ @@ -105,9 +116,9 @@ public ValueWrapper(Value value, String decodeType) { } /** - * @param value the Value get from service - * @param decodeType the decodeType get from the service to decode the byte array, - * but now the service no return the decodeType, so use the utf-8 + * @param value the Value get from service + * @param decodeType the decodeType get from the service to decode the byte array, + * but now the service no return the decodeType, so use the utf-8 * @param timezoneOffset the timezone offset get from the service to calculate local time */ public ValueWrapper(Value value, String decodeType, int timezoneOffset) { @@ -118,6 +129,7 @@ public ValueWrapper(Value value, String decodeType, int timezoneOffset) { /** * get the original data structure, the Value is the return from nebula-graph + * * @return Value */ public Value getValue() { @@ -126,6 +138,7 @@ public Value getValue() { /** * judge the Value is Empty type, the Empty type is the nebula's type + * * @return boolean */ public boolean isEmpty() { @@ -134,6 +147,7 @@ public boolean isEmpty() { /** * judge the Value is Null type,the Null type is the nebula's type + * * @return boolean */ public boolean isNull() { @@ -142,6 +156,7 @@ public boolean isNull() { /** * judge the Value is Boolean type + * * @return boolean */ public boolean isBoolean() { @@ -150,6 +165,7 @@ public boolean isBoolean() { /** * judge the Value is Long type + * * @return boolean */ public boolean isLong() { @@ -158,6 +174,7 @@ public boolean isLong() { /** * judge the Value is Double type + * * @return boolean */ public boolean isDouble() { @@ -166,6 +183,7 @@ public boolean isDouble() { /** * judge the Value is String type + * * @return boolean */ public boolean isString() { @@ -174,6 +192,7 @@ public boolean isString() { /** * judge the Value is List type, the List type is the nebula's type + * * @return boolean */ public boolean isList() { @@ -182,6 +201,7 @@ public boolean isList() { /** * judge the Value is Set type, the Set type is the nebula's type + * * @return boolean */ public boolean isSet() { @@ -190,6 +210,7 @@ public boolean isSet() { /** * judge the Value is Map type, the Map type is the nebula's type + * * @return boolean */ public boolean isMap() { @@ -198,6 +219,7 @@ public boolean isMap() { /** * judge the Value is Time type, the Time type is the nebula's type + * * @return boolean */ public boolean isTime() { @@ -206,6 +228,7 @@ public boolean isTime() { /** * judge the Value is Date type, the Date type is the nebula's type + * * @return boolean */ public boolean isDate() { @@ -214,6 +237,7 @@ public boolean isDate() { /** * judge the Value is DateTime type, the DateTime type is the nebula's type + * * @return boolean */ public boolean isDateTime() { @@ -222,6 +246,7 @@ public boolean isDateTime() { /** * judge the Value is Vertex type, the Vertex type is the nebula's type + * * @return boolean */ public boolean isVertex() { @@ -230,6 +255,7 @@ public boolean isVertex() { /** * judge the Value is Edge type, the Edge type is the nebula's type + * * @return boolean */ public boolean isEdge() { @@ -238,6 +264,7 @@ public boolean isEdge() { /** * judge the Value is Path type, the Path type is the nebula's type + * * @return boolean */ public boolean isPath() { @@ -246,20 +273,31 @@ public boolean isPath() { /** * judge the Value is Geography type, the Geography type is the nebula's type + * * @return boolean */ public boolean isGeography() { return value.getSetField() == Value.GGVAL; } + /** + * judge the Value is Duration type, the Duration type is the nebula's type + * + * @return boolean + */ + public boolean isDuration() { + return value.getSetField() == Value.DUVAL; + } + /** * Convert the original data type Value to NullType + * * @return NullType * @throws InvalidValueException if the value type is not null */ public NullType asNull() throws InvalidValueException { if (value.getSetField() == Value.NVAL) { - return new NullType(((com.vesoft.nebula.NullType)value.getFieldValue()).getValue()); + return new NullType(((com.vesoft.nebula.NullType) value.getFieldValue()).getValue()); } else { throw new InvalidValueException( "Cannot get field nullType because value's type is " + descType()); @@ -268,25 +306,27 @@ public NullType asNull() throws InvalidValueException { /** * Convert the original data type Value to boolean + * * @return boolean * @throws InvalidValueException if the value type is not boolean */ public boolean asBoolean() throws InvalidValueException { if (value.getSetField() == Value.BVAL) { - return (boolean)(value.getFieldValue()); + return (boolean) (value.getFieldValue()); } throw new InvalidValueException( - "Cannot get field boolean because value's type is " + descType()); + "Cannot get field boolean because value's type is " + descType()); } /** * Convert the original data type Value to long + * * @return long * @throws InvalidValueException if the value type is not long */ public long asLong() throws InvalidValueException { if (value.getSetField() == Value.IVAL) { - return (long)(value.getFieldValue()); + return (long) (value.getFieldValue()); } else { throw new InvalidValueException( "Cannot get field long because value's type is " + descType()); @@ -295,13 +335,14 @@ public long asLong() throws InvalidValueException { /** * Convert the original data type Value to String + * * @return String - * @throws InvalidValueException if the value type is not string + * @throws InvalidValueException if the value type is not string * @throws UnsupportedEncodingException if decode bianry failed */ public String asString() throws InvalidValueException, UnsupportedEncodingException { if (value.getSetField() == Value.SVAL) { - return new String((byte[])value.getFieldValue(), decodeType); + return new String((byte[]) value.getFieldValue(), decodeType); } throw new InvalidValueException( "Cannot get field string because value's type is " + descType()); @@ -309,12 +350,13 @@ public String asString() throws InvalidValueException, UnsupportedEncodingExcept /** * Convert the original data type Value to double + * * @return double * @throws InvalidValueException if the value type is not double */ public double asDouble() throws InvalidValueException { if (value.getSetField() == Value.FVAL) { - return (double)value.getFieldValue(); + return (double) value.getFieldValue(); } throw new InvalidValueException( "Cannot get field double because value's type is " + descType()); @@ -322,13 +364,14 @@ public double asDouble() throws InvalidValueException { /** * Convert the original data type Value to ArrayList + * * @return ArrayList of ValueWrapper * @throws InvalidValueException if the value type is not list */ public ArrayList asList() throws InvalidValueException { if (value.getSetField() != Value.LVAL) { throw new InvalidValueException( - "Cannot get field type `list' because value's type is " + descType()); + "Cannot get field type `list' because value's type is " + descType()); } ArrayList values = new ArrayList<>(); for (Value value : value.getLVal().getValues()) { @@ -339,13 +382,14 @@ public ArrayList asList() throws InvalidValueException { /** * Convert the original data type Value to HashSet + * * @return HashSet of ValueWrapper * @throws InvalidValueException if the value type is not set */ public HashSet asSet() throws InvalidValueException { if (value.getSetField() != Value.UVAL) { throw new InvalidValueException( - "Cannot get field type `set' because value's type is " + descType()); + "Cannot get field type `set' because value's type is " + descType()); } HashSet values = new HashSet<>(); for (Value value : value.getUVal().getValues()) { @@ -356,14 +400,15 @@ public HashSet asSet() throws InvalidValueException { /** * Convert the original data type Value to HashMap + * * @return HashMap, the key is String, value is ValueWrapper * @throws InvalidValueException if the value type is not map */ public HashMap asMap() - throws InvalidValueException, UnsupportedEncodingException { + throws InvalidValueException, UnsupportedEncodingException { if (value.getSetField() != Value.MVAL) { throw new InvalidValueException( - "Cannot get field type `set' because value's type is " + descType()); + "Cannot get field type `set' because value's type is " + descType()); } HashMap kvs = new HashMap<>(); Map inValues = value.getMVal().getKvs(); @@ -376,21 +421,23 @@ public HashMap asMap() /** * Convert the original data type Value to TimeWrapper + * * @return TimeWrapper * @throws InvalidValueException if the value type is not time */ public TimeWrapper asTime() throws InvalidValueException { if (value.getSetField() == Value.TVAL) { return (TimeWrapper) new TimeWrapper(value.getTVal()) - .setDecodeType(decodeType) - .setTimezoneOffset(timezoneOffset); + .setDecodeType(decodeType) + .setTimezoneOffset(timezoneOffset); } throw new InvalidValueException( - "Cannot get field time because value's type is " + descType()); + "Cannot get field time because value's type is " + descType()); } /** * Convert the original data type Value to DateWrapper + * * @return DateWrapper * @throws InvalidValueException if the value type is not date */ @@ -399,35 +446,37 @@ public DateWrapper asDate() throws InvalidValueException { return new DateWrapper(value.getDVal()); } throw new InvalidValueException( - "Cannot get field date because value's type is " + descType()); + "Cannot get field date because value's type is " + descType()); } /** * Convert the original data type Value to DateTimeWrapper + * * @return DateTimeWrapper * @throws InvalidValueException if the value type is not datetime */ public DateTimeWrapper asDateTime() throws InvalidValueException { if (value.getSetField() == Value.DTVAL) { return (DateTimeWrapper) new DateTimeWrapper(value.getDtVal()) - .setDecodeType(decodeType) - .setTimezoneOffset(timezoneOffset); + .setDecodeType(decodeType) + .setTimezoneOffset(timezoneOffset); } throw new InvalidValueException( - "Cannot get field datetime because value's type is " + descType()); + "Cannot get field datetime because value's type is " + descType()); } /** * Convert the original data type Value to Node + * * @return Node - * @throws InvalidValueException if the value type is not vertex + * @throws InvalidValueException if the value type is not vertex * @throws UnsupportedEncodingException if decode binary failed */ - public Node asNode() throws InvalidValueException, UnsupportedEncodingException { + public Node asNode() throws InvalidValueException, UnsupportedEncodingException { if (value.getSetField() == Value.VVAL) { return (Node) new Node(value.getVVal()) - .setDecodeType(decodeType) - .setTimezoneOffset(timezoneOffset); + .setDecodeType(decodeType) + .setTimezoneOffset(timezoneOffset); } throw new InvalidValueException( "Cannot get field Node because value's type is " + descType()); @@ -442,8 +491,8 @@ public Node asNode() throws InvalidValueException, UnsupportedEncodingException public Relationship asRelationship() throws InvalidValueException { if (value.getSetField() == Value.EVAL) { return (Relationship) new Relationship(value.getEVal()) - .setDecodeType(decodeType) - .setTimezoneOffset(timezoneOffset); + .setDecodeType(decodeType) + .setTimezoneOffset(timezoneOffset); } throw new InvalidValueException( "Cannot get field Relationship because value's type is " + descType()); @@ -451,15 +500,16 @@ public Relationship asRelationship() throws InvalidValueException { /** * Convert the original data type Value to Path + * * @return PathWrapper - * @throws InvalidValueException if the value type is not path + * @throws InvalidValueException if the value type is not path * @throws UnsupportedEncodingException if decode bianry failed */ public PathWrapper asPath() throws InvalidValueException, UnsupportedEncodingException { if (value.getSetField() == Value.PVAL) { return (PathWrapper) new PathWrapper(value.getPVal()) - .setDecodeType(decodeType) - .setTimezoneOffset(timezoneOffset); + .setDecodeType(decodeType) + .setTimezoneOffset(timezoneOffset); } throw new InvalidValueException( "Cannot get field PathWrapper because value's type is " + descType()); @@ -467,6 +517,7 @@ public PathWrapper asPath() throws InvalidValueException, UnsupportedEncodingExc /** * Convert the original data type Value to geography + * * @return GeographyWrapper * @throws InvalidValueException if the value type is not geography */ @@ -480,6 +531,22 @@ public GeographyWrapper asGeography() throws InvalidValueException { "Cannot get field GeographyWrapper because value's type is " + descType()); } + /** + * Convert the original data type Value to duration + * + * @return DurationWrapper + * @throws InvalidValueException if the value type is not duration + */ + public DurationWrapper asDuration() throws InvalidValueException { + if (value.getSetField() == Value.DUVAL) { + return (DurationWrapper) new DurationWrapper(value.getDuVal()) + .setDecodeType(decodeType) + .setTimezoneOffset(timezoneOffset); + } + throw new InvalidValueException("Cannot get field DurationWrapper because value's type is " + + descType()); + } + @Override public boolean equals(Object o) { if (this == o) { @@ -490,7 +557,7 @@ public boolean equals(Object o) { } ValueWrapper that = (ValueWrapper) o; return Objects.equals(value, that.value) - && Objects.equals(decodeType, that.decodeType); + && Objects.equals(decodeType, that.decodeType); } @Override @@ -500,6 +567,7 @@ public int hashCode() { /** * Convert Value to String format + * * @return String */ @Override diff --git a/client/src/main/java/com/vesoft/nebula/client/storage/data/BaseTableRow.java b/client/src/main/java/com/vesoft/nebula/client/storage/data/BaseTableRow.java index 9e30afeee..1a2951a19 100644 --- a/client/src/main/java/com/vesoft/nebula/client/storage/data/BaseTableRow.java +++ b/client/src/main/java/com/vesoft/nebula/client/storage/data/BaseTableRow.java @@ -7,6 +7,7 @@ import com.vesoft.nebula.client.graph.data.DateTimeWrapper; import com.vesoft.nebula.client.graph.data.DateWrapper; +import com.vesoft.nebula.client.graph.data.DurationWrapper; import com.vesoft.nebula.client.graph.data.GeographyWrapper; import com.vesoft.nebula.client.graph.data.TimeWrapper; import com.vesoft.nebula.client.graph.data.ValueWrapper; @@ -72,6 +73,10 @@ public GeographyWrapper getGeography(int i) { return values.get(i).asGeography(); } + public DurationWrapper getDuration(int i) { + return values.get(i).asDuration(); + } + public List getValues() { return values; } diff --git a/client/src/test/java/com/vesoft/nebula/client/graph/data/TestData.java b/client/src/test/java/com/vesoft/nebula/client/graph/data/TestData.java index b0175a7e4..bd1a369ed 100644 --- a/client/src/test/java/com/vesoft/nebula/client/graph/data/TestData.java +++ b/client/src/test/java/com/vesoft/nebula/client/graph/data/TestData.java @@ -9,6 +9,7 @@ import com.vesoft.nebula.DataSet; import com.vesoft.nebula.Date; import com.vesoft.nebula.DateTime; +import com.vesoft.nebula.Duration; import com.vesoft.nebula.Edge; import com.vesoft.nebula.ErrorCode; import com.vesoft.nebula.Geography; @@ -94,58 +95,57 @@ public Path getPath(String startId, int stepsNum) { } - public Vertex getSimpleVertex() { Map props1 = new HashMap<>(); - props1.put("tag1_prop".getBytes(), new Value(Value.IVAL, (long)100)); + props1.put("tag1_prop".getBytes(), new Value(Value.IVAL, (long) 100)); Map props2 = new HashMap<>(); - props2.put("tag2_prop".getBytes(), new Value(Value.IVAL, (long)200)); + props2.put("tag2_prop".getBytes(), new Value(Value.IVAL, (long) 200)); List tags = Arrays.asList(new Tag("tag1".getBytes(), props1), - new Tag("tag2".getBytes(), props2)); + new Tag("tag2".getBytes(), props2)); return new Vertex(new Value(Value.SVAL, "vertex".getBytes()), tags); } public Edge getSimpleEdge(boolean isReverse) { Map props = new HashMap<>(); - props.put("edge_prop".getBytes(), new Value(Value.IVAL, (long)100)); + props.put("edge_prop".getBytes(), new Value(Value.IVAL, (long) 100)); int type = 1; if (isReverse) { type = -1; } return new Edge(new Value(Value.SVAL, "Tom".getBytes()), - new Value(Value.SVAL, "Lily".getBytes()), - type, - "classmate".getBytes(), - 10, - props); + new Value(Value.SVAL, "Lily".getBytes()), + type, + "classmate".getBytes(), + 10, + props); } public Path getSimplePath(boolean isReverse) { Map props1 = new HashMap<>(); - props1.put("tag1_prop".getBytes(), new Value(Value.IVAL, (long)200)); + props1.put("tag1_prop".getBytes(), new Value(Value.IVAL, (long) 200)); List tags2 = Collections.singletonList(new Tag("tag1".getBytes(), props1)); Vertex vertex1 = new Vertex(new Value(Value.SVAL, "vertex1".getBytes()), tags2); List steps = new ArrayList<>(); Map props3 = new HashMap<>(); - props3.put("edge1_prop".getBytes(), new Value(Value.IVAL, (long)100)); + props3.put("edge1_prop".getBytes(), new Value(Value.IVAL, (long) 100)); steps.add(new Step(vertex1, 1, "classmate".getBytes(), 100, props3)); Map props2 = new HashMap<>(); - props2.put("tag2_prop".getBytes(), new Value(Value.IVAL, (long)300)); + props2.put("tag2_prop".getBytes(), new Value(Value.IVAL, (long) 300)); List tags3 = Collections.singletonList(new Tag("tag2".getBytes(), props2)); Vertex vertex2 = new Vertex(new Value(Value.SVAL, "vertex2".getBytes()), tags3); Map props4 = new HashMap<>(); - props4.put("edge2_prop".getBytes(), new Value(Value.IVAL, (long)200)); + props4.put("edge2_prop".getBytes(), new Value(Value.IVAL, (long) 200)); steps.add(new Step(vertex2, isReverse ? -1 : 1, "classmate".getBytes(), 10, props4)); Map props0 = new HashMap<>(); - props0.put("tag0_prop".getBytes(), new Value(Value.IVAL, (long)100)); + props0.put("tag0_prop".getBytes(), new Value(Value.IVAL, (long) 100)); List tags1 = Collections.singletonList(new Tag("tag0".getBytes(), props0)); Vertex vertex0 = new Vertex(new Value(Value.SVAL, "vertex0".getBytes()), tags1); return new Path(vertex0, steps); @@ -171,11 +171,11 @@ public DataSet getDateset() { new Value(Value.LVAL, new NList(list)), new Value(Value.UVAL, new NSet(set)), new Value(Value.MVAL, new NMap(map)), - new Value(Value.TVAL, new Time((byte)10, (byte)30, (byte)0, 100)), - new Value(Value.DVAL, new Date((short)2020, (byte)10, (byte)10)), + new Value(Value.TVAL, new Time((byte) 10, (byte) 30, (byte) 0, 100)), + new Value(Value.DVAL, new Date((short) 2020, (byte) 10, (byte) 10)), new Value(Value.DTVAL, - new DateTime((short)2020, (byte)10, - (byte)10, (byte)10, (byte)30, (byte)0, 100)), + new DateTime((short) 2020, (byte) 10, + (byte) 10, (byte) 10, (byte) 30, (byte) 0, 100)), new Value(Value.VVAL, getVertex("Tom")), new Value(Value.EVAL, getEdge("Tom", "Lily")), new Value(Value.PVAL, getPath("Tom", 3)), @@ -184,30 +184,32 @@ public DataSet getDateset() { new Value(Value.GGVAL, new Geography(Geography.PGVAL, new Polygon(Arrays.asList( Arrays.asList(new Coordinate(1.0, 2.0), new Coordinate(2.0, 4.0)), Arrays.asList(new Coordinate(3.0, 6.0), new Coordinate(4.0, 8.0)) - )))), + )))), new Value(Value.GGVAL, new Geography(Geography.LSVAL, new LineString(Arrays.asList( new Coordinate(1.0, 2.0), new Coordinate(2.0, 4.0) - )))))); + )))), + new Value(Value.DUVAL, new Duration(100, 20, 1)))); final List columnNames = Arrays.asList( - "col0_empty".getBytes(), - "col1_null".getBytes(), - "col2_bool".getBytes(), - "col3_int".getBytes(), - "col4_double".getBytes(), - "col5_string".getBytes(), - "col6_list".getBytes(), - "col7_set".getBytes(), - "col8_map".getBytes(), - "col9_time".getBytes(), - "col10_date".getBytes(), - "col11_datetime".getBytes(), - "col12_vertex".getBytes(), - "col13_edge".getBytes(), - "col14_path".getBytes(), - "col15_point".getBytes(), - "col16_polygon".getBytes(), - "col17_linestring".getBytes()); + "col0_empty".getBytes(), + "col1_null".getBytes(), + "col2_bool".getBytes(), + "col3_int".getBytes(), + "col4_double".getBytes(), + "col5_string".getBytes(), + "col6_list".getBytes(), + "col7_set".getBytes(), + "col8_map".getBytes(), + "col9_time".getBytes(), + "col10_date".getBytes(), + "col11_datetime".getBytes(), + "col12_vertex".getBytes(), + "col13_edge".getBytes(), + "col14_path".getBytes(), + "col15_point".getBytes(), + "col16_polygon".getBytes(), + "col17_linestring".getBytes(), + "col18_duration".getBytes()); return new DataSet(columnNames, Collections.singletonList(row)); } @@ -222,10 +224,10 @@ public void testNode() { node.keys("tag0").stream().sorted().collect(Collectors.toList()), names.stream().sorted().collect(Collectors.toList())); List propValues = Arrays.asList(new Value(Value.IVAL, 0L), - new Value(Value.IVAL, 1L), - new Value(Value.IVAL, 2L), - new Value(Value.IVAL, 3L), - new Value(Value.IVAL, 4L)); + new Value(Value.IVAL, 1L), + new Value(Value.IVAL, 2L), + new Value(Value.IVAL, 3L), + new Value(Value.IVAL, 4L)); // TODO: Check the List } catch (Exception e) { @@ -253,14 +255,14 @@ public void testRelationShip() { // check get values List values = relationShip.values(); assert values.get(0).isLong(); - ArrayList longVals = new ArrayList<>(); + ArrayList longVals = new ArrayList<>(); for (ValueWrapper val : values) { assert val.isLong(); longVals.add(val.asLong()); } List expectVals = Arrays.asList(0L, 1L, 2L, 3L, 4L); assert Objects.equals(expectVals, - longVals.stream().sorted().collect(Collectors.toList())); + longVals.stream().sorted().collect(Collectors.toList())); // check properties HashMap properties = relationShip.properties(); @@ -307,11 +309,11 @@ public void testPathWrapper() { for (int i = 0; i < 4; i++) { if (i % 2 == 0) { relationships.add(new Relationship(getEdge(String.format("vertex%d", i + 1), - String.format("vertex%d", i)))); + String.format("vertex%d", i)))); } else { relationships.add( new Relationship(getEdge(String.format("vertex%d", i), - String.format("vertex%d", i + 1)))); + String.format("vertex%d", i + 1)))); } } @@ -326,7 +328,7 @@ public void testPathWrapper() { @Test public void testResult() { try { - ExecutionResponse resp = new ExecutionResponse(); + ExecutionResponse resp = new ExecutionResponse(); resp.error_code = ErrorCode.SUCCEEDED; resp.error_msg = "test".getBytes(); resp.comment = "test_comment".getBytes(); @@ -343,14 +345,16 @@ public void testResult() { Assert.assertEquals(1000, resultSet.getLatency()); assert resultSet.getPlanDesc() != null; List expectColNames = Arrays.asList( - "col0_empty", "col1_null", "col2_bool", "col3_int", "col4_double", "col5_string", - "col6_list", "col7_set", "col8_map", "col9_time", "col10_date", "col11_datetime", - "col12_vertex", "col13_edge", "col14_path", "col15_point", "col16_polygon", - "col17_linestring"); + "col0_empty", "col1_null", "col2_bool", "col3_int", "col4_double", + "col5_string", + "col6_list", "col7_set", "col8_map", "col9_time", "col10_date", + "col11_datetime", + "col12_vertex", "col13_edge", "col14_path", "col15_point", "col16_polygon", + "col17_linestring", "col18_duration"); assert Objects.equals(resultSet.keys(), expectColNames); assert resultSet.getRows().size() == 1; ResultSet.Record record = resultSet.rowValues(0); - assert record.size() == 18; + assert record.size() == 19; assert record.get(0).isEmpty(); assert record.get(1).isNull(); @@ -369,12 +373,12 @@ public void testResult() { assert Objects.equals("value1", record.get(5).asString()); Assert.assertArrayEquals( - record.get(6).asList().stream().map(ValueWrapper::asLong).toArray(), - Arrays.asList((long)1, (long)2).toArray()); + record.get(6).asList().stream().map(ValueWrapper::asLong).toArray(), + Arrays.asList((long) 1, (long) 2).toArray()); assert record.get(7).isSet(); Set set = record.get(7).asSet().stream().map(ValueWrapper::asLong) - .collect(Collectors.toSet()); + .collect(Collectors.toSet()); assert set.size() == 2; assert set.contains((long) 1); assert set.contains((long) 2); @@ -383,61 +387,61 @@ public void testResult() { HashMap map = record.get(8).asMap(); assert map.keySet().size() == 2; Assert.assertArrayEquals(map.keySet().toArray(), - Arrays.asList("key1", "key2").toArray()); + Arrays.asList("key1", "key2").toArray()); Assert.assertArrayEquals(map.values().stream().map(ValueWrapper::asLong).toArray(), - Arrays.asList((long)1, (long)2).toArray()); + Arrays.asList((long) 1, (long) 2).toArray()); assert record.get(9).isTime(); assert record.get(9).asTime() instanceof TimeWrapper; TimeWrapper timeWrapper = (TimeWrapper) new TimeWrapper( - new Time((byte)10, (byte)30, (byte)0, 100)).setTimezoneOffset(28800); + new Time((byte) 10, (byte) 30, (byte) 0, 100)).setTimezoneOffset(28800); assert Objects.equals(record.get(9).asTime(), timeWrapper); Assert.assertEquals("utc time: 10:30:00.000100, timezoneOffset: 28800", - timeWrapper.toString()); + timeWrapper.toString()); Assert.assertEquals("18:30:00.000100", timeWrapper.getLocalTimeStr()); Assert.assertEquals("10:30:00.000100", timeWrapper.getUTCTimeStr()); Assert.assertEquals(new Time( - (byte)18, (byte)30, (byte)0, 100), timeWrapper.getLocalTime()); + (byte) 18, (byte) 30, (byte) 0, 100), timeWrapper.getLocalTime()); assert record.get(10).isDate(); assert record.get(10).asDate() instanceof DateWrapper; - DateWrapper dateWrapper = new DateWrapper(new Date((short)2020, (byte)10, (byte)10)); + DateWrapper dateWrapper = new DateWrapper(new Date((short) 2020, (byte) 10, (byte) 10)); assert Objects.equals(record.get(10).asDate(), dateWrapper); Assert.assertEquals("2020-10-10", dateWrapper.toString()); assert record.get(11).isDateTime(); DateTimeWrapper dateTimeWrapper = (DateTimeWrapper) new DateTimeWrapper( - new DateTime((short)2020, (byte)10, - (byte)10, (byte)10, (byte)30, (byte)0, 100)).setTimezoneOffset(28800); + new DateTime((short) 2020, (byte) 10, (byte) 10, (byte) 10, (byte) 30, + (byte) 0, 100)).setTimezoneOffset(28800); assert record.get(11).asDateTime() instanceof DateTimeWrapper; assert Objects.equals(record.get(11).asDateTime(), dateTimeWrapper); Assert.assertEquals("utc datetime: 2020-10-10T10:30:00.000100, timezoneOffset: 28800", - dateTimeWrapper.toString()); + dateTimeWrapper.toString()); Assert.assertEquals("2020-10-10T18:30:00.000100", - dateTimeWrapper.getLocalDateTimeStr()); + dateTimeWrapper.getLocalDateTimeStr()); Assert.assertEquals("2020-10-10T10:30:00.000100", - dateTimeWrapper.getUTCDateTimeStr()); + dateTimeWrapper.getUTCDateTimeStr()); Assert.assertEquals( - new DateTime((short)2020, (byte)10, - (byte)10, (byte)18, (byte)30, (byte)0, 100), - dateTimeWrapper.getLocalDateTime()); + new DateTime((short) 2020, (byte) 10, + (byte) 10, (byte) 18, (byte) 30, (byte) 0, 100), + dateTimeWrapper.getLocalDateTime()); assert record.get(12).isVertex(); assert Objects.equals(record.get(12).asNode(), - new Node(getVertex("Tom"))); + new Node(getVertex("Tom"))); assert record.get(13).isEdge(); assert Objects.equals(record.get(13).asRelationship(), - new Relationship(getEdge("Tom", "Lily"))); + new Relationship(getEdge("Tom", "Lily"))); assert record.get(14).isPath(); assert Objects.equals(record.get(14).asPath(), - new PathWrapper(getPath("Tom", 3))); + new PathWrapper(getPath("Tom", 3))); assert resultSet.toString().length() > 100; assert record.get(15).isGeography(); assert Objects.equals(record.get(15).asGeography().toString(), - new PointWrapper(new Point(new Coordinate(1.0, 2.0))).toString()); + new PointWrapper(new Point(new Coordinate(1.0, 2.0))).toString()); assert record.get(16).isGeography(); assert Objects.equals(record.get(16).asGeography().toString(), @@ -452,6 +456,10 @@ public void testResult() { new Coordinate(1.0, 2.0), new Coordinate(2.0, 4.0) ))).toString()); + + assert record.get(18).isDuration(); + assert Objects.equals(record.get(18).asDuration(), + new DurationWrapper(new Duration(100, 20, 1))); } catch (Exception e) { e.printStackTrace(); assert (false); @@ -463,43 +471,43 @@ public void testToString() { try { // test node ValueWrapper valueWrapper = new ValueWrapper( - new Value(Value.VVAL, getSimpleVertex()), "utf-8",28800); + new Value(Value.VVAL, getSimpleVertex()), "utf-8", 28800); String expectString = - "(\"vertex\" :tag1 {tag1_prop: 100} :tag2 {tag2_prop: 200})"; + "(\"vertex\" :tag1 {tag1_prop: 100} :tag2 {tag2_prop: 200})"; Assert.assertEquals(expectString, valueWrapper.asNode().toString()); // test relationship valueWrapper = new ValueWrapper( - new Value(Value.EVAL, getSimpleEdge(false)), "utf-8", 28800); + new Value(Value.EVAL, getSimpleEdge(false)), "utf-8", 28800); expectString = "(\"Tom\")-[:classmate@10{edge_prop: 100}]->(\"Lily\")"; Assert.assertEquals(expectString, valueWrapper.asRelationship().toString()); valueWrapper = new ValueWrapper( - new Value(Value.EVAL, getSimpleEdge(true)), "utf-8", 28800); + new Value(Value.EVAL, getSimpleEdge(true)), "utf-8", 28800); expectString = "(\"Lily\")-[:classmate@10{edge_prop: 100}]->(\"Tom\")"; Assert.assertEquals(expectString, valueWrapper.asRelationship().toString()); // test path valueWrapper = new ValueWrapper( - new Value(Value.PVAL, getSimplePath(true)), "utf-8", 28800); - expectString = - "(\"vertex0\" :tag0 {tag0_prop: 100})" + new Value(Value.PVAL, getSimplePath(true)), "utf-8", 28800); + expectString = "(\"vertex0\" :tag0 {tag0_prop: 100})" + "-[:classmate@100{edge1_prop: 100}]->" + "(\"vertex1\" :tag1 {tag1_prop: 200})<-[:classmate@10{edge2_prop: 200}]-" + "(\"vertex2\" :tag2 {tag2_prop: 300})"; Assert.assertEquals(expectString, valueWrapper.asPath().toString()); valueWrapper = new ValueWrapper( - new Value(Value.PVAL, getSimplePath(false)), "utf-8", 28800); - expectString = - "(\"vertex0\" :tag0 {tag0_prop: 100})" + new Value(Value.PVAL, getSimplePath(false)), "utf-8", 28800); + expectString = "(\"vertex0\" :tag0 {tag0_prop: 100})" + "-[:classmate@100{edge1_prop: 100}]->" + "(\"vertex1\" :tag1 {tag1_prop: 200})-[:classmate@10{edge2_prop: 200}]->" + "(\"vertex2\" :tag2 {tag2_prop: 300})"; Assert.assertEquals(expectString, valueWrapper.asPath().toString()); + // test Geography valueWrapper = new ValueWrapper( - new Value(Value.GGVAL, new Geography(Geography.PTVAL, new Point(new Coordinate(1.0, - 2.0)))), "utf-8", 28800); + new Value(Value.GGVAL, new Geography(Geography.PTVAL, + new Point(new Coordinate(1.0, + 2.0)))), "utf-8", 28800); expectString = "POINT(1.0 2.0)"; Assert.assertEquals(expectString, valueWrapper.asGeography().toString()); @@ -513,12 +521,21 @@ public void testToString() { valueWrapper = new ValueWrapper( new Value(Value.GGVAL, new Geography(Geography.LSVAL, - new LineString(Arrays.asList( - new Coordinate(1.0, 2.0), - new Coordinate(2.0, 4.0) - )))), "utf-8", 28800); + new LineString(Arrays.asList( + new Coordinate(1.0, 2.0), + new Coordinate(2.0, 4.0) + )))), "utf-8", 28800); expectString = "LINESTRING(1.0 2.0,2.0 4.0)"; Assert.assertEquals(expectString, valueWrapper.asGeography().toString()); + + // test Duration + valueWrapper = new ValueWrapper(new Value(Value.DUVAL, new Duration(100, 20, 1)), + "utf-8", 28800); + expectString = "P1M0DT100.00002S"; + String expectDurationString = "duration({months:1, seconds:100, microseconds:20})"; + Assert.assertEquals(expectString, valueWrapper.asDuration().toString()); + Assert.assertEquals(expectDurationString, + valueWrapper.asDuration().getDurationString()); } catch (Exception e) { e.printStackTrace(); assert (false); diff --git a/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java b/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java index 571a65273..1320e5b9d 100644 --- a/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java +++ b/client/src/test/java/com/vesoft/nebula/client/graph/data/TestDataFromServer.java @@ -10,6 +10,7 @@ import com.vesoft.nebula.Coordinate; import com.vesoft.nebula.Date; import com.vesoft.nebula.DateTime; +import com.vesoft.nebula.Duration; import com.vesoft.nebula.ErrorCode; import com.vesoft.nebula.Geography; import com.vesoft.nebula.LineString; @@ -58,7 +59,8 @@ public void setUp() throws Exception { + "CREATE EDGE IF NOT EXISTS like(likeness double);" + "CREATE EDGE IF NOT EXISTS friend(start_year int, end_year int);" + "CREATE TAG INDEX IF NOT EXISTS person_name_index ON person(name(8));" - + "CREATE TAG IF NOT EXISTS any_shape(geo geography);"); + + "CREATE TAG IF NOT EXISTS any_shape(geo geography);" + + "CREATE TAG IF NOT EXISTS tag_duration(col duration);"); Assert.assertTrue(resp.getErrorMessage(), resp.isSucceeded()); TimeUnit.SECONDS.sleep(10); String insertVertexes = "INSERT VERTEX person(name, age, grade,friends, book_num, " @@ -122,6 +124,11 @@ public void setUp() throws Exception { + "(ST_GeogFromText('POLYGON((0 1, 1 2, 2 3, 0 1))'));"; resp = session.execute(insertShape); Assert.assertTrue(resp.getErrorMessage(), resp.isSucceeded()); + + String insertDuration = "INSERT VERTEX tag_duration(prop) VALUES 'duration':" + + "(duration({months:1, seconds:100, microseconds:20}));"; + resp = session.execute(insertDuration); + Assert.assertTrue(resp.getErrorMessage(), resp.isSucceeded()); } @After @@ -267,6 +274,26 @@ public void testAllSchemaType() { Assert.assertEquals(geographyWrapper.toString(), properties.get("geo").asGeography().toString()); + result = session.execute( + "FETCH PROP ON tag_duration 'duration' yield vertex as vertices_"); + Assert.assertTrue(result.isSucceeded()); + Assert.assertEquals("", result.getErrorMessage()); + Assert.assertFalse(result.getLatency() <= 0); + Assert.assertEquals("", result.getComment()); + Assert.assertEquals(ErrorCode.SUCCEEDED.getValue(), result.getErrorCode()); + Assert.assertEquals("test_data", result.getSpaceName()); + Assert.assertFalse(result.isEmpty()); + Assert.assertEquals(1, result.rowsSize()); + + Assert.assertTrue(result.rowValues(0).get(0).isVertex()); + node = result.rowValues(0).get(0).asNode(); + Assert.assertEquals("duration", node.getId().asString()); + Assert.assertEquals(Arrays.asList("tag_duration"), node.tagNames()); + properties = node.properties("prop"); + DurationWrapper durationWrapper = new DurationWrapper(new Duration(1, 100, 20)); + Assert.assertEquals(durationWrapper, properties.get("prop").asDuration()); + Assert.assertEquals(durationWrapper.toString(), + properties.get("prop").asDuration().toString()); } catch (IOErrorException | UnsupportedEncodingException e) { e.printStackTrace();