Merge pull request #15082 from ClickHouse/try-improve-array-has-built-time

Update SourceVisitor for GatherUtils.
This commit is contained in:
Nikolai Kochetov 2020-09-21 17:08:14 +03:00 committed by GitHub
commit 334289fd57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 364 additions and 114 deletions

View File

@ -19,12 +19,12 @@ struct ConstSource;
using NumericArraySources = typename TypeListMap<NumericArraySource, TypeListNumbersAndUInt128>::Type;
using BasicArraySources = typename AppendToTypeList<GenericArraySource, NumericArraySources>::Type;
using NullableArraySources = typename TypeListMap<NullableArraySource, BasicArraySources>::Type;
using BasicAndNullableArraySources = typename TypeListConcat<BasicArraySources, NullableArraySources>::Type;
using ConstArraySources = typename TypeListMap<ConstSource, BasicAndNullableArraySources>::Type;
using TypeListArraySources = typename TypeListConcat<BasicAndNullableArraySources, ConstArraySources>::Type;
//using NullableArraySources = typename TypeListMap<NullableArraySource, BasicArraySources>::Type;
//using BasicAndNullableArraySources = typename TypeListConcat<BasicArraySources, NullableArraySources>::Type;
//using ConstArraySources = typename TypeListMap<ConstSource, BasicAndNullableArraySources>::Type;
//using TypeListArraySources = typename TypeListConcat<BasicAndNullableArraySources, ConstArraySources>::Type;
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, TypeListArraySources>::Type
class ArraySourceVisitor : public ApplyTypeListForClass<Visitor, BasicArraySources>::Type
{
protected:
~ArraySourceVisitor() = default;

View File

@ -32,20 +32,30 @@ void callSelectMemberFunctionWithTupleArgument(Tuple & tuple, Args && ... args)
callSelectMemberFunctionWithTupleArgument<Base, Tuple, index + 1>(tuple, args ..., std::get<index>(tuple));
}
template <typename Base, typename Tuple, int index, typename ... Args>
void callSelectSource(bool is_const, bool is_nullable, Tuple & tuple, Args && ... args)
{
if constexpr (index == std::tuple_size<Tuple>::value)
Base::selectSource(is_const, is_nullable, args ...);
else
callSelectSource<Base, Tuple, index + 1>(is_const, is_nullable, tuple, args ..., std::get<index>(tuple));
}
template <typename Base, typename ... Args>
struct ArraySourceSelectorVisitor final : public ArraySourceVisitorImpl<ArraySourceSelectorVisitor<Base, Args ...>>
{
explicit ArraySourceSelectorVisitor(Args && ... args) : packed_args(args ...) {}
explicit ArraySourceSelectorVisitor(IArraySource & source, Args && ... args) : packed_args(args ...), array_source(source) {}
using Tuple = std::tuple<Args && ...>;
template <typename Source>
void visitImpl(Source & source)
{
callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source);
callSelectSource<Base, Tuple, 0>(array_source.isConst(), array_source.isNullable(), packed_args, source);
}
Tuple packed_args;
IArraySource & array_source;
};
template <typename Base>
@ -54,7 +64,7 @@ struct ArraySourceSelector
template <typename ... Args>
static void select(IArraySource & source, Args && ... args)
{
ArraySourceSelectorVisitor<Base, Args ...> visitor(args ...);
ArraySourceSelectorVisitor<Base, Args ...> visitor(source, args ...);
source.accept(visitor);
}
};
@ -87,56 +97,6 @@ struct ArraySinkSelector
}
};
template <typename Base, typename ... Args>
struct ValueSourceSelectorVisitor final : public ValueSourceVisitorImpl<ValueSourceSelectorVisitor<Base, Args ...>>
{
explicit ValueSourceSelectorVisitor(Args && ... args) : packed_args(args ...) {}
using Tuple = std::tuple<Args && ...>;
template <typename Source>
void visitImpl(Source & source)
{
callSelectMemberFunctionWithTupleArgument<Base, Tuple, 0>(packed_args, source);
}
Tuple packed_args;
};
template <typename Base>
struct ValueSourceSelector
{
template <typename ... Args>
static void select(IValueSource & source, Args && ... args)
{
ValueSourceSelectorVisitor<Base, Args ...> visitor(args ...);
source.accept(visitor);
}
};
template <typename Base>
struct ArraySinkSourceSelector
{
template <typename ... Args>
static void select(IArraySource & source, IArraySink & sink, Args && ... args)
{
ArraySinkSelector<Base>::select(sink, source, args ...);
}
template <typename Sink, typename ... Args>
static void selectImpl(Sink && sink, IArraySource & source, Args && ... args)
{
ArraySourceSelector<Base>::select(source, sink, args ...);
}
template <typename Source, typename Sink, typename ... Args>
static void selectImpl(Source && source, Sink && sink, Args && ... args)
{
Base::selectSourceSink(source, sink, args ...);
}
};
template <typename Base>
struct ArraySourcePairSelector
{
@ -147,15 +107,17 @@ struct ArraySourcePairSelector
}
template <typename FirstSource, typename ... Args>
static void selectImpl(FirstSource && first, IArraySource & second, Args && ... args)
static void selectSource(bool is_const, bool is_nullable, FirstSource && first, IArraySource & second, Args && ... args)
{
ArraySourceSelector<Base>::select(second, first, args ...);
ArraySourceSelector<Base>::select(second, is_const, is_nullable, first, args ...);
}
template <typename SecondSource, typename FirstSource, typename ... Args>
static void selectImpl(SecondSource && second, FirstSource && first, Args && ... args)
static void selectSource(bool is_second_const, bool is_second_nullable, SecondSource && second,
bool is_first_const, bool is_first_nullable, FirstSource && first, Args && ... args)
{
Base::selectSourcePair(first, second, args ...);
Base::selectSourcePair(is_first_const, is_first_nullable, first,
is_second_const, is_second_nullable, second, args ...);
}
};

View File

@ -23,37 +23,54 @@ struct ArrayConcat : public ArraySourceSelector<ArrayConcat>
{
using Sources = std::vector<std::unique_ptr<IArraySource>>;
// template <typename Source>
// static void selectSource(Source && source, const Sources & sources, ColumnArray::MutablePtr & result)
// {
// using SourceType = typename std::decay<Source>::type;
// using Sink = typename SourceType::SinkType;
// result = ColumnArray::create(source.createValuesColumn());
// Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
//
// concat<SourceType, Sink>(sources, std::move(sink));
// }
//
// template <typename Source>
// static void selectImpl(ConstSource<Source> && source, const Sources & sources, ColumnArray::MutablePtr & result)
// {
// using SourceType = typename std::decay<Source>::type;
// using Sink = typename SourceType::SinkType;
// result = ColumnArray::create(source.createValuesColumn());
// Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
//
// concat<SourceType, Sink>(sources, std::move(sink));
// }
template <typename Source>
static void selectImpl(Source && source, const Sources & sources, ColumnArray::MutablePtr & result)
static void selectSource(bool /*is_const*/, bool is_nullable, Source & source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
}
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
template <typename Source>
static void selectImpl(ConstSource<Source> && source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
auto & nullable_source = static_cast<NullableSource &>(source);
concat<SourceType, Sink>(sources, std::move(sink));
}
template <typename Source>
static void selectImpl(ConstSource<Source> & source, const Sources & sources, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
concat<NullableSource, NullableSink>(sources, std::move(sink));
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
concat<SourceType, Sink>(sources, std::move(sink));
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasAllSelectArraySourcePair : public ArraySourcePairSelector<ArrayHasAllSelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::All>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::All>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::All>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::All>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::All>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasAnySelectArraySourcePair : public ArraySourcePairSelector<ArrayHasAnySelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::Any>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::Any>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::Any>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::Any>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::Any>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -11,9 +11,53 @@ namespace
struct ArrayHasSubstrSelectArraySourcePair : public ArraySourcePairSelector<ArrayHasSubstrSelectArraySourcePair>
{
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(FirstSource && first, SecondSource && second, ColumnUInt8 & result)
static void callFunction(FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
arrayAllAny<ArraySearchType::Substr>(first, second, result);
using SourceType = typename std::decay<SecondSource>::type;
if (is_second_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_second_const)
arrayAllAny<ArraySearchType::Substr>(first, static_cast<ConstSource<NullableSource> &>(second), result);
else
arrayAllAny<ArraySearchType::Substr>(first, static_cast<NullableSource &>(second), result);
}
else
{
if (is_second_const)
arrayAllAny<ArraySearchType::Substr>(first, static_cast<ConstSource<SourceType> &>(second), result);
else
arrayAllAny<ArraySearchType::Substr>(first, second, result);
}
}
template <typename FirstSource, typename SecondSource>
static void selectSourcePair(bool is_first_const, bool is_first_nullable, FirstSource && first,
bool is_second_const, bool is_second_nullable, SecondSource && second,
ColumnUInt8 & result)
{
using SourceType = typename std::decay<FirstSource>::type;
if (is_first_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
if (is_first_const)
callFunction(static_cast<ConstSource<NullableSource> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(static_cast<NullableSource &>(first), is_second_const, is_second_nullable, second, result);
}
else
{
if (is_first_const)
callFunction(static_cast<ConstSource<SourceType> &>(first), is_second_const, is_second_nullable, second, result);
else
callFunction(first, is_second_const, is_second_nullable, second, result);
}
}
};

View File

@ -13,13 +13,37 @@ namespace
struct SliceDynamicOffsetBoundedSelectArraySource : public ArraySourceSelector<SliceDynamicOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, const IColumn & offset_column, const IColumn & length_column, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source,
const IColumn & offset_column, const IColumn & length_column, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceDynamicOffsetBounded(source, sink, offset_column, length_column);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset_column, length_column);
else
sliceDynamicOffsetBounded(static_cast<NullableSource &>(source), sink, offset_column, length_column);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset_column, length_column);
else
sliceDynamicOffsetBounded(source, sink, offset_column, length_column);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceDynamicOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceDynamicOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, const IColumn & offset_column, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, const IColumn & offset_column, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceDynamicOffsetUnbounded(source, sink, offset_column);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset_column);
else
sliceDynamicOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset_column);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceDynamicOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset_column);
else
sliceDynamicOffsetUnbounded(source, sink, offset_column);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromLeftConstantOffsetBoundedSelectArraySource
: public ArraySourceSelector<SliceFromLeftConstantOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromLeftConstantOffsetBounded(source, sink, offset, length);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset, length);
else
sliceFromLeftConstantOffsetBounded(static_cast<NullableSource &>(source), sink, offset, length);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset, length);
else
sliceFromLeftConstantOffsetBounded(source, sink, offset, length);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromLeftConstantOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceFromLeftConstantOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromLeftConstantOffsetUnbounded(source, sink, offset);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset);
else
sliceFromLeftConstantOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromLeftConstantOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset);
else
sliceFromLeftConstantOffsetUnbounded(source, sink, offset);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromRightConstantOffsetBoundedSelectArraySource
: public ArraySourceSelector<SliceFromRightConstantOffsetBoundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ssize_t & length, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromRightConstantOffsetBounded(source, sink, offset, length);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetBounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset, length);
else
sliceFromRightConstantOffsetBounded(static_cast<NullableSource &>(source), sink, offset, length);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetBounded(static_cast<ConstSource<SourceType> &>(source), sink, offset, length);
else
sliceFromRightConstantOffsetBounded(source, sink, offset, length);
}
}
};

View File

@ -14,13 +14,36 @@ struct SliceFromRightConstantOffsetUnboundedSelectArraySource
: public ArraySourceSelector<SliceFromRightConstantOffsetUnboundedSelectArraySource>
{
template <typename Source>
static void selectImpl(Source && source, size_t & offset, ColumnArray::MutablePtr & result)
static void selectSource(bool is_const, bool is_nullable, Source && source, size_t & offset, ColumnArray::MutablePtr & result)
{
using SourceType = typename std::decay<Source>::type;
using Sink = typename SourceType::SinkType;
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
sliceFromRightConstantOffsetUnbounded(source, sink, offset);
if (is_nullable)
{
using NullableSource = NullableArraySource<SourceType>;
using NullableSink = typename NullableSource::SinkType;
auto & nullable_source = static_cast<NullableSource &>(source);
result = ColumnArray::create(nullable_source.createValuesColumn());
NullableSink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetUnbounded(static_cast<ConstSource<NullableSource> &>(source), sink, offset);
else
sliceFromRightConstantOffsetUnbounded(static_cast<NullableSource &>(source), sink, offset);
}
else
{
result = ColumnArray::create(source.createValuesColumn());
Sink sink(result->getData(), result->getOffsets(), source.getColumnSize());
if (is_const)
sliceFromRightConstantOffsetUnbounded(static_cast<ConstSource<SourceType> &>(source), sink, offset);
else
sliceFromRightConstantOffsetUnbounded(source, sink, offset);
}
}
};