Skip to content

Commit f963bfb

Browse files
authored
negative add unit has been fixed (#4772)
1 parent 0a651a8 commit f963bfb

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

ydb/library/yql/providers/s3/path_generator/ut/yql_generate_partitioning_rules_ut.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,38 @@ Y_UNIT_TEST_SUITE(TGenerateTests) {
318318
}
319319
)", {"year"}), yexception, "Location path 1971/ is composed by different projection value sets { ${year} = 1971-01-01 } and { ${year} = 1971-01-02 }");;
320320
}
321+
322+
Y_UNIT_TEST(SuccessGenerateDateWithNegativeNow) {
323+
auto generator = CreatePathGenerator(R"(
324+
{
325+
"projection.enabled" : true,
326+
"projection.city.type" : "enum",
327+
"projection.city.values" : "MSK,SPB",
328+
"projection.code.type" : "date",
329+
"projection.code.min" : "NOW - 3 DAYS",
330+
"projection.code.max" : "NOW",
331+
"projection.code.format" : "%F",
332+
"projection.code.interval" : 1,
333+
"projection.code.unit" : "DAYS",
334+
"storage.location.template" : "/${city}/${code}/"
335+
}
336+
)", {"city", "code"});
337+
auto nowBefore = TInstant::Now();
338+
auto rules = generator->GetRules();
339+
auto nowAfter = TInstant::Now();
340+
341+
TSet<TString> items;
342+
for (auto from = std::min(nowBefore, nowAfter) - TDuration::Days(3); from <= std::max(nowBefore, nowAfter); from += TDuration::Days(1)) {
343+
items.insert("MSK/" + from.FormatLocalTime("%F") + "/");
344+
items.insert("SPB/" + from.FormatLocalTime("%F") + "/");
345+
}
346+
347+
UNIT_ASSERT_VALUES_EQUAL(rules.size(), 8);
348+
for (const auto& rule: rules) {
349+
UNIT_ASSERT(items.contains(rule.Path));
350+
UNIT_ASSERT_VALUES_EQUAL(rule.ColumnValues.size(), 2);
351+
}
352+
}
321353
}
322354

323355
}

ydb/library/yql/providers/s3/path_generator/yql_s3_path_generator.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,20 @@ bool IsOverflow(ui64 a, ui64 b) {
157157
return b > diff;
158158
}
159159

160+
ui64 AbsToUi64(i64 value) {
161+
if (value >= 0) {
162+
return value;
163+
}
164+
if (value == std::numeric_limits<i64>::min()) {
165+
return (ui64)std::numeric_limits<i64>::max() + 1;
166+
}
167+
return -value;
168+
}
169+
170+
bool IsOverflow(ui64 a, i64 b) {
171+
return b > 0 ? IsOverflow(a, (ui64)b) : a < AbsToUi64(b);
172+
}
173+
160174
TDuration FromUnit(int64_t interval, IPathGenerator::EIntervalUnit unit) {
161175
switch (unit) {
162176
case IPathGenerator::EIntervalUnit::MILLISECONDS:
@@ -203,13 +217,17 @@ TInstant AddUnit(TInstant current, int64_t interval, IPathGenerator::EIntervalUn
203217
return DoAddYears(current, interval);
204218
}
205219

220+
const TDuration delta = FromUnit(abs(interval), unit);
221+
if (delta.GetValue() > std::numeric_limits<i64>::max()) {
222+
ythrow yexception() << "Interval is overflowed";
223+
}
206224

207-
const TDuration delta = FromUnit(interval, unit);
208-
if (IsOverflow(current.GetValue(), delta.GetValue())) {
225+
const i64 deltaValue = (interval > 0 ? 1LL : -1LL) * delta.GetValue();
226+
if (IsOverflow(current.GetValue(), deltaValue)) {
209227
ythrow yexception() << "Timestamp is overflowed";
210228
}
211229

212-
return current + delta;
230+
return interval > 0 ? current + delta : current - delta;
213231
}
214232

215233
TInstant ParseDate(const TString& dateStr, const TInstant& now) {

0 commit comments

Comments
 (0)