@@ -216,6 +216,7 @@ void fillRowVectorChildren(
216216 }
217217 }
218218}
219+
219220} // namespace
220221
221222void SelectiveStructColumnReaderBase::getValues (
@@ -228,16 +229,14 @@ void SelectiveStructColumnReaderBase::getValues(
228229 VELOX_CHECK (
229230 result->get ()->type ()->isRow (),
230231 " Struct reader expects a result of type ROW." );
231- auto & rowType = result->get ()->type ()->asRow ();
232- if (!result->unique () || result->get ()->isLazy ()) {
232+ checkOutputType (outputType_, asRowType (requestedType_->type ));
233+ const auto & outDataType = outputType_ ? outputType_ : result->get ()->type ();
234+ auto & rowType = outDataType->asRow ();
235+ if (outputType_ || !result->unique () || result->get ()->isLazy ()) {
233236 std::vector<VectorPtr> children (rowType.size ());
234237 fillRowVectorChildren (*result->get ()->pool (), rowType, children);
235238 *result = std::make_unique<RowVector>(
236- result->get ()->pool (),
237- result->get ()->type (),
238- nullptr ,
239- 0 ,
240- std::move (children));
239+ result->get ()->pool (), outDataType, nullptr , 0 , std::move (children));
241240 }
242241 auto * resultRow = static_cast <RowVector*>(result->get ());
243242 resultRow->resize (rows.size ());
@@ -277,7 +276,7 @@ void SelectiveStructColumnReaderBase::getValues(
277276 }
278277 resultRow->childAt (channel) = std::make_shared<LazyVector>(
279278 &memoryPool_,
280- resultRow-> type () ->childAt (channel),
279+ outDataType ->childAt (channel),
281280 rows.size (),
282281 std::make_unique<ColumnLoader>(this , children_[index], numReads_));
283282 } else {
@@ -287,4 +286,52 @@ void SelectiveStructColumnReaderBase::getValues(
287286 }
288287}
289288
289+ void SelectiveStructColumnReaderBase::setOutputType (
290+ const RowTypePtr& outputType) {
291+ outputType_ = outputType;
292+ }
293+
294+ /* *
295+ * Check the output type against requested type on compatibility.
296+ * @param outputType: the output type from user.
297+ * @param requestedType: the type from Parquet.
298+ */
299+ void SelectiveStructColumnReaderBase::checkOutputType (
300+ const RowTypePtr& outputType,
301+ const RowTypePtr& requestedType) {
302+ if (outputType == nullptr ) {
303+ return ;
304+ }
305+ VELOX_CHECK_NOT_NULL (requestedType);
306+ for (int i = 0 ; i < outputType->size (); ++i) {
307+ if (!requestedType->containsChild (outputType->nameOf (i)))
308+ continue ;
309+
310+ bool isPartitionColumn = false ;
311+ for (const auto & childSpec : scanSpec_->children ()) {
312+ if (childSpec->fieldName () == outputType->nameOf (i) &&
313+ childSpec->isConstant ()) {
314+ isPartitionColumn = true ;
315+ break ;
316+ }
317+ }
318+ // Skip the type check for partition column because requested type does not
319+ // contain it.
320+ if (isPartitionColumn)
321+ continue ;
322+
323+ const auto & childOutputType = outputType->childAt (i);
324+ const auto & childRequestedType =
325+ requestedType->findChild (outputType->nameOf (i));
326+ if (auto rowTypePtr = asRowType (childOutputType)) {
327+ VELOX_CHECK_NOT_NULL (asRowType (childRequestedType));
328+ checkOutputType (
329+ asRowType (childOutputType), asRowType (childRequestedType));
330+ continue ;
331+ }
332+ VELOX_CHECK (BaseVector::compatibleKind (
333+ childOutputType->kind (), childRequestedType->kind ()));
334+ }
335+ }
336+
290337} // namespace facebook::velox::dwio::common
0 commit comments