Define procedure API for temporal types (#229)
This commit is contained in:
parent
8ea281649a
commit
0a23eb11ae
@ -125,6 +125,18 @@ struct mgp_edge;
|
||||
/// Path containing mgp_vertex and mgp_edge instances.
|
||||
struct mgp_path;
|
||||
|
||||
/// Date stored in Memgraph.
|
||||
struct mgp_date;
|
||||
|
||||
/// Local time stored in Memgraph.
|
||||
struct mgp_local_time;
|
||||
|
||||
/// Local date-time stored in Memgraph.
|
||||
struct mgp_local_date_time;
|
||||
|
||||
/// Duration stored in Memgraph.
|
||||
struct mgp_duration;
|
||||
|
||||
/// All available types that can be stored in a mgp_value
|
||||
enum mgp_value_type {
|
||||
// NOTE: New types need to be appended, so as not to break ABI.
|
||||
@ -138,6 +150,10 @@ enum mgp_value_type {
|
||||
MGP_VALUE_TYPE_VERTEX,
|
||||
MGP_VALUE_TYPE_EDGE,
|
||||
MGP_VALUE_TYPE_PATH,
|
||||
MGP_VALUE_TYPE_DATE,
|
||||
MGP_VALUE_TYPE_LOCAL_TIME,
|
||||
MGP_VALUE_TYPE_LOCAL_DATE_TIME,
|
||||
MGP_VALUE_TYPE_DURATION,
|
||||
};
|
||||
|
||||
/// Free the memory used by the given mgp_value instance.
|
||||
@ -209,6 +225,38 @@ enum mgp_error mgp_value_make_edge(struct mgp_edge *val, struct mgp_value **resu
|
||||
/// MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate a mgp_value.
|
||||
enum mgp_error mgp_value_make_path(struct mgp_path *val, struct mgp_value **result);
|
||||
|
||||
/// Create a mgp_value storing a mgp_date.
|
||||
/// You need to free the instance through mgp_value_destroy. The ownership of
|
||||
/// the date is transferred to the created mgp_value and destroying the mgp_value will
|
||||
/// destroy the mgp_date. Therefore, if a mgp_value is successfully created you
|
||||
/// must not call mgp_date_destroy on the given date.
|
||||
/// MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate a mgp_value.
|
||||
enum mgp_error mgp_value_make_date(struct mgp_date *val, struct mgp_value **result);
|
||||
|
||||
/// Create a mgp_value storing a mgp_local_time.
|
||||
/// You need to free the instance through mgp_value_destroy. The ownership of
|
||||
/// the local time is transferred to the created mgp_value and destroying the mgp_value will
|
||||
/// destroy the mgp_local_time. Therefore, if a mgp_value is successfully created you
|
||||
/// must not call mgp_local_time_destroy on the given local time.
|
||||
/// MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate a mgp_value.
|
||||
enum mgp_error mgp_value_make_local_time(struct mgp_local_time *val, struct mgp_value **result);
|
||||
|
||||
/// Create a mgp_value storing a mgp_local_date_time.
|
||||
/// You need to free the instance through mgp_value_destroy. The ownership of
|
||||
/// the local date-time is transferred to the created mgp_value and destroying the mgp_value will
|
||||
/// destroy the mgp_local_date_time. Therefore, if a mgp_value is successfully created you
|
||||
/// must not call mgp_local_date_time_destroy on the given local date-time.
|
||||
/// MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate a mgp_value.
|
||||
enum mgp_error mgp_value_make_local_date_time(struct mgp_local_date_time *val, struct mgp_value **result);
|
||||
|
||||
/// Create a mgp_value storing a mgp_duration.
|
||||
/// You need to free the instance through mgp_value_destroy. The ownership of
|
||||
/// the duration is transferred to the created mgp_value and destroying the mgp_value will
|
||||
/// destroy the mgp_duration. Therefore, if a mgp_value is successfully created you
|
||||
/// must not call mgp_duration_destroy on the given duration.
|
||||
/// MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate a mgp_value.
|
||||
enum mgp_error mgp_value_make_duration(struct mgp_duration *val, struct mgp_value **result);
|
||||
|
||||
/// Get the type of the value contained in mgp_value.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_get_type(struct mgp_value *val, enum mgp_value_type *result);
|
||||
@ -253,6 +301,22 @@ enum mgp_error mgp_value_is_edge(struct mgp_value *val, int *result);
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_is_path(struct mgp_value *val, int *result);
|
||||
|
||||
/// Result is non-zero if the given mgp_value stores a date.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_is_date(struct mgp_value *val, int *result);
|
||||
|
||||
/// Result is non-zero if the given mgp_value stores a local time.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_is_local_time(struct mgp_value *val, int *result);
|
||||
|
||||
/// Result is non-zero if the given mgp_value stores a local date-time.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_is_local_date_time(struct mgp_value *val, int *result);
|
||||
|
||||
/// Result is non-zero if the given mgp_value stores a duration.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_is_duration(struct mgp_value *val, int *result);
|
||||
|
||||
/// Get the contained boolean value.
|
||||
/// Non-zero values represent `true`, while zero represents `false`.
|
||||
/// Result is undefined if mgp_value does not contain the expected type.
|
||||
@ -299,6 +363,26 @@ enum mgp_error mgp_value_get_edge(struct mgp_value *val, struct mgp_edge **resul
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_get_path(struct mgp_value *val, struct mgp_path **result);
|
||||
|
||||
/// Get the contained date.
|
||||
/// Result is undefined if mgp_value does not contain the expected type.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_get_date(struct mgp_value *val, struct mgp_date **result);
|
||||
|
||||
/// Get the contained local time.
|
||||
/// Result is undefined if mgp_value does not contain the expected type.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_get_local_time(struct mgp_value *val, struct mgp_local_time **result);
|
||||
|
||||
/// Get the contained local date-time.
|
||||
/// Result is undefined if mgp_value does not contain the expected type.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_get_local_date_time(struct mgp_value *val, struct mgp_local_date_time **result);
|
||||
|
||||
/// Get the contained duration.
|
||||
/// Result is undefined if mgp_value does not contain the expected type.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_value_get_duration(struct mgp_value *val, struct mgp_duration **result);
|
||||
|
||||
/// Create an empty list with given capacity.
|
||||
/// You need to free the created instance with mgp_list_destroy.
|
||||
/// The created list will have allocated enough memory for `capacity` elements
|
||||
@ -774,6 +858,302 @@ enum mgp_error mgp_vertices_iterator_underlying_graph_is_mutable(struct mgp_vert
|
||||
/// Result is NULL if the end of the iteration has been reached.
|
||||
enum mgp_error mgp_vertices_iterator_get(struct mgp_vertices_iterator *it, struct mgp_vertex **result);
|
||||
|
||||
/// @name Temporal Types
|
||||
///
|
||||
///@{
|
||||
|
||||
struct mgp_date_parameters {
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
};
|
||||
|
||||
/// Create a date from a string following the ISO 8601 format.
|
||||
/// Resulting date must be freed with mgp_date_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the string cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_from_string(const char *string, struct mgp_memory *memory, struct mgp_date **date);
|
||||
|
||||
/// Create a date from mgp_date_parameter.
|
||||
/// Resulting date must be freed with mgp_date_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the parameters cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_from_parameters(struct mgp_date_parameters *parameters, struct mgp_memory *memory,
|
||||
struct mgp_date **date);
|
||||
|
||||
/// Copy a mgp_date.
|
||||
/// Resulting pointer must be freed with mgp_date_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_copy(struct mgp_date *date, struct mgp_memory *memory, struct mgp_date **result);
|
||||
|
||||
/// Free the memory used by a mgp_date.
|
||||
void mgp_date_destroy(struct mgp_date *date);
|
||||
|
||||
/// Result is non-zero if given dates are equal, otherwise 0.
|
||||
enum mgp_error mgp_date_equal(struct mgp_date *first, struct mgp_date *second, int *result);
|
||||
|
||||
/// Get the year property of the date.
|
||||
enum mgp_error mgp_date_get_year(struct mgp_date *date, int *year);
|
||||
|
||||
/// Get the month property of the date.
|
||||
enum mgp_error mgp_date_get_month(struct mgp_date *date, int *month);
|
||||
|
||||
/// Get the day property of the date.
|
||||
enum mgp_error mgp_date_get_day(struct mgp_date *date, int *day);
|
||||
|
||||
/// Get the date as microseconds from Unix epoch.
|
||||
enum mgp_error mgp_date_timestamp(struct mgp_date *date, int64_t *timestamp);
|
||||
|
||||
/// Get the date representing current date.
|
||||
/// Resulting date must be freed with mgp_date_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_now(struct mgp_memory *memory, struct mgp_date **date);
|
||||
|
||||
/// Add a duration to the date.
|
||||
/// Resulting date must be freed with mgp_date_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid date.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_add_duration(struct mgp_date *date, struct mgp_duration *dur, struct mgp_memory *memory,
|
||||
struct mgp_date **result);
|
||||
|
||||
/// Subtract a duration from the date.
|
||||
/// Resulting date must be freed with mgp_date_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid date.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_sub_duration(struct mgp_date *date, struct mgp_duration *dur, struct mgp_memory *memory,
|
||||
struct mgp_date **result);
|
||||
|
||||
/// Get a duration between two dates.
|
||||
/// Resulting duration must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_date_diff(struct mgp_date *first, struct mgp_date *second, struct mgp_memory *memory,
|
||||
struct mgp_duration **result);
|
||||
|
||||
struct mgp_local_time_parameters {
|
||||
int hour;
|
||||
int minute;
|
||||
int second;
|
||||
int millisecond;
|
||||
int microsecond;
|
||||
};
|
||||
|
||||
/// Create a local time from a string following the ISO 8601 format.
|
||||
/// Resulting local time must be freed with mgp_local_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the string cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_from_string(const char *string, struct mgp_memory *memory,
|
||||
struct mgp_local_time **local_time);
|
||||
|
||||
/// Create a local time from mgp_local_time_parameters.
|
||||
/// Resulting local time must be freed with mgp_local_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the parameters cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_from_parameters(struct mgp_local_time_parameters *parameters, struct mgp_memory *memory,
|
||||
struct mgp_local_time **local_time);
|
||||
|
||||
/// Copy a mgp_local_time.
|
||||
/// Resulting pointer must be freed with mgp_local_time_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_copy(struct mgp_local_time *local_time, struct mgp_memory *memory,
|
||||
struct mgp_local_time **result);
|
||||
|
||||
/// Free the memory used by a mgp_local_time.
|
||||
void mgp_local_time_destroy(struct mgp_local_time *local_time);
|
||||
|
||||
/// Result is non-zero if given local times are equal, otherwise 0.
|
||||
enum mgp_error mgp_local_time_equal(struct mgp_local_time *first, struct mgp_local_time *second, int *result);
|
||||
|
||||
/// Get the hour property of the local time.
|
||||
enum mgp_error mgp_local_time_get_hour(struct mgp_local_time *local_time, int *hour);
|
||||
|
||||
/// Get the minute property of the local time.
|
||||
enum mgp_error mgp_local_time_get_minute(struct mgp_local_time *local_time, int *minute);
|
||||
|
||||
/// Get the second property of the local time.
|
||||
enum mgp_error mgp_local_time_get_second(struct mgp_local_time *local_time, int *second);
|
||||
|
||||
/// Get the millisecond property of the local time.
|
||||
enum mgp_error mgp_local_time_get_millisecond(struct mgp_local_time *local_time, int *millisecond);
|
||||
|
||||
/// Get the microsecond property of the local time.
|
||||
enum mgp_error mgp_local_time_get_microsecond(struct mgp_local_time *local_time, int *microsecond);
|
||||
|
||||
/// Get the local time as microseconds from midnight.
|
||||
enum mgp_error mgp_local_time_timestamp(struct mgp_local_time *local_time, int64_t *timestamp);
|
||||
|
||||
/// Get the local time representing current time.
|
||||
/// Resulting pointer must be freed with mgp_local_time_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_now(struct mgp_memory *memory, struct mgp_local_time **local_time);
|
||||
|
||||
/// Add a duration to the local time.
|
||||
/// Resulting pointer must be freed with mgp_local_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid local time.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_add_duration(struct mgp_local_time *local_time, struct mgp_duration *dur,
|
||||
struct mgp_memory *memory, struct mgp_local_time **result);
|
||||
|
||||
/// Subtract a duration from the local time.
|
||||
/// Resulting pointer must be freed with mgp_local_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid local time.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_sub_duration(struct mgp_local_time *local_time, struct mgp_duration *dur,
|
||||
struct mgp_memory *memory, struct mgp_local_time **result);
|
||||
|
||||
/// Get a duration between two local times.
|
||||
/// Resulting pointer must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_date.
|
||||
enum mgp_error mgp_local_time_diff(struct mgp_local_time *first, struct mgp_local_time *second,
|
||||
struct mgp_memory *memory, struct mgp_duration **result);
|
||||
|
||||
struct mgp_local_date_time_parameters {
|
||||
struct mgp_date_parameters *date_parameters;
|
||||
struct mgp_local_time_parameters *local_time_parameters;
|
||||
};
|
||||
|
||||
/// Create a local date-time from a string following the ISO 8601 format.
|
||||
/// Resulting local date-time must be freed with mgp_local_date_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the string cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_from_string(const char *string, struct mgp_memory *memory,
|
||||
struct mgp_local_date_time **local_date_time);
|
||||
|
||||
/// Create a local date-time from mgp_local_date_time_parameters.
|
||||
/// Resulting local date-time must be freed with mgp_local_date_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the parameters cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_from_parameters(struct mgp_local_date_time_parameters *parameters,
|
||||
struct mgp_memory *memory,
|
||||
struct mgp_local_date_time **local_date_time);
|
||||
|
||||
/// Copy a mgp_local_date_time.
|
||||
/// Resulting pointer must be freed with mgp_local_date_time_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_copy(struct mgp_local_date_time *local_date_time, struct mgp_memory *memory,
|
||||
struct mgp_local_date_time **result);
|
||||
|
||||
/// Free the memory used by a mgp_local_date_time.
|
||||
void mgp_local_date_time_destroy(struct mgp_local_date_time *local_date_time);
|
||||
|
||||
/// Result is non-zero if given local date-times are equal, otherwise 0.
|
||||
enum mgp_error mgp_local_date_time_equal(struct mgp_local_date_time *first, struct mgp_local_date_time *second,
|
||||
int *result);
|
||||
|
||||
/// Get the year property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_year(struct mgp_local_date_time *local_date_time, int *year);
|
||||
|
||||
/// Get the month property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_month(struct mgp_local_date_time *local_date_time, int *month);
|
||||
|
||||
/// Get the day property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_day(struct mgp_local_date_time *local_date_time, int *day);
|
||||
|
||||
/// Get the hour property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_hour(struct mgp_local_date_time *local_date_time, int *hour);
|
||||
|
||||
/// Get the minute property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_minute(struct mgp_local_date_time *local_date_time, int *minute);
|
||||
|
||||
/// Get the second property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_second(struct mgp_local_date_time *local_date_time, int *second);
|
||||
|
||||
/// Get the milisecond property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_millisecond(struct mgp_local_date_time *local_date_time, int *millisecond);
|
||||
|
||||
/// Get the microsecond property of the local date-time.
|
||||
enum mgp_error mgp_local_date_time_get_microsecond(struct mgp_local_date_time *local_date_time, int *microsecond);
|
||||
|
||||
/// Get the local date-time as microseconds from Unix epoch.
|
||||
enum mgp_error mgp_local_date_time_timestamp(struct mgp_local_date_time *local_date_time, int64_t *timestamp);
|
||||
|
||||
/// Get the local date-time representing current date and time.
|
||||
/// Resulting local date-time must be freed with mgp_local_date_time_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_now(struct mgp_memory *memory, struct mgp_local_date_time **local_date_time);
|
||||
|
||||
/// Add a duration to the local date-time.
|
||||
/// Resulting local date-time must be freed with mgp_local_date_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid local date-time.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_add_duration(struct mgp_local_date_time *local_date_time, struct mgp_duration *dur,
|
||||
struct mgp_memory *memory, struct mgp_local_date_time **result);
|
||||
|
||||
/// Subtract a duration from the local date-time.
|
||||
/// Resulting local date-time must be freed with mgp_local_date_time_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid local date-time.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_sub_duration(struct mgp_local_date_time *local_date_time, struct mgp_duration *dur,
|
||||
struct mgp_memory *memory, struct mgp_local_date_time **result);
|
||||
|
||||
/// Get a duration between two local date-times.
|
||||
/// Resulting duration must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_local_date_time.
|
||||
enum mgp_error mgp_local_date_time_diff(struct mgp_local_date_time *first, struct mgp_local_date_time *second,
|
||||
struct mgp_memory *memory, struct mgp_duration **result);
|
||||
|
||||
struct mgp_duration_parameters {
|
||||
double day;
|
||||
double hour;
|
||||
double minute;
|
||||
double second;
|
||||
double millisecond;
|
||||
double microsecond;
|
||||
};
|
||||
|
||||
/// Create a duration from a string following the ISO 8601 format.
|
||||
/// Resulting duration must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the string cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_from_string(const char *string, struct mgp_memory *memory, struct mgp_duration **duration);
|
||||
|
||||
/// Create a duration from mgp_duration_parameters.
|
||||
/// Resulting duration must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the parameters cannot be parsed correctly.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_from_parameters(struct mgp_duration_parameters *parameters, struct mgp_memory *memory,
|
||||
struct mgp_duration **duration);
|
||||
|
||||
/// Create a duration from microseconds.
|
||||
/// Resulting duration must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_from_microseconds(int64_t microseconds, struct mgp_memory *memory,
|
||||
struct mgp_duration **duration);
|
||||
|
||||
/// Copy a mgp_duration.
|
||||
/// Resulting pointer must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_copy(struct mgp_duration *duration, struct mgp_memory *memory,
|
||||
struct mgp_duration **result);
|
||||
|
||||
/// Free the memory used by a mgp_duration.
|
||||
void mgp_duration_destroy(struct mgp_duration *duration);
|
||||
|
||||
/// Result is non-zero if given durations are equal, otherwise 0.
|
||||
enum mgp_error mgp_duration_equal(struct mgp_duration *first, struct mgp_duration *second, int *result);
|
||||
|
||||
/// Get the duration as microseconds.
|
||||
enum mgp_error mgp_duration_get_microseconds(struct mgp_duration *duration, int64_t *microseconds);
|
||||
|
||||
/// Apply unary minus operator to the duration.
|
||||
/// Resulting pointer must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_neg(struct mgp_duration *dur, struct mgp_memory *memory, struct mgp_duration **result);
|
||||
|
||||
/// Add two durations.
|
||||
/// Resulting pointer must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid duration.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_add(struct mgp_duration *first, struct mgp_duration *second, struct mgp_memory *memory,
|
||||
struct mgp_duration **result);
|
||||
|
||||
/// Subtract two durations.
|
||||
/// Resulting pointer must be freed with mgp_duration_destroy.
|
||||
/// Return MGP_ERROR_INVALID_ARGUMENT if the operation results in an invalid duration.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_duration.
|
||||
enum mgp_error mgp_duration_sub(struct mgp_duration *first, struct mgp_duration *second, struct mgp_memory *memory,
|
||||
struct mgp_duration **result);
|
||||
///@}
|
||||
|
||||
/// Advance the iterator to the next vertex and return it.
|
||||
/// The previous mgp_vertex obtained through mgp_vertices_iterator_get
|
||||
/// will be invalidated, and you must not use its value.
|
||||
@ -857,6 +1237,22 @@ enum mgp_error mgp_type_path(struct mgp_type **result);
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate the new type.
|
||||
enum mgp_error mgp_type_list(struct mgp_type *element_type, struct mgp_type **result);
|
||||
|
||||
/// Get the type representing a date.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate the new type.
|
||||
enum mgp_error mgp_type_date(struct mgp_type **result);
|
||||
|
||||
/// Get the type representing a local time.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate the new type.
|
||||
enum mgp_error mgp_type_local_time(struct mgp_type **result);
|
||||
|
||||
/// Get the type representing a local date-time.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate the new type.
|
||||
enum mgp_error mgp_type_local_date_time(struct mgp_type **result);
|
||||
|
||||
/// Get the type representing a duration.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate the new type.
|
||||
enum mgp_error mgp_type_duration(struct mgp_type **result);
|
||||
|
||||
/// Build a type representing either a `null` value or a value of given `type`.
|
||||
///
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate the new type.
|
||||
|
@ -21,6 +21,7 @@ from functools import wraps
|
||||
import inspect
|
||||
import sys
|
||||
import typing
|
||||
import datetime
|
||||
|
||||
|
||||
import _mgp
|
||||
@ -951,7 +952,15 @@ Number = typing.Union[int, float]
|
||||
|
||||
Map = typing.Union[dict, Edge, Vertex]
|
||||
|
||||
Any = typing.Union[bool, str, Number, Map, Path, list]
|
||||
Date = datetime.date
|
||||
|
||||
LocalTime = datetime.time
|
||||
|
||||
LocalDateTime = datetime.datetime
|
||||
|
||||
Duration = datetime.timedelta
|
||||
|
||||
Any = typing.Union[bool, str, Number, Map, Path, list, Date, LocalTime, LocalDateTime, Duration]
|
||||
|
||||
List = typing.List
|
||||
|
||||
@ -980,7 +989,11 @@ def _typing_to_cypher_type(type_):
|
||||
Map: _mgp.type_map(),
|
||||
Vertex: _mgp.type_node(),
|
||||
Edge: _mgp.type_relationship(),
|
||||
Path: _mgp.type_path()
|
||||
Path: _mgp.type_path(),
|
||||
Date: _mgp.type_date(),
|
||||
LocalTime: _mgp.type_local_time(),
|
||||
LocalDateTime: _mgp.type_local_date_time(),
|
||||
Duration: _mgp.type_duration()
|
||||
}
|
||||
try:
|
||||
return simple_types[type_]
|
||||
|
@ -129,8 +129,6 @@ class PathType : public CypherType {
|
||||
bool SatisfiesType(const query::TypedValue &value) const override { return value.IsPath(); }
|
||||
};
|
||||
|
||||
// TODO: There's also Temporal Types, but we currently do not support those.
|
||||
|
||||
// You'd think that MapType would be a composite type like ListType, but nope.
|
||||
// Why? No-one really knows. It's defined like that in "CIP2015-09-16 Public
|
||||
// Type System and Type Annotations"
|
||||
@ -149,6 +147,44 @@ class MapType : public CypherType {
|
||||
}
|
||||
};
|
||||
|
||||
// Temporal Types
|
||||
|
||||
class DateType : public CypherType {
|
||||
public:
|
||||
std::string_view GetPresentableName() const override { return "DATE"; }
|
||||
|
||||
bool SatisfiesType(const mgp_value &value) const override { return value.type == MGP_VALUE_TYPE_DATE; }
|
||||
|
||||
bool SatisfiesType(const query::TypedValue &value) const override { return value.IsDate(); }
|
||||
};
|
||||
|
||||
class LocalTimeType : public CypherType {
|
||||
public:
|
||||
std::string_view GetPresentableName() const override { return "LOCAL_TIME"; }
|
||||
|
||||
bool SatisfiesType(const mgp_value &value) const override { return value.type == MGP_VALUE_TYPE_LOCAL_TIME; }
|
||||
|
||||
bool SatisfiesType(const query::TypedValue &value) const override { return value.IsLocalTime(); }
|
||||
};
|
||||
|
||||
class LocalDateTimeType : public CypherType {
|
||||
public:
|
||||
std::string_view GetPresentableName() const override { return "LOCAL_DATE_TIME"; }
|
||||
|
||||
bool SatisfiesType(const mgp_value &value) const override { return value.type == MGP_VALUE_TYPE_LOCAL_DATE_TIME; }
|
||||
|
||||
bool SatisfiesType(const query::TypedValue &value) const override { return value.IsLocalDateTime(); }
|
||||
};
|
||||
|
||||
class DurationType : public CypherType {
|
||||
public:
|
||||
std::string_view GetPresentableName() const override { return "DURATION"; }
|
||||
|
||||
bool SatisfiesType(const mgp_value &value) const override { return value.type == MGP_VALUE_TYPE_DURATION; }
|
||||
|
||||
bool SatisfiesType(const query::TypedValue &value) const override { return value.IsDuration(); }
|
||||
};
|
||||
|
||||
// Composite Types
|
||||
|
||||
class ListType : public CypherType {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "utils/math.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/temporal.hpp"
|
||||
|
||||
// This file contains implementation of top level C API functions, but this is
|
||||
// all actually part of query::procedure. So use that namespace for simplicity.
|
||||
@ -163,6 +164,9 @@ template <typename TFunc, typename... Args>
|
||||
} catch (const std::exception &e) {
|
||||
spdlog::error("Unexpected error during mg API call: {}", e.what());
|
||||
return MGP_ERROR_UNKNOWN_ERROR;
|
||||
} catch (const utils::temporal::InvalidArgumentException &e) {
|
||||
spdlog::error("Invalid argument was sent to an mg API call for temporal types: {}", e.what());
|
||||
return MGP_ERROR_INVALID_ARGUMENT;
|
||||
} catch (...) {
|
||||
spdlog::error("Unexpected error during mg API call");
|
||||
return MGP_ERROR_UNKNOWN_ERROR;
|
||||
@ -262,8 +266,15 @@ mgp_value_type FromTypedValueType(query::TypedValue::Type type) {
|
||||
return MGP_VALUE_TYPE_EDGE;
|
||||
case query::TypedValue::Type::Path:
|
||||
return MGP_VALUE_TYPE_PATH;
|
||||
case query::TypedValue::Type::Date:
|
||||
return MGP_VALUE_TYPE_DATE;
|
||||
case query::TypedValue::Type::LocalTime:
|
||||
return MGP_VALUE_TYPE_LOCAL_TIME;
|
||||
case query::TypedValue::Type::LocalDateTime:
|
||||
return MGP_VALUE_TYPE_LOCAL_DATE_TIME;
|
||||
case query::TypedValue::Type::Duration:
|
||||
return MGP_VALUE_TYPE_DURATION;
|
||||
default:
|
||||
// TODO(antonio2368): Implement this when we add mgp temporal types
|
||||
LOG_FATAL("Unsupported value in the procedures");
|
||||
}
|
||||
}
|
||||
@ -312,6 +323,14 @@ query::TypedValue ToTypedValue(const mgp_value &val, utils::MemoryResource *memo
|
||||
}
|
||||
return query::TypedValue(std::move(tv_path));
|
||||
}
|
||||
case MGP_VALUE_TYPE_DATE:
|
||||
return query::TypedValue(val.date_v->date, memory);
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME:
|
||||
return query::TypedValue(val.local_time_v->local_time, memory);
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME:
|
||||
return query::TypedValue(val.local_date_time_v->local_date_time, memory);
|
||||
case MGP_VALUE_TYPE_DURATION:
|
||||
return query::TypedValue(val.duration_v->duration, memory);
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,6 +374,26 @@ mgp_value::mgp_value(mgp_path *val, utils::MemoryResource *m) noexcept
|
||||
MG_ASSERT(val->GetMemoryResource() == m, "Unable to take ownership of a pointer with different allocator.");
|
||||
}
|
||||
|
||||
mgp_value::mgp_value(mgp_date *val, utils::MemoryResource *m) noexcept
|
||||
: type(MGP_VALUE_TYPE_DATE), memory(m), date_v(val) {
|
||||
MG_ASSERT(val->GetMemoryResource() == m, "Unable to take ownership of a pointer with different allocator.");
|
||||
}
|
||||
|
||||
mgp_value::mgp_value(mgp_local_time *val, utils::MemoryResource *m) noexcept
|
||||
: type(MGP_VALUE_TYPE_LOCAL_TIME), memory(m), local_time_v(val) {
|
||||
MG_ASSERT(val->GetMemoryResource() == m, "Unable to take ownership of a pointer with different allocator.");
|
||||
}
|
||||
|
||||
mgp_value::mgp_value(mgp_local_date_time *val, utils::MemoryResource *m) noexcept
|
||||
: type(MGP_VALUE_TYPE_LOCAL_DATE_TIME), memory(m), local_date_time_v(val) {
|
||||
MG_ASSERT(val->GetMemoryResource() == m, "Unable to take ownership of a pointer with different allocator.");
|
||||
}
|
||||
|
||||
mgp_value::mgp_value(mgp_duration *val, utils::MemoryResource *m) noexcept
|
||||
: type(MGP_VALUE_TYPE_DURATION), memory(m), duration_v(val) {
|
||||
MG_ASSERT(val->GetMemoryResource() == m, "Unable to take ownership of a pointer with different allocator.");
|
||||
}
|
||||
|
||||
mgp_value::mgp_value(const query::TypedValue &tv, mgp_graph *graph, utils::MemoryResource *m)
|
||||
: type(FromTypedValueType(tv.type())), memory(m) {
|
||||
switch (type) {
|
||||
@ -427,6 +466,26 @@ mgp_value::mgp_value(const query::TypedValue &tv, mgp_graph *graph, utils::Memor
|
||||
path_v = allocator.new_object<mgp_path>(std::move(tmp_path));
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_DATE: {
|
||||
utils::Allocator<mgp_date> allocator(m);
|
||||
date_v = allocator.new_object<mgp_date>(tv.ValueDate());
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME: {
|
||||
utils::Allocator<mgp_local_time> allocator(m);
|
||||
local_time_v = allocator.new_object<mgp_local_time>(tv.ValueLocalTime());
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME: {
|
||||
utils::Allocator<mgp_local_date_time> allocator(m);
|
||||
local_date_time_v = allocator.new_object<mgp_local_date_time>(tv.ValueLocalDateTime());
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_DURATION: {
|
||||
utils::Allocator<mgp_duration> allocator(m);
|
||||
duration_v = allocator.new_object<mgp_duration>(tv.ValueDuration());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,8 +540,33 @@ mgp_value::mgp_value(const storage::PropertyValue &pv, utils::MemoryResource *m)
|
||||
break;
|
||||
}
|
||||
case storage::PropertyValue::Type::TemporalData: {
|
||||
// TODO(antonio2368): Add support for temporala data types
|
||||
LOG_FATAL("Unsupported type");
|
||||
const auto &temporal_data = pv.ValueTemporalData();
|
||||
switch (temporal_data.type) {
|
||||
case storage::TemporalType::Date: {
|
||||
type = MGP_VALUE_TYPE_DATE;
|
||||
utils::Allocator<mgp_date> allocator(m);
|
||||
date_v = allocator.new_object<mgp_date>(temporal_data.microseconds);
|
||||
break;
|
||||
}
|
||||
case storage::TemporalType::LocalTime: {
|
||||
type = MGP_VALUE_TYPE_LOCAL_TIME;
|
||||
utils::Allocator<mgp_local_time> allocator(m);
|
||||
local_time_v = allocator.new_object<mgp_local_time>(temporal_data.microseconds);
|
||||
break;
|
||||
}
|
||||
case storage::TemporalType::LocalDateTime: {
|
||||
type = MGP_VALUE_TYPE_LOCAL_DATE_TIME;
|
||||
utils::Allocator<mgp_local_date_time> allocator(m);
|
||||
local_date_time_v = allocator.new_object<mgp_local_date_time>(temporal_data.microseconds);
|
||||
break;
|
||||
}
|
||||
case storage::TemporalType::Duration: {
|
||||
type = MGP_VALUE_TYPE_DURATION;
|
||||
utils::Allocator<mgp_duration> allocator(m);
|
||||
duration_v = allocator.new_object<mgp_duration>(temporal_data.microseconds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -528,6 +612,26 @@ mgp_value::mgp_value(const mgp_value &other, utils::MemoryResource *m) : type(ot
|
||||
path_v = allocator.new_object<mgp_path>(*other.path_v);
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_DATE: {
|
||||
utils::Allocator<mgp_date> allocator(m);
|
||||
date_v = allocator.new_object<mgp_date>(*other.date_v);
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME: {
|
||||
utils::Allocator<mgp_local_time> allocator(m);
|
||||
local_time_v = allocator.new_object<mgp_local_time>(*other.local_time_v);
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME: {
|
||||
utils::Allocator<mgp_local_date_time> allocator(m);
|
||||
local_date_time_v = allocator.new_object<mgp_local_date_time>(*other.local_date_time_v);
|
||||
break;
|
||||
}
|
||||
case MGP_VALUE_TYPE_DURATION: {
|
||||
utils::Allocator<mgp_duration> allocator(m);
|
||||
duration_v = allocator.new_object<mgp_duration>(*other.duration_v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,6 +665,18 @@ void DeleteValueMember(mgp_value *value) noexcept {
|
||||
case MGP_VALUE_TYPE_PATH:
|
||||
allocator.delete_object(value->path_v);
|
||||
return;
|
||||
case MGP_VALUE_TYPE_DATE:
|
||||
allocator.delete_object(value->date_v);
|
||||
return;
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME:
|
||||
allocator.delete_object(value->local_time_v);
|
||||
return;
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME:
|
||||
allocator.delete_object(value->local_date_time_v);
|
||||
return;
|
||||
case MGP_VALUE_TYPE_DURATION:
|
||||
allocator.delete_object(value->duration_v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,6 +748,47 @@ mgp_value::mgp_value(mgp_value &&other, utils::MemoryResource *m) : type(other.t
|
||||
path_v = allocator.new_object<mgp_path>(std::move(*other.path_v));
|
||||
}
|
||||
break;
|
||||
case MGP_VALUE_TYPE_DATE:
|
||||
static_assert(std::is_pointer_v<decltype(date_v)>, "Expected to move date_v by copying pointers.");
|
||||
if (*other.GetMemoryResource() == *m) {
|
||||
date_v = other.date_v;
|
||||
other.type = MGP_VALUE_TYPE_NULL;
|
||||
} else {
|
||||
utils::Allocator<mgp_date> allocator(m);
|
||||
date_v = allocator.new_object<mgp_date>(*other.date_v);
|
||||
}
|
||||
break;
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME:
|
||||
static_assert(std::is_pointer_v<decltype(local_time_v)>, "Expected to move local_time_v by copying pointers.");
|
||||
if (*other.GetMemoryResource() == *m) {
|
||||
local_time_v = other.local_time_v;
|
||||
other.type = MGP_VALUE_TYPE_NULL;
|
||||
} else {
|
||||
utils::Allocator<mgp_local_time> allocator(m);
|
||||
local_time_v = allocator.new_object<mgp_local_time>(*other.local_time_v);
|
||||
}
|
||||
break;
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME:
|
||||
static_assert(std::is_pointer_v<decltype(local_date_time_v)>,
|
||||
"Expected to move local_date_time_v by copying pointers.");
|
||||
if (*other.GetMemoryResource() == *m) {
|
||||
local_date_time_v = other.local_date_time_v;
|
||||
other.type = MGP_VALUE_TYPE_NULL;
|
||||
} else {
|
||||
utils::Allocator<mgp_local_date_time> allocator(m);
|
||||
local_date_time_v = allocator.new_object<mgp_local_date_time>(*other.local_date_time_v);
|
||||
}
|
||||
break;
|
||||
case MGP_VALUE_TYPE_DURATION:
|
||||
static_assert(std::is_pointer_v<decltype(duration_v)>, "Expected to move duration_v by copying pointers.");
|
||||
if (*other.GetMemoryResource() == *m) {
|
||||
duration_v = other.duration_v;
|
||||
other.type = MGP_VALUE_TYPE_NULL;
|
||||
} else {
|
||||
utils::Allocator<mgp_duration> allocator(m);
|
||||
duration_v = allocator.new_object<mgp_duration>(*other.duration_v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
DeleteValueMember(&other);
|
||||
other.type = MGP_VALUE_TYPE_NULL;
|
||||
@ -675,6 +832,10 @@ DEFINE_MGP_VALUE_MAKE(map)
|
||||
DEFINE_MGP_VALUE_MAKE(vertex)
|
||||
DEFINE_MGP_VALUE_MAKE(edge)
|
||||
DEFINE_MGP_VALUE_MAKE(path)
|
||||
DEFINE_MGP_VALUE_MAKE(date)
|
||||
DEFINE_MGP_VALUE_MAKE(local_time)
|
||||
DEFINE_MGP_VALUE_MAKE(local_date_time)
|
||||
DEFINE_MGP_VALUE_MAKE(duration)
|
||||
|
||||
namespace {
|
||||
mgp_value_type MgpValueGetType(const mgp_value &val) noexcept { return val.type; }
|
||||
@ -704,6 +865,10 @@ DEFINE_MGP_VALUE_IS(map, MAP)
|
||||
DEFINE_MGP_VALUE_IS(vertex, VERTEX)
|
||||
DEFINE_MGP_VALUE_IS(edge, EDGE)
|
||||
DEFINE_MGP_VALUE_IS(path, PATH)
|
||||
DEFINE_MGP_VALUE_IS(date, DATE)
|
||||
DEFINE_MGP_VALUE_IS(local_time, LOCAL_TIME)
|
||||
DEFINE_MGP_VALUE_IS(local_date_time, LOCAL_DATE_TIME)
|
||||
DEFINE_MGP_VALUE_IS(duration, DURATION)
|
||||
|
||||
mgp_error mgp_value_get_bool(mgp_value *val, int *result) {
|
||||
*result = val->bool_v ? 1 : 0;
|
||||
@ -735,6 +900,10 @@ DEFINE_MGP_VALUE_GET(map)
|
||||
DEFINE_MGP_VALUE_GET(vertex)
|
||||
DEFINE_MGP_VALUE_GET(edge)
|
||||
DEFINE_MGP_VALUE_GET(path)
|
||||
DEFINE_MGP_VALUE_GET(date)
|
||||
DEFINE_MGP_VALUE_GET(local_time)
|
||||
DEFINE_MGP_VALUE_GET(local_date_time)
|
||||
DEFINE_MGP_VALUE_GET(duration)
|
||||
|
||||
mgp_error mgp_list_make_empty(size_t capacity, mgp_memory *memory, mgp_list **result) {
|
||||
return WrapExceptions(
|
||||
@ -975,6 +1144,274 @@ mgp_error mgp_path_equal(mgp_path *p1, mgp_path *p2, int *result) {
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_from_string(const char *string, mgp_memory *memory, mgp_date **date) {
|
||||
return WrapExceptions([string, memory] { return NewRawMgpObject<mgp_date>(memory, string); }, date);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_from_parameters(mgp_date_parameters *parameters, mgp_memory *memory, mgp_date **date) {
|
||||
return WrapExceptions([parameters, memory] { return NewRawMgpObject<mgp_date>(memory, parameters); }, date);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_copy(mgp_date *date, mgp_memory *memory, mgp_date **result) {
|
||||
return WrapExceptions([date, memory] { return NewRawMgpObject<mgp_date>(memory, *date); }, result);
|
||||
}
|
||||
|
||||
void mgp_date_destroy(mgp_date *date) { DeleteRawMgpObject(date); }
|
||||
|
||||
mgp_error mgp_date_equal(mgp_date *first, mgp_date *second, int *result) {
|
||||
return WrapExceptions([first, second] { return first->date == second->date; }, result);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_get_year(mgp_date *date, int *year) {
|
||||
return WrapExceptions([date] { return date->date.years; }, year);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_get_month(mgp_date *date, int *month) {
|
||||
return WrapExceptions([date] { return date->date.months; }, month);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_get_day(mgp_date *date, int *day) {
|
||||
return WrapExceptions([date] { return date->date.days; }, day);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_timestamp(mgp_date *date, int64_t *timestamp) {
|
||||
return WrapExceptions([date] { return static_cast<int>(date->date.MicrosecondsSinceEpoch()); }, timestamp);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_now(mgp_memory *memory, mgp_date **date) {
|
||||
return WrapExceptions([memory] { return NewRawMgpObject<mgp_date>(memory, utils::UtcToday()); }, date);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_add_duration(mgp_date *date, mgp_duration *dur, mgp_memory *memory, mgp_date **result) {
|
||||
return WrapExceptions([date, dur, memory] { return NewRawMgpObject<mgp_date>(memory, date->date + dur->duration); },
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_sub_duration(mgp_date *date, mgp_duration *dur, mgp_memory *memory, mgp_date **result) {
|
||||
return WrapExceptions([date, dur, memory] { return NewRawMgpObject<mgp_date>(memory, date->date - dur->duration); },
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_date_diff(mgp_date *first, mgp_date *second, mgp_memory *memory, mgp_duration **result) {
|
||||
return WrapExceptions(
|
||||
[first, second, memory] { return NewRawMgpObject<mgp_duration>(memory, first->date - second->date); }, result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_from_string(const char *string, mgp_memory *memory, mgp_local_time **local_time) {
|
||||
return WrapExceptions([string, memory] { return NewRawMgpObject<mgp_local_time>(memory, string); }, local_time);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_from_parameters(mgp_local_time_parameters *parameters, mgp_memory *memory,
|
||||
mgp_local_time **local_time) {
|
||||
return WrapExceptions([parameters, memory] { return NewRawMgpObject<mgp_local_time>(memory, parameters); },
|
||||
local_time);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_copy(mgp_local_time *local_time, mgp_memory *memory, mgp_local_time **result) {
|
||||
return WrapExceptions([local_time, memory] { return NewRawMgpObject<mgp_local_time>(memory, *local_time); }, result);
|
||||
}
|
||||
|
||||
void mgp_local_time_destroy(mgp_local_time *local_time) { DeleteRawMgpObject(local_time); }
|
||||
|
||||
mgp_error mgp_local_time_equal(mgp_local_time *first, mgp_local_time *second, int *result) {
|
||||
return WrapExceptions([first, second] { return first->local_time == second->local_time; }, result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_get_hour(mgp_local_time *local_time, int *hour) {
|
||||
return WrapExceptions([local_time] { return local_time->local_time.hours; }, hour);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_get_minue(mgp_local_time *local_time, int *minute) {
|
||||
return WrapExceptions([local_time] { return local_time->local_time.minutes; }, minute);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_get_second(mgp_local_time *local_time, int *second) {
|
||||
return WrapExceptions([local_time] { return local_time->local_time.seconds; }, second);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_get_millisecond(mgp_local_time *local_time, int *millisecond) {
|
||||
return WrapExceptions([local_time] { return local_time->local_time.milliseconds; }, millisecond);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_get_microsecond(mgp_local_time *local_time, int *microsecond) {
|
||||
return WrapExceptions([local_time] { return local_time->local_time.microseconds; }, microsecond);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_timestamp(mgp_local_time *local_time, int64_t *timestamp) {
|
||||
return WrapExceptions([local_time] { return static_cast<int>(local_time->local_time.MicrosecondsSinceEpoch()); },
|
||||
timestamp);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_now(mgp_memory *memory, mgp_local_time **local_time) {
|
||||
return WrapExceptions([memory] { return NewRawMgpObject<mgp_local_time>(memory, utils::UtcLocalTime()); },
|
||||
local_time);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_add_duration(mgp_local_time *local_time, mgp_duration *dur, mgp_memory *memory,
|
||||
mgp_local_time **result) {
|
||||
return WrapExceptions(
|
||||
[local_time, dur, memory] {
|
||||
return NewRawMgpObject<mgp_local_time>(memory, local_time->local_time + dur->duration);
|
||||
},
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_sub_duration(mgp_local_time *local_time, mgp_duration *dur, mgp_memory *memory,
|
||||
mgp_local_time **result) {
|
||||
return WrapExceptions(
|
||||
[local_time, dur, memory] {
|
||||
return NewRawMgpObject<mgp_local_time>(memory, local_time->local_time - dur->duration);
|
||||
},
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_time_diff(mgp_local_time *first, mgp_local_time *second, mgp_memory *memory,
|
||||
mgp_duration **result) {
|
||||
return WrapExceptions(
|
||||
[first, second, memory] { return NewRawMgpObject<mgp_duration>(memory, first->local_time - second->local_time); },
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_from_string(const char *string, mgp_memory *memory,
|
||||
mgp_local_date_time **local_date_time) {
|
||||
return WrapExceptions([string, memory] { return NewRawMgpObject<mgp_local_date_time>(memory, string); },
|
||||
local_date_time);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_from_parameters(mgp_local_date_time_parameters *parameters, mgp_memory *memory,
|
||||
mgp_local_date_time **local_date_time) {
|
||||
return WrapExceptions([parameters, memory] { return NewRawMgpObject<mgp_local_date_time>(memory, parameters); },
|
||||
local_date_time);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_copy(mgp_local_date_time *local_date_time, mgp_memory *memory,
|
||||
mgp_local_date_time **result) {
|
||||
return WrapExceptions(
|
||||
[local_date_time, memory] { return NewRawMgpObject<mgp_local_date_time>(memory, *local_date_time); }, result);
|
||||
}
|
||||
|
||||
void mgp_local_date_time_destroy(mgp_local_date_time *local_date_time) { DeleteRawMgpObject(local_date_time); }
|
||||
|
||||
mgp_error mgp_local_date_time_equal(mgp_local_date_time *first, mgp_local_date_time *second, int *result) {
|
||||
return WrapExceptions([first, second] { return first->local_date_time == second->local_date_time; }, result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_year(mgp_local_date_time *local_date_time, int *year) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.years; }, year);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_month(mgp_local_date_time *local_date_time, int *month) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.months; }, month);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_day(mgp_local_date_time *local_date_time, int *day) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.days; }, day);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_hour(mgp_local_date_time *local_date_time, int *hour) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.hours; }, hour);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_minute(mgp_local_date_time *local_date_time, int *minute) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.minutes; }, minute);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_second(mgp_local_date_time *local_date_time, int *second) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.seconds; }, second);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_millisecond(mgp_local_date_time *local_date_time, int *millisecond) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.milliseconds; },
|
||||
millisecond);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_get_microsecond(mgp_local_date_time *local_date_time, int *microsecond) {
|
||||
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.microseconds; },
|
||||
microsecond);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_timestamp(mgp_local_date_time *local_date_time, int64_t *timestamp) {
|
||||
return WrapExceptions(
|
||||
[local_date_time] { return static_cast<int>(local_date_time->local_date_time.MicrosecondsSinceEpoch()); },
|
||||
timestamp);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_now(mgp_memory *memory, mgp_local_date_time **local_date_time) {
|
||||
return WrapExceptions([memory] { return NewRawMgpObject<mgp_local_date_time>(memory, utils::UtcLocalDateTime()); },
|
||||
local_date_time);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_add_duration(mgp_local_date_time *local_date_time, mgp_duration *dur, mgp_memory *memory,
|
||||
mgp_local_date_time **result) {
|
||||
return WrapExceptions(
|
||||
[local_date_time, dur, memory] {
|
||||
return NewRawMgpObject<mgp_local_date_time>(memory, local_date_time->local_date_time + dur->duration);
|
||||
},
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_sub_duration(mgp_local_date_time *local_date_time, mgp_duration *dur, mgp_memory *memory,
|
||||
mgp_local_date_time **result) {
|
||||
return WrapExceptions(
|
||||
[local_date_time, dur, memory] {
|
||||
return NewRawMgpObject<mgp_local_date_time>(memory, local_date_time->local_date_time - dur->duration);
|
||||
},
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_local_date_time_diff(mgp_local_date_time *first, mgp_local_date_time *second, mgp_memory *memory,
|
||||
mgp_duration **result) {
|
||||
return WrapExceptions(
|
||||
[first, second, memory] {
|
||||
return NewRawMgpObject<mgp_duration>(memory, first->local_date_time - second->local_date_time);
|
||||
},
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_from_string(const char *string, mgp_memory *memory, mgp_duration **duration) {
|
||||
return WrapExceptions([memory, string] { return NewRawMgpObject<mgp_duration>(memory, string); }, duration);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_from_parameters(mgp_duration_parameters *parameters, mgp_memory *memory,
|
||||
mgp_duration **duration) {
|
||||
return WrapExceptions([memory, parameters] { return NewRawMgpObject<mgp_duration>(memory, parameters); }, duration);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_from_microseconds(int64_t microseconds, mgp_memory *memory, mgp_duration **duration) {
|
||||
return WrapExceptions([microseconds, memory] { return NewRawMgpObject<mgp_duration>(memory, microseconds); },
|
||||
duration);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_copy(mgp_duration *duration, mgp_memory *memory, mgp_duration **result) {
|
||||
return WrapExceptions([duration, memory] { return NewRawMgpObject<mgp_duration>(memory, *duration); }, result);
|
||||
}
|
||||
|
||||
void mgp_duration_destroy(mgp_duration *duration) { DeleteRawMgpObject(duration); }
|
||||
|
||||
mgp_error mgp_duration_get_microseconds(mgp_duration *duration, int64_t *microseconds) {
|
||||
return WrapExceptions([duration] { return duration->duration.microseconds; }, microseconds);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_equal(mgp_duration *first, mgp_duration *second, int *result) {
|
||||
return WrapExceptions([first, second] { return first->duration == second->duration; }, result);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_neg(mgp_duration *dur, mgp_memory *memory, mgp_duration **result) {
|
||||
return WrapExceptions([memory, dur] { return NewRawMgpObject<mgp_duration>(memory, -dur->duration); }, result);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_add(mgp_duration *first, mgp_duration *second, mgp_memory *memory, mgp_duration **result) {
|
||||
return WrapExceptions(
|
||||
[memory, first, second] { return NewRawMgpObject<mgp_duration>(memory, first->duration + second->duration); },
|
||||
result);
|
||||
}
|
||||
|
||||
mgp_error mgp_duration_sub(mgp_duration *first, mgp_duration *second, mgp_memory *memory, mgp_duration **result) {
|
||||
return WrapExceptions(
|
||||
[memory, first, second] { return NewRawMgpObject<mgp_duration>(memory, first->duration - second->duration); },
|
||||
result);
|
||||
}
|
||||
|
||||
/// Plugin Result
|
||||
|
||||
mgp_error mgp_result_set_error_msg(mgp_result *res, const char *msg) {
|
||||
@ -1106,6 +1543,18 @@ storage::PropertyValue ToPropertyValue(const mgp_value &value) {
|
||||
return ToPropertyValue(*value.list_v);
|
||||
case MGP_VALUE_TYPE_MAP:
|
||||
return ToPropertyValue(*value.map_v);
|
||||
case MGP_VALUE_TYPE_DATE:
|
||||
return storage::PropertyValue{
|
||||
storage::TemporalData{storage::TemporalType::Date, value.date_v->date.MicrosecondsSinceEpoch()}};
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME:
|
||||
return storage::PropertyValue{storage::TemporalData{storage::TemporalType::LocalTime,
|
||||
value.local_time_v->local_time.MicrosecondsSinceEpoch()}};
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME:
|
||||
return storage::PropertyValue{storage::TemporalData{
|
||||
storage::TemporalType::LocalDateTime, value.local_date_time_v->local_date_time.MicrosecondsSinceEpoch()}};
|
||||
case MGP_VALUE_TYPE_DURATION:
|
||||
return storage::PropertyValue{
|
||||
storage::TemporalData{storage::TemporalType::Duration, value.duration_v->duration.microseconds}};
|
||||
case MGP_VALUE_TYPE_VERTEX:
|
||||
throw ValueConversionException{"A vertex is not a valid property value! "};
|
||||
case MGP_VALUE_TYPE_EDGE:
|
||||
@ -1754,6 +2203,10 @@ DEFINE_MGP_TYPE_GETTER(Map, map);
|
||||
DEFINE_MGP_TYPE_GETTER(Node, node);
|
||||
DEFINE_MGP_TYPE_GETTER(Relationship, relationship);
|
||||
DEFINE_MGP_TYPE_GETTER(Path, path);
|
||||
DEFINE_MGP_TYPE_GETTER(Date, date);
|
||||
DEFINE_MGP_TYPE_GETTER(LocalTime, local_time);
|
||||
DEFINE_MGP_TYPE_GETTER(LocalDateTime, local_date_time);
|
||||
DEFINE_MGP_TYPE_GETTER(Duration, duration);
|
||||
|
||||
mgp_error mgp_type_list(mgp_type *type, mgp_type **result) {
|
||||
return WrapExceptions(
|
||||
@ -1850,6 +2303,10 @@ mgp_error mgp_proc_add_opt_arg(mgp_proc *proc, const char *name, mgp_type *type,
|
||||
case MGP_VALUE_TYPE_STRING:
|
||||
case MGP_VALUE_TYPE_LIST:
|
||||
case MGP_VALUE_TYPE_MAP:
|
||||
case MGP_VALUE_TYPE_DATE:
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME:
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME:
|
||||
case MGP_VALUE_TYPE_DURATION:
|
||||
break;
|
||||
}
|
||||
// Default value must be of required `type`.
|
||||
@ -1941,16 +2398,18 @@ std::ostream &PrintValue(const TypedValue &value, std::ostream *stream) {
|
||||
PrintValue(item.second, &stream);
|
||||
});
|
||||
return (*stream) << "}";
|
||||
case TypedValue::Type::Date:
|
||||
return (*stream) << value.ValueDate();
|
||||
case TypedValue::Type::LocalTime:
|
||||
return (*stream) << value.ValueLocalTime();
|
||||
case TypedValue::Type::LocalDateTime:
|
||||
return (*stream) << value.ValueLocalDateTime();
|
||||
case TypedValue::Type::Duration:
|
||||
return (*stream) << value.ValueDuration();
|
||||
case TypedValue::Type::Vertex:
|
||||
case TypedValue::Type::Edge:
|
||||
case TypedValue::Type::Path:
|
||||
LOG_FATAL("value must not be a graph element");
|
||||
case TypedValue::Type::Date:
|
||||
case TypedValue::Type::LocalTime:
|
||||
case TypedValue::Type::LocalDateTime:
|
||||
case TypedValue::Type::Duration:
|
||||
// TODO(antonio2368): Check how to print out nicely temporal types
|
||||
LOG_FATAL("Temporal types not imlemented yet");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "utils/pmr/map.hpp"
|
||||
#include "utils/pmr/string.hpp"
|
||||
#include "utils/pmr/vector.hpp"
|
||||
#include "utils/temporal.hpp"
|
||||
/// Wraps memory resource used in custom procedures.
|
||||
///
|
||||
/// This should have been `using mgp_memory = utils::MemoryResource`, but that's
|
||||
@ -53,6 +54,11 @@ struct mgp_value {
|
||||
/// Take ownership of the mgp_path, MemoryResource must match.
|
||||
mgp_value(mgp_path *, utils::MemoryResource *) noexcept;
|
||||
|
||||
mgp_value(mgp_date *, utils::MemoryResource *) noexcept;
|
||||
mgp_value(mgp_local_time *, utils::MemoryResource *) noexcept;
|
||||
mgp_value(mgp_local_date_time *, utils::MemoryResource *) noexcept;
|
||||
mgp_value(mgp_duration *, utils::MemoryResource *) noexcept;
|
||||
|
||||
/// Construct by copying query::TypedValue using utils::MemoryResource.
|
||||
/// mgp_graph is needed to construct mgp_vertex and mgp_edge.
|
||||
/// @throw std::bad_alloc
|
||||
@ -102,9 +108,214 @@ struct mgp_value {
|
||||
mgp_vertex *vertex_v;
|
||||
mgp_edge *edge_v;
|
||||
mgp_path *path_v;
|
||||
mgp_date *date_v;
|
||||
mgp_local_time *local_time_v;
|
||||
mgp_local_date_time *local_date_time_v;
|
||||
mgp_duration *duration_v;
|
||||
};
|
||||
};
|
||||
|
||||
inline utils::DateParameters MapDateParameters(const mgp_date_parameters *parameters) {
|
||||
return {.years = parameters->year, .months = parameters->month, .days = parameters->day};
|
||||
}
|
||||
|
||||
struct mgp_date {
|
||||
/// Allocator type so that STL containers are aware that we need one.
|
||||
/// We don't actually need this, but it simplifies the C API, because we store
|
||||
/// the allocator which was used to allocate `this`.
|
||||
using allocator_type = utils::Allocator<mgp_date>;
|
||||
|
||||
// Hopefully utils::Date copy constructor remains noexcept, so that we can
|
||||
// have everything noexcept here.
|
||||
static_assert(std::is_nothrow_copy_constructible_v<utils::Date>);
|
||||
|
||||
mgp_date(const utils::Date &date, utils::MemoryResource *memory) noexcept : memory(memory), date(date) {}
|
||||
|
||||
mgp_date(const std::string_view string, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), date(utils::ParseDateParameters(string).first) {}
|
||||
|
||||
mgp_date(const mgp_date_parameters *parameters, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), date(MapDateParameters(parameters)) {}
|
||||
|
||||
mgp_date(const int64_t microseconds, utils::MemoryResource *memory) noexcept : memory(memory), date(microseconds) {}
|
||||
|
||||
mgp_date(const mgp_date &other, utils::MemoryResource *memory) noexcept : memory(memory), date(other.date) {}
|
||||
|
||||
mgp_date(mgp_date &&other, utils::MemoryResource *memory) noexcept : memory(memory), date(other.date) {}
|
||||
|
||||
mgp_date(mgp_date &&other) noexcept : memory(other.memory), date(other.date) {}
|
||||
|
||||
/// Copy construction without utils::MemoryResource is not allowed.
|
||||
mgp_date(const mgp_date &) = delete;
|
||||
|
||||
mgp_date &operator=(const mgp_date &) = delete;
|
||||
mgp_date &operator=(mgp_date &&) = delete;
|
||||
|
||||
~mgp_date() = default;
|
||||
|
||||
utils::MemoryResource *GetMemoryResource() const noexcept { return memory; }
|
||||
|
||||
utils::MemoryResource *memory;
|
||||
utils::Date date;
|
||||
};
|
||||
|
||||
inline utils::LocalTimeParameters MapLocalTimeParameters(const mgp_local_time_parameters *parameters) {
|
||||
return {.hours = parameters->hour,
|
||||
.minutes = parameters->minute,
|
||||
.seconds = parameters->second,
|
||||
.milliseconds = parameters->millisecond,
|
||||
.microseconds = parameters->microsecond};
|
||||
}
|
||||
|
||||
struct mgp_local_time {
|
||||
/// Allocator type so that STL containers are aware that we need one.
|
||||
/// We don't actually need this, but it simplifies the C API, because we store
|
||||
/// the allocator which was used to allocate `this`.
|
||||
using allocator_type = utils::Allocator<mgp_local_time>;
|
||||
|
||||
// Hopefully utils::LocalTime copy constructor remains noexcept, so that we can
|
||||
// have everything noexcept here.
|
||||
static_assert(std::is_nothrow_copy_constructible_v<utils::LocalTime>);
|
||||
|
||||
mgp_local_time(const std::string_view string, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_time(utils::ParseLocalTimeParameters(string).first) {}
|
||||
|
||||
mgp_local_time(const mgp_local_time_parameters *parameters, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_time(MapLocalTimeParameters(parameters)) {}
|
||||
|
||||
mgp_local_time(const utils::LocalTime &local_time, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_time(local_time) {}
|
||||
|
||||
mgp_local_time(const int64_t microseconds, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_time(microseconds) {}
|
||||
|
||||
mgp_local_time(const mgp_local_time &other, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_time(other.local_time) {}
|
||||
|
||||
mgp_local_time(mgp_local_time &&other, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_time(other.local_time) {}
|
||||
|
||||
mgp_local_time(mgp_local_time &&other) noexcept : memory(other.memory), local_time(other.local_time) {}
|
||||
|
||||
/// Copy construction without utils::MemoryResource is not allowed.
|
||||
mgp_local_time(const mgp_local_time &) = delete;
|
||||
|
||||
mgp_local_time &operator=(const mgp_local_time &) = delete;
|
||||
mgp_local_time &operator=(mgp_local_time &&) = delete;
|
||||
|
||||
~mgp_local_time() = default;
|
||||
|
||||
utils::MemoryResource *GetMemoryResource() const noexcept { return memory; }
|
||||
|
||||
utils::MemoryResource *memory;
|
||||
utils::LocalTime local_time;
|
||||
};
|
||||
|
||||
inline utils::LocalDateTime CreateLocalDateTimeFromString(const std::string_view string) {
|
||||
const auto &[date_parameters, local_time_parameters] = utils::ParseLocalDateTimeParameters(string);
|
||||
return utils::LocalDateTime{date_parameters, local_time_parameters};
|
||||
}
|
||||
|
||||
struct mgp_local_date_time {
|
||||
/// Allocator type so that STL containers are aware that we need one.
|
||||
/// We don't actually need this, but it simplifies the C API, because we store
|
||||
/// the allocator which was used to allocate `this`.
|
||||
using allocator_type = utils::Allocator<mgp_local_date_time>;
|
||||
|
||||
// Hopefully utils::LocalDateTime copy constructor remains noexcept, so that we can
|
||||
// have everything noexcept here.
|
||||
static_assert(std::is_nothrow_copy_constructible_v<utils::LocalDateTime>);
|
||||
|
||||
mgp_local_date_time(const utils::LocalDateTime &local_date_time, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_date_time(local_date_time) {}
|
||||
|
||||
mgp_local_date_time(const std::string_view string, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_date_time(CreateLocalDateTimeFromString(string)) {}
|
||||
|
||||
mgp_local_date_time(const mgp_local_date_time_parameters *parameters, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory),
|
||||
local_date_time(MapDateParameters(parameters->date_parameters),
|
||||
MapLocalTimeParameters(parameters->local_time_parameters)) {}
|
||||
|
||||
mgp_local_date_time(const int64_t microseconds, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_date_time(microseconds) {}
|
||||
|
||||
mgp_local_date_time(const mgp_local_date_time &other, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_date_time(other.local_date_time) {}
|
||||
|
||||
mgp_local_date_time(mgp_local_date_time &&other, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), local_date_time(other.local_date_time) {}
|
||||
|
||||
mgp_local_date_time(mgp_local_date_time &&other) noexcept
|
||||
: memory(other.memory), local_date_time(other.local_date_time) {}
|
||||
|
||||
/// Copy construction without utils::MemoryResource is not allowed.
|
||||
mgp_local_date_time(const mgp_local_date_time &) = delete;
|
||||
|
||||
mgp_local_date_time &operator=(const mgp_local_date_time &) = delete;
|
||||
mgp_local_date_time &operator=(mgp_local_date_time &&) = delete;
|
||||
|
||||
~mgp_local_date_time() = default;
|
||||
|
||||
utils::MemoryResource *GetMemoryResource() const noexcept { return memory; }
|
||||
|
||||
utils::MemoryResource *memory;
|
||||
utils::LocalDateTime local_date_time;
|
||||
};
|
||||
|
||||
inline utils::DurationParameters MapDurationParameters(const mgp_duration_parameters *parameters) {
|
||||
return {.days = parameters->day,
|
||||
.hours = parameters->hour,
|
||||
.minutes = parameters->minute,
|
||||
.seconds = parameters->second,
|
||||
.milliseconds = parameters->millisecond,
|
||||
.microseconds = parameters->microsecond};
|
||||
}
|
||||
|
||||
struct mgp_duration {
|
||||
/// Allocator type so that STL containers are aware that we need one.
|
||||
/// We don't actually need this, but it simplifies the C API, because we store
|
||||
/// the allocator which was used to allocate `this`.
|
||||
using allocator_type = utils::Allocator<mgp_duration>;
|
||||
|
||||
// Hopefully utils::Duration copy constructor remains noexcept, so that we can
|
||||
// have everything noexcept here.
|
||||
static_assert(std::is_nothrow_copy_constructible_v<utils::Duration>);
|
||||
|
||||
mgp_duration(const std::string_view string, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), duration(utils::ParseDurationParameters(string)) {}
|
||||
|
||||
mgp_duration(const mgp_duration_parameters *parameters, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), duration(MapDurationParameters(parameters)) {}
|
||||
|
||||
mgp_duration(const utils::Duration &duration, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), duration(duration) {}
|
||||
|
||||
mgp_duration(const int64_t microseconds, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), duration(microseconds) {}
|
||||
|
||||
mgp_duration(const mgp_duration &other, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), duration(other.duration) {}
|
||||
|
||||
mgp_duration(mgp_duration &&other, utils::MemoryResource *memory) noexcept
|
||||
: memory(memory), duration(other.duration) {}
|
||||
|
||||
mgp_duration(mgp_duration &&other) noexcept : memory(other.memory), duration(other.duration) {}
|
||||
|
||||
/// Copy construction without utils::MemoryResource is not allowed.
|
||||
mgp_duration(const mgp_duration &) = delete;
|
||||
|
||||
mgp_duration &operator=(const mgp_duration &) = delete;
|
||||
mgp_duration &operator=(mgp_duration &&) = delete;
|
||||
|
||||
~mgp_duration() = default;
|
||||
|
||||
utils::MemoryResource *GetMemoryResource() const noexcept { return memory; }
|
||||
|
||||
utils::MemoryResource *memory;
|
||||
utils::Duration duration;
|
||||
};
|
||||
|
||||
struct mgp_list {
|
||||
/// Allocator type so that STL containers are aware that we need one.
|
||||
using allocator_type = utils::Allocator<mgp_list>;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "query/procedure/py_module.hpp"
|
||||
|
||||
#include <datetime.h>
|
||||
#include <pyerrors.h>
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
@ -9,6 +10,7 @@
|
||||
|
||||
#include "query/procedure/mg_procedure_helpers.hpp"
|
||||
#include "query/procedure/mg_procedure_impl.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/on_scope_exit.hpp"
|
||||
#include "utils/pmr/vector.hpp"
|
||||
|
||||
@ -1127,6 +1129,10 @@ DEFINE_PY_MGP_MODULE_TYPE(Map, map);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(Node, node);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(Relationship, relationship);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(Path, path);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(Date, date);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(LocalTime, local_time);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(LocalDateTime, local_date_time);
|
||||
DEFINE_PY_MGP_MODULE_TYPE(Duration, duration);
|
||||
|
||||
static PyMethodDef PyMgpModuleMethods[] = {
|
||||
{"type_nullable", PyMgpModuleTypeNullable, METH_O,
|
||||
@ -1145,6 +1151,10 @@ static PyMethodDef PyMgpModuleMethods[] = {
|
||||
"Get the type representing graph relationship values."},
|
||||
{"type_path", PyMgpModuleTypePath, METH_NOARGS,
|
||||
"Get the type representing a graph path (walk) from one node to another."},
|
||||
{"type_date", PyMgpModuleTypeDate, METH_NOARGS, "Get the type representing a Date."},
|
||||
{"type_local_time", PyMgpModuleTypeLocalTime, METH_NOARGS, "Get the type representing a LocalTime."},
|
||||
{"type_local_date_time", PyMgpModuleTypeLocalDateTime, METH_NOARGS, "Get the type representing a LocalDateTime."},
|
||||
{"type_duration", PyMgpModuleTypeDuration, METH_NOARGS, "Get the type representing a Duration."},
|
||||
{nullptr},
|
||||
};
|
||||
|
||||
@ -1956,6 +1966,10 @@ PyObject *PyInitMgpModule() {
|
||||
}
|
||||
}
|
||||
clean_up.Disable();
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
PyDateTime_IMPORT;
|
||||
|
||||
return mgp;
|
||||
}
|
||||
|
||||
@ -2055,6 +2069,30 @@ py::Object MgpValueToPyObject(const mgp_value &value, PyGraph *py_graph) {
|
||||
py::Object py_path(reinterpret_cast<PyObject *>(MakePyPath(*p, py_graph)));
|
||||
return py_mgp.CallMethod("Path", py_path);
|
||||
}
|
||||
case MGP_VALUE_TYPE_DATE: {
|
||||
const auto &date = value.date_v->date;
|
||||
py::Object py_date(PyDate_FromDate(date.years, date.months, date.days));
|
||||
return py_date;
|
||||
}
|
||||
case MGP_VALUE_TYPE_LOCAL_TIME: {
|
||||
const auto &local_time = value.local_time_v->local_time;
|
||||
py::Object py_local_time(PyTime_FromTime(local_time.hours, local_time.minutes, local_time.seconds,
|
||||
local_time.milliseconds * 1000 + local_time.microseconds));
|
||||
return py_local_time;
|
||||
}
|
||||
case MGP_VALUE_TYPE_LOCAL_DATE_TIME: {
|
||||
const auto &local_time = value.local_date_time_v->local_date_time.local_time;
|
||||
const auto &date = value.local_date_time_v->local_date_time.date;
|
||||
py::Object py_local_date_time(
|
||||
PyDateTime_FromDateAndTime(date.years, date.months, date.days, local_time.hours, local_time.minutes,
|
||||
local_time.seconds, local_time.milliseconds * 1000 + local_time.microseconds));
|
||||
return py_local_date_time;
|
||||
}
|
||||
case MGP_VALUE_TYPE_DURATION: {
|
||||
const auto &duration = value.duration_v->duration;
|
||||
py::Object py_duration(PyDelta_FromDSU(0, 0, duration.microseconds));
|
||||
return py_duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2247,6 +2285,108 @@ mgp_value *PyObjectToMgpValue(PyObject *o, mgp_memory *memory) {
|
||||
throw std::invalid_argument("'mgp.Path' is missing '_path' attribute");
|
||||
}
|
||||
return PyObjectToMgpValue(path.Ptr(), memory);
|
||||
} else if (PyDate_CheckExact(o)) {
|
||||
mgp_date_parameters parameters{
|
||||
.year = PyDateTime_GET_YEAR(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.month = PyDateTime_GET_MONTH(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.day = PyDateTime_GET_DAY(o)}; // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
MgpUniquePtr<mgp_date> date{nullptr, mgp_date_destroy};
|
||||
|
||||
if (const auto err = CreateMgpObject(date, mgp_date_from_parameters, ¶meters, memory);
|
||||
err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_date"};
|
||||
}
|
||||
if (const auto err = mgp_value_make_date(date.get(), &mgp_v); err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_value"};
|
||||
}
|
||||
static_cast<void>(date.release());
|
||||
} else if (PyTime_CheckExact(o)) {
|
||||
mgp_local_time_parameters parameters{
|
||||
.hour = PyDateTime_TIME_GET_HOUR(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.minute = PyDateTime_TIME_GET_MINUTE(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.second = PyDateTime_TIME_GET_SECOND(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.millisecond =
|
||||
PyDateTime_TIME_GET_MICROSECOND(o) / // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
1000,
|
||||
.microsecond =
|
||||
PyDateTime_TIME_GET_MICROSECOND(o) % // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
1000};
|
||||
MgpUniquePtr<mgp_local_time> local_time{nullptr, mgp_local_time_destroy};
|
||||
|
||||
if (const auto err = CreateMgpObject(local_time, mgp_local_time_from_parameters, ¶meters, memory);
|
||||
err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_local_time"};
|
||||
}
|
||||
if (const auto err = mgp_value_make_local_time(local_time.get(), &mgp_v); err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_value"};
|
||||
}
|
||||
static_cast<void>(local_time.release());
|
||||
} else if (PyDateTime_CheckExact(o)) {
|
||||
mgp_date_parameters date_parameters{
|
||||
.year = PyDateTime_GET_YEAR(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.month = PyDateTime_GET_MONTH(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.day = PyDateTime_GET_DAY(o)}; // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
mgp_local_time_parameters local_time_parameters{
|
||||
.hour = PyDateTime_DATE_GET_HOUR(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.minute = PyDateTime_DATE_GET_MINUTE(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.second = PyDateTime_DATE_GET_SECOND(o), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
.millisecond =
|
||||
PyDateTime_DATE_GET_MICROSECOND(o) / // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
1000,
|
||||
.microsecond =
|
||||
PyDateTime_DATE_GET_MICROSECOND(o) % // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
1000};
|
||||
|
||||
mgp_local_date_time_parameters parameters{&date_parameters, &local_time_parameters};
|
||||
|
||||
MgpUniquePtr<mgp_local_date_time> local_date_time{nullptr, mgp_local_date_time_destroy};
|
||||
|
||||
if (const auto err = CreateMgpObject(local_date_time, mgp_local_date_time_from_parameters, ¶meters, memory);
|
||||
err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_local_date_time"};
|
||||
}
|
||||
if (const auto err = mgp_value_make_local_date_time(local_date_time.get(), &mgp_v);
|
||||
err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_value"};
|
||||
}
|
||||
static_cast<void>(local_date_time.release());
|
||||
} else if (PyDelta_CheckExact(o)) {
|
||||
constexpr int64_t microseconds_in_days = static_cast<std::chrono::microseconds>(std::chrono::days{1}).count();
|
||||
const auto days =
|
||||
PyDateTime_DELTA_GET_DAYS(o); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
auto microseconds =
|
||||
std::abs(days) * microseconds_in_days +
|
||||
PyDateTime_DELTA_GET_SECONDS(o) * 1000 * // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
1000 +
|
||||
PyDateTime_DELTA_GET_MICROSECONDS(o); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast,hicpp-signed-bitwise)
|
||||
microseconds *= days < 0 ? -1 : 1;
|
||||
|
||||
MgpUniquePtr<mgp_duration> duration{nullptr, mgp_duration_destroy};
|
||||
|
||||
if (const auto err = CreateMgpObject(duration, mgp_duration_from_microseconds, microseconds, memory);
|
||||
err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_duration"};
|
||||
}
|
||||
if (const auto err = mgp_value_make_duration(duration.get(), &mgp_v); err == MGP_ERROR_UNABLE_TO_ALLOCATE) {
|
||||
throw std::bad_alloc{};
|
||||
} else if (err != MGP_ERROR_NO_ERROR) {
|
||||
throw std::runtime_error{"Unexpected error while creating mgp_value"};
|
||||
}
|
||||
static_cast<void>(duration.release());
|
||||
} else {
|
||||
throw std::invalid_argument("Unsupported PyObject conversion");
|
||||
}
|
||||
|
@ -47,18 +47,18 @@ Date::Date(const int64_t microseconds) {
|
||||
|
||||
Date::Date(const DateParameters &date_parameters) {
|
||||
if (!IsInBounds(0, 9999, date_parameters.years)) {
|
||||
throw utils::BasicException(
|
||||
throw temporal::InvalidArgumentException(
|
||||
"Creating a Date with invalid year parameter. The value should be an integer between 0 and 9999.");
|
||||
}
|
||||
|
||||
if (!IsInBounds(1, 12, date_parameters.months)) {
|
||||
throw utils::BasicException(
|
||||
throw temporal::InvalidArgumentException(
|
||||
"Creating a Date with invalid month parameter. The value should be an integer between 1 and 12.");
|
||||
}
|
||||
|
||||
if (!IsInBounds(1, 31, date_parameters.days) ||
|
||||
!IsValidDay(date_parameters.days, date_parameters.months, date_parameters.years)) {
|
||||
throw utils::BasicException(
|
||||
throw temporal::InvalidArgumentException(
|
||||
"Creating a Date with invalid day parameter. The value should be an integer between 1 and 31, depending on the "
|
||||
"month and year.");
|
||||
}
|
||||
@ -74,7 +74,7 @@ tm GetUtcFromSystemClockOrThrow() {
|
||||
const auto today = chrono::system_clock::to_time_t(chrono::system_clock::now());
|
||||
tm utc_today;
|
||||
if (!gmtime_r(&today, &utc_today)) {
|
||||
throw utils::BasicException("Can't access clock's UTC time");
|
||||
throw temporal::InvalidArgumentException("Can't access clock's UTC time");
|
||||
}
|
||||
return utc_today;
|
||||
}
|
||||
@ -132,13 +132,13 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
|
||||
if (!std::any_of(
|
||||
valid_sizes.begin(), valid_sizes.end(),
|
||||
[date_string_size = date_string.size()](const auto valid_size) { return valid_size == date_string_size; })) {
|
||||
throw utils::BasicException("Invalid string for date. {}", kSupportedDateFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid string for date. {}", kSupportedDateFormatsHelpMessage);
|
||||
}
|
||||
|
||||
DateParameters date_parameters;
|
||||
auto maybe_year = ParseNumber<int64_t>(date_string, 4);
|
||||
if (!maybe_year) {
|
||||
throw utils::BasicException("Invalid year in the string. {}", kSupportedDateFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid year in the string. {}", kSupportedDateFormatsHelpMessage);
|
||||
}
|
||||
date_parameters.years = *maybe_year;
|
||||
date_string.remove_prefix(4);
|
||||
@ -151,7 +151,7 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
|
||||
|
||||
auto maybe_month = ParseNumber<int64_t>(date_string, 2);
|
||||
if (!maybe_month) {
|
||||
throw utils::BasicException("Invalid month in the string. {}", kSupportedDateFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid month in the string. {}", kSupportedDateFormatsHelpMessage);
|
||||
}
|
||||
date_parameters.months = *maybe_month;
|
||||
date_string.remove_prefix(2);
|
||||
@ -159,21 +159,21 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
|
||||
if (!date_string.empty()) {
|
||||
if (date_string.front() == '-') {
|
||||
if (!is_extended_format) {
|
||||
throw utils::BasicException("Invalid format for the date. {}", kSupportedDateFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid format for the date. {}", kSupportedDateFormatsHelpMessage);
|
||||
}
|
||||
date_string.remove_prefix(1);
|
||||
}
|
||||
|
||||
auto maybe_day = ParseNumber<int64_t>(date_string, 2);
|
||||
if (!maybe_day) {
|
||||
throw utils::BasicException("Invalid month in the string. {}", kSupportedDateFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid month in the string. {}", kSupportedDateFormatsHelpMessage);
|
||||
}
|
||||
date_parameters.days = *maybe_day;
|
||||
date_string.remove_prefix(2);
|
||||
}
|
||||
|
||||
if (!date_string.empty()) {
|
||||
throw utils::BasicException("Invalid format for the date. {}", kSupportedDateFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid format for the date. {}", kSupportedDateFormatsHelpMessage);
|
||||
}
|
||||
|
||||
return {date_parameters, is_extended_format};
|
||||
@ -242,7 +242,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
}
|
||||
|
||||
if (*using_colon ^ has_colon) {
|
||||
throw utils::BasicException(
|
||||
throw temporal::InvalidArgumentException(
|
||||
"Invalid format for the local time. A separator should be used consistently or not at all. {}",
|
||||
kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
@ -252,7 +252,8 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
}
|
||||
|
||||
if (local_time_string.empty()) {
|
||||
throw utils::BasicException("Invalid format for the local time. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid format for the local time. {}",
|
||||
kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
};
|
||||
|
||||
@ -260,7 +261,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
|
||||
const auto maybe_hour = ParseNumber<int64_t>(local_time_string, 2);
|
||||
if (!maybe_hour) {
|
||||
throw utils::BasicException("Invalid hour in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid hour in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
local_time_parameters.hours = *maybe_hour;
|
||||
local_time_string.remove_prefix(2);
|
||||
@ -273,7 +274,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
|
||||
const auto maybe_minute = ParseNumber<int64_t>(local_time_string, 2);
|
||||
if (!maybe_minute) {
|
||||
throw utils::BasicException("Invalid minutes in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid minutes in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
local_time_parameters.minutes = *maybe_minute;
|
||||
local_time_string.remove_prefix(2);
|
||||
@ -286,7 +287,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
|
||||
const auto maybe_seconds = ParseNumber<int64_t>(local_time_string, 2);
|
||||
if (!maybe_seconds) {
|
||||
throw utils::BasicException("Invalid seconds in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid seconds in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
local_time_parameters.seconds = *maybe_seconds;
|
||||
local_time_string.remove_prefix(2);
|
||||
@ -296,13 +297,14 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
}
|
||||
|
||||
if (local_time_string.front() != '.') {
|
||||
throw utils::BasicException("Invalid format for local time. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid format for local time. {}", kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
local_time_string.remove_prefix(1);
|
||||
|
||||
const auto maybe_milliseconds = ParseNumber<int64_t>(local_time_string, 3);
|
||||
if (!maybe_milliseconds) {
|
||||
throw utils::BasicException("Invalid milliseconds in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid milliseconds in the string. {}",
|
||||
kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
local_time_parameters.milliseconds = *maybe_milliseconds;
|
||||
local_time_string.remove_prefix(3);
|
||||
@ -313,13 +315,14 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
|
||||
const auto maybe_microseconds = ParseNumber<int64_t>(local_time_string, 3);
|
||||
if (!maybe_microseconds) {
|
||||
throw utils::BasicException("Invalid microseconds in the string. {}", kSupportedTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid microseconds in the string. {}",
|
||||
kSupportedTimeFormatsHelpMessage);
|
||||
}
|
||||
local_time_parameters.microseconds = *maybe_microseconds;
|
||||
local_time_string.remove_prefix(3);
|
||||
|
||||
if (!local_time_string.empty()) {
|
||||
throw utils::BasicException("Extra characters present at the end of the string.");
|
||||
throw temporal::InvalidArgumentException("Extra characters present at the end of the string.");
|
||||
}
|
||||
|
||||
return {local_time_parameters, *using_colon};
|
||||
@ -328,12 +331,12 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
|
||||
LocalTime::LocalTime(const int64_t microseconds) {
|
||||
auto chrono_microseconds = std::chrono::microseconds(microseconds);
|
||||
if (chrono_microseconds.count() < 0) {
|
||||
throw utils::BasicException("Negative LocalTime specified in microseconds");
|
||||
throw temporal::InvalidArgumentException("Negative LocalTime specified in microseconds");
|
||||
}
|
||||
|
||||
const auto parsed_hours = GetAndSubtractDuration<std::chrono::hours>(chrono_microseconds);
|
||||
if (parsed_hours > 23) {
|
||||
throw utils::BasicException("Invalid LocalTime specified in microseconds");
|
||||
throw temporal::InvalidArgumentException("Invalid LocalTime specified in microseconds");
|
||||
}
|
||||
|
||||
hours = parsed_hours;
|
||||
@ -345,24 +348,24 @@ LocalTime::LocalTime(const int64_t microseconds) {
|
||||
|
||||
LocalTime::LocalTime(const LocalTimeParameters &local_time_parameters) {
|
||||
if (!IsInBounds(0, 23, local_time_parameters.hours)) {
|
||||
throw utils::BasicException("Creating a LocalTime with invalid hour parameter.");
|
||||
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid hour parameter.");
|
||||
}
|
||||
|
||||
if (!IsInBounds(0, 59, local_time_parameters.minutes)) {
|
||||
throw utils::BasicException("Creating a LocalTime with invalid minutes parameter.");
|
||||
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid minutes parameter.");
|
||||
}
|
||||
|
||||
// ISO 8601 supports leap seconds, but we ignore it for now to simplify the implementation
|
||||
if (!IsInBounds(0, 59, local_time_parameters.seconds)) {
|
||||
throw utils::BasicException("Creating a LocalTime with invalid seconds parameter.");
|
||||
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid seconds parameter.");
|
||||
}
|
||||
|
||||
if (!IsInBounds(0, 999, local_time_parameters.milliseconds)) {
|
||||
throw utils::BasicException("Creating a LocalTime with invalid milliseconds parameter.");
|
||||
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid milliseconds parameter.");
|
||||
}
|
||||
|
||||
if (!IsInBounds(0, 999, local_time_parameters.microseconds)) {
|
||||
throw utils::BasicException("Creating a LocalTime with invalid microseconds parameter.");
|
||||
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid microseconds parameter.");
|
||||
}
|
||||
|
||||
hours = local_time_parameters.hours;
|
||||
@ -433,7 +436,8 @@ or both parts should be written in their basic forms without the separators.)hel
|
||||
std::pair<DateParameters, LocalTimeParameters> ParseLocalDateTimeParameters(std::string_view string) {
|
||||
auto t_position = string.find('T');
|
||||
if (t_position == std::string_view::npos) {
|
||||
throw utils::BasicException("Invalid LocalDateTime format. {}", kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid LocalDateTime format. {}",
|
||||
kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -444,20 +448,22 @@ std::pair<DateParameters, LocalTimeParameters> ParseLocalDateTimeParameters(std:
|
||||
// which denotes the basic format. The opposite case also aplies.
|
||||
auto local_time_substring = string.substr(t_position + 1);
|
||||
if (local_time_substring.empty()) {
|
||||
throw utils::BasicException("Invalid LocalDateTime format. {}", kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
throw temporal::InvalidArgumentException("Invalid LocalDateTime format. {}",
|
||||
kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
}
|
||||
|
||||
auto [local_time_parameters, extended_time_format] = ParseLocalTimeParameters(local_time_substring);
|
||||
|
||||
if (extended_date_format ^ extended_time_format) {
|
||||
throw utils::BasicException(
|
||||
throw temporal::InvalidArgumentException(
|
||||
"Invalid LocalDateTime format. Both date and time should be in the basic or extended format. {}",
|
||||
kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
}
|
||||
|
||||
return {date_parameters, local_time_parameters};
|
||||
} catch (const utils::BasicException &e) {
|
||||
throw utils::BasicException("Invalid LocalDateTime format. {}", kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
} catch (const temporal::InvalidArgumentException &e) {
|
||||
throw temporal::InvalidArgumentException("Invalid LocalDateTime format. {}",
|
||||
kSupportedLocalDateTimeFormatsHelpMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -630,7 +636,7 @@ DurationParameters ParseDurationParameters(std::string_view string) {
|
||||
// The string needs to start with P followed by one of the two options:
|
||||
// - string in a duration specific format
|
||||
if (string.empty() || string.front() != 'P') {
|
||||
throw utils::BasicException("Duration string is empty.");
|
||||
throw temporal::InvalidArgumentException("Duration string is empty.");
|
||||
}
|
||||
|
||||
if (auto maybe_duration_parameters = TryParseDurationString(string); maybe_duration_parameters) {
|
||||
@ -705,7 +711,7 @@ int64_t Duration::SubSecondsAsNanoseconds() const {
|
||||
|
||||
Duration Duration::operator-() const {
|
||||
if (microseconds == std::numeric_limits<decltype(microseconds)>::min()) [[unlikely]] {
|
||||
throw utils::BasicException("Duration arithmetic overflows");
|
||||
throw temporal::InvalidArgumentException("Duration arithmetic overflows");
|
||||
}
|
||||
Duration result{-microseconds};
|
||||
return result;
|
||||
|
@ -40,6 +40,12 @@ bool Underflows(const TType &lhs, const TType &rhs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace temporal {
|
||||
struct InvalidArgumentException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
} // namespace temporal
|
||||
|
||||
struct DurationParameters {
|
||||
double days{0};
|
||||
double hours{0};
|
||||
|
Loading…
Reference in New Issue
Block a user