Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support duration type #194

Merged
merged 5 commits into from
Jan 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 87 additions & 32 deletions nebula2/data/DataObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
NullType,
DateTime,
Time,
Duration,
)


Expand Down Expand Up @@ -174,9 +175,6 @@ def __eq__(self, other):

return self.__dict__ == other.__dict__

def __ne__(self, other):
return not (self == other)


class DataSetWrapper(object):
def __init__(self, data_set, decode_type='utf-8', timezone_offset: int = 0):
Expand Down Expand Up @@ -223,6 +221,7 @@ def get_row_types(self):
ttypes.Value.UVAL = 14
ttypes.Value.GVAL = 15
ttypes.Value.GGVAL = 16
ttypes.Value.DUVAL = 17
"""
if len(self._data_set.rows) == 0:
return []
Expand Down Expand Up @@ -324,117 +323,124 @@ def get_value(self):
return self._value

def is_null(self):
"""judge the value if is Null type
"""check if the value is Null type

:return: true or false
"""
return self._value.getType() == Value.NVAL

def is_empty(self):
"""judge the value if is Empty type
"""check if the value is Empty type

:return: true or false
"""
return self._value.getType() == Value.__EMPTY__

def is_bool(self):
"""judge the value if is Bool type
"""check if the value is Bool type

:return: true or false
"""
return self._value.getType() == Value.BVAL

def is_int(self):
"""judge the value if is Int type
"""check if the value is Int type

:return: true or false
"""
return self._value.getType() == Value.IVAL

def is_double(self):
"""judge the value if is Double type
"""check if the value is Double type

:return: true or false
"""
return self._value.getType() == Value.FVAL

def is_string(self):
"""judge the value if is String type
"""check if the value is String type

:return: true or false
"""
return self._value.getType() == Value.SVAL

def is_list(self):
"""judge the value if is List type
"""check if the value is List type

:return: true or false
"""
return self._value.getType() == Value.LVAL

def is_set(self):
"""judge the value if is Set type
"""check if the value is Set type

:return: true or false
"""
return self._value.getType() == Value.UVAL

def is_map(self):
"""judge the value if is Map type
"""check if the value is Map type

:return: true or false
"""
return self._value.getType() == Value.MVAL

def is_time(self):
"""judge the value if is Time type
"""check if the value is Time type

:return: true or false
"""
return self._value.getType() == Value.TVAL

def is_date(self):
"""judge the value if is Date type
"""check if the value is Date type

:return: true or false
"""
return self._value.getType() == Value.DVAL

def is_datetime(self):
"""judge the value if is Datetime type
"""check if the value is Datetime type

:return: true or false
"""
return self._value.getType() == Value.DTVAL

def is_vertex(self):
"""judge the value if is Vertex type
"""check if the value is Vertex type

:return: true or false
"""
return self._value.getType() == Value.VVAL

def is_edge(self):
"""judge the value if is Edge type
"""check if the value is Edge type

:return: true or false
"""
return self._value.getType() == Value.EVAL

def is_path(self):
"""judge the value if is Path type
"""check if the value is Path type

:return: true or false
"""
return self._value.getType() == Value.PVAL

def is_geography(self):
"""judge the value if is Geography type
"""check if the value is Geography type

:return: true or false
"""
return self._value.getType() == Value.GGVAL

def is_duration(self):
"""check if the value is Duration type

:return: true or false
"""
return self._value.getType() == Value.DUVAL

def as_null(self):
"""converts the original data type to Null type

Expand Down Expand Up @@ -646,6 +652,17 @@ def as_geography(self):
"expect geography type, but is " + self._get_type_name()
)

def as_duration(self):
"""converts the original data type to Duration type

:return: DurationWrapper type
"""
if self._value.getType() == Value.DUVAL:
return DurationWrapper(self._value.get_duVal())
raise InvalidValueTypeException(
"expect duration type, but is " + self._get_type_name()
)

def _get_type_name(self):
if self.is_empty():
return "empty"
Expand Down Expand Up @@ -679,6 +696,8 @@ def _get_type_name(self):
return "path"
if self.is_geography():
return "geography"
if self.is_duration():
return "duration"
return "unknown"

def __eq__(self, o: object) -> bool:
Expand Down Expand Up @@ -711,13 +730,15 @@ def __eq__(self, o: object) -> bool:
elif self.is_path():
return self.as_path() == o.as_path()
elif self.is_time():
return self.as_time() == self.as_time()
return self.as_time() == o.as_time()
elif self.is_date():
return self.as_date() == self.as_date()
return self.as_date() == o.as_date()
elif self.is_datetime():
return self.as_datetime() == self.as_datetime()
return self.as_datetime() == o.as_datetime()
elif self.is_geography():
return self.as_geography() == self.as_geography()
return self.as_geography() == o.as_geography()
elif self.is_duration():
return self.as_duration() == o.as_duration()
else:
raise RuntimeError(
'Unsupported type:{} to compare'.format(self._get_type_name())
Expand Down Expand Up @@ -757,6 +778,8 @@ def __repr__(self):
return str(self.as_datetime())
elif self.is_geography():
return str(self.as_geography())
elif self.is_duration():
return str(self.as_duration())
else:
raise RuntimeError(
'Unsupported type:{} to compare'.format(self._get_type_name())
Expand Down Expand Up @@ -1237,6 +1260,47 @@ def __repr__(self):
)


class DurationWrapper(BaseObject):
def __init__(self, duration):
super(DurationWrapper, self).__init__()
self._duration = duration

def get_seconds(self):
"""get seconds

:return: int64 seconds
"""
return self._duration.seconds

def get_microseconds(self):
"""get microseconds

:return: int32 microseconds
"""
return self._duration.microseconds

def get_months(self):
"""get month

:return: int32 month
"""
return self._duration.months

def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return (
self._duration.seconds == other.get_seconds()
and self._duration.microseconds == other.get_microseconds()
and self._duration.months == other.get_months()
)

def __repr__(self):
totalSeconds = self._duration.seconds + (self._duration.microseconds) // 1000000
remainMicroSeconds = self._duration.microseconds % 1000000
return f"P{self._duration.months}MT{totalSeconds}.{remainMicroSeconds:06d}000S"


class GenValue(object):
@classmethod
def gen_vertex(cls, vid, tags):
Expand Down Expand Up @@ -1373,9 +1437,6 @@ def __eq__(self, other):

return self.get_id() == other.get_id()

def __ne__(self, other):
return not (self == other)


class Relationship(BaseObject):
def __init__(self, edge: Edge):
Expand Down Expand Up @@ -1481,9 +1542,6 @@ def __eq__(self, other):
and self.ranking() == self.ranking()
)

def __ne__(self, other):
return not (self == other)


class Segment:
start_node = None
Expand Down Expand Up @@ -1688,6 +1746,3 @@ def __eq__(self, other):
return False

return self._segments == other.segments()

def __ne__(self, other):
return not (self == other)
1 change: 1 addition & 0 deletions nebula2/data/ResultSet.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ def get_row_types(self):
ttypes.Value.UVAL = 14
ttypes.Value.GVAL = 15
ttypes.Value.GGVAL = 16
ttypes.Value.DUVAL = 17
"""
if self._data_set_wrapper is None:
return []
Expand Down
16 changes: 10 additions & 6 deletions tests/test_data_from_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def setUpClass(cls) -> None:
start_school date, morning time, property double,
is_girl bool, child_name fixed_string(10), expend float,
first_out_city timestamp, hobby string);
CREATE TAG IF NOT EXISTS student(name string);
CREATE TAG IF NOT EXISTS student(name string, interval duration);
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));
Expand Down Expand Up @@ -73,9 +73,12 @@ def setUpClass(cls) -> None:
)
assert resp.is_succeeded(), resp.error_msg()
resp = cls.session.execute(
"INSERT VERTEX student(name) VALUES "
"'Bob':('Bob'), 'Lily':('Lily'), "
"'Tom':('Tom'), 'Jerry':('Jerry'), 'John':('John')"
"INSERT VERTEX student(name, interval) VALUES "
"'Bob':('Bob', duration({months:1, seconds:100, microseconds:20})),"
"'Lily':('Lily', duration({years: 1, seconds: 0})),"
"'Tom':('Tom', duration({years: 1, seconds: 0})),"
"'Jerry':('Jerry', duration({years: 1, seconds: 0})),"
"'John':('John', duration({years: 1, seconds: 0}))"
)
assert resp.is_succeeded(), resp.error_msg()

Expand Down Expand Up @@ -233,15 +236,15 @@ def test_path_type(self):
assert resp.row_values(0)[0].is_path()
path = resp.row_values(0)[0].as_path()
expected_str = (
'("Bob" :student{name: "Bob"} '
'("Bob" :student{interval: P1MT100.000020000S, name: "Bob"} '
':person{hobby: __NULL__, expend: 100.0, book_num: 100, '
'property: 1000.0, grade: 3, child_name: "Hello Worl", '
'start_school: 2017-09-10, friends: 10, '
'morning: utc time: 23:10:00.000000, timezone_offset: 28800, first_out_city: 1111, '
'name: "Bob", age: 10, '
'birthday: utc datetime: 2010-09-10T02:08:02.000000, timezone_offset: 28800, is_girl: False})'
'-[:friend@0{end_year: 2020, start_year: 2018}]->'
'("Lily" :student{name: "Lily"} '
'("Lily" :student{interval: P12MT0.000000000S, name: "Lily"} '
':person{is_girl: False, '
'birthday: utc datetime: 2010-09-10T02:08:02.000000, timezone_offset: 28800, age: 9, '
'book_num: 100, grade: 3, property: 1000.0, hobby: __NULL__, expend: 100.0, '
Expand Down Expand Up @@ -292,6 +295,7 @@ def test_complex_types(self):
"person.property": 1000,
"person.start_school": '2017-09-10',
"student.name": "Bob",
"student.interval": "P1MT100.000020000S",
}
]
json_obj = json.loads(resp)
Expand Down
Loading