From: Vladimir Davydov via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: Timur Safin via Tarantool-patches <tarantool-patches@dev.tarantool.org> Cc: v.shpilevoy@tarantool.org Subject: Re: [Tarantool-patches] [PATCH v5 4/8] box, datetime: messagepack support for datetime Date: Tue, 17 Aug 2021 21:36:07 +0300 [thread overview] Message-ID: <20210817183607.akhqcqos2dmbkbol@esperanza> (raw) In-Reply-To: <5e5afbb7249c1dfa56f2695fc6a7140be98fa39d.1629071531.git.tsafin@tarantool.org> On Mon, Aug 16, 2021 at 02:59:38AM +0300, Timur Safin via Tarantool-patches wrote: > Serialize datetime_t as newly introduced MP_EXT type. > It saves 1 required integer field and upto 2 optional > unsigned fields in very compact fashion. > - secs is required field; > - but nsec, offset are both optional; > > * json, yaml serialization formats, lua output mode > supported; > * exported symbols for datetime messagepack size calculations > so they are available for usage on Lua side. > > Part of #5941 > Part of #5946 > --- > extra/exports | 5 +- > src/box/field_def.c | 35 +++--- > src/box/field_def.h | 1 + > src/box/lua/serialize_lua.c | 7 +- > src/box/msgpack.c | 7 +- > src/box/tuple_compare.cc | 20 ++++ > src/lib/core/CMakeLists.txt | 4 +- > src/lib/core/datetime.c | 9 ++ > src/lib/core/datetime.h | 11 ++ > src/lib/core/mp_datetime.c | 189 ++++++++++++++++++++++++++++++ > src/lib/core/mp_datetime.h | 89 ++++++++++++++ > src/lib/core/mp_extension_types.h | 1 + > src/lib/mpstream/mpstream.c | 11 ++ > src/lib/mpstream/mpstream.h | 4 + > src/lua/msgpack.c | 12 ++ > src/lua/msgpackffi.lua | 18 +++ > src/lua/serializer.c | 4 + > src/lua/serializer.h | 2 + > src/lua/utils.c | 1 - > test/unit/datetime.c | 125 +++++++++++++++++++- > test/unit/datetime.result | 115 +++++++++++++++++- > third_party/lua-cjson/lua_cjson.c | 8 ++ > third_party/lua-yaml/lyaml.cc | 6 +- Please add a Lua test checking that serialization (msgpack, yaml, json) works fine. Should be added in this patch. > 23 files changed, 661 insertions(+), 23 deletions(-) > create mode 100644 src/lib/core/mp_datetime.c > create mode 100644 src/lib/core/mp_datetime.h > > diff --git a/src/box/field_def.c b/src/box/field_def.c > index 51acb8025..2682a42ee 100644 > --- a/src/box/field_def.c > +++ b/src/box/field_def.c > @@ -72,6 +72,7 @@ const uint32_t field_mp_type[] = { > /* [FIELD_TYPE_UUID] = */ 0, /* only MP_UUID is supported */ > /* [FIELD_TYPE_ARRAY] = */ 1U << MP_ARRAY, > /* [FIELD_TYPE_MAP] = */ (1U << MP_MAP), > + /* [FIELD_TYPE_DATETIME] = */ 0, /* only MP_DATETIME is supported */ > }; > > const uint32_t field_ext_type[] = { > @@ -83,11 +84,13 @@ const uint32_t field_ext_type[] = { > /* [FIELD_TYPE_INTEGER] = */ 0, > /* [FIELD_TYPE_BOOLEAN] = */ 0, > /* [FIELD_TYPE_VARBINARY] = */ 0, > - /* [FIELD_TYPE_SCALAR] = */ (1U << MP_DECIMAL) | (1U << MP_UUID), > + /* [FIELD_TYPE_SCALAR] = */ (1U << MP_DECIMAL) | (1U << MP_UUID) | > + (1U << MP_DATETIME), > /* [FIELD_TYPE_DECIMAL] = */ 1U << MP_DECIMAL, > /* [FIELD_TYPE_UUID] = */ 1U << MP_UUID, > /* [FIELD_TYPE_ARRAY] = */ 0, > /* [FIELD_TYPE_MAP] = */ 0, > + /* [FIELD_TYPE_DATETIME] = */ 1U << MP_DATETIME, > }; > > const char *field_type_strs[] = { > @@ -104,6 +107,7 @@ const char *field_type_strs[] = { > /* [FIELD_TYPE_UUID] = */ "uuid", > /* [FIELD_TYPE_ARRAY] = */ "array", > /* [FIELD_TYPE_MAP] = */ "map", > + /* [FIELD_TYPE_DATETIME] = */ "datetime", > }; This doesn't belong to this patch. Please split in two: - encoding datetime as msgpack/yaml/json - this patch - indexing of datetime - next patch > > const char *on_conflict_action_strs[] = { > @@ -128,20 +132,21 @@ field_type_by_name_wrapper(const char *str, uint32_t len) > * values can be stored in the j type. > */ > static const bool field_type_compatibility[] = { > - /* ANY UNSIGNED STRING NUMBER DOUBLE INTEGER BOOLEAN VARBINARY SCALAR DECIMAL UUID ARRAY MAP */ > -/* ANY */ true, false, false, false, false, false, false, false, false, false, false, false, false, > -/* UNSIGNED */ true, true, false, true, false, true, false, false, true, false, false, false, false, > -/* STRING */ true, false, true, false, false, false, false, false, true, false, false, false, false, > -/* NUMBER */ true, false, false, true, false, false, false, false, true, false, false, false, false, > -/* DOUBLE */ true, false, false, true, true, false, false, false, true, false, false, false, false, > -/* INTEGER */ true, false, false, true, false, true, false, false, true, false, false, false, false, > -/* BOOLEAN */ true, false, false, false, false, false, true, false, true, false, false, false, false, > -/* VARBINARY*/ true, false, false, false, false, false, false, true, true, false, false, false, false, > -/* SCALAR */ true, false, false, false, false, false, false, false, true, false, false, false, false, > -/* DECIMAL */ true, false, false, true, false, false, false, false, true, true, false, false, false, > -/* UUID */ true, false, false, false, false, false, false, false, false, false, true, false, false, > -/* ARRAY */ true, false, false, false, false, false, false, false, false, false, false, true, false, > -/* MAP */ true, false, false, false, false, false, false, false, false, false, false, false, true, > + /* ANY UNSIGNED STRING NUMBER DOUBLE INTEGER BOOLEAN VARBINARY SCALAR DECIMAL UUID ARRAY MAP DATETIME */ > +/* ANY */ true, false, false, false, false, false, false, false, false, false, false, false, false, false, > +/* UNSIGNED */ true, true, false, true, false, true, false, false, true, false, false, false, false, false, > +/* STRING */ true, false, true, false, false, false, false, false, true, false, false, false, false, false, > +/* NUMBER */ true, false, false, true, false, false, false, false, true, false, false, false, false, false, > +/* DOUBLE */ true, false, false, true, true, false, false, false, true, false, false, false, false, false, > +/* INTEGER */ true, false, false, true, false, true, false, false, true, false, false, false, false, false, > +/* BOOLEAN */ true, false, false, false, false, false, true, false, true, false, false, false, false, false, > +/* VARBINARY*/ true, false, false, false, false, false, false, true, true, false, false, false, false, false, > +/* SCALAR */ true, false, false, false, false, false, false, false, true, false, false, false, false, false, > +/* DECIMAL */ true, false, false, true, false, false, false, false, true, true, false, false, false, false, > +/* UUID */ true, false, false, false, false, false, false, false, false, false, true, false, false, false, > +/* ARRAY */ true, false, false, false, false, false, false, false, false, false, false, true, false, false, > +/* MAP */ true, false, false, false, false, false, false, false, false, false, false, false, true, false, > +/* DATETIME */ true, false, false, false, false, false, false, false, true, false, false, false, false, true, > }; > > bool > diff --git a/src/box/field_def.h b/src/box/field_def.h > index c5cfe5e86..120b2a93d 100644 > --- a/src/box/field_def.h > +++ b/src/box/field_def.h > @@ -63,6 +63,7 @@ enum field_type { > FIELD_TYPE_UUID, > FIELD_TYPE_ARRAY, > FIELD_TYPE_MAP, > + FIELD_TYPE_DATETIME, > field_type_MAX > }; > > diff --git a/src/box/lua/serialize_lua.c b/src/box/lua/serialize_lua.c > index 1f791980f..51855011b 100644 > --- a/src/box/lua/serialize_lua.c > +++ b/src/box/lua/serialize_lua.c > @@ -768,7 +768,7 @@ static int > dump_node(struct lua_dumper *d, struct node *nd, int indent) > { > struct luaL_field *field = &nd->field; > - char buf[FPCONV_G_FMT_BUFSIZE]; > + char buf[FPCONV_G_FMT_BUFSIZE + 8]; Why +8? Better use max(FPCONV_G_FMT_BUFSIZE, <your buf size>). > int ltype = lua_type(d->L, -1); > const char *str = NULL; > size_t len = 0; > @@ -861,6 +861,11 @@ dump_node(struct lua_dumper *d, struct node *nd, int indent) > str = tt_uuid_str(field->uuidval); > len = UUID_STR_LEN; > break; > + case MP_DATETIME: > + nd->mask |= NODE_QUOTE; > + str = buf; > + len = datetime_to_string(field->dateval, buf, sizeof buf); sizeof(buf) Please fix here and in other places. > + break; > default: > d->err = EINVAL; > snprintf(d->err_msg, sizeof(d->err_msg), > diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc > index 43cd29ce9..9a69f2a72 100644 > --- a/src/box/tuple_compare.cc > +++ b/src/box/tuple_compare.cc > @@ -36,6 +36,7 @@ > #include "lib/core/decimal.h" > #include "lib/core/mp_decimal.h" > #include "uuid/mp_uuid.h" > +#include "lib/core/mp_datetime.h" > #include "lib/core/mp_extension_types.h" > > /* {{{ tuple_compare */ > @@ -76,6 +77,7 @@ enum mp_class { > MP_CLASS_STR, > MP_CLASS_BIN, > MP_CLASS_UUID, > + MP_CLASS_DATETIME, > MP_CLASS_ARRAY, > MP_CLASS_MAP, > mp_class_max, > @@ -99,6 +101,8 @@ static enum mp_class mp_ext_classes[] = { > /* .MP_UNKNOWN_EXTENSION = */ mp_class_max, /* unsupported */ > /* .MP_DECIMAL = */ MP_CLASS_NUMBER, > /* .MP_UUID = */ MP_CLASS_UUID, > + /* .MP_ERROR = */ mp_class_max, > + /* .MP_DATETIME = */ MP_CLASS_DATETIME, > }; > > static enum mp_class > @@ -390,6 +394,19 @@ mp_compare_uuid(const char *field_a, const char *field_b) > return memcmp(field_a + 2, field_b + 2, UUID_PACKED_LEN); > } > > +static int > +mp_compare_datetime(const char *lhs, const char *rhs) > +{ > + struct datetime lhs_dt, rhs_dt; > + struct datetime *ret; > + ret = mp_decode_datetime(&lhs, &lhs_dt); > + assert(ret != NULL); > + ret = mp_decode_datetime(&rhs, &rhs_dt); > + assert(ret != NULL); > + (void)ret; > + return datetime_compare(&lhs_dt, &rhs_dt); > +} > + Comparators is a part of indexing hence belong to the next patch. > typedef int (*mp_compare_f)(const char *, const char *); > static mp_compare_f mp_class_comparators[] = { > /* .MP_CLASS_NIL = */ NULL, > @@ -398,6 +415,7 @@ static mp_compare_f mp_class_comparators[] = { > /* .MP_CLASS_STR = */ mp_compare_str, > /* .MP_CLASS_BIN = */ mp_compare_bin, > /* .MP_CLASS_UUID = */ mp_compare_uuid, > + /* .MP_CLASS_DATETIME=*/ mp_compare_datetime, > /* .MP_CLASS_ARRAY = */ NULL, > /* .MP_CLASS_MAP = */ NULL, > }; > @@ -478,6 +496,8 @@ tuple_compare_field(const char *field_a, const char *field_b, > return mp_compare_decimal(field_a, field_b); > case FIELD_TYPE_UUID: > return mp_compare_uuid(field_a, field_b); > + case FIELD_TYPE_DATETIME: > + return mp_compare_datetime(field_a, field_b); > default: > unreachable(); > return 0; > diff --git a/src/lib/core/datetime.c b/src/lib/core/datetime.c > index c24a0df82..baf9cc8ae 100644 > --- a/src/lib/core/datetime.c > +++ b/src/lib/core/datetime.c > @@ -165,3 +165,12 @@ datetime_to_string(const struct datetime *date, char *buf, uint32_t len) > } > #undef ADVANCE > > +int > +datetime_compare(const struct datetime *lhs, const struct datetime *rhs) > +{ > + int result = COMPARE_RESULT(lhs->secs, rhs->secs); > + if (result != 0) > + return result; > + > + return COMPARE_RESULT(lhs->nsec, rhs->nsec); What about offset? Shouldn't you take it into account (convert all dates to UTC)? > +} > diff --git a/src/lib/core/datetime.h b/src/lib/core/datetime.h > index 964e76fcc..5122e422e 100644 > --- a/src/lib/core/datetime.h > +++ b/src/lib/core/datetime.h > @@ -70,6 +70,17 @@ struct datetime_interval { > int32_t nsec; > }; > > +/** > + * Compare arguments of a datetime type > + * @param lhs left datetime argument > + * @param rhs right datetime argument > + * @retval < 0 if lhs less than rhs > + * @retval = 0 if lhs and rhs equal > + * @retval > 0 if lhs greater than rhs > + */ > +int > +datetime_compare(const struct datetime *lhs, const struct datetime *rhs); > + > /** > * Convert datetime to string using default format > * @param date source datetime value > diff --git a/src/lib/core/mp_datetime.c b/src/lib/core/mp_datetime.c > new file mode 100644 > index 000000000..d0a3e562c > --- /dev/null > +++ b/src/lib/core/mp_datetime.c > @@ -0,0 +1,189 @@ > +/* > + * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file. > + * > + * Redistribution and use in source and binary forms, with or > + * without modification, are permitted provided that the following > + * conditions are met: > + * > + * 1. Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * > + * 2. Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the following > + * disclaimer in the documentation and/or other materials > + * provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL > + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, > + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR > + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#include "mp_datetime.h" > +#include "msgpuck.h" > +#include "mp_extension_types.h" > + > +/* > + Datetime MessagePack serialization schema is MP_EXT (0xC7 for 1 byte length) > + extension, which creates container of 1 to 3 integers. > + > + +----+---+-----------+====~~~~~~~====+-----~~~~~~~~-------+....~~~~~~~....+ > + |0xC7| 4 |len (uint8)| seconds (int) | nanoseconds (uint) | offset (uint) | > + +----+---+-----------+====~~~~~~~====+-----~~~~~~~~-------+....~~~~~~~....+ > + > + MessagePack extension MP_EXT (0xC7), after 1-byte length, contains: > + > + - signed integer seconds part (required). Depending on the value of > + seconds it may be from 1 to 8 bytes positive or negative integer number; > + > + - [optional] fraction time in nanoseconds as unsigned integer. > + If this value is 0 then it's not saved (unless there is offset field, > + as below); > + > + - [optional] timzeone offset in minutes as unsigned integer. > + If this field is 0 then it's not saved. > + */ > + > +static inline uint32_t > +mp_sizeof_Xint(int64_t n) mp_sizeof_xint - Let's not mix camel-case and underscores. I think this should be put somewhere in a public header so that everyone can use them: mp_utils.h? > +{ > + return n < 0 ? mp_sizeof_int(n) : mp_sizeof_uint(n); > +} > + > +static inline char * > +mp_encode_Xint(char *data, int64_t v) > +{ > + return v < 0 ? mp_encode_int(data, v) : mp_encode_uint(data, v); > +} > + > +static inline int64_t > +mp_decode_Xint(const char **data) > +{ > + switch (mp_typeof(**data)) { > + case MP_UINT: > + return (int64_t)mp_decode_uint(data); assert(value <= INT64_MAX) ? > + case MP_INT: > + return mp_decode_int(data); > + default: > + mp_unreachable(); > + } > + return 0; > +} > + > +static inline uint32_t > +mp_sizeof_datetime_raw(const struct datetime *date) > +{ > + uint32_t sz = mp_sizeof_Xint(date->secs); > + > + // even if nanosecs == 0 we need to output anything > + // if we have non-null tz offset > + if (date->nsec != 0 || date->offset != 0) > + sz += mp_sizeof_Xint(date->nsec); > + if (date->offset) if (date->offset != 0) Please be consistent.
next prev parent reply other threads:[~2021-08-17 18:36 UTC|newest] Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-08-15 23:59 [Tarantool-patches] [PATCH v5 0/8] Initial datetime implementation Timur Safin via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 1/8] build: add Christian Hansen c-dt to the build Timur Safin via Tarantool-patches 2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:24 ` Safin Timur via Tarantool-patches 2021-08-18 8:56 ` Serge Petrenko via Tarantool-patches 2021-08-17 15:50 ` Vladimir Davydov via Tarantool-patches 2021-08-18 10:04 ` Safin Timur via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 2/8] lua: built-in module datetime Timur Safin via Tarantool-patches 2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:30 ` Safin Timur via Tarantool-patches 2021-08-18 8:56 ` Serge Petrenko via Tarantool-patches 2021-08-17 16:52 ` Vladimir Davydov via Tarantool-patches 2021-08-17 19:16 ` Vladimir Davydov via Tarantool-patches 2021-08-18 13:38 ` Safin Timur via Tarantool-patches 2021-08-18 10:03 ` Safin Timur via Tarantool-patches 2021-08-18 10:06 ` Safin Timur via Tarantool-patches 2021-08-18 11:45 ` Vladimir Davydov via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 3/8] lua, datetime: display datetime Timur Safin via Tarantool-patches 2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:32 ` Safin Timur via Tarantool-patches 2021-08-17 17:06 ` Vladimir Davydov via Tarantool-patches 2021-08-18 14:10 ` Safin Timur via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 4/8] box, datetime: messagepack support for datetime Timur Safin via Tarantool-patches 2021-08-16 0:20 ` Safin Timur via Tarantool-patches 2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches 2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:42 ` Safin Timur via Tarantool-patches 2021-08-18 9:01 ` Serge Petrenko via Tarantool-patches 2021-08-17 18:36 ` Vladimir Davydov via Tarantool-patches [this message] 2021-08-18 14:27 ` Safin Timur via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 5/8] box, datetime: datetime comparison for indices Timur Safin via Tarantool-patches 2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:43 ` Safin Timur via Tarantool-patches 2021-08-18 9:03 ` Serge Petrenko via Tarantool-patches 2021-08-17 19:05 ` Vladimir Davydov via Tarantool-patches 2021-08-18 17:18 ` Safin Timur via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 6/8] lua, datetime: time intervals support Timur Safin via Tarantool-patches 2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:44 ` Safin Timur via Tarantool-patches 2021-08-17 18:52 ` Vladimir Davydov via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 7/8] datetime: perf test for datetime parser Timur Safin via Tarantool-patches 2021-08-17 19:13 ` Vladimir Davydov via Tarantool-patches 2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 8/8] datetime: changelog for datetime module Timur Safin via Tarantool-patches 2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches 2021-08-17 23:44 ` Safin Timur via Tarantool-patches 2021-08-18 9:04 ` Serge Petrenko via Tarantool-patches 2021-08-17 12:15 ` [Tarantool-patches] [PATCH v5 0/8] Initial datetime implementation Serge Petrenko via Tarantool-patches [not found] ` <20210818082222.mofgheciutpipelz@esperanza> 2021-08-18 8:25 ` Vladimir Davydov via Tarantool-patches 2021-08-18 13:24 ` Safin Timur via Tarantool-patches 2021-08-18 14:22 ` Vladimir Davydov via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210817183607.akhqcqos2dmbkbol@esperanza \ --to=tarantool-patches@dev.tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --cc=vdavydov@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v5 4/8] box, datetime: messagepack support for datetime' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox