11/*
2- * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
2+ * SPDX-FileCopyrightText: Copyright (c) 2025-2026 , NVIDIA CORPORATION.
33 * SPDX-License-Identifier: Apache-2.0
44 */
55
@@ -105,9 +105,32 @@ void hybrid_scan_reader_impl::setup_page_index(
105105void hybrid_scan_reader_impl::select_columns (read_columns_mode read_columns_mode,
106106 parquet_reader_options const & options)
107107{
108- // Select only columns required by the filter
109- if (read_columns_mode == read_columns_mode::FILTER_COLUMNS ) {
108+ if (read_columns_mode == read_columns_mode::ALL_COLUMNS ) {
109+ if (_is_all_columns_selected) { return ; }
110+
111+ // Select only columns required by the options and filter.
112+ // Using as is from:
113+ // https://github.com/rapidsai/cudf/blob/a8b25cd205dc5d04b9918dcb0b3abd6b8c4e4a74/cpp/src/io/parquet/reader_impl.cpp#L556-L569
114+ std::optional<std::vector<std::string>> filter_only_columns_names;
115+ if (options.get_filter ().has_value () and options.get_columns ().has_value ()) {
116+ filter_only_columns_names = cudf::io::parquet::detail::get_column_names_in_expression (
117+ options.get_filter (), *(options.get_columns ()));
118+ _num_filter_only_columns = filter_only_columns_names->size ();
119+ }
120+ std::tie (_input_columns, _output_buffers, _output_column_schemas) =
121+ _metadata->select_columns (options.get_columns (),
122+ filter_only_columns_names,
123+ options.is_enabled_use_pandas_metadata (),
124+ _strings_to_categorical,
125+ options.is_enabled_ignore_missing_columns (),
126+ _options.timestamp_type .id ());
127+
128+ _is_all_columns_selected = true ;
129+ _is_filter_columns_selected = false ;
130+ _is_payload_columns_selected = false ;
131+ } else if (read_columns_mode == read_columns_mode::FILTER_COLUMNS ) {
110132 if (_is_filter_columns_selected) { return ; }
133+
111134 // list, struct, dictionary are not supported by AST filter yet.
112135 _filter_columns_names =
113136 names_from_expression (
@@ -124,6 +147,7 @@ void hybrid_scan_reader_impl::select_columns(read_columns_mode read_columns_mode
124147
125148 _is_filter_columns_selected = true ;
126149 _is_payload_columns_selected = false ;
150+ _is_all_columns_selected = false ;
127151 } else {
128152 if (_is_payload_columns_selected) { return ; }
129153
@@ -137,6 +161,7 @@ void hybrid_scan_reader_impl::select_columns(read_columns_mode read_columns_mode
137161
138162 _is_payload_columns_selected = true ;
139163 _is_filter_columns_selected = false ;
164+ _is_all_columns_selected = false ;
140165 }
141166
142167 // Reset the rows processed so far
@@ -418,6 +443,17 @@ hybrid_scan_reader_impl::payload_column_chunks_byte_ranges(
418443 return get_input_column_chunk_byte_ranges (row_group_indices);
419444}
420445
446+ std::pair<std::vector<byte_range_info>, std::vector<cudf::size_type>>
447+ hybrid_scan_reader_impl::all_column_chunks_byte_ranges (
448+ cudf::host_span<std::vector<size_type> const > row_group_indices,
449+ parquet_reader_options const & options)
450+ {
451+ CUDF_EXPECTS (not row_group_indices.empty (), " Empty input row group indices encountered" );
452+
453+ select_columns (read_columns_mode::ALL_COLUMNS , options);
454+ return get_input_column_chunk_byte_ranges (row_group_indices);
455+ }
456+
421457table_with_metadata hybrid_scan_reader_impl::materialize_filter_columns (
422458 cudf::host_span<std::vector<size_type> const > row_group_indices,
423459 std::vector<rmm::device_buffer>&& column_chunk_buffers,
@@ -482,6 +518,29 @@ table_with_metadata hybrid_scan_reader_impl::materialize_payload_columns(
482518 return read_chunk_internal (read_mode::READ_ALL , read_columns_mode::PAYLOAD_COLUMNS , row_mask);
483519}
484520
521+ table_with_metadata hybrid_scan_reader_impl::materialize_all_columns (
522+ cudf::host_span<std::vector<size_type> const > row_group_indices,
523+ std::vector<rmm::device_buffer>&& column_chunk_buffers,
524+ parquet_reader_options const & options,
525+ rmm::cuda_stream_view stream)
526+ {
527+ CUDF_EXPECTS (not row_group_indices.empty (), " Empty input row group indices encountered" );
528+
529+ reset_internal_state ();
530+
531+ initialize_options (row_group_indices, options, stream);
532+
533+ select_columns (read_columns_mode::ALL_COLUMNS , options);
534+
535+ // Convert the input expression (must be done after column selection)
536+ _expr_conv = build_converted_expression (options.get_filter ());
537+
538+ prepare_data (read_mode::READ_ALL , row_group_indices, std::move (column_chunk_buffers), {});
539+
540+ // Use the main reader's function
541+ return reader_impl::read_chunk_internal (read_mode::READ_ALL );
542+ }
543+
485544void hybrid_scan_reader_impl::setup_chunking_for_filter_columns (
486545 std::size_t chunk_read_limit,
487546 std::size_t pass_read_limit,
@@ -643,6 +702,8 @@ void hybrid_scan_reader_impl::initialize_options(
643702named_to_reference_converter hybrid_scan_reader_impl::build_converted_expression (
644703 std::optional<std::reference_wrapper<const ast::expression>> filter)
645704{
705+ if (not filter.has_value ()) { return named_to_reference_converter (std::nullopt , {}, {}); }
706+
646707 table_metadata metadata;
647708 populate_metadata (metadata);
648709 auto expr_conv =
@@ -821,14 +882,16 @@ table_with_metadata hybrid_scan_reader_impl::finalize_output(
821882 // Create a table from the output columns.
822883 auto read_table = std::make_unique<table>(std::move (out_columns));
823884
885+ CUDF_EXPECTS (row_mask.is_empty () or row_mask.type ().id () == type_id::BOOL8 ,
886+ " Input row mask must be empty or a boolean column" );
887+
824888 // If the input row mask is empty, return the table as is.
825889 if (row_mask.is_empty ()) { return {std::move (read_table), std::move (out_metadata)}; }
826890
827- // If reading filter columns, compute the predicate, apply it to the table, and update the input
828- // row mask to reflect the final surviving rows.
891+ // For filter columns, apply the filter expression and update the input row mask
829892 if constexpr (std::is_same_v<RowMaskView, cudf::mutable_column_view>) {
830893 CUDF_EXPECTS (read_columns_mode == read_columns_mode::FILTER_COLUMNS , " Invalid read mode" );
831- // Apply the row selection predicate on the read table to get the final row mask
894+
832895 auto final_row_mask =
833896 cudf::detail::compute_column (*read_table,
834897 _expr_conv.get_converted_expr ().value ().get (),
@@ -850,11 +913,9 @@ table_with_metadata hybrid_scan_reader_impl::finalize_output(
850913 // Return the final output table and metadata
851914 return {std::move (output_table), std::move (out_metadata)};
852915 }
853- // Otherwise , simply apply the input row mask to the table.
916+ // For payload columns , simply apply the input row mask to the table.
854917 else {
855918 CUDF_EXPECTS (read_columns_mode == read_columns_mode::PAYLOAD_COLUMNS , " Invalid read mode" );
856- CUDF_EXPECTS (row_mask.type ().id () == type_id::BOOL8 ,
857- " Predicate filter should return a boolean" );
858919
859920 auto const mask_offset = _rows_processed_so_far;
860921 _rows_processed_so_far += read_table->num_rows ();
0 commit comments