Skip to content

Commit 46027f6

Browse files
committed
box, datetime: datetime comparison for indices
* storage hints implemented for datetime_t values; * proper comparison for indices of datetime type. Part of tarantool#5941 Part of tarantool#5946
1 parent e1961ba commit 46027f6

File tree

7 files changed

+165
-4
lines changed

7 files changed

+165
-4
lines changed

src/box/field_def.c

+18
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,21 @@ field_type_by_name(const char *name, size_t len)
193193
return FIELD_TYPE_ANY;
194194
return field_type_MAX;
195195
}
196+
197+
const bool field_type_index_allowed[] =
198+
{
199+
/* [FIELD_TYPE_ANY] = */ false,
200+
/* [FIELD_TYPE_UNSIGNED] = */ true,
201+
/* [FIELD_TYPE_STRING] = */ true,
202+
/* [FIELD_TYPE_NUMBER] = */ true,
203+
/* [FIELD_TYPE_DOUBLE] = */ true,
204+
/* [FIELD_TYPE_INTEGER] = */ true,
205+
/* [FIELD_TYPE_BOOLEAN] = */ true,
206+
/* [FIELD_TYPE_VARBINARY]= */ true,
207+
/* [FIELD_TYPE_SCALAR] = */ true,
208+
/* [FIELD_TYPE_DECIMAL] = */ true,
209+
/* [FIELD_TYPE_UUID] = */ true,
210+
/* [FIELD_TYPE_ARRAY] = */ false,
211+
/* [FIELD_TYPE_MAP] = */ false,
212+
/* [FIELD_TYPE_DATETIME] = */ true,
213+
};

src/box/field_def.h

+3
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ extern const uint32_t field_ext_type[];
120120
extern const struct opt_def field_def_reg[];
121121
extern const struct field_def field_def_default;
122122

123+
/** helper table for checking allowed indices for types */
124+
extern const bool field_type_index_allowed[];
125+
123126
/**
124127
* @brief Field definition
125128
* Contains information about of one tuple field.

src/box/memtx_space.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -748,8 +748,7 @@ memtx_space_check_index_def(struct space *space, struct index_def *index_def)
748748
/* Check that there are no ANY, ARRAY, MAP parts */
749749
for (uint32_t i = 0; i < key_def->part_count; i++) {
750750
struct key_part *part = &key_def->parts[i];
751-
if (part->type <= FIELD_TYPE_ANY ||
752-
part->type >= FIELD_TYPE_ARRAY) {
751+
if (!field_type_index_allowed[part->type]) {
753752
diag_set(ClientError, ER_MODIFY_INDEX,
754753
index_def->name, space_name(space),
755754
tt_sprintf("field type '%s' is not supported",

src/box/tuple_compare.cc

+30
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,8 @@ tuple_compare_field_with_type(const char *field_a, enum mp_type a_type,
538538
field_b, b_type);
539539
case FIELD_TYPE_UUID:
540540
return mp_compare_uuid(field_a, field_b);
541+
case FIELD_TYPE_DATETIME:
542+
return mp_compare_datetime(field_a, field_b);
541543
default:
542544
unreachable();
543545
return 0;
@@ -1630,6 +1632,18 @@ hint_uuid_raw(const char *data)
16301632
return hint_create(MP_CLASS_UUID, val);
16311633
}
16321634

1635+
static inline hint_t
1636+
hint_datetime(struct datetime_t *date)
1637+
{
1638+
/*
1639+
* Use at most HINT_VALUE_BITS from datetime
1640+
* seconds field as a hint value
1641+
*/
1642+
uint64_t val = (uint64_t)date->secs & HINT_VALUE_MAX;
1643+
1644+
return hint_create(MP_CLASS_DATETIME, val);
1645+
}
1646+
16331647
static inline uint64_t
16341648
hint_str_raw(const char *s, uint32_t len)
16351649
{
@@ -1761,6 +1775,17 @@ field_hint_uuid(const char *field)
17611775
return hint_uuid_raw(data);
17621776
}
17631777

1778+
static inline hint_t
1779+
field_hint_datetime(const char *field)
1780+
{
1781+
assert(mp_typeof(*field) == MP_EXT);
1782+
int8_t ext_type;
1783+
uint32_t len = mp_decode_extl(&field, &ext_type);
1784+
assert(ext_type == MP_DATETIME);
1785+
struct datetime_t date;
1786+
return hint_datetime(datetime_unpack(&field, len, &date));
1787+
}
1788+
17641789
static inline hint_t
17651790
field_hint_string(const char *field, struct coll *coll)
17661791
{
@@ -1849,6 +1874,8 @@ field_hint(const char *field, struct coll *coll)
18491874
return field_hint_decimal(field);
18501875
case FIELD_TYPE_UUID:
18511876
return field_hint_uuid(field);
1877+
case FIELD_TYPE_DATETIME:
1878+
return field_hint_datetime(field);
18521879
default:
18531880
unreachable();
18541881
}
@@ -1963,6 +1990,9 @@ key_def_set_hint_func(struct key_def *def)
19631990
case FIELD_TYPE_UUID:
19641991
key_def_set_hint_func<FIELD_TYPE_UUID>(def);
19651992
break;
1993+
case FIELD_TYPE_DATETIME:
1994+
key_def_set_hint_func<FIELD_TYPE_DATETIME>(def);
1995+
break;
19661996
default:
19671997
/* Invalid key definition. */
19681998
def->key_hint = NULL;

src/box/vinyl.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,7 @@ vinyl_space_check_index_def(struct space *space, struct index_def *index_def)
662662
/* Check that there are no ANY, ARRAY, MAP parts */
663663
for (uint32_t i = 0; i < key_def->part_count; i++) {
664664
struct key_part *part = &key_def->parts[i];
665-
if (part->type <= FIELD_TYPE_ANY ||
666-
part->type >= FIELD_TYPE_ARRAY) {
665+
if (!field_type_index_allowed[part->type]) {
667666
diag_set(ClientError, ER_MODIFY_INDEX,
668667
index_def->name, space_name(space),
669668
tt_sprintf("field type '%s' is not supported",

test/engine/datetime.result

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
-- test-run result file version 2
2+
env = require('test_run')
3+
| ---
4+
| ...
5+
test_run = env.new()
6+
| ---
7+
| ...
8+
engine = test_run:get_cfg('engine')
9+
| ---
10+
| ...
11+
12+
date = require('datetime')
13+
| ---
14+
| ...
15+
16+
_ = box.schema.space.create('T', {engine = engine})
17+
| ---
18+
| ...
19+
_ = box.space.T:create_index('pk', {parts={1,'datetime'}})
20+
| ---
21+
| ...
22+
23+
box.space.T:insert{date('1970-01-01')}\
24+
box.space.T:insert{date('1970-01-02')}\
25+
box.space.T:insert{date('1970-01-03')}\
26+
box.space.T:insert{date('2000-01-01')}
27+
| ---
28+
| ...
29+
30+
o = box.space.T:select{}
31+
| ---
32+
| ...
33+
assert(tostring(o[1][1]) == '1970-01-01T00:00Z')
34+
| ---
35+
| - true
36+
| ...
37+
assert(tostring(o[2][1]) == '1970-01-02T00:00Z')
38+
| ---
39+
| - true
40+
| ...
41+
assert(tostring(o[3][1]) == '1970-01-03T00:00Z')
42+
| ---
43+
| - true
44+
| ...
45+
assert(tostring(o[4][1]) == '2000-01-01T00:00Z')
46+
| ---
47+
| - true
48+
| ...
49+
50+
for i = 1,16 do\
51+
box.space.T:insert{date.now()}\
52+
end
53+
| ---
54+
| ...
55+
56+
a = box.space.T:select{}
57+
| ---
58+
| ...
59+
err = nil
60+
| ---
61+
| ...
62+
for i = 1, #a - 1 do\
63+
if tostring(a[i][1]) >= tostring(a[i+1][1]) then\
64+
err = {a[i][1], a[i+1][1]}\
65+
break\
66+
end\
67+
end
68+
| ---
69+
| ...
70+
71+
err
72+
| ---
73+
| - null
74+
| ...
75+
box.space.T:drop()
76+
| ---
77+
| ...

test/engine/datetime.test.lua

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
env = require('test_run')
2+
test_run = env.new()
3+
engine = test_run:get_cfg('engine')
4+
5+
date = require('datetime')
6+
7+
_ = box.schema.space.create('T', {engine = engine})
8+
_ = box.space.T:create_index('pk', {parts={1,'datetime'}})
9+
10+
box.space.T:insert{date('1970-01-01')}\
11+
box.space.T:insert{date('1970-01-02')}\
12+
box.space.T:insert{date('1970-01-03')}\
13+
box.space.T:insert{date('2000-01-01')}
14+
15+
o = box.space.T:select{}
16+
assert(tostring(o[1][1]) == '1970-01-01T00:00Z')
17+
assert(tostring(o[2][1]) == '1970-01-02T00:00Z')
18+
assert(tostring(o[3][1]) == '1970-01-03T00:00Z')
19+
assert(tostring(o[4][1]) == '2000-01-01T00:00Z')
20+
21+
for i = 1,16 do\
22+
box.space.T:insert{date.now()}\
23+
end
24+
25+
a = box.space.T:select{}
26+
err = nil
27+
for i = 1, #a - 1 do\
28+
if tostring(a[i][1]) >= tostring(a[i+1][1]) then\
29+
err = {a[i][1], a[i+1][1]}\
30+
break\
31+
end\
32+
end
33+
34+
err
35+
box.space.T:drop()

0 commit comments

Comments
 (0)