Make transform always return the first match

This commit is contained in:
Raúl Marín 2024-04-10 23:39:47 +02:00
parent 1f289c5d25
commit 8e26c4460b
5 changed files with 28 additions and 5 deletions

View File

@ -675,7 +675,7 @@ There are two variations of this function:
Signature:
For `x` equal to one of the elements in `array_from`, the function returns the corresponding element in `array_to`, i.e. the one at the same array index. Otherwise, it returns `default`. If multiple matching elements exist `array_from`, an arbitrary corresponding element from `array_to` is returned.
For `x` equal to one of the elements in `array_from`, the function returns the corresponding element in `array_to`, i.e. the one at the same array index. Otherwise, it returns `default`. If multiple matching elements exist `array_from`, it returns the element corresponding to the first of them.
`transform(T, Array(T), Array(U), U) -> U`

View File

@ -296,6 +296,19 @@ public:
return it->getMapped();
}
/// Only inserts the value if key isn't already present
void ALWAYS_INLINE insertIfNotPresent(const Key & x, const Cell::Mapped & value)
{
LookupResult it;
bool inserted;
this->emplace(x, it, inserted);
if (inserted)
{
new (&it->getMapped()) typename Cell::Mapped();
it->getMapped() = value;
}
}
const typename Cell::Mapped & ALWAYS_INLINE at(const Key & x) const
{
if (auto it = this->find(x); it != this->end())

View File

@ -755,7 +755,6 @@ namespace
WhichDataType which(from_type);
/// Note: Doesn't check the duplicates in the `from` array.
/// Field may be of Float type, but for the purpose of bitwise equality we can treat them as UInt64
if (isNativeNumber(which) || which.isDecimal32() || which.isDecimal64() || which.isEnum())
{
@ -777,7 +776,7 @@ namespace
#pragma clang diagnostic pop
memcpy(dst, ref.data, ref.size);
table[key] = i;
table.insertIfNotPresent(key, i);
}
}
}
@ -790,7 +789,7 @@ namespace
if (applyVisitor(FieldVisitorAccurateEquals(), (*cache.from_column)[i], (*from_column_uncasted)[i]))
{
StringRef ref = cache.from_column->getDataAt(i);
table[ref] = i;
table.insertIfNotPresent(ref, i);
}
}
}
@ -804,7 +803,7 @@ namespace
{
SipHash hash;
cache.from_column->updateHashWithValue(i, hash);
table[hash.get128()] = i;
table.insertIfNotPresent(hash.get128(), i);
}
}
}

View File

@ -0,0 +1,4 @@
1
1
(2,2)
2

View File

@ -0,0 +1,7 @@
SELECT transform(1, [1, 1, 1], [1, 4, 5]);
SELECT transform('1', ['1', '1', '1'], ['1', '4', '5']);
SELECT transform((0, 0), [(0, 0), (0, 0), (0, 0)], [(2, 2), (5, 5), (10, 10)]);
-- https://github.com/ClickHouse/ClickHouse/issues/62183
-- Case is turned into caseWithExpression, which then it's turned into transform
select case 1 when 1 then 2 when 1 then 4 end;