From 039e00c8bfe474b3dda47335f388237c614d9d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=B5=B5=E7=A9=BA=E4=BA=8B=E3=82=B9=E3=83=94=E3=83=AA?= =?UTF-8?q?=E3=83=83=E3=83=88?= Date: Fri, 13 Dec 2024 13:44:21 +0800 Subject: [PATCH] [Doc] Add meaning of 0 for variables (#53714) (cherry picked from commit b42eff7ae3538bc2e4e6bba68fb959d7089086a7) # Conflicts: # .github/CODEOWNERS # .github/PULL_REQUEST_TEMPLATE.md # .github/workflows/ci-comment-tools.yml # .github/workflows/ci-merged-sonarcloud-fe.yml # .github/workflows/ci-merged.yml # .github/workflows/ci-pipeline-branch.yml # .github/workflows/ci-pipeline.yml # .github/workflows/ci-report.yml # .github/workflows/ci-sync.yml # .github/workflows/inspection-pipeline.yml # .github/workflows/pr-checker.yml # .gitignore # .trivyignore # README.md # be/.gitignore # be/CMakeLists.txt # be/cmake_modules/FindClangTidy.cmake # be/src/agent/agent_task.cpp # be/src/agent/finish_task.cpp # be/src/agent/heartbeat_server.cpp # be/src/agent/publish_version.cpp # be/src/agent/report_task.cpp # be/src/agent/task_worker_pool.cpp # be/src/agent/utils.cpp # be/src/agent/utils.h # be/src/bench/CMakeLists.txt # be/src/bench/block_cache_bench.cpp # be/src/bench/chunks_sorter_bench.cpp # be/src/bench/csv_reader_bench.cpp # be/src/bench/get_dict_codes_bench.cpp # be/src/bench/orc_column_reader_bench.cpp # be/src/bench/parquet_dict_decode_bench.cpp # be/src/bench/persistent_index_bench.cpp # be/src/bench/runtime_filter_bench.cpp # be/src/bench/shuffle_chunk_bench.cpp # be/src/block_cache/CMakeLists.txt # be/src/block_cache/block_cache.cpp # be/src/block_cache/block_cache.h # be/src/block_cache/cache_options.h # be/src/block_cache/datacache_utils.cpp # be/src/block_cache/datacache_utils.h # be/src/block_cache/disk_space_monitor.cpp # be/src/block_cache/kv_cache.h # be/src/block_cache/starcache_wrapper.cpp # be/src/block_cache/starcache_wrapper.h # be/src/column/adaptive_nullable_column.cpp # be/src/column/adaptive_nullable_column.h # be/src/column/array_column.h # be/src/column/array_view_column.h # be/src/column/binary_column.cpp # be/src/column/binary_column.h # be/src/column/bytes.h # be/src/column/chunk.cpp # be/src/column/chunk.h # be/src/column/column.cpp # be/src/column/column.h # be/src/column/column_builder.h # be/src/column/column_hash.h # be/src/column/column_helper.cpp # be/src/column/column_helper.h # be/src/column/column_viewer.cpp # be/src/column/const_column.cpp # be/src/column/const_column.h # be/src/column/datum.h # be/src/column/field.h # be/src/column/fixed_length_column_base.cpp # be/src/column/fixed_length_column_base.h # be/src/column/hash_set.h # be/src/column/json_column.cpp # be/src/column/json_column.h # be/src/column/map_column.h # be/src/column/nullable_column.cpp # be/src/column/nullable_column.h # be/src/column/object_column.cpp # be/src/column/object_column.h # be/src/column/schema.cpp # be/src/column/struct_column.cpp # be/src/column/struct_column.h # be/src/column/vectorized_fwd.h # be/src/common/config.h # be/src/common/daemon.cpp # be/src/common/logconfig.cpp # be/src/common/logging.h # be/src/common/status.cpp # be/src/common/status.h # be/src/connector/CMakeLists.txt # be/src/connector/connector.cpp # be/src/connector/connector.h # be/src/connector/hive_connector.cpp # be/src/connector/hive_connector.h # be/src/connector/lake_connector.cpp # be/src/connector/lake_connector.h # be/src/exec/CMakeLists.txt # be/src/exec/aggregate/agg_hash_map.h # be/src/exec/aggregate/agg_hash_set.h # be/src/exec/aggregate/aggregate_base_node.cpp # be/src/exec/aggregator.cpp # be/src/exec/aggregator.h # be/src/exec/analytor.cpp # be/src/exec/analytor.h # be/src/exec/arrow_to_starrocks_converter.cpp # be/src/exec/arrow_to_starrocks_converter.h # be/src/exec/capture_version_node.cpp # be/src/exec/chunks_sorter.cpp # be/src/exec/chunks_sorter.h # be/src/exec/chunks_sorter_full_sort.h # be/src/exec/chunks_sorter_heap_sort.h # be/src/exec/chunks_sorter_topn.h # be/src/exec/connector_scan_node.cpp # be/src/exec/csv_scanner.cpp # be/src/exec/csv_scanner.h # be/src/exec/data_sink.cpp # be/src/exec/data_sink.h # be/src/exec/dictionary_cache_writer.h # be/src/exec/es/es_predicate.cpp # be/src/exec/es/es_scan_reader.cpp # be/src/exec/except_hash_set.cpp # be/src/exec/except_hash_set.h # be/src/exec/exec_node.h # be/src/exec/file_scanner.cpp # be/src/exec/hash_join_components.cpp # be/src/exec/hash_join_components.h # be/src/exec/hash_join_node.cpp # be/src/exec/hash_join_node.h # be/src/exec/hash_joiner.cpp # be/src/exec/hash_joiner.h # be/src/exec/hdfs_scanner.cpp # be/src/exec/hdfs_scanner.h # be/src/exec/hdfs_scanner_orc.cpp # be/src/exec/hdfs_scanner_parquet.cpp # be/src/exec/hdfs_scanner_text.cpp # be/src/exec/iceberg/iceberg_delete_builder.cpp # be/src/exec/iceberg/iceberg_delete_builder.h # be/src/exec/intersect_hash_set.cpp # be/src/exec/intersect_hash_set.h # be/src/exec/jdbc_scanner.cpp # be/src/exec/jdbc_scanner.h # be/src/exec/jni_scanner.cpp # be/src/exec/jni_scanner.h # be/src/exec/join_hash_map.cpp # be/src/exec/join_hash_map.h # be/src/exec/join_hash_map.tpp # be/src/exec/json_scanner.cpp # be/src/exec/json_scanner.h # be/src/exec/local_file_writer.cpp # be/src/exec/olap_common.cpp # be/src/exec/olap_common.h # be/src/exec/olap_scan_node.cpp # be/src/exec/olap_scan_node.h # be/src/exec/olap_scan_prepare.cpp # be/src/exec/olap_scan_prepare.h # be/src/exec/olap_utils.h # be/src/exec/orc_scanner.cpp # be/src/exec/parquet_reader.cpp # be/src/exec/parquet_reader.h # be/src/exec/parquet_scanner.cpp # be/src/exec/partition/chunks_partitioner.cpp # be/src/exec/partition/chunks_partitioner.h # be/src/exec/partition/partition_hash_map.h # be/src/exec/partition/partition_hash_variant.cpp # be/src/exec/partition/partition_hash_variant.h # be/src/exec/pipeline/aggregate/aggregate_blocking_sink_operator.h # be/src/exec/pipeline/aggregate/aggregate_blocking_source_operator.h # be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_sink_operator.h # be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_source_operator.h # be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_sink_operator.h # be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_source_operator.h # be/src/exec/pipeline/aggregate/aggregate_streaming_sink_operator.h # be/src/exec/pipeline/aggregate/aggregate_streaming_source_operator.h # be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_sink_operator.h # be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_source_operator.h # be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_sink_operator.h # be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_source_operator.h # be/src/exec/pipeline/aggregate/spillable_aggregate_distinct_blocking_operator.h # be/src/exec/pipeline/audit_statistics_reporter.cpp # be/src/exec/pipeline/audit_statistics_reporter.h # be/src/exec/pipeline/chunk_accumulate_operator.h # be/src/exec/pipeline/context_with_dependency.h # be/src/exec/pipeline/exchange/exchange_sink_operator.cpp # be/src/exec/pipeline/exchange/local_exchange_sink_operator.h # be/src/exec/pipeline/exchange/local_exchange_source_operator.h # be/src/exec/pipeline/exchange/mem_limited_chunk_queue.cpp # be/src/exec/pipeline/exchange/multi_cast_local_exchange_sink_operator.h # be/src/exec/pipeline/exchange/multi_cast_local_exchange_source_operator.h # be/src/exec/pipeline/exchange/sink_buffer.cpp # be/src/exec/pipeline/exchange/sink_buffer.h # be/src/exec/pipeline/exec_state_reporter.cpp # be/src/exec/pipeline/fragment_context.cpp # be/src/exec/pipeline/fragment_context.h # be/src/exec/pipeline/fragment_executor.cpp # be/src/exec/pipeline/fragment_executor.h # be/src/exec/pipeline/hash_partition_context.cpp # be/src/exec/pipeline/hash_partition_context.h # be/src/exec/pipeline/hashjoin/hash_join_build_operator.cpp # be/src/exec/pipeline/hashjoin/hash_join_build_operator.h # be/src/exec/pipeline/hashjoin/hash_join_probe_operator.cpp # be/src/exec/pipeline/hashjoin/hash_join_probe_operator.h # be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.cpp # be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.h # be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.cpp # be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.h # be/src/exec/pipeline/limit_operator.cpp # be/src/exec/pipeline/limit_operator.h # be/src/exec/pipeline/nljoin/nljoin_build_operator.h # be/src/exec/pipeline/nljoin/nljoin_context.cpp # be/src/exec/pipeline/nljoin/nljoin_context.h # be/src/exec/pipeline/nljoin/nljoin_probe_operator.cpp # be/src/exec/pipeline/nljoin/nljoin_probe_operator.h # be/src/exec/pipeline/nljoin/spillable_nljoin_probe_operator.h # be/src/exec/pipeline/operator.cpp # be/src/exec/pipeline/operator.h # be/src/exec/pipeline/pipeline.h # be/src/exec/pipeline/pipeline_driver.cpp # be/src/exec/pipeline/pipeline_driver.h # be/src/exec/pipeline/pipeline_fwd.h # be/src/exec/pipeline/query_context.cpp # be/src/exec/pipeline/query_context.h # be/src/exec/pipeline/result_sink_operator.cpp # be/src/exec/pipeline/result_sink_operator.h # be/src/exec/pipeline/runtime_filter_types.h # be/src/exec/pipeline/scan/chunk_source.h # be/src/exec/pipeline/scan/connector_scan_operator.cpp # be/src/exec/pipeline/scan/connector_scan_operator.h # be/src/exec/pipeline/scan/meta_scan_operator.cpp # be/src/exec/pipeline/scan/meta_scan_operator.h # be/src/exec/pipeline/scan/meta_scan_prepare_operator.cpp # be/src/exec/pipeline/scan/morsel.cpp # be/src/exec/pipeline/scan/morsel.h # be/src/exec/pipeline/scan/olap_chunk_source.cpp # be/src/exec/pipeline/scan/olap_chunk_source.h # be/src/exec/pipeline/scan/olap_scan_context.cpp # be/src/exec/pipeline/scan/olap_scan_context.h # be/src/exec/pipeline/scan/olap_scan_operator.cpp # be/src/exec/pipeline/scan/olap_scan_operator.h # be/src/exec/pipeline/scan/scan_operator.cpp # be/src/exec/pipeline/scan/scan_operator.h # be/src/exec/pipeline/scan/schema_scan_operator.cpp # be/src/exec/pipeline/scan/schema_scan_operator.h # be/src/exec/pipeline/select_operator.cpp # be/src/exec/pipeline/select_operator.h # be/src/exec/pipeline/sort/local_partition_topn_context.cpp # be/src/exec/pipeline/sort/local_partition_topn_context.h # be/src/exec/pipeline/sort/sort_context.cpp # be/src/exec/pipeline/sort/sort_context.h # be/src/exec/pipeline/stream_epoch_manager.h # be/src/exec/pipeline/stream_pipeline_driver.h # be/src/exec/pipeline/table_function_operator.h # be/src/exec/query_cache/cache_manager.h # be/src/exec/query_cache/cache_operator.cpp # be/src/exec/query_cache/cache_operator.h # be/src/exec/query_cache/cache_param.h # be/src/exec/query_cache/multilane_operator.h # be/src/exec/scan_node.cpp # be/src/exec/scan_node.h # be/src/exec/schema_scan_node.cpp # be/src/exec/select_node.cpp # be/src/exec/select_node.h # be/src/exec/sorted_streaming_aggregator.cpp # be/src/exec/sorted_streaming_aggregator.h # be/src/exec/sorting/compare_column.cpp # be/src/exec/sorting/merge.h # be/src/exec/sorting/merge_column.cpp # be/src/exec/sorting/sort_permute.h # be/src/exec/sorting/sorting.h # be/src/exec/spill/common.h # be/src/exec/spill/mem_table.cpp # be/src/exec/spill/mem_table.h # be/src/exec/spill/spiller.h # be/src/exec/stream/aggregate/agg_group_state.cpp # be/src/exec/stream/aggregate/agg_group_state.h # be/src/exec/stream/aggregate/agg_state_data.cpp # be/src/exec/stream/aggregate/agg_state_data.h # be/src/exec/stream/aggregate/stream_aggregate_operator.h # be/src/exec/stream/aggregate/stream_aggregator.h # be/src/exec/stream/scan/stream_scan_operator.h # be/src/exec/stream/state/mem_state_table.cpp # be/src/exec/stream/state/mem_state_table.h # be/src/exec/stream/state/state_table.h # be/src/exec/tablet_info.cpp # be/src/exec/tablet_info.h # be/src/exec/tablet_scanner.cpp # be/src/exec/tablet_scanner.h # be/src/exec/tablet_sink.cpp # be/src/exec/tablet_sink.h # be/src/exec/tablet_sink_index_channel.cpp # be/src/exec/tablet_sink_index_channel.h # be/src/exec/tablet_sink_sender.cpp # be/src/exec/topn_node.cpp # be/src/exec/topn_node.h # be/src/exec/union_node.h # be/src/exec/write_combined_txn_log.h # be/src/exprs/CMakeLists.txt # be/src/exprs/agg/aggregate.h # be/src/exprs/agg/aggregate_factory.h # be/src/exprs/agg/approx_top_k.h # be/src/exprs/agg/array_agg.h # be/src/exprs/agg/array_union_agg.h # be/src/exprs/agg/avg.h # be/src/exprs/agg/bitmap_agg.h # be/src/exprs/agg/count.h # be/src/exprs/agg/distinct.h # be/src/exprs/agg/factory/aggregate_factory.cpp # be/src/exprs/agg/factory/aggregate_factory.hpp # be/src/exprs/agg/factory/aggregate_resolver.hpp # be/src/exprs/agg/factory/aggregate_resolver_approx.cpp # be/src/exprs/agg/factory/aggregate_resolver_avg.cpp # be/src/exprs/agg/factory/aggregate_resolver_minmaxany.cpp # be/src/exprs/agg/factory/aggregate_resolver_others.cpp # be/src/exprs/agg/group_concat.h # be/src/exprs/agg/hll_ndv.h # be/src/exprs/agg/hll_union.h # be/src/exprs/agg/hll_union_count.h # be/src/exprs/agg/java_udaf_function.h # be/src/exprs/agg/nullable_aggregate.h # be/src/exprs/agg/percentile_approx.h # be/src/exprs/agg/percentile_cont.h # be/src/exprs/agg/percentile_union.h # be/src/exprs/agg/sum.h # be/src/exprs/agg/window.h # be/src/exprs/arithmetic_expr.cpp # be/src/exprs/arithmetic_operation.h # be/src/exprs/array_element_expr.cpp # be/src/exprs/array_functions.tpp # be/src/exprs/array_map_expr.cpp # be/src/exprs/binary_predicate.cpp # be/src/exprs/bitmap_functions.cpp # be/src/exprs/builtin_functions.h # be/src/exprs/case_expr.cpp # be/src/exprs/cast_expr.cpp # be/src/exprs/cast_expr.h # be/src/exprs/compound_predicate.cpp # be/src/exprs/debug_expr.cpp # be/src/exprs/debug_expr.h # be/src/exprs/decimal_binary_function.h # be/src/exprs/expr.cpp # be/src/exprs/expr.h # be/src/exprs/expr_context.cpp # be/src/exprs/expr_context.h # be/src/exprs/function_call_expr.cpp # be/src/exprs/function_call_expr.h # be/src/exprs/function_context.cpp # be/src/exprs/function_context.h # be/src/exprs/function_helper.cpp # be/src/exprs/function_helper.h # be/src/exprs/in_const_predicate.hpp # be/src/exprs/java_function_call_expr.cpp # be/src/exprs/java_function_call_expr.h # be/src/exprs/jit/jit_expr.cpp # be/src/exprs/json_functions.h # be/src/exprs/like_predicate.cpp # be/src/exprs/literal.cpp # be/src/exprs/literal.h # be/src/exprs/locate.cpp # be/src/exprs/map_apply_expr.cpp # be/src/exprs/map_functions.cpp # be/src/exprs/math_functions.cpp # be/src/exprs/math_functions.h # be/src/exprs/percentile_functions.cpp # be/src/exprs/runtime_filter_bank.cpp # be/src/exprs/runtime_filter_bank.h # be/src/exprs/split.cpp # be/src/exprs/string_functions.cpp # be/src/exprs/string_functions.h # be/src/exprs/table_function/generate_series.h # be/src/exprs/table_function/java_udtf_function.h # be/src/exprs/table_function/json_each.h # be/src/exprs/table_function/list_rowsets.cpp # be/src/exprs/table_function/list_rowsets.h # be/src/exprs/table_function/multi_unnest.h # be/src/exprs/table_function/subdivide_bitmap.h # be/src/exprs/table_function/table_function.h # be/src/exprs/table_function/unnest.h # be/src/exprs/unary_function.h # be/src/exprs/utility_functions.cpp # be/src/exprs/utility_functions.h # be/src/formats/CMakeLists.txt # be/src/formats/csv/json_converter.h # be/src/formats/orc/apache-orc/c++/include/orc/Common.hh # be/src/formats/orc/apache-orc/c++/src/Int128.cc # be/src/formats/orc/apache-orc/c++/src/Statistics.hh # be/src/formats/orc/orc_chunk_reader.cpp # be/src/formats/parquet/chunk_writer.cpp # be/src/formats/parquet/chunk_writer.h # be/src/formats/parquet/column_chunk_reader.cpp # be/src/formats/parquet/column_chunk_reader.h # be/src/formats/parquet/column_chunk_writer.cpp # be/src/formats/parquet/column_chunk_writer.h # be/src/formats/parquet/column_converter.cpp # be/src/formats/parquet/column_converter.h # be/src/formats/parquet/column_read_order_ctx.cpp # be/src/formats/parquet/column_read_order_ctx.h # be/src/formats/parquet/column_reader.cpp # be/src/formats/parquet/column_reader.h # be/src/formats/parquet/encoding.cpp # be/src/formats/parquet/encoding.h # be/src/formats/parquet/encoding_dict.h # be/src/formats/parquet/file_reader.cpp # be/src/formats/parquet/file_reader.h # be/src/formats/parquet/file_writer.cpp # be/src/formats/parquet/file_writer.h # be/src/formats/parquet/group_reader.cpp # be/src/formats/parquet/group_reader.h # be/src/formats/parquet/level_builder.cpp # be/src/formats/parquet/level_builder.h # be/src/formats/parquet/level_codec.cpp # be/src/formats/parquet/level_codec.h # be/src/formats/parquet/meta_helper.cpp # be/src/formats/parquet/meta_helper.h # be/src/formats/parquet/metadata.cpp # be/src/formats/parquet/metadata.h # be/src/formats/parquet/page_index_reader.cpp # be/src/formats/parquet/page_index_reader.h # be/src/formats/parquet/page_reader.cpp # be/src/formats/parquet/page_reader.h # be/src/formats/parquet/parquet_file_writer.cpp # be/src/formats/parquet/parquet_file_writer.h # be/src/formats/parquet/schema.cpp # be/src/formats/parquet/schema.h # be/src/formats/parquet/statistics_helper.cpp # be/src/formats/parquet/statistics_helper.h # be/src/formats/parquet/stored_column_reader.cpp # be/src/formats/parquet/stored_column_reader.h # be/src/formats/parquet/stored_column_reader_with_index.cpp # be/src/formats/parquet/stored_column_reader_with_index.h # be/src/formats/parquet/utils.cpp # be/src/formats/parquet/utils.h # be/src/fs/CMakeLists.txt # be/src/fs/fs.cpp # be/src/fs/fs.h # be/src/fs/fs_broker.cpp # be/src/fs/fs_s3.cpp # be/src/fs/fs_s3.h # be/src/fs/fs_starlet.cpp # be/src/fs/hdfs/fs_hdfs.cpp # be/src/gen_cpp/CMakeLists.txt # be/src/geo/wkt_parse.cpp # be/src/geo/wkt_yacc.y # be/src/gutil/CMakeLists.txt # be/src/gutil/strings/join.h # be/src/http/action/checksum_action.cpp # be/src/http/action/datacache_action.cpp # be/src/http/action/memory_metrics_action.cpp # be/src/http/action/metrics_action.h # be/src/http/action/stream_load.cpp # be/src/http/action/stream_load.h # be/src/http/action/update_config_action.cpp # be/src/http/default_path_handlers.cpp # be/src/http/download_action.cpp # be/src/http/http_client.h # be/src/http/http_common.h # be/src/io/cache_input_stream.cpp # be/src/io/cache_input_stream.h # be/src/io/cache_select_input_stream.hpp # be/src/io/direct_s3_output_stream.cpp # be/src/io/s3_input_stream.cpp # be/src/io/s3_input_stream.h # be/src/io/s3_output_stream.cpp # be/src/runtime/CMakeLists.txt # be/src/runtime/broker_mgr.cpp # be/src/runtime/buffer_control_block.cpp # be/src/runtime/buffer_control_block.h # be/src/runtime/chunk_cursor.h # be/src/runtime/customized_result_writer.cpp # be/src/runtime/customized_result_writer.h # be/src/runtime/data_stream_mgr.h # be/src/runtime/data_stream_sender.cpp # be/src/runtime/data_stream_sender.h # be/src/runtime/descriptors.cpp # be/src/runtime/descriptors.h # be/src/runtime/exec_env.cpp # be/src/runtime/exec_env.h # be/src/runtime/file_result_writer.h # be/src/runtime/fragment_mgr.cpp # be/src/runtime/fragment_mgr.h # be/src/runtime/global_dict/miscs.cpp # be/src/runtime/global_dict/parser.cpp # be/src/runtime/global_dict/parser.h # be/src/runtime/http_result_writer.cpp # be/src/runtime/http_result_writer.h # be/src/runtime/lake_snapshot_loader.cpp # be/src/runtime/lake_tablets_channel.cpp # be/src/runtime/load_channel.cpp # be/src/runtime/load_channel.h # be/src/runtime/load_path_mgr.cpp # be/src/runtime/local_tablets_channel.cpp # be/src/runtime/local_tablets_channel.h # be/src/runtime/mem_pool.h # be/src/runtime/metadata_result_writer.cpp # be/src/runtime/metadata_result_writer.h # be/src/runtime/mysql_result_writer.cpp # be/src/runtime/mysql_result_writer.h # be/src/runtime/plan_fragment_executor.cpp # be/src/runtime/query_statistics.cpp # be/src/runtime/query_statistics.h # be/src/runtime/result_buffer_mgr.cpp # be/src/runtime/result_buffer_mgr.h # be/src/runtime/result_queue_mgr.h # be/src/runtime/result_sink.cpp # be/src/runtime/result_sink.h # be/src/runtime/result_writer.h # be/src/runtime/runtime_filter_worker.cpp # be/src/runtime/runtime_filter_worker.h # be/src/runtime/runtime_state.cpp # be/src/runtime/runtime_state.h # be/src/runtime/schema_table_sink.cpp # be/src/runtime/small_file_mgr.h # be/src/runtime/snapshot_loader.cpp # be/src/runtime/statistic_result_writer.cpp # be/src/runtime/statistic_result_writer.h # be/src/runtime/stream_load/stream_load_context.cpp # be/src/runtime/stream_load/stream_load_context.h # be/src/runtime/stream_load/stream_load_pipe.cpp # be/src/runtime/stream_load/stream_load_pipe.h # be/src/runtime/stream_load/transaction_mgr.h # be/src/runtime/table_function_table_sink.cpp # be/src/runtime/table_function_table_sink.h # be/src/runtime/tablets_channel.h # be/src/runtime/time_types.h # be/src/runtime/types.cpp # be/src/runtime/types.h # be/src/runtime/user_function_cache.cpp # be/src/runtime/user_function_cache.h # be/src/runtime/variable_result_writer.cpp # be/src/runtime/variable_result_writer.h # be/src/script/CMakeLists.txt # be/src/script/script.cpp # be/src/serde/column_array_serde.cpp # be/src/service/CMakeLists.txt # be/src/service/internal_service.cpp # be/src/service/internal_service.h # be/src/service/mem_hook.cpp # be/src/service/service_be/CMakeLists.txt # be/src/service/service_be/internal_service.cpp # be/src/service/service_be/internal_service.h # be/src/service/service_be/lake_service.cpp # be/src/service/service_be/lake_service.h # be/src/service/service_be/starrocks_be.cpp # be/src/service/staros_worker.cpp # be/src/service/staros_worker.h # be/src/service/starrocks_main.cpp # be/src/simd/simd.h # be/src/storage/CMakeLists.txt # be/src/storage/aggregate_iterator.cpp # be/src/storage/aggregate_type.cpp # be/src/storage/aggregate_type.h # be/src/storage/async_delta_writer.cpp # be/src/storage/base_tablet.h # be/src/storage/chunk_aggregator.cpp # be/src/storage/chunk_helper.cpp # be/src/storage/chunk_helper.h # be/src/storage/chunk_iterator.cpp # be/src/storage/chunk_iterator.h # be/src/storage/column_aggregate_func.cpp # be/src/storage/column_aggregate_func.h # be/src/storage/column_expr_predicate.h # be/src/storage/column_in_predicate.cpp # be/src/storage/column_not_in_predicate.cpp # be/src/storage/column_null_predicate.cpp # be/src/storage/column_operator_predicate.h # be/src/storage/column_or_predicate.cpp # be/src/storage/column_or_predicate.h # be/src/storage/column_predicate.h # be/src/storage/column_predicate_cmp.cpp # be/src/storage/column_predicate_dict_conjuct.cpp # be/src/storage/column_predicate_rewriter.cpp # be/src/storage/column_predicate_rewriter.h # be/src/storage/compaction.cpp # be/src/storage/compaction_manager.h # be/src/storage/compaction_task.cpp # be/src/storage/compaction_task.h # be/src/storage/compaction_utils.cpp # be/src/storage/compaction_utils.h # be/src/storage/delta_writer.cpp # be/src/storage/delta_writer.h # be/src/storage/horizontal_compaction_task.cpp # be/src/storage/lake/async_delta_writer.cpp # be/src/storage/lake/async_delta_writer.h # be/src/storage/lake/delta_writer.cpp # be/src/storage/lake/delta_writer.h # be/src/storage/lake/general_tablet_writer.cpp # be/src/storage/lake/horizontal_compaction_task.cpp # be/src/storage/lake/lake_primary_index.cpp # be/src/storage/lake/lake_primary_key_compaction_conflict_resolver.cpp # be/src/storage/lake/lake_primary_key_compaction_conflict_resolver.h # be/src/storage/lake/location_provider.h # be/src/storage/lake/meta_file.cpp # be/src/storage/lake/meta_file.h # be/src/storage/lake/metacache.h # be/src/storage/lake/pk_tablet_writer.cpp # be/src/storage/lake/rowset.cpp # be/src/storage/lake/rowset.h # be/src/storage/lake/schema_change.cpp # be/src/storage/lake/starlet_location_provider.cpp # be/src/storage/lake/starlet_location_provider.h # be/src/storage/lake/tablet.cpp # be/src/storage/lake/tablet.h # be/src/storage/lake/tablet_manager.cpp # be/src/storage/lake/tablet_manager.h # be/src/storage/lake/tablet_reader.cpp # be/src/storage/lake/tablet_reader.h # be/src/storage/lake/tablet_writer.h # be/src/storage/lake/transactions.cpp # be/src/storage/lake/transactions.h # be/src/storage/lake/txn_log_applier.cpp # be/src/storage/lake/update_manager.cpp # be/src/storage/lake/update_manager.h # be/src/storage/lake/vacuum.cpp # be/src/storage/lake/versioned_tablet.cpp # be/src/storage/lake/versioned_tablet.h # be/src/storage/lake/vertical_compaction_task.cpp # be/src/storage/local_primary_key_recover.cpp # be/src/storage/memtable.cpp # be/src/storage/memtable.h # be/src/storage/memtable_flush_executor.cpp # be/src/storage/memtable_flush_executor.h # be/src/storage/merge_iterator.cpp # be/src/storage/meta_reader.cpp # be/src/storage/meta_reader.h # be/src/storage/metadata_util.cpp # be/src/storage/olap_common.h # be/src/storage/olap_meta_reader.cpp # be/src/storage/olap_runtime_range_pruner.h # be/src/storage/olap_runtime_range_pruner.hpp # be/src/storage/options.h # be/src/storage/persistent_index.cpp # be/src/storage/predicate_parser.cpp # be/src/storage/predicate_parser.h # be/src/storage/predicate_tree/predicate_tree.cpp # be/src/storage/predicate_tree/predicate_tree.h # be/src/storage/predicate_tree/predicate_tree.hpp # be/src/storage/predicate_tree/predicate_tree_fwd.h # be/src/storage/primary_index.cpp # be/src/storage/projection_iterator.cpp # be/src/storage/protobuf_file.cpp # be/src/storage/protobuf_file.h # be/src/storage/range.h # be/src/storage/roaring2range.h # be/src/storage/row_source_mask.cpp # be/src/storage/rowset/array_column_iterator.h # be/src/storage/rowset/array_column_writer.cpp # be/src/storage/rowset/base_rowset.h # be/src/storage/rowset/binary_dict_page.h # be/src/storage/rowset/binary_plain_page.h # be/src/storage/rowset/binary_prefix_page.cpp # be/src/storage/rowset/binary_prefix_page.h # be/src/storage/rowset/bitmap_range_iterator.h # be/src/storage/rowset/bitshuffle_page.h # be/src/storage/rowset/cast_column_iterator.h # be/src/storage/rowset/column_iterator.h # be/src/storage/rowset/column_iterator_decorator.h # be/src/storage/rowset/column_reader.cpp # be/src/storage/rowset/column_reader.h # be/src/storage/rowset/column_writer.cpp # be/src/storage/rowset/column_writer.h # be/src/storage/rowset/default_value_column_iterator.cpp # be/src/storage/rowset/default_value_column_iterator.h # be/src/storage/rowset/fill_subfield_iterator.h # be/src/storage/rowset/frame_of_reference_page.h # be/src/storage/rowset/horizontal_update_rowset_writer.cpp # be/src/storage/rowset/indexed_column_reader.cpp # be/src/storage/rowset/indexed_column_reader.h # be/src/storage/rowset/json_column_iterator.cpp # be/src/storage/rowset/map_column_iterator.h # be/src/storage/rowset/ordinal_page_index.cpp # be/src/storage/rowset/ordinal_page_index.h # be/src/storage/rowset/page_decoder.h # be/src/storage/rowset/parsed_page.cpp # be/src/storage/rowset/parsed_page.h # be/src/storage/rowset/plain_page.h # be/src/storage/rowset/rle_page.h # be/src/storage/rowset/rowid_column_iterator.h # be/src/storage/rowset/rowset.cpp # be/src/storage/rowset/rowset.h # be/src/storage/rowset/rowset_meta.cpp # be/src/storage/rowset/rowset_meta.h # be/src/storage/rowset/rowset_options.h # be/src/storage/rowset/rowset_writer.cpp # be/src/storage/rowset/rowset_writer.h # be/src/storage/rowset/rowset_writer_context.h # be/src/storage/rowset/scalar_column_iterator.cpp # be/src/storage/rowset/scalar_column_iterator.h # be/src/storage/rowset/segment.cpp # be/src/storage/rowset/segment.h # be/src/storage/rowset/segment_iterator.cpp # be/src/storage/rowset/segment_options.h # be/src/storage/rowset/segment_rewriter.cpp # be/src/storage/rowset/segment_rewriter.h # be/src/storage/rowset/segment_writer.cpp # be/src/storage/rowset/struct_column_iterator.cpp # be/src/storage/rowset_update_state.cpp # be/src/storage/schema_change.cpp # be/src/storage/schema_change_utils.cpp # be/src/storage/schema_change_utils.h # be/src/storage/segment_flush_executor.cpp # be/src/storage/segment_flush_executor.h # be/src/storage/segment_replicate_executor.cpp # be/src/storage/segment_replicate_executor.h # be/src/storage/snapshot_manager.cpp # be/src/storage/table_reader.cpp # be/src/storage/table_reader.h # be/src/storage/tablet.cpp # be/src/storage/tablet.h # be/src/storage/tablet_index.cpp # be/src/storage/tablet_manager.h # be/src/storage/tablet_meta.h # be/src/storage/tablet_reader.cpp # be/src/storage/tablet_reader.h # be/src/storage/tablet_reader_params.h # be/src/storage/tablet_schema.cpp # be/src/storage/tablet_schema.h # be/src/storage/tablet_updates.cpp # be/src/storage/tablet_updates.h # be/src/storage/txn_manager.cpp # be/src/storage/txn_manager.h # be/src/storage/types.cpp # be/src/storage/union_iterator.cpp # be/src/storage/vertical_compaction_task.cpp # be/src/storage/zone_map_detail.h # be/src/testutil/column_test_helper.h # be/src/testutil/exprs_test_helper.h # be/src/testutil/init_test_env.h # be/src/testutil/schema_test_helper.cpp # be/src/testutil/schema_test_helper.h # be/src/types/CMakeLists.txt # be/src/types/bitmap_value.cpp # be/src/types/bitmap_value.h # be/src/types/bitmap_value_detail.h # be/src/types/constexpr.h # be/src/types/hll.cpp # be/src/types/hll.h # be/src/types/logical_type_infra.h # be/src/types/timestamp_value.cpp # be/src/types/timestamp_value.h # be/src/udf/CMakeLists.txt # be/src/udf/java/java_data_converter.h # be/src/udf/java/java_udf.h # be/src/util/CMakeLists.txt # be/src/util/arrow/row_batch.cpp # be/src/util/arrow/row_batch.h # be/src/util/arrow/starrocks_column_to_arrow.cpp # be/src/util/arrow/starrocks_column_to_arrow.h # be/src/util/arrow/utils.h # be/src/util/bit_packing.h # be/src/util/bit_stream_utils.h # be/src/util/bit_stream_utils.inline.h # be/src/util/bitmap_intersect.h # be/src/util/brpc_stub_cache.h # be/src/util/c_string.h # be/src/util/cpu_info.h # be/src/util/debug/query_trace_impl.h # be/src/util/decimal_types.h # be/src/util/failpoint/fail_point.cpp # be/src/util/filesystem_util.cc # be/src/util/hdfs_util.cpp # be/src/util/int96.cpp # be/src/util/json_converter.h # be/src/util/lru_cache.cpp # be/src/util/lru_cache.h # be/src/util/misc.cpp # be/src/util/mysql_row_buffer.cpp # be/src/util/phmap/phmap.h # be/src/util/raw_container.h # be/src/util/rle_encoding.h # be/src/util/starrocks_metrics.h # be/src/util/system_metrics.cpp # be/src/util/system_metrics.h # be/src/util/threadpool.h # be/src/util/thrift_rpc_helper.cpp # be/src/util/thrift_rpc_helper.h # be/src/util/thrift_util.h # be/src/util/timezone_hsscan.h # be/src/util/uid_util.cpp # be/src/util/uid_util.h # be/test/CMakeLists.txt # be/test/agent/agent_task_test.cpp # be/test/agent/heartbeat_server_test.cpp # be/test/block_cache/block_cache_test.cpp # be/test/block_cache/datacache_utils_test.cpp # be/test/block_cache/disk_space_monitor_test.cpp # be/test/column/avx_numeric_column.h # be/test/column/avx_numeric_column_test.cpp # be/test/column/binary_column_test.cpp # be/test/column/field_test.cpp # be/test/column/fixed_length_column_test.cpp # be/test/column/object_column_test.cpp # be/test/column/timestamp_value_test.cpp # be/test/exec/agg_hash_map_test.cpp # be/test/exec/chunks_sorter_test.cpp # be/test/exec/column_value_range_test.cpp # be/test/exec/hdfs_scan_node_test.cpp # be/test/exec/hdfs_scanner_test.cpp # be/test/exec/join_hash_map_test.cpp # be/test/exec/lake_meta_scanner_test.cpp # be/test/exec/parquet_scanner_test.cpp # be/test/exec/pipeline/mem_limited_chunk_queue_test.cpp # be/test/exprs/agg/aggregate_test.cpp # be/test/exprs/array_functions_test.cpp # be/test/exprs/cast_expr_test.cpp # be/test/exprs/like_test.cpp # be/test/exprs/string_fn_money_format_decimal_test.cpp # be/test/exprs/string_fn_test.cpp # be/test/exprs/time_functions_test.cpp # be/test/formats/csv/string_converter_test.cpp # be/test/formats/csv/varbinary_converter_test.cpp # be/test/formats/orc/orc_chunk_reader_test.cpp # be/test/formats/parquet/column_converter_test.cpp # be/test/formats/parquet/file_reader_test.cpp # be/test/formats/parquet/file_writer_test.cpp # be/test/formats/parquet/group_reader_test.cpp # be/test/formats/parquet/iceberg_schema_evolution_file_reader_test.cpp # be/test/formats/parquet/page_index_test.cpp # be/test/formats/parquet/parquet_cli_reader.h # be/test/formats/parquet/parquet_file_writer_test.cpp # be/test/formats/parquet/parquet_ut_base.cpp # be/test/formats/parquet/parquet_ut_base.h # be/test/fs/fs_posix_test.cpp # be/test/fs/fs_s3_test.cpp # be/test/fs/fs_test.cpp # be/test/http/stream_load_test.cpp # be/test/io/cache_input_stream_test.cpp # be/test/io/s3_input_stream_test.cpp # be/test/io/s3_output_stream_test.cpp # be/test/runtime/decimalv3_test.cpp # be/test/runtime/lake_tablets_channel_test.cpp # be/test/runtime/large_int_value_test.cpp # be/test/runtime/load_channel_test.cpp # be/test/runtime/local_tablets_channel_test.cpp # be/test/runtime/stream_load_pipe_test.cpp # be/test/runtime/type_descriptor_test.cpp # be/test/serde/column_array_serde_test.cpp # be/test/service/lake_service_test.cpp # be/test/storage/aggregate_iterator_test.cpp # be/test/storage/base_compaction_test.cpp # be/test/storage/chunk_helper_test.cpp # be/test/storage/column_predicate_test.cpp # be/test/storage/conjunctive_predicates_test.cpp # be/test/storage/delta_column_group_test.cpp # be/test/storage/lake/alter_tablet_meta_test.cpp # be/test/storage/lake/async_delta_writer_test.cpp # be/test/storage/lake/auto_increment_partial_update_test.cpp # be/test/storage/lake/compaction_policy_test.cpp # be/test/storage/lake/compaction_task_test.cpp # be/test/storage/lake/condition_update_test.cpp # be/test/storage/lake/delta_writer_test.cpp # be/test/storage/lake/lake_primary_key_consistency_test.cpp # be/test/storage/lake/lake_scan_node_test.cpp # be/test/storage/lake/meta_file_test.cpp # be/test/storage/lake/partial_update_test.cpp # be/test/storage/lake/primary_key_compaction_task_test.cpp # be/test/storage/lake/primary_key_publish_test.cpp # be/test/storage/lake/replication_txn_manager_test.cpp # be/test/storage/lake/rowset_test.cpp # be/test/storage/lake/schema_change_test.cpp # be/test/storage/lake/tablet_manager_test.cpp # be/test/storage/lake/tablet_writer_test.cpp # be/test/storage/lake/test_util.h # be/test/storage/meta_reader_test.cpp # be/test/storage/projection_iterator_test.cpp # be/test/storage/publish_version_manager_test.cpp # be/test/storage/publish_version_task_test.cpp # be/test/storage/roaring2range_test.cpp # be/test/storage/rows_mapper_test.cpp # be/test/storage/rowset/column_reader_writer_test.cpp # be/test/storage/rowset/default_value_column_iterator_test.cpp # be/test/storage/rowset/frame_of_reference_page_test.cpp # be/test/storage/rowset/rle_page_test.cpp # be/test/storage/rowset/segment_rewriter_test.cpp # be/test/storage/rowset/segment_test.cpp # be/test/storage/rowset_update_state_test.cpp # be/test/storage/tablet_index_test.cpp # be/test/storage/tablet_updates_test.cpp # be/test/storage/task/engine_storage_migration_task_test.cpp # be/test/storage/union_iterator_test.cpp # be/test/types/bitmap_value_test.cpp # be/test/util/arrow/starrocks_column_to_arrow_test.cpp # be/test/util/bit_stream_utils_test.cpp # be/test/util/brpc_stub_cache_test.cpp # be/test/util/mysql_row_buffer_test.cpp # be/test/util/threadpool_test.cpp # bin/common.sh # bin/show_be_version.sh # bin/start_backend.sh # bin/start_fe.sh # bin/stop_be.sh # build.sh # contrib/starrocks-python-client/README.md # contrib/starrocks-python-client/setup.py # contrib/starrocks-python-client/starrocks/__init__.py # contrib/starrocks-python-client/starrocks/dialect.py # contrib/starrocks-python-client/test/test_suite.py # docker/dockerfiles/dev-env/dev-env.Dockerfile # docker/dockerfiles/toolchains/toolchains-centos7.Dockerfile # docker/dockerfiles/toolchains/toolchains-ubuntu.Dockerfile # docs/docusaurus/i18n/zh/docusaurus-plugin-content-docs/current.json # docs/en/administration/management/FE_configuration.md # docs/en/administration/management/resource_management/query_queues.md # docs/en/administration/management/resource_management/resource_group.md # docs/en/data_source/catalog/iceberg_catalog.md # docs/en/developers/build-starrocks/build_starrocks_on_ubuntu.md # docs/en/ecosystem_release/flink_connector.md # docs/en/ecosystem_release/kafka_connector.md # docs/en/ecosystem_release/spark_connector.md # docs/en/integrations/BI_integrations/Metabase.md # docs/en/introduction/Architecture.md # docs/en/loading/Kafka-connector-starrocks.md # docs/en/quick_start/hudi.md # docs/en/release_notes/release-2.5.md # docs/en/release_notes/release-3.0.md # docs/en/release_notes/release-3.2.md # docs/en/sql-reference/System_limit.md # docs/en/sql-reference/System_variable.md # docs/en/sql-reference/sql-functions/aggregate-functions/any_value.md # docs/en/sql-reference/sql-functions/aggregate-functions/approx_count_distinct.md # docs/en/sql-reference/sql-functions/aggregate-functions/approx_top_k.md # docs/en/sql-reference/sql-functions/aggregate-functions/avg.md # docs/en/sql-reference/sql-functions/aggregate-functions/corr.md # docs/en/sql-reference/sql-functions/aggregate-functions/count.md # docs/en/sql-reference/sql-functions/aggregate-functions/count_if.md # docs/en/sql-reference/sql-functions/aggregate-functions/covar_pop.md # docs/en/sql-reference/sql-functions/aggregate-functions/covar_samp.md # docs/en/sql-reference/sql-functions/aggregate-functions/group_concat.md # docs/en/sql-reference/sql-functions/aggregate-functions/grouping.md # docs/en/sql-reference/sql-functions/aggregate-functions/grouping_id.md # docs/en/sql-reference/sql-functions/aggregate-functions/hll_raw_agg.md # docs/en/sql-reference/sql-functions/aggregate-functions/hll_union.md # docs/en/sql-reference/sql-functions/aggregate-functions/hll_union_agg.md # docs/en/sql-reference/sql-functions/aggregate-functions/max.md # docs/en/sql-reference/sql-functions/aggregate-functions/max_by.md # docs/en/sql-reference/sql-functions/aggregate-functions/min.md # docs/en/sql-reference/sql-functions/aggregate-functions/min_by.md # docs/en/sql-reference/sql-functions/aggregate-functions/multi_distinct_count.md # docs/en/sql-reference/sql-functions/aggregate-functions/multi_distinct_sum.md # docs/en/sql-reference/sql-functions/aggregate-functions/percentile_approx.md # docs/en/sql-reference/sql-functions/aggregate-functions/percentile_cont.md # docs/en/sql-reference/sql-functions/aggregate-functions/percentile_disc.md # docs/en/sql-reference/sql-functions/aggregate-functions/retention.md # docs/en/sql-reference/sql-functions/aggregate-functions/std.md # docs/en/sql-reference/sql-functions/aggregate-functions/stddev.md # docs/en/sql-reference/sql-functions/aggregate-functions/stddev_samp.md # docs/en/sql-reference/sql-functions/aggregate-functions/sum.md # docs/en/sql-reference/sql-functions/aggregate-functions/var_samp.md # docs/en/sql-reference/sql-functions/aggregate-functions/variance.md # docs/en/sql-reference/sql-functions/aggregate-functions/window_funnel.md # docs/en/sql-reference/sql-functions/array-functions/all_match.md # docs/en/sql-reference/sql-functions/array-functions/any_match.md # docs/en/sql-reference/sql-functions/array-functions/array_agg.md # docs/en/sql-reference/sql-functions/array-functions/array_append.md # docs/en/sql-reference/sql-functions/array-functions/array_avg.md # docs/en/sql-reference/sql-functions/array-functions/array_concat.md # docs/en/sql-reference/sql-functions/array-functions/array_contains.md # docs/en/sql-reference/sql-functions/array-functions/array_contains_all.md # docs/en/sql-reference/sql-functions/array-functions/array_contains_seq.md # docs/en/sql-reference/sql-functions/array-functions/array_cum_sum.md # docs/en/sql-reference/sql-functions/array-functions/array_difference.md # docs/en/sql-reference/sql-functions/array-functions/array_distinct.md # docs/en/sql-reference/sql-functions/array-functions/array_filter.md # docs/en/sql-reference/sql-functions/array-functions/array_generate.md # docs/en/sql-reference/sql-functions/array-functions/array_intersect.md # docs/en/sql-reference/sql-functions/array-functions/array_join.md # docs/en/sql-reference/sql-functions/array-functions/array_length.md # docs/en/sql-reference/sql-functions/array-functions/array_map.md # docs/en/sql-reference/sql-functions/array-functions/array_max.md # docs/en/sql-reference/sql-functions/array-functions/array_min.md # docs/en/sql-reference/sql-functions/array-functions/array_position.md # docs/en/sql-reference/sql-functions/array-functions/array_remove.md # docs/en/sql-reference/sql-functions/array-functions/array_slice.md # docs/en/sql-reference/sql-functions/array-functions/array_sort.md # docs/en/sql-reference/sql-functions/array-functions/array_sortby.md # docs/en/sql-reference/sql-functions/array-functions/array_sum.md # docs/en/sql-reference/sql-functions/array-functions/array_to_bitmap.md # docs/en/sql-reference/sql-functions/array-functions/array_unique_agg.md # docs/en/sql-reference/sql-functions/array-functions/arrays_overlap.md # docs/en/sql-reference/sql-functions/array-functions/cardinality.md # docs/en/sql-reference/sql-functions/array-functions/element_at.md # docs/en/sql-reference/sql-functions/array-functions/reverse.md # docs/en/sql-reference/sql-functions/array-functions/unnest.md # docs/en/sql-reference/sql-functions/binary-functions/from_binary.md # docs/en/sql-reference/sql-functions/binary-functions/to_binary.md # docs/en/sql-reference/sql-functions/bit-functions/bit_shift_left.md # docs/en/sql-reference/sql-functions/bit-functions/bit_shift_right.md # docs/en/sql-reference/sql-functions/bit-functions/bit_shift_right_logical.md # docs/en/sql-reference/sql-functions/bit-functions/bitand.md # docs/en/sql-reference/sql-functions/bit-functions/bitnot.md # docs/en/sql-reference/sql-functions/bit-functions/bitor.md # docs/en/sql-reference/sql-functions/bit-functions/bitxor.md # docs/en/sql-reference/sql-functions/bitmap-functions/base64_to_bitmap.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_agg.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_and.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_andnot.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_contains.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_count.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_empty.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_from_binary.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_from_string.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_has_any.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_hash.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_intersect.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_max.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_min.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_or.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_remove.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_subset_in_range.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_subset_limit.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_to_array.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_to_base64.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_to_binary.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_to_string.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_union.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_union_count.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_union_int.md # docs/en/sql-reference/sql-functions/bitmap-functions/bitmap_xor.md # docs/en/sql-reference/sql-functions/bitmap-functions/intersect_count.md # docs/en/sql-reference/sql-functions/bitmap-functions/sub_bitmap.md # docs/en/sql-reference/sql-functions/bitmap-functions/subdivide_bitmap.md # docs/en/sql-reference/sql-functions/bitmap-functions/to_bitmap.md # docs/en/sql-reference/sql-functions/bitmap-functions/unnest_bitmap.md # docs/en/sql-reference/sql-functions/cast.md # docs/en/sql-reference/sql-functions/condition-functions/case_when.md # docs/en/sql-reference/sql-functions/condition-functions/coalesce.md # docs/en/sql-reference/sql-functions/condition-functions/if.md # docs/en/sql-reference/sql-functions/condition-functions/ifnull.md # docs/en/sql-reference/sql-functions/condition-functions/nullif.md # docs/en/sql-reference/sql-functions/crytographic-functions/aes_decrypt.md # docs/en/sql-reference/sql-functions/crytographic-functions/aes_encrypt.md # docs/en/sql-reference/sql-functions/crytographic-functions/base64_decode_binary.md # docs/en/sql-reference/sql-functions/crytographic-functions/base64_decode_string.md # docs/en/sql-reference/sql-functions/crytographic-functions/from_base64.md # docs/en/sql-reference/sql-functions/crytographic-functions/sm3.md # docs/en/sql-reference/sql-functions/crytographic-functions/to_base64.md # docs/en/sql-reference/sql-functions/date-time-functions/add_months.md # docs/en/sql-reference/sql-functions/date-time-functions/convert_tz.md # docs/en/sql-reference/sql-functions/date-time-functions/curdate.md # docs/en/sql-reference/sql-functions/date-time-functions/current_timestamp.md # docs/en/sql-reference/sql-functions/date-time-functions/curtime.md # docs/en/sql-reference/sql-functions/date-time-functions/date.md # docs/en/sql-reference/sql-functions/date-time-functions/date_add.md # docs/en/sql-reference/sql-functions/date-time-functions/date_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/date_format.md # docs/en/sql-reference/sql-functions/date-time-functions/date_slice.md # docs/en/sql-reference/sql-functions/date-time-functions/date_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/date_trunc.md # docs/en/sql-reference/sql-functions/date-time-functions/datediff.md # docs/en/sql-reference/sql-functions/date-time-functions/day.md # docs/en/sql-reference/sql-functions/date-time-functions/day_of_week_iso.md # docs/en/sql-reference/sql-functions/date-time-functions/dayname.md # docs/en/sql-reference/sql-functions/date-time-functions/dayofmonth.md # docs/en/sql-reference/sql-functions/date-time-functions/dayofweek.md # docs/en/sql-reference/sql-functions/date-time-functions/dayofyear.md # docs/en/sql-reference/sql-functions/date-time-functions/days_add.md # docs/en/sql-reference/sql-functions/date-time-functions/days_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/days_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/from_days.md # docs/en/sql-reference/sql-functions/date-time-functions/from_unixtime.md # docs/en/sql-reference/sql-functions/date-time-functions/hour.md # docs/en/sql-reference/sql-functions/date-time-functions/hours_add.md # docs/en/sql-reference/sql-functions/date-time-functions/hours_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/hours_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/jodatime_format.md # docs/en/sql-reference/sql-functions/date-time-functions/last_day.md # docs/en/sql-reference/sql-functions/date-time-functions/makedate.md # docs/en/sql-reference/sql-functions/date-time-functions/microseconds_add.md # docs/en/sql-reference/sql-functions/date-time-functions/microseconds_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/milliseconds_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/minute.md # docs/en/sql-reference/sql-functions/date-time-functions/minutes_add.md # docs/en/sql-reference/sql-functions/date-time-functions/minutes_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/minutes_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/month.md # docs/en/sql-reference/sql-functions/date-time-functions/monthname.md # docs/en/sql-reference/sql-functions/date-time-functions/months_add.md # docs/en/sql-reference/sql-functions/date-time-functions/months_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/months_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/next_day.md # docs/en/sql-reference/sql-functions/date-time-functions/now.md # docs/en/sql-reference/sql-functions/date-time-functions/previous_day.md # docs/en/sql-reference/sql-functions/date-time-functions/quarter.md # docs/en/sql-reference/sql-functions/date-time-functions/second.md # docs/en/sql-reference/sql-functions/date-time-functions/seconds_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/seconds_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/str2date.md # docs/en/sql-reference/sql-functions/date-time-functions/str_to_date.md # docs/en/sql-reference/sql-functions/date-time-functions/str_to_jodatime.md # docs/en/sql-reference/sql-functions/date-time-functions/time_slice.md # docs/en/sql-reference/sql-functions/date-time-functions/time_to_sec.md # docs/en/sql-reference/sql-functions/date-time-functions/timediff.md # docs/en/sql-reference/sql-functions/date-time-functions/timestamp.md # docs/en/sql-reference/sql-functions/date-time-functions/timestampadd.md # docs/en/sql-reference/sql-functions/date-time-functions/timestampdiff.md # docs/en/sql-reference/sql-functions/date-time-functions/to_date.md # docs/en/sql-reference/sql-functions/date-time-functions/to_days.md # docs/en/sql-reference/sql-functions/date-time-functions/to_iso8601.md # docs/en/sql-reference/sql-functions/date-time-functions/to_tera_date.md # docs/en/sql-reference/sql-functions/date-time-functions/to_tera_timestamp.md # docs/en/sql-reference/sql-functions/date-time-functions/unix_timestamp.md # docs/en/sql-reference/sql-functions/date-time-functions/utc_time.md # docs/en/sql-reference/sql-functions/date-time-functions/utc_timestamp.md # docs/en/sql-reference/sql-functions/date-time-functions/week.md # docs/en/sql-reference/sql-functions/date-time-functions/week_iso.md # docs/en/sql-reference/sql-functions/date-time-functions/weekofyear.md # docs/en/sql-reference/sql-functions/date-time-functions/weeks_add.md # docs/en/sql-reference/sql-functions/date-time-functions/weeks_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/weeks_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/year.md # docs/en/sql-reference/sql-functions/date-time-functions/years_diff.md # docs/en/sql-reference/sql-functions/date-time-functions/years_sub.md # docs/en/sql-reference/sql-functions/date-time-functions/yearweek.md # docs/en/sql-reference/sql-functions/dict-functions/dict_mapping.md # docs/en/sql-reference/sql-functions/hash-functions/murmur_hash3_32.md # docs/en/sql-reference/sql-functions/hash-functions/xx_hash3_128.md # docs/en/sql-reference/sql-functions/hash-functions/xx_hash3_64.md # docs/en/sql-reference/sql-functions/json-functions/json-constructor-functions/json_array.md # docs/en/sql-reference/sql-functions/json-functions/json-constructor-functions/json_object.md # docs/en/sql-reference/sql-functions/json-functions/json-constructor-functions/parse_json.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/arrow-function.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/cast.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_bool.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_double.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_int.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_string.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_each.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_exists.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_keys.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_length.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_query.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_string.md # docs/en/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/to_json.md # docs/en/sql-reference/sql-functions/like-predicate-functions/like.md # docs/en/sql-reference/sql-functions/like-predicate-functions/regexp.md # docs/en/sql-reference/sql-functions/like-predicate-functions/regexp_extract.md # docs/en/sql-reference/sql-functions/like-predicate-functions/regexp_extract_all.md # docs/en/sql-reference/sql-functions/like-predicate-functions/regexp_replace.md # docs/en/sql-reference/sql-functions/map-functions/cardinality.md # docs/en/sql-reference/sql-functions/map-functions/distinct_map_keys.md # docs/en/sql-reference/sql-functions/map-functions/element_at.md # docs/en/sql-reference/sql-functions/map-functions/map_apply.md # docs/en/sql-reference/sql-functions/map-functions/map_concat.md # docs/en/sql-reference/sql-functions/map-functions/map_filter.md # docs/en/sql-reference/sql-functions/map-functions/map_from_arrays.md # docs/en/sql-reference/sql-functions/map-functions/map_keys.md # docs/en/sql-reference/sql-functions/map-functions/map_size.md # docs/en/sql-reference/sql-functions/map-functions/map_values.md # docs/en/sql-reference/sql-functions/map-functions/transform_keys.md # docs/en/sql-reference/sql-functions/map-functions/transform_values.md # docs/en/sql-reference/sql-functions/math-functions/abs.md # docs/en/sql-reference/sql-functions/math-functions/acos.md # docs/en/sql-reference/sql-functions/math-functions/asin.md # docs/en/sql-reference/sql-functions/math-functions/atan.md # docs/en/sql-reference/sql-functions/math-functions/atan2.md # docs/en/sql-reference/sql-functions/math-functions/bin.md # docs/en/sql-reference/sql-functions/math-functions/cbrt.md # docs/en/sql-reference/sql-functions/math-functions/ceil.md # docs/en/sql-reference/sql-functions/math-functions/ceiling.md # docs/en/sql-reference/sql-functions/math-functions/conv.md # docs/en/sql-reference/sql-functions/math-functions/cos.md # docs/en/sql-reference/sql-functions/math-functions/cos_similarity.md # docs/en/sql-reference/sql-functions/math-functions/cos_similarity_norm.md # docs/en/sql-reference/sql-functions/math-functions/cosh.md # docs/en/sql-reference/sql-functions/math-functions/cot.md # docs/en/sql-reference/sql-functions/math-functions/degrees.md # docs/en/sql-reference/sql-functions/math-functions/divide.md # docs/en/sql-reference/sql-functions/math-functions/e.md # docs/en/sql-reference/sql-functions/math-functions/exp.md # docs/en/sql-reference/sql-functions/math-functions/floor.md # docs/en/sql-reference/sql-functions/math-functions/fmod.md # docs/en/sql-reference/sql-functions/math-functions/greatest.md # docs/en/sql-reference/sql-functions/math-functions/least.md # docs/en/sql-reference/sql-functions/math-functions/ln.md # docs/en/sql-reference/sql-functions/math-functions/log.md # docs/en/sql-reference/sql-functions/math-functions/log10.md # docs/en/sql-reference/sql-functions/math-functions/log2.md # docs/en/sql-reference/sql-functions/math-functions/mod.md # docs/en/sql-reference/sql-functions/math-functions/multiply.md # docs/en/sql-reference/sql-functions/math-functions/negative.md # docs/en/sql-reference/sql-functions/math-functions/pi.md # docs/en/sql-reference/sql-functions/math-functions/pmod.md # docs/en/sql-reference/sql-functions/math-functions/positive.md # docs/en/sql-reference/sql-functions/math-functions/pow.md # docs/en/sql-reference/sql-functions/math-functions/radians.md # docs/en/sql-reference/sql-functions/math-functions/rand.md # docs/en/sql-reference/sql-functions/math-functions/round.md # docs/en/sql-reference/sql-functions/math-functions/sign.md # docs/en/sql-reference/sql-functions/math-functions/sin.md # docs/en/sql-reference/sql-functions/math-functions/sinh.md # docs/en/sql-reference/sql-functions/math-functions/sqrt.md # docs/en/sql-reference/sql-functions/math-functions/square.md # docs/en/sql-reference/sql-functions/math-functions/tan.md # docs/en/sql-reference/sql-functions/math-functions/tanh.md # docs/en/sql-reference/sql-functions/math-functions/truncate.md # docs/en/sql-reference/sql-functions/percentile-functions/percentile_approx_raw.md # docs/en/sql-reference/sql-functions/percentile-functions/percentile_empty.md # docs/en/sql-reference/sql-functions/percentile-functions/percentile_hash.md # docs/en/sql-reference/sql-functions/percentile-functions/percentile_union.md # docs/en/sql-reference/sql-functions/scalar-functions/hll_cardinality.md # docs/en/sql-reference/sql-functions/scalar-functions/hll_empty.md # docs/en/sql-reference/sql-functions/scalar-functions/hll_hash.md # docs/en/sql-reference/sql-functions/spatial-functions/st_astext.md # docs/en/sql-reference/sql-functions/spatial-functions/st_circle.md # docs/en/sql-reference/sql-functions/spatial-functions/st_contains.md # docs/en/sql-reference/sql-functions/spatial-functions/st_distance_sphere.md # docs/en/sql-reference/sql-functions/spatial-functions/st_geometryfromtext.md # docs/en/sql-reference/sql-functions/spatial-functions/st_linefromtext.md # docs/en/sql-reference/sql-functions/spatial-functions/st_point.md # docs/en/sql-reference/sql-functions/spatial-functions/st_polygon.md # docs/en/sql-reference/sql-functions/spatial-functions/st_x.md # docs/en/sql-reference/sql-functions/spatial-functions/st_y.md # docs/en/sql-reference/sql-functions/string-functions/append_trailing_char_if_absent.md # docs/en/sql-reference/sql-functions/string-functions/ascii.md # docs/en/sql-reference/sql-functions/string-functions/char.md # docs/en/sql-reference/sql-functions/string-functions/char_length.md # docs/en/sql-reference/sql-functions/string-functions/character_length.md # docs/en/sql-reference/sql-functions/string-functions/concat.md # docs/en/sql-reference/sql-functions/string-functions/concat_ws.md # docs/en/sql-reference/sql-functions/string-functions/crc32.md # docs/en/sql-reference/sql-functions/string-functions/ends_with.md # docs/en/sql-reference/sql-functions/string-functions/find_in_set.md # docs/en/sql-reference/sql-functions/string-functions/group_concat.md # docs/en/sql-reference/sql-functions/string-functions/hex.md # docs/en/sql-reference/sql-functions/string-functions/hex_decode_binary.md # docs/en/sql-reference/sql-functions/string-functions/hex_decode_string.md # docs/en/sql-reference/sql-functions/string-functions/instr.md # docs/en/sql-reference/sql-functions/string-functions/lcase.md # docs/en/sql-reference/sql-functions/string-functions/left.md # docs/en/sql-reference/sql-functions/string-functions/length.md # docs/en/sql-reference/sql-functions/string-functions/locate.md # docs/en/sql-reference/sql-functions/string-functions/lower.md # docs/en/sql-reference/sql-functions/string-functions/lpad.md # docs/en/sql-reference/sql-functions/string-functions/ltrim.md # docs/en/sql-reference/sql-functions/string-functions/money_format.md # docs/en/sql-reference/sql-functions/string-functions/ngram_search.md # docs/en/sql-reference/sql-functions/string-functions/null_or_empty.md # docs/en/sql-reference/sql-functions/string-functions/parse_url.md # docs/en/sql-reference/sql-functions/string-functions/repeat.md # docs/en/sql-reference/sql-functions/string-functions/replace.md # docs/en/sql-reference/sql-functions/string-functions/reverse.md # docs/en/sql-reference/sql-functions/string-functions/right.md # docs/en/sql-reference/sql-functions/string-functions/rpad.md # docs/en/sql-reference/sql-functions/string-functions/rtrim.md # docs/en/sql-reference/sql-functions/string-functions/space.md # docs/en/sql-reference/sql-functions/string-functions/split.md # docs/en/sql-reference/sql-functions/string-functions/split_part.md # docs/en/sql-reference/sql-functions/string-functions/starts_with.md # docs/en/sql-reference/sql-functions/string-functions/str_to_map.md # docs/en/sql-reference/sql-functions/string-functions/strcmp.md # docs/en/sql-reference/sql-functions/string-functions/strleft.md # docs/en/sql-reference/sql-functions/string-functions/strright.md # docs/en/sql-reference/sql-functions/string-functions/substring.md # docs/en/sql-reference/sql-functions/string-functions/substring_index.md # docs/en/sql-reference/sql-functions/string-functions/translate.md # docs/en/sql-reference/sql-functions/string-functions/trim.md # docs/en/sql-reference/sql-functions/string-functions/ucase.md # docs/en/sql-reference/sql-functions/string-functions/unhex.md # docs/en/sql-reference/sql-functions/string-functions/upper.md # docs/en/sql-reference/sql-functions/string-functions/url_decode.md # docs/en/sql-reference/sql-functions/string-functions/url_encode.md # docs/en/sql-reference/sql-functions/string-functions/url_extract_host.md # docs/en/sql-reference/sql-functions/string-functions/url_extract_parameter.md # docs/en/sql-reference/sql-functions/struct-functions/named_struct.md # docs/en/sql-reference/sql-functions/struct-functions/row.md # docs/en/sql-reference/sql-functions/table-functions/files.md # docs/en/sql-reference/sql-functions/table-functions/generate_series.md # docs/en/sql-reference/sql-functions/utility-functions/catalog.md # docs/en/sql-reference/sql-functions/utility-functions/current_role.md # docs/en/sql-reference/sql-functions/utility-functions/current_version.md # docs/en/sql-reference/sql-functions/utility-functions/database.md # docs/en/sql-reference/sql-functions/utility-functions/get_query_profile.md # docs/en/sql-reference/sql-functions/utility-functions/host_name.md # docs/en/sql-reference/sql-functions/utility-functions/is_role_in_session.md # docs/en/sql-reference/sql-functions/utility-functions/isnotnull.md # docs/en/sql-reference/sql-functions/utility-functions/isnull.md # docs/en/sql-reference/sql-functions/utility-functions/last_query_id.md # docs/en/sql-reference/sql-functions/utility-functions/sleep.md # docs/en/sql-reference/sql-functions/utility-functions/uuid.md # docs/en/sql-reference/sql-functions/utility-functions/uuid_numeric.md # docs/en/sql-reference/sql-functions/utility-functions/version.md # docs/en/sql-reference/sql-statements/Database/SHOW_DATA.md # docs/en/sql-reference/sql-statements/Function/CREATE_FUNCTION.md # docs/en/sql-reference/sql-statements/table_bucket_part_index/ALTER_TABLE.md # docs/en/sql-reference/template_for_config.md # docs/en/table_design/data_distribution/expression_partitioning.md # docs/en/table_design/indexes/Bitmap_index.md # docs/zh/administration/management/FE_configuration.md # docs/zh/administration/management/resource_management/query_queues.md # docs/zh/data_source/catalog/iceberg_catalog.md # docs/zh/deployment/environment_configurations.md # docs/zh/developers/build-starrocks/build_starrocks_on_ubuntu.md # docs/zh/ecosystem_release/flink_connector.md # docs/zh/ecosystem_release/kafka_connector.md # docs/zh/ecosystem_release/spark_connector.md # docs/zh/introduction/what_is_starrocks.md # docs/zh/loading/Kafka-connector-starrocks.md # docs/zh/quick_start/helm.md # docs/zh/release_notes/release-2.5.md # docs/zh/release_notes/release-3.0.md # docs/zh/release_notes/release-3.2.md # docs/zh/sql-reference/System_variable.md # docs/zh/sql-reference/sql-functions/aggregate-functions/any_value.md # docs/zh/sql-reference/sql-functions/aggregate-functions/approx_count_distinct.md # docs/zh/sql-reference/sql-functions/aggregate-functions/approx_top_k.md # docs/zh/sql-reference/sql-functions/aggregate-functions/avg.md # docs/zh/sql-reference/sql-functions/aggregate-functions/corr.md # docs/zh/sql-reference/sql-functions/aggregate-functions/count.md # docs/zh/sql-reference/sql-functions/aggregate-functions/count_if.md # docs/zh/sql-reference/sql-functions/aggregate-functions/covar_pop.md # docs/zh/sql-reference/sql-functions/aggregate-functions/covar_samp.md # docs/zh/sql-reference/sql-functions/aggregate-functions/group_concat.md # docs/zh/sql-reference/sql-functions/aggregate-functions/grouping.md # docs/zh/sql-reference/sql-functions/aggregate-functions/grouping_id.md # docs/zh/sql-reference/sql-functions/aggregate-functions/hll_raw_agg.md # docs/zh/sql-reference/sql-functions/aggregate-functions/hll_union.md # docs/zh/sql-reference/sql-functions/aggregate-functions/hll_union_agg.md # docs/zh/sql-reference/sql-functions/aggregate-functions/max.md # docs/zh/sql-reference/sql-functions/aggregate-functions/max_by.md # docs/zh/sql-reference/sql-functions/aggregate-functions/min.md # docs/zh/sql-reference/sql-functions/aggregate-functions/min_by.md # docs/zh/sql-reference/sql-functions/aggregate-functions/multi_distinct_count.md # docs/zh/sql-reference/sql-functions/aggregate-functions/multi_distinct_sum.md # docs/zh/sql-reference/sql-functions/aggregate-functions/percentile_approx.md # docs/zh/sql-reference/sql-functions/aggregate-functions/percentile_cont.md # docs/zh/sql-reference/sql-functions/aggregate-functions/percentile_disc.md # docs/zh/sql-reference/sql-functions/aggregate-functions/retention.md # docs/zh/sql-reference/sql-functions/aggregate-functions/std.md # docs/zh/sql-reference/sql-functions/aggregate-functions/stddev.md # docs/zh/sql-reference/sql-functions/aggregate-functions/stddev_samp.md # docs/zh/sql-reference/sql-functions/aggregate-functions/sum.md # docs/zh/sql-reference/sql-functions/aggregate-functions/var_samp.md # docs/zh/sql-reference/sql-functions/aggregate-functions/variance.md # docs/zh/sql-reference/sql-functions/aggregate-functions/window_funnel.md # docs/zh/sql-reference/sql-functions/array-functions/all_match.md # docs/zh/sql-reference/sql-functions/array-functions/any_match.md # docs/zh/sql-reference/sql-functions/array-functions/array_agg.md # docs/zh/sql-reference/sql-functions/array-functions/array_append.md # docs/zh/sql-reference/sql-functions/array-functions/array_avg.md # docs/zh/sql-reference/sql-functions/array-functions/array_concat.md # docs/zh/sql-reference/sql-functions/array-functions/array_contains.md # docs/zh/sql-reference/sql-functions/array-functions/array_contains_all.md # docs/zh/sql-reference/sql-functions/array-functions/array_cum_sum.md # docs/zh/sql-reference/sql-functions/array-functions/array_difference.md # docs/zh/sql-reference/sql-functions/array-functions/array_distinct.md # docs/zh/sql-reference/sql-functions/array-functions/array_filter.md # docs/zh/sql-reference/sql-functions/array-functions/array_generate.md # docs/zh/sql-reference/sql-functions/array-functions/array_intersect.md # docs/zh/sql-reference/sql-functions/array-functions/array_join.md # docs/zh/sql-reference/sql-functions/array-functions/array_length.md # docs/zh/sql-reference/sql-functions/array-functions/array_map.md # docs/zh/sql-reference/sql-functions/array-functions/array_max.md # docs/zh/sql-reference/sql-functions/array-functions/array_min.md # docs/zh/sql-reference/sql-functions/array-functions/array_position.md # docs/zh/sql-reference/sql-functions/array-functions/array_remove.md # docs/zh/sql-reference/sql-functions/array-functions/array_slice.md # docs/zh/sql-reference/sql-functions/array-functions/array_sort.md # docs/zh/sql-reference/sql-functions/array-functions/array_sortby.md # docs/zh/sql-reference/sql-functions/array-functions/array_sum.md # docs/zh/sql-reference/sql-functions/array-functions/array_to_bitmap.md # docs/zh/sql-reference/sql-functions/array-functions/array_unique_agg.md # docs/zh/sql-reference/sql-functions/array-functions/arrays_overlap.md # docs/zh/sql-reference/sql-functions/array-functions/cardinality.md # docs/zh/sql-reference/sql-functions/array-functions/element_at.md # docs/zh/sql-reference/sql-functions/array-functions/reverse.md # docs/zh/sql-reference/sql-functions/array-functions/unnest.md # docs/zh/sql-reference/sql-functions/binary-functions/from_binary.md # docs/zh/sql-reference/sql-functions/binary-functions/to_binary.md # docs/zh/sql-reference/sql-functions/bit-functions/bit_shift_left.md # docs/zh/sql-reference/sql-functions/bit-functions/bit_shift_right.md # docs/zh/sql-reference/sql-functions/bit-functions/bit_shift_right_logical.md # docs/zh/sql-reference/sql-functions/bit-functions/bitand.md # docs/zh/sql-reference/sql-functions/bit-functions/bitnot.md # docs/zh/sql-reference/sql-functions/bit-functions/bitor.md # docs/zh/sql-reference/sql-functions/bit-functions/bitxor.md # docs/zh/sql-reference/sql-functions/bitmap-functions/base64_to_bitmap.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_agg.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_and.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_andnot.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_contains.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_count.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_empty.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_from_binary.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_from_string.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_has_any.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_hash.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_intersect.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_max.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_min.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_or.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_remove.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_subset_in_range.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_subset_limit.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_to_array.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_to_base64.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_to_binary.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_to_string.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_union.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_union_count.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_union_int.md # docs/zh/sql-reference/sql-functions/bitmap-functions/bitmap_xor.md # docs/zh/sql-reference/sql-functions/bitmap-functions/intersect_count.md # docs/zh/sql-reference/sql-functions/bitmap-functions/sub_bitmap.md # docs/zh/sql-reference/sql-functions/bitmap-functions/subdivide_bitmap.md # docs/zh/sql-reference/sql-functions/bitmap-functions/to_bitmap.md # docs/zh/sql-reference/sql-functions/bitmap-functions/unnest_bitmap.md # docs/zh/sql-reference/sql-functions/cast.md # docs/zh/sql-reference/sql-functions/condition-functions/case_when.md # docs/zh/sql-reference/sql-functions/condition-functions/coalesce.md # docs/zh/sql-reference/sql-functions/condition-functions/if.md # docs/zh/sql-reference/sql-functions/condition-functions/ifnull.md # docs/zh/sql-reference/sql-functions/condition-functions/nullif.md # docs/zh/sql-reference/sql-functions/crytographic-functions/aes_decrypt.md # docs/zh/sql-reference/sql-functions/crytographic-functions/aes_encrypt.md # docs/zh/sql-reference/sql-functions/crytographic-functions/base64_decode_binary.md # docs/zh/sql-reference/sql-functions/crytographic-functions/base64_decode_string.md # docs/zh/sql-reference/sql-functions/crytographic-functions/from_base64.md # docs/zh/sql-reference/sql-functions/crytographic-functions/md5.md # docs/zh/sql-reference/sql-functions/crytographic-functions/md5sum.md # docs/zh/sql-reference/sql-functions/crytographic-functions/md5sum_numeric.md # docs/zh/sql-reference/sql-functions/crytographic-functions/sha2.md # docs/zh/sql-reference/sql-functions/crytographic-functions/sm3.md # docs/zh/sql-reference/sql-functions/crytographic-functions/to_base64.md # docs/zh/sql-reference/sql-functions/date-time-functions/add_months.md # docs/zh/sql-reference/sql-functions/date-time-functions/convert_tz.md # docs/zh/sql-reference/sql-functions/date-time-functions/curdate.md # docs/zh/sql-reference/sql-functions/date-time-functions/current_timestamp.md # docs/zh/sql-reference/sql-functions/date-time-functions/curtime.md # docs/zh/sql-reference/sql-functions/date-time-functions/date.md # docs/zh/sql-reference/sql-functions/date-time-functions/date_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/date_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/date_format.md # docs/zh/sql-reference/sql-functions/date-time-functions/date_slice.md # docs/zh/sql-reference/sql-functions/date-time-functions/date_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/date_trunc.md # docs/zh/sql-reference/sql-functions/date-time-functions/datediff.md # docs/zh/sql-reference/sql-functions/date-time-functions/day.md # docs/zh/sql-reference/sql-functions/date-time-functions/day_of_week_iso.md # docs/zh/sql-reference/sql-functions/date-time-functions/dayname.md # docs/zh/sql-reference/sql-functions/date-time-functions/dayofmonth.md # docs/zh/sql-reference/sql-functions/date-time-functions/dayofweek.md # docs/zh/sql-reference/sql-functions/date-time-functions/dayofyear.md # docs/zh/sql-reference/sql-functions/date-time-functions/days_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/days_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/days_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/from_days.md # docs/zh/sql-reference/sql-functions/date-time-functions/from_unixtime.md # docs/zh/sql-reference/sql-functions/date-time-functions/hour.md # docs/zh/sql-reference/sql-functions/date-time-functions/hours_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/hours_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/hours_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/jodatime_format.md # docs/zh/sql-reference/sql-functions/date-time-functions/last_day.md # docs/zh/sql-reference/sql-functions/date-time-functions/makedate.md # docs/zh/sql-reference/sql-functions/date-time-functions/microseconds_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/microseconds_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/milliseconds_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/minute.md # docs/zh/sql-reference/sql-functions/date-time-functions/minutes_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/minutes_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/minutes_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/month.md # docs/zh/sql-reference/sql-functions/date-time-functions/monthname.md # docs/zh/sql-reference/sql-functions/date-time-functions/months_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/months_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/months_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/next_day.md # docs/zh/sql-reference/sql-functions/date-time-functions/now.md # docs/zh/sql-reference/sql-functions/date-time-functions/previous_day.md # docs/zh/sql-reference/sql-functions/date-time-functions/quarter.md # docs/zh/sql-reference/sql-functions/date-time-functions/second.md # docs/zh/sql-reference/sql-functions/date-time-functions/seconds_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/seconds_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/seconds_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/str2date.md # docs/zh/sql-reference/sql-functions/date-time-functions/str_to_date.md # docs/zh/sql-reference/sql-functions/date-time-functions/str_to_jodatime.md # docs/zh/sql-reference/sql-functions/date-time-functions/time_slice.md # docs/zh/sql-reference/sql-functions/date-time-functions/time_to_sec.md # docs/zh/sql-reference/sql-functions/date-time-functions/timediff.md # docs/zh/sql-reference/sql-functions/date-time-functions/timestamp.md # docs/zh/sql-reference/sql-functions/date-time-functions/timestampadd.md # docs/zh/sql-reference/sql-functions/date-time-functions/timestampdiff.md # docs/zh/sql-reference/sql-functions/date-time-functions/to_date.md # docs/zh/sql-reference/sql-functions/date-time-functions/to_days.md # docs/zh/sql-reference/sql-functions/date-time-functions/to_iso8601.md # docs/zh/sql-reference/sql-functions/date-time-functions/to_tera_date.md # docs/zh/sql-reference/sql-functions/date-time-functions/to_tera_timestamp.md # docs/zh/sql-reference/sql-functions/date-time-functions/unix_timestamp.md # docs/zh/sql-reference/sql-functions/date-time-functions/utc_timestamp.md # docs/zh/sql-reference/sql-functions/date-time-functions/week.md # docs/zh/sql-reference/sql-functions/date-time-functions/week_iso.md # docs/zh/sql-reference/sql-functions/date-time-functions/weekofyear.md # docs/zh/sql-reference/sql-functions/date-time-functions/weeks_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/weeks_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/weeks_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/year.md # docs/zh/sql-reference/sql-functions/date-time-functions/years_add.md # docs/zh/sql-reference/sql-functions/date-time-functions/years_diff.md # docs/zh/sql-reference/sql-functions/date-time-functions/years_sub.md # docs/zh/sql-reference/sql-functions/date-time-functions/yearweek.md # docs/zh/sql-reference/sql-functions/dict-functions/dict_mapping.md # docs/zh/sql-reference/sql-functions/hash-functions/murmur_hash3_32.md # docs/zh/sql-reference/sql-functions/hash-functions/xx_hash3_128.md # docs/zh/sql-reference/sql-functions/hash-functions/xx_hash3_64.md # docs/zh/sql-reference/sql-functions/json-functions/json-constructor-functions/json_array.md # docs/zh/sql-reference/sql-functions/json-functions/json-constructor-functions/json_object.md # docs/zh/sql-reference/sql-functions/json-functions/json-constructor-functions/parse_json.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/arrow-function.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/cast.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_bool.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_double.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_int.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/get_json_string.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_each.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_exists.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_keys.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_length.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/json_string.md # docs/zh/sql-reference/sql-functions/json-functions/json-query-and-processing-functions/to_json.md # docs/zh/sql-reference/sql-functions/like-predicate-functions/like.md # docs/zh/sql-reference/sql-functions/like-predicate-functions/regexp.md # docs/zh/sql-reference/sql-functions/like-predicate-functions/regexp_extract.md # docs/zh/sql-reference/sql-functions/like-predicate-functions/regexp_extract_all.md # docs/zh/sql-reference/sql-functions/like-predicate-functions/regexp_replace.md # docs/zh/sql-reference/sql-functions/map-functions/cardinality.md # docs/zh/sql-reference/sql-functions/map-functions/distinct_map_keys.md # docs/zh/sql-reference/sql-functions/map-functions/element_at.md # docs/zh/sql-reference/sql-functions/map-functions/map_apply.md # docs/zh/sql-reference/sql-functions/map-functions/map_concat.md # docs/zh/sql-reference/sql-functions/map-functions/map_filter.md # docs/zh/sql-reference/sql-functions/map-functions/map_from_arrays.md # docs/zh/sql-reference/sql-functions/map-functions/map_keys.md # docs/zh/sql-reference/sql-functions/map-functions/map_size.md # docs/zh/sql-reference/sql-functions/map-functions/map_values.md # docs/zh/sql-reference/sql-functions/map-functions/transform_keys.md # docs/zh/sql-reference/sql-functions/map-functions/transform_values.md # docs/zh/sql-reference/sql-functions/math-functions/abs.md # docs/zh/sql-reference/sql-functions/math-functions/acos.md # docs/zh/sql-reference/sql-functions/math-functions/asin.md # docs/zh/sql-reference/sql-functions/math-functions/atan.md # docs/zh/sql-reference/sql-functions/math-functions/atan2.md # docs/zh/sql-reference/sql-functions/math-functions/bin.md # docs/zh/sql-reference/sql-functions/math-functions/cbrt.md # docs/zh/sql-reference/sql-functions/math-functions/ceil.md # docs/zh/sql-reference/sql-functions/math-functions/ceiling.md # docs/zh/sql-reference/sql-functions/math-functions/conv.md # docs/zh/sql-reference/sql-functions/math-functions/cos.md # docs/zh/sql-reference/sql-functions/math-functions/cos_similarity.md # docs/zh/sql-reference/sql-functions/math-functions/cos_similarity_norm.md # docs/zh/sql-reference/sql-functions/math-functions/cosh.md # docs/zh/sql-reference/sql-functions/math-functions/cot.md # docs/zh/sql-reference/sql-functions/math-functions/degrees.md # docs/zh/sql-reference/sql-functions/math-functions/divide.md # docs/zh/sql-reference/sql-functions/math-functions/e.md # docs/zh/sql-reference/sql-functions/math-functions/exp.md # docs/zh/sql-reference/sql-functions/math-functions/floor.md # docs/zh/sql-reference/sql-functions/math-functions/fmod.md # docs/zh/sql-reference/sql-functions/math-functions/greatest.md # docs/zh/sql-reference/sql-functions/math-functions/least.md # docs/zh/sql-reference/sql-functions/math-functions/ln.md # docs/zh/sql-reference/sql-functions/math-functions/log.md # docs/zh/sql-reference/sql-functions/math-functions/log10.md # docs/zh/sql-reference/sql-functions/math-functions/log2.md # docs/zh/sql-reference/sql-functions/math-functions/mod.md # docs/zh/sql-reference/sql-functions/math-functions/multiply.md # docs/zh/sql-reference/sql-functions/math-functions/negative.md # docs/zh/sql-reference/sql-functions/math-functions/pi.md # docs/zh/sql-reference/sql-functions/math-functions/pmod.md # docs/zh/sql-reference/sql-functions/math-functions/positive.md # docs/zh/sql-reference/sql-functions/math-functions/pow.md # docs/zh/sql-reference/sql-functions/math-functions/radians.md # docs/zh/sql-reference/sql-functions/math-functions/rand.md # docs/zh/sql-reference/sql-functions/math-functions/round.md # docs/zh/sql-reference/sql-functions/math-functions/sign.md # docs/zh/sql-reference/sql-functions/math-functions/sin.md # docs/zh/sql-reference/sql-functions/math-functions/sinh.md # docs/zh/sql-reference/sql-functions/math-functions/sqrt.md # docs/zh/sql-reference/sql-functions/math-functions/square.md # docs/zh/sql-reference/sql-functions/math-functions/tan.md # docs/zh/sql-reference/sql-functions/math-functions/tanh.md # docs/zh/sql-reference/sql-functions/math-functions/truncate.md # docs/zh/sql-reference/sql-functions/percentile-functions/percentile_approx_raw.md # docs/zh/sql-reference/sql-functions/percentile-functions/percentile_empty.md # docs/zh/sql-reference/sql-functions/percentile-functions/percentile_hash.md # docs/zh/sql-reference/sql-functions/percentile-functions/percentile_union.md # docs/zh/sql-reference/sql-functions/scalar-functions/hll_cardinality.md # docs/zh/sql-reference/sql-functions/scalar-functions/hll_empty.md # docs/zh/sql-reference/sql-functions/scalar-functions/hll_hash.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_astext.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_circle.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_contains.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_distance_sphere.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_geometryfromtext.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_linefromtext.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_point.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_polygon.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_x.md # docs/zh/sql-reference/sql-functions/spatial-functions/st_y.md # docs/zh/sql-reference/sql-functions/string-functions/append_trailing_char_if_absent.md # docs/zh/sql-reference/sql-functions/string-functions/ascii.md # docs/zh/sql-reference/sql-functions/string-functions/char.md # docs/zh/sql-reference/sql-functions/string-functions/char_length.md # docs/zh/sql-reference/sql-functions/string-functions/character_length.md # docs/zh/sql-reference/sql-functions/string-functions/concat.md # docs/zh/sql-reference/sql-functions/string-functions/concat_ws.md # docs/zh/sql-reference/sql-functions/string-functions/crc32.md # docs/zh/sql-reference/sql-functions/string-functions/ends_with.md # docs/zh/sql-reference/sql-functions/string-functions/find_in_set.md # docs/zh/sql-reference/sql-functions/string-functions/group_concat.md # docs/zh/sql-reference/sql-functions/string-functions/hex.md # docs/zh/sql-reference/sql-functions/string-functions/hex_decode_binary.md # docs/zh/sql-reference/sql-functions/string-functions/hex_decode_string.md # docs/zh/sql-reference/sql-functions/string-functions/instr.md # docs/zh/sql-reference/sql-functions/string-functions/lcase.md # docs/zh/sql-reference/sql-functions/string-functions/left.md # docs/zh/sql-reference/sql-functions/string-functions/length.md # docs/zh/sql-reference/sql-functions/string-functions/locate.md # docs/zh/sql-reference/sql-functions/string-functions/lower.md # docs/zh/sql-reference/sql-functions/string-functions/lpad.md # docs/zh/sql-reference/sql-functions/string-functions/ltrim.md # docs/zh/sql-reference/sql-functions/string-functions/money_format.md # docs/zh/sql-reference/sql-functions/string-functions/ngram_search.md # docs/zh/sql-reference/sql-functions/string-functions/null_or_empty.md # docs/zh/sql-reference/sql-functions/string-functions/parse_url.md # docs/zh/sql-reference/sql-functions/string-functions/repeat.md # docs/zh/sql-reference/sql-functions/string-functions/replace.md # docs/zh/sql-reference/sql-functions/string-functions/reverse.md # docs/zh/sql-reference/sql-functions/string-functions/right.md # docs/zh/sql-reference/sql-functions/string-functions/rpad.md # docs/zh/sql-reference/sql-functions/string-functions/rtrim.md # docs/zh/sql-reference/sql-functions/string-functions/space.md # docs/zh/sql-reference/sql-functions/string-functions/split.md # docs/zh/sql-reference/sql-functions/string-functions/split_part.md # docs/zh/sql-reference/sql-functions/string-functions/starts_with.md # docs/zh/sql-reference/sql-functions/string-functions/str_to_map.md # docs/zh/sql-reference/sql-functions/string-functions/strleft.md # docs/zh/sql-reference/sql-functions/string-functions/strright.md # docs/zh/sql-reference/sql-functions/string-functions/substring.md # docs/zh/sql-reference/sql-functions/string-functions/substring_index.md # docs/zh/sql-reference/sql-functions/string-functions/translate.md # docs/zh/sql-reference/sql-functions/string-functions/trim.md # docs/zh/sql-reference/sql-functions/string-functions/ucase.md # docs/zh/sql-reference/sql-functions/string-functions/unhex.md # docs/zh/sql-reference/sql-functions/string-functions/upper.md # docs/zh/sql-reference/sql-functions/string-functions/url_decode.md # docs/zh/sql-reference/sql-functions/string-functions/url_encode.md # docs/zh/sql-reference/sql-functions/string-functions/url_extract_host.md # docs/zh/sql-reference/sql-functions/string-functions/url_extract_parameter.md # docs/zh/sql-reference/sql-functions/struct-functions/named_struct.md # docs/zh/sql-reference/sql-functions/struct-functions/row.md # docs/zh/sql-reference/sql-functions/table-functions/files.md # docs/zh/sql-reference/sql-functions/table-functions/generate_series.md # docs/zh/sql-reference/sql-functions/utility-functions/catalog.md # docs/zh/sql-reference/sql-functions/utility-functions/current_role.md # docs/zh/sql-reference/sql-functions/utility-functions/current_version.md # docs/zh/sql-reference/sql-functions/utility-functions/database.md # docs/zh/sql-reference/sql-functions/utility-functions/get_query_profile.md # docs/zh/sql-reference/sql-functions/utility-functions/host_name.md # docs/zh/sql-reference/sql-functions/utility-functions/is_role_in_session.md # docs/zh/sql-reference/sql-functions/utility-functions/isnull.md # docs/zh/sql-reference/sql-functions/utility-functions/last_query_id.md # docs/zh/sql-reference/sql-functions/utility-functions/sleep.md # docs/zh/sql-reference/sql-functions/utility-functions/uuid.md # docs/zh/sql-reference/sql-functions/utility-functions/uuid_numeric.md # docs/zh/sql-reference/sql-functions/utility-functions/version.md # docs/zh/sql-reference/sql-statements/Function/CREATE_FUNCTION.md # docs/zh/sql-reference/sql-statements/materialized_view/ALTER_MATERIALIZED_VIEW.md # docs/zh/sql-reference/sql-statements/table_bucket_part_index/ALTER_TABLE.md # docs/zh/sql-reference/sql-statements/table_bucket_part_index/SELECT.md # docs/zh/sql-reference/template_for_config.md # docs/zh/table_design/data_distribution/expression_partitioning.md # env.sh # fe/fe-core/pom.xml # fe/fe-core/src/main/java/com/starrocks/StarRocksFE.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterHandler.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterJobExecutor.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterJobMgr.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterJobV2.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterJobV2Builder.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterMVJobExecutor.java # fe/fe-core/src/main/java/com/starrocks/alter/AlterOpType.java # fe/fe-core/src/main/java/com/starrocks/alter/CompactionHandler.java # fe/fe-core/src/main/java/com/starrocks/alter/LakeTableAlterJobV2Builder.java # fe/fe-core/src/main/java/com/starrocks/alter/LakeTableAlterMetaJob.java # fe/fe-core/src/main/java/com/starrocks/alter/LakeTableAlterMetaJobBase.java # fe/fe-core/src/main/java/com/starrocks/alter/LakeTableSchemaChangeJob.java # fe/fe-core/src/main/java/com/starrocks/alter/MaterializedViewHandler.java # fe/fe-core/src/main/java/com/starrocks/alter/OlapTableAlterJobV2Builder.java # fe/fe-core/src/main/java/com/starrocks/alter/OnlineOptimizeJobV2.java # fe/fe-core/src/main/java/com/starrocks/alter/OptimizeJobV2.java # fe/fe-core/src/main/java/com/starrocks/alter/OptimizeJobV2Builder.java # fe/fe-core/src/main/java/com/starrocks/alter/RollupJobV2.java # fe/fe-core/src/main/java/com/starrocks/alter/SchemaChangeHandler.java # fe/fe-core/src/main/java/com/starrocks/alter/SchemaChangeJobV2.java # fe/fe-core/src/main/java/com/starrocks/alter/SystemHandler.java # fe/fe-core/src/main/java/com/starrocks/analysis/Analyzer.java # fe/fe-core/src/main/java/com/starrocks/analysis/BloomFilterIndexUtil.java # fe/fe-core/src/main/java/com/starrocks/analysis/DescriptorTable.java # fe/fe-core/src/main/java/com/starrocks/analysis/DictQueryExpr.java # fe/fe-core/src/main/java/com/starrocks/analysis/FunctionCallExpr.java # fe/fe-core/src/main/java/com/starrocks/analysis/FunctionName.java # fe/fe-core/src/main/java/com/starrocks/analysis/HintNode.java # fe/fe-core/src/main/java/com/starrocks/analysis/InvertedIndexUtil.java # fe/fe-core/src/main/java/com/starrocks/analysis/JoinOperator.java # fe/fe-core/src/main/java/com/starrocks/analysis/LabelName.java # fe/fe-core/src/main/java/com/starrocks/analysis/OutFileClause.java # fe/fe-core/src/main/java/com/starrocks/analysis/ParseNode.java # fe/fe-core/src/main/java/com/starrocks/analysis/SortInfo.java # fe/fe-core/src/main/java/com/starrocks/analysis/TableName.java # fe/fe-core/src/main/java/com/starrocks/analysis/VarBinaryLiteral.java # fe/fe-core/src/main/java/com/starrocks/authentication/AuthenticationMgr.java # fe/fe-core/src/main/java/com/starrocks/authentication/AuthenticationProvider.java # fe/fe-core/src/main/java/com/starrocks/authentication/KerberosAuthenticationProvider.java # fe/fe-core/src/main/java/com/starrocks/authentication/LDAPAuthProviderForNative.java # fe/fe-core/src/main/java/com/starrocks/authentication/PlainPasswordAuthenticationProvider.java # fe/fe-core/src/main/java/com/starrocks/authentication/UserPropertyInfo.java # fe/fe-core/src/main/java/com/starrocks/backup/BackupHandler.java # fe/fe-core/src/main/java/com/starrocks/backup/BackupJob.java # fe/fe-core/src/main/java/com/starrocks/backup/BackupJobInfo.java # fe/fe-core/src/main/java/com/starrocks/backup/BackupMeta.java # fe/fe-core/src/main/java/com/starrocks/backup/BlobStorage.java # fe/fe-core/src/main/java/com/starrocks/backup/RestoreJob.java # fe/fe-core/src/main/java/com/starrocks/backup/mv/MVRestoreUpdater.java # fe/fe-core/src/main/java/com/starrocks/binlog/BinlogManager.java # fe/fe-core/src/main/java/com/starrocks/catalog/AggregateFunction.java # fe/fe-core/src/main/java/com/starrocks/catalog/AggregateType.java # fe/fe-core/src/main/java/com/starrocks/catalog/Catalog.java # fe/fe-core/src/main/java/com/starrocks/catalog/CatalogRecycleBin.java # fe/fe-core/src/main/java/com/starrocks/catalog/CatalogUtils.java # fe/fe-core/src/main/java/com/starrocks/catalog/ColocateTableIndex.java # fe/fe-core/src/main/java/com/starrocks/catalog/Column.java # fe/fe-core/src/main/java/com/starrocks/catalog/Database.java # fe/fe-core/src/main/java/com/starrocks/catalog/DeltaLakeTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/Dictionary.java # fe/fe-core/src/main/java/com/starrocks/catalog/DictionaryMgr.java # fe/fe-core/src/main/java/com/starrocks/catalog/DistributionInfo.java # fe/fe-core/src/main/java/com/starrocks/catalog/ExternalOlapTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/FileTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/Function.java # fe/fe-core/src/main/java/com/starrocks/catalog/FunctionSet.java # fe/fe-core/src/main/java/com/starrocks/catalog/GlobalFunctionMgr.java # fe/fe-core/src/main/java/com/starrocks/catalog/HiveTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/HudiTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/IcebergTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/IcebergView.java # fe/fe-core/src/main/java/com/starrocks/catalog/Index.java # fe/fe-core/src/main/java/com/starrocks/catalog/JDBCTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/KuduTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/ListPartitionInfo.java # fe/fe-core/src/main/java/com/starrocks/catalog/MaterializedIndex.java # fe/fe-core/src/main/java/com/starrocks/catalog/MaterializedView.java # fe/fe-core/src/main/java/com/starrocks/catalog/MetadataViewer.java # fe/fe-core/src/main/java/com/starrocks/catalog/MvBaseTableUpdateInfo.java # fe/fe-core/src/main/java/com/starrocks/catalog/MvRefreshArbiter.java # fe/fe-core/src/main/java/com/starrocks/catalog/MvUpdateInfo.java # fe/fe-core/src/main/java/com/starrocks/catalog/MysqlTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/OdpsTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/OlapTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/PaimonTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/Partition.java # fe/fe-core/src/main/java/com/starrocks/catalog/PhysicalPartition.java # fe/fe-core/src/main/java/com/starrocks/catalog/ResourceGroupClassifier.java # fe/fe-core/src/main/java/com/starrocks/catalog/ResourceGroupMgr.java # fe/fe-core/src/main/java/com/starrocks/catalog/ResourceMgr.java # fe/fe-core/src/main/java/com/starrocks/catalog/ScalarFunction.java # fe/fe-core/src/main/java/com/starrocks/catalog/StructField.java # fe/fe-core/src/main/java/com/starrocks/catalog/Table.java # fe/fe-core/src/main/java/com/starrocks/catalog/TableFunctionTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/TableProperty.java # fe/fe-core/src/main/java/com/starrocks/catalog/TabletInvertedIndex.java # fe/fe-core/src/main/java/com/starrocks/catalog/TabletStatMgr.java # fe/fe-core/src/main/java/com/starrocks/catalog/TempPartitions.java # fe/fe-core/src/main/java/com/starrocks/catalog/Type.java # fe/fe-core/src/main/java/com/starrocks/catalog/View.java # fe/fe-core/src/main/java/com/starrocks/catalog/constraint/ForeignKeyConstraint.java # fe/fe-core/src/main/java/com/starrocks/catalog/constraint/UniqueConstraint.java # fe/fe-core/src/main/java/com/starrocks/catalog/mv/MVTimelinessArbiter.java # fe/fe-core/src/main/java/com/starrocks/catalog/mv/MVTimelinessListPartitionArbiter.java # fe/fe-core/src/main/java/com/starrocks/catalog/mv/MVTimelinessNonPartitionArbiter.java # fe/fe-core/src/main/java/com/starrocks/catalog/mv/MVTimelinessRangePartitionArbiter.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/information/TaskRunsSystemTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/information/TasksSystemTable.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/sys/GrantsTo.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/sys/RoleEdges.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/sys/SysFeLocks.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/sys/SysFeMemoryUsage.java # fe/fe-core/src/main/java/com/starrocks/catalog/system/sys/SysObjectDependencies.java # fe/fe-core/src/main/java/com/starrocks/clone/ColocateTableBalancer.java # fe/fe-core/src/main/java/com/starrocks/clone/DiskAndTabletLoadReBalancer.java # fe/fe-core/src/main/java/com/starrocks/clone/DynamicPartitionScheduler.java # fe/fe-core/src/main/java/com/starrocks/clone/TabletChecker.java # fe/fe-core/src/main/java/com/starrocks/clone/TabletSchedCtx.java # fe/fe-core/src/main/java/com/starrocks/clone/TabletScheduler.java # fe/fe-core/src/main/java/com/starrocks/common/AlreadyExistsException.java # fe/fe-core/src/main/java/com/starrocks/common/AnalysisException.java # fe/fe-core/src/main/java/com/starrocks/common/AuthenticationException.java # fe/fe-core/src/main/java/com/starrocks/common/Config.java # fe/fe-core/src/main/java/com/starrocks/common/ConfigBase.java # fe/fe-core/src/main/java/com/starrocks/common/DdlException.java # fe/fe-core/src/main/java/com/starrocks/common/ErrorCode.java # fe/fe-core/src/main/java/com/starrocks/common/ErrorReport.java # fe/fe-core/src/main/java/com/starrocks/common/FeConstants.java # fe/fe-core/src/main/java/com/starrocks/common/InvertedIndexParams.java # fe/fe-core/src/main/java/com/starrocks/common/LoadException.java # fe/fe-core/src/main/java/com/starrocks/common/MarkDownParser.java # fe/fe-core/src/main/java/com/starrocks/common/MetaNotFoundException.java # fe/fe-core/src/main/java/com/starrocks/common/NgramBfIndexParamsKey.java # fe/fe-core/src/main/java/com/starrocks/common/NoAliveBackendException.java # fe/fe-core/src/main/java/com/starrocks/common/NotImplementedException.java # fe/fe-core/src/main/java/com/starrocks/common/TimeoutException.java # fe/fe-core/src/main/java/com/starrocks/common/TraceManager.java # fe/fe-core/src/main/java/com/starrocks/common/io/DeepCopy.java # fe/fe-core/src/main/java/com/starrocks/common/io/ParamsKey.java # fe/fe-core/src/main/java/com/starrocks/common/proc/BackendsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/ComputeNodeProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/DbsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/EsPartitionsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/EsShardProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/HMSTablePartitionsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/IndexInfoProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/IndicesProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/JobsDbProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/LakeTabletsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/LocalTabletsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/PartitionsProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/ProcUtils.java # fe/fe-core/src/main/java/com/starrocks/common/proc/ReplicasProcNode.java # fe/fe-core/src/main/java/com/starrocks/common/proc/StatisticProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/TableProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/proc/TablesProcDir.java # fe/fe-core/src/main/java/com/starrocks/common/profile/Tracer.java # fe/fe-core/src/main/java/com/starrocks/common/profile/TracerImpl.java # fe/fe-core/src/main/java/com/starrocks/common/profile/Tracers.java # fe/fe-core/src/main/java/com/starrocks/common/profile/Var.java # fe/fe-core/src/main/java/com/starrocks/common/profile/VarTracer.java # fe/fe-core/src/main/java/com/starrocks/common/util/AutoInferUtil.java # fe/fe-core/src/main/java/com/starrocks/common/util/BrokerUtil.java # fe/fe-core/src/main/java/com/starrocks/common/util/Daemon.java # fe/fe-core/src/main/java/com/starrocks/common/util/DynamicPartitionUtil.java # fe/fe-core/src/main/java/com/starrocks/common/util/KafkaUtil.java # fe/fe-core/src/main/java/com/starrocks/common/util/ParseUtil.java # fe/fe-core/src/main/java/com/starrocks/common/util/ProfileManager.java # fe/fe-core/src/main/java/com/starrocks/common/util/PropertyAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/common/util/PulsarUtil.java # fe/fe-core/src/main/java/com/starrocks/common/util/SmallFileMgr.java # fe/fe-core/src/main/java/com/starrocks/common/util/TimeUtils.java # fe/fe-core/src/main/java/com/starrocks/common/util/Util.java # fe/fe-core/src/main/java/com/starrocks/common/util/concurrent/QueryableReentrantReadWriteLock.java # fe/fe-core/src/main/java/com/starrocks/common/util/concurrent/lock/AutoCloseableLock.java # fe/fe-core/src/main/java/com/starrocks/common/util/concurrent/lock/Locker.java # fe/fe-core/src/main/java/com/starrocks/connector/CachingRemoteFileIO.java # fe/fe-core/src/main/java/com/starrocks/connector/CatalogConnectorMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/ConnectorFactory.java # fe/fe-core/src/main/java/com/starrocks/connector/ConnectorMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/ConnectorPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/ConnectorTableInfo.java # fe/fe-core/src/main/java/com/starrocks/connector/MetaPreparationItem.java # fe/fe-core/src/main/java/com/starrocks/connector/PartitionInfo.java # fe/fe-core/src/main/java/com/starrocks/connector/PartitionUtil.java # fe/fe-core/src/main/java/com/starrocks/connector/PredicateSearchKey.java # fe/fe-core/src/main/java/com/starrocks/connector/RemoteFileIO.java # fe/fe-core/src/main/java/com/starrocks/connector/RemoteFileInfo.java # fe/fe-core/src/main/java/com/starrocks/connector/RemoteFileOperations.java # fe/fe-core/src/main/java/com/starrocks/connector/RemotePathKey.java # fe/fe-core/src/main/java/com/starrocks/connector/delta/DeltaLakeCacheUpdateProcessor.java # fe/fe-core/src/main/java/com/starrocks/connector/delta/DeltaLakeMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/delta/DeltaLakeMetadataFactory.java # fe/fe-core/src/main/java/com/starrocks/connector/delta/DeltaUtils.java # fe/fe-core/src/main/java/com/starrocks/connector/delta/FileScanTask.java # fe/fe-core/src/main/java/com/starrocks/connector/delta/ScanFileUtils.java # fe/fe-core/src/main/java/com/starrocks/connector/elasticsearch/EsRepository.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/CachingHiveMetastore.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/ConnectorTableMetadataProcessor.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveCacheUpdateProcessor.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveCommitter.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveConnector.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveMetadataFactory.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveMetastore.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveMetastoreApiConverter.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveMetastoreOperations.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveRemoteFileIO.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveStatisticsProvider.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveWriteUtils.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/Partition.java # fe/fe-core/src/main/java/com/starrocks/connector/hive/RemoteFileInputFormat.java # fe/fe-core/src/main/java/com/starrocks/connector/hudi/HudiConnector.java # fe/fe-core/src/main/java/com/starrocks/connector/hudi/HudiMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/hudi/HudiMetadataFactory.java # fe/fe-core/src/main/java/com/starrocks/connector/hudi/HudiRemoteFileIO.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/CachingIcebergCatalog.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergAlterTableExecutor.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergApiConverter.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergCatalog.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergConnector.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergMetaSpec.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergMetaSplit.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergPartitionUtils.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/cost/IcebergStatisticProvider.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/glue/IcebergGlueCatalog.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/hadoop/IcebergHadoopCatalog.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/hive/IcebergHiveCatalog.java # fe/fe-core/src/main/java/com/starrocks/connector/iceberg/rest/IcebergRESTCatalog.java # fe/fe-core/src/main/java/com/starrocks/connector/jdbc/JDBCMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/jdbc/MysqlSchemaResolver.java # fe/fe-core/src/main/java/com/starrocks/connector/kudu/KuduMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/kudu/KuduPredicateConverter.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/MetadataCollectJob.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/MetadataExecutor.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/MetadataTable.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/MetadataTableType.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/TableMetaConnector.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/TableMetaMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/LogicalIcebergMetadataTable.java # fe/fe-core/src/main/java/com/starrocks/connector/odps/OdpsMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/paimon/PaimonConnector.java # fe/fe-core/src/main/java/com/starrocks/connector/paimon/PaimonMetadata.java # fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/AstBuilder.java # fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/TrinoParserUtils.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/CachedPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/DefaultTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/DeltaLakePartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/HivePartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/HudiPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/IcebergPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/JDBCPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/KuduPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/OdpsPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/OlapPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/partitiontraits/PaimonPartitionTraits.java # fe/fe-core/src/main/java/com/starrocks/connector/statistics/ConnectorColumnStatsCacheLoader.java # fe/fe-core/src/main/java/com/starrocks/connector/statistics/ConnectorTableColumnStats.java # fe/fe-core/src/main/java/com/starrocks/connector/statistics/StatisticsUtils.java # fe/fe-core/src/main/java/com/starrocks/connector/unified/UnifiedMetadata.java # fe/fe-core/src/main/java/com/starrocks/consistency/CheckConsistencyJob.java # fe/fe-core/src/main/java/com/starrocks/consistency/ConsistencyChecker.java # fe/fe-core/src/main/java/com/starrocks/consistency/LockChecker.java # fe/fe-core/src/main/java/com/starrocks/consistency/MetaRecoveryDaemon.java # fe/fe-core/src/main/java/com/starrocks/credential/CloudConfigurationFactory.java # fe/fe-core/src/main/java/com/starrocks/datacache/DataCacheSelectExecutor.java # fe/fe-core/src/main/java/com/starrocks/fs/HdfsUtil.java # fe/fe-core/src/main/java/com/starrocks/fs/hdfs/HdfsFsManager.java # fe/fe-core/src/main/java/com/starrocks/fs/hdfs/HdfsService.java # fe/fe-core/src/main/java/com/starrocks/fs/hdfs/WildcardURI.java # fe/fe-core/src/main/java/com/starrocks/ha/BDBHA.java # fe/fe-core/src/main/java/com/starrocks/ha/HAProtocol.java # fe/fe-core/src/main/java/com/starrocks/ha/LeaderInfo.java # fe/fe-core/src/main/java/com/starrocks/http/BaseAction.java # fe/fe-core/src/main/java/com/starrocks/http/HttpConnectProcessor.java # fe/fe-core/src/main/java/com/starrocks/http/HttpServer.java # fe/fe-core/src/main/java/com/starrocks/http/action/WebBaseAction.java # fe/fe-core/src/main/java/com/starrocks/http/meta/ColocateMetaService.java # fe/fe-core/src/main/java/com/starrocks/http/meta/GlobalDictMetaService.java # fe/fe-core/src/main/java/com/starrocks/http/meta/MetaService.java # fe/fe-core/src/main/java/com/starrocks/http/rest/BootstrapFinishAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/CancelStreamLoad.java # fe/fe-core/src/main/java/com/starrocks/http/rest/CheckDecommissionAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/GetDdlStmtAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/GetLoadInfoAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/GetLogFileAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/GetStreamLoadState.java # fe/fe-core/src/main/java/com/starrocks/http/rest/LoadAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/MetaReplayerCheckAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/MetricsAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/MigrationAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/RestBaseAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/RestBaseResult.java # fe/fe-core/src/main/java/com/starrocks/http/rest/RowCountAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/SetConfigAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/ShowDataAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/ShowMetaInfoAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/ShowProcAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/StopFeAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/StorageTypeCheckAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/SyncCloudTableMetaAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/TableQueryPlanAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/TableRowCountAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/TableSchemaAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/TransactionLoadAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/TriggerAction.java # fe/fe-core/src/main/java/com/starrocks/http/rest/transaction/BypassWriteTransactionHandler.java # fe/fe-core/src/main/java/com/starrocks/http/rest/transaction/TransactionOperationHandler.java # fe/fe-core/src/main/java/com/starrocks/http/rest/transaction/TransactionWithChannelHandler.java # fe/fe-core/src/main/java/com/starrocks/http/rest/transaction/TransactionWithoutChannelHandler.java # fe/fe-core/src/main/java/com/starrocks/journal/JournalEntity.java # fe/fe-core/src/main/java/com/starrocks/journal/bdbje/BDBTool.java # fe/fe-core/src/main/java/com/starrocks/journal/bdbje/Timestamp.java # fe/fe-core/src/main/java/com/starrocks/lake/LakeMaterializedView.java # fe/fe-core/src/main/java/com/starrocks/lake/LakeTable.java # fe/fe-core/src/main/java/com/starrocks/lake/LakeTableHelper.java # fe/fe-core/src/main/java/com/starrocks/lake/StarMgrMetaSyncer.java # fe/fe-core/src/main/java/com/starrocks/lake/StarOSAgent.java # fe/fe-core/src/main/java/com/starrocks/lake/TxnInfoHelper.java # fe/fe-core/src/main/java/com/starrocks/lake/Utils.java # fe/fe-core/src/main/java/com/starrocks/lake/backup/LakeBackupJob.java # fe/fe-core/src/main/java/com/starrocks/lake/backup/LakeRestoreJob.java # fe/fe-core/src/main/java/com/starrocks/lake/compaction/CompactionMgr.java # fe/fe-core/src/main/java/com/starrocks/lake/compaction/CompactionScheduler.java # fe/fe-core/src/main/java/com/starrocks/lake/compaction/CompactionTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/lake/delete/LakeDeleteJob.java # fe/fe-core/src/main/java/com/starrocks/lake/vacuum/AutovacuumDaemon.java # fe/fe-core/src/main/java/com/starrocks/leader/LeaderImpl.java # fe/fe-core/src/main/java/com/starrocks/leader/MetaHelper.java # fe/fe-core/src/main/java/com/starrocks/leader/ReportHandler.java # fe/fe-core/src/main/java/com/starrocks/listener/LoadJobMVListener.java # fe/fe-core/src/main/java/com/starrocks/listener/LoadJobStatsListener.java # fe/fe-core/src/main/java/com/starrocks/load/BrokerFileGroup.java # fe/fe-core/src/main/java/com/starrocks/load/DeleteInfo.java # fe/fe-core/src/main/java/com/starrocks/load/DeleteJob.java # fe/fe-core/src/main/java/com/starrocks/load/DeleteMgr.java # fe/fe-core/src/main/java/com/starrocks/load/EtlStatus.java # fe/fe-core/src/main/java/com/starrocks/load/ExportChecker.java # fe/fe-core/src/main/java/com/starrocks/load/ExportJob.java # fe/fe-core/src/main/java/com/starrocks/load/ExportMgr.java # fe/fe-core/src/main/java/com/starrocks/load/InsertOverwriteJob.java # fe/fe-core/src/main/java/com/starrocks/load/InsertOverwriteJobMgr.java # fe/fe-core/src/main/java/com/starrocks/load/InsertOverwriteJobRunner.java # fe/fe-core/src/main/java/com/starrocks/load/Load.java # fe/fe-core/src/main/java/com/starrocks/load/OlapDeleteJob.java # fe/fe-core/src/main/java/com/starrocks/load/PartitionUtils.java # fe/fe-core/src/main/java/com/starrocks/load/TabletDeleteInfo.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/BrokerLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/BrokerLoadPendingTask.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/BulkLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/InsertLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/LoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/LoadJobFinalOperation.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/LoadLoadingTask.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/LoadMgr.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/LoadTask.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/LoadsHistorySyncer.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/ManualLoadTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/MiniLoadTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/SparkEtlJobHandler.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/SparkLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/SparkLoadPendingTask.java # fe/fe-core/src/main/java/com/starrocks/load/loadv2/SparkRepository.java # fe/fe-core/src/main/java/com/starrocks/load/pipe/FilePipeSource.java # fe/fe-core/src/main/java/com/starrocks/load/pipe/Pipe.java # fe/fe-core/src/main/java/com/starrocks/load/pipe/PipeListener.java # fe/fe-core/src/main/java/com/starrocks/load/pipe/PipeManager.java # fe/fe-core/src/main/java/com/starrocks/load/pipe/filelist/FileListTableRepo.java # fe/fe-core/src/main/java/com/starrocks/load/pipe/filelist/RepoCreator.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/KafkaProgress.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/KafkaRoutineLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/KafkaTaskInfo.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/PulsarRoutineLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/PulsarTaskInfo.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RLTaskTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RoutineLoadFunctionalExprProvider.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RoutineLoadJob.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RoutineLoadMgr.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RoutineLoadScheduler.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RoutineLoadTaskInfo.java # fe/fe-core/src/main/java/com/starrocks/load/routineload/RoutineLoadTaskScheduler.java # fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadFunctionalExprProvider.java # fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadInfo.java # fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadMgr.java # fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadTask.java # fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/metric/MaterializedViewMetricsEntity.java # fe/fe-core/src/main/java/com/starrocks/metric/MetricRepo.java # fe/fe-core/src/main/java/com/starrocks/monitor/jvm/JvmStats.java # fe/fe-core/src/main/java/com/starrocks/mv/MVMetaVersionRepairer.java # fe/fe-core/src/main/java/com/starrocks/mv/MVRepairHandler.java # fe/fe-core/src/main/java/com/starrocks/mv/analyzer/MVPartitionExprResolver.java # fe/fe-core/src/main/java/com/starrocks/mv/analyzer/MVPartitionSlotRefResolver.java # fe/fe-core/src/main/java/com/starrocks/mysql/privilege/Password.java # fe/fe-core/src/main/java/com/starrocks/persist/BackendTabletsInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/CreateInsertOverwriteJobLog.java # fe/fe-core/src/main/java/com/starrocks/persist/CreateUserInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/DatabaseInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/DropPartitionInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/EditLog.java # fe/fe-core/src/main/java/com/starrocks/persist/MetaCleaner.java # fe/fe-core/src/main/java/com/starrocks/persist/ModifyPartitionInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/OperationType.java # fe/fe-core/src/main/java/com/starrocks/persist/PhysicalPartitionPersistInfoV2.java # fe/fe-core/src/main/java/com/starrocks/persist/RecoverInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/RolePrivilegeCollectionInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/TableInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/UserPrivilegeCollectionInfo.java # fe/fe-core/src/main/java/com/starrocks/persist/gson/GsonUtils.java # fe/fe-core/src/main/java/com/starrocks/planner/AggregationNode.java # fe/fe-core/src/main/java/com/starrocks/planner/AnalyticEvalNode.java # fe/fe-core/src/main/java/com/starrocks/planner/BinlogScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/DeltaLakeScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/EsScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/ExchangeNode.java # fe/fe-core/src/main/java/com/starrocks/planner/ExportSink.java # fe/fe-core/src/main/java/com/starrocks/planner/FileScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/FileTableScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/FragmentNormalizer.java # fe/fe-core/src/main/java/com/starrocks/planner/HashDistributionPruner.java # fe/fe-core/src/main/java/com/starrocks/planner/HashJoinNode.java # fe/fe-core/src/main/java/com/starrocks/planner/HdfsScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/HiveTableSink.java # fe/fe-core/src/main/java/com/starrocks/planner/HudiScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/IcebergMetadataScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/IcebergScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/IcebergTableSink.java # fe/fe-core/src/main/java/com/starrocks/planner/JDBCScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/JoinNode.java # fe/fe-core/src/main/java/com/starrocks/planner/KuduScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/LoadScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/MetaScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/MysqlScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/MysqlTableSink.java # fe/fe-core/src/main/java/com/starrocks/planner/OdpsScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/OlapScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/OlapTableSink.java # fe/fe-core/src/main/java/com/starrocks/planner/PaimonScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/PlanFragment.java # fe/fe-core/src/main/java/com/starrocks/planner/PlanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/ProjectNode.java # fe/fe-core/src/main/java/com/starrocks/planner/RepeatNode.java # fe/fe-core/src/main/java/com/starrocks/planner/RuntimeFilterPushDownContext.java # fe/fe-core/src/main/java/com/starrocks/planner/ScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/SchemaScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/SelectNode.java # fe/fe-core/src/main/java/com/starrocks/planner/SetOperationNode.java # fe/fe-core/src/main/java/com/starrocks/planner/SortNode.java # fe/fe-core/src/main/java/com/starrocks/planner/StreamLoadPlanner.java # fe/fe-core/src/main/java/com/starrocks/planner/StreamLoadScanNode.java # fe/fe-core/src/main/java/com/starrocks/planner/TableFunctionNode.java # fe/fe-core/src/main/java/com/starrocks/plugin/BuiltinPluginLoader.java # fe/fe-core/src/main/java/com/starrocks/plugin/DynamicPluginLoader.java # fe/fe-core/src/main/java/com/starrocks/plugin/PluginException.java # fe/fe-core/src/main/java/com/starrocks/plugin/PluginLoader.java # fe/fe-core/src/main/java/com/starrocks/plugin/PluginMgr.java # fe/fe-core/src/main/java/com/starrocks/plugin/PluginZip.java # fe/fe-core/src/main/java/com/starrocks/qe/BackendSelector.java # fe/fe-core/src/main/java/com/starrocks/qe/ColocatedBackendSelector.java # fe/fe-core/src/main/java/com/starrocks/qe/ConnectContext.java # fe/fe-core/src/main/java/com/starrocks/qe/ConnectProcessor.java # fe/fe-core/src/main/java/com/starrocks/qe/ConnectScheduler.java # fe/fe-core/src/main/java/com/starrocks/qe/CoordinatorPreprocessor.java # fe/fe-core/src/main/java/com/starrocks/qe/DDLStmtExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/DefaultCoordinator.java # fe/fe-core/src/main/java/com/starrocks/qe/ExecuteExceptionHandler.java # fe/fe-core/src/main/java/com/starrocks/qe/ExecuteScriptExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/HDFSBackendSelector.java # fe/fe-core/src/main/java/com/starrocks/qe/LeaderOpExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/NormalBackendSelector.java # fe/fe-core/src/main/java/com/starrocks/qe/QeProcessor.java # fe/fe-core/src/main/java/com/starrocks/qe/QeProcessorImpl.java # fe/fe-core/src/main/java/com/starrocks/qe/QueryQueueManager.java # fe/fe-core/src/main/java/com/starrocks/qe/QueryStateException.java # fe/fe-core/src/main/java/com/starrocks/qe/QueryStatisticsInfo.java # fe/fe-core/src/main/java/com/starrocks/qe/ResultReceiver.java # fe/fe-core/src/main/java/com/starrocks/qe/SessionVariable.java # fe/fe-core/src/main/java/com/starrocks/qe/SetDefaultRoleExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/SetRoleExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/ShortCircuitExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/ShortCircuitHybridExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/ShowMaterializedViewStatus.java # fe/fe-core/src/main/java/com/starrocks/qe/StmtExecutor.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/Coordinator.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/Deployer.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/FeExecuteCoordinator.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/QueryRuntimeProfile.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/SchedulerException.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/TFragmentInstanceFactory.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/assignment/BackendSelectorFactory.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/assignment/FragmentAssignmentStrategy.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/assignment/FragmentAssignmentStrategyFactory.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/assignment/LocalFragmentAssignmentStrategy.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/assignment/RemoteFragmentAssignmentStrategy.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/AllAtOnceExecutionSchedule.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/ExecutionDAG.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/ExecutionSchedule.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/FragmentInstance.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/FragmentInstanceExecState.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/JobSpec.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/PhasedExecutionSchedule.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/dag/ScheduleNextTurnRunner.java # fe/fe-core/src/main/java/com/starrocks/qe/scheduler/slot/GlobalSlotProvider.java # fe/fe-core/src/main/java/com/starrocks/replication/ReplicationJob.java # fe/fe-core/src/main/java/com/starrocks/replication/ReplicationMgr.java # fe/fe-core/src/main/java/com/starrocks/replication/ReplicationTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/rpc/BrpcProxy.java # fe/fe-core/src/main/java/com/starrocks/rpc/PBackendService.java # fe/fe-core/src/main/java/com/starrocks/scheduler/Constants.java # fe/fe-core/src/main/java/com/starrocks/scheduler/DataCacheSelectProcessor.java # fe/fe-core/src/main/java/com/starrocks/scheduler/MVActiveChecker.java # fe/fe-core/src/main/java/com/starrocks/scheduler/MvTaskRunContext.java # fe/fe-core/src/main/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessor.java # fe/fe-core/src/main/java/com/starrocks/scheduler/TableSnapshotInfo.java # fe/fe-core/src/main/java/com/starrocks/scheduler/TableWithPartitions.java # fe/fe-core/src/main/java/com/starrocks/scheduler/TaskManager.java # fe/fe-core/src/main/java/com/starrocks/scheduler/TaskRun.java # fe/fe-core/src/main/java/com/starrocks/scheduler/TaskRunManager.java # fe/fe-core/src/main/java/com/starrocks/scheduler/history/TableKeeper.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVMaintenanceJob.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVMaintenanceTask.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVPCTRefreshListPartitioner.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVPCTRefreshNonPartitioner.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVPCTRefreshPartitioner.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVPCTRefreshPlanBuilder.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVPCTRefreshRangePartitioner.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVTraceUtils.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVVersionManager.java # fe/fe-core/src/main/java/com/starrocks/scheduler/mv/TxnBasedEpochCoordinator.java # fe/fe-core/src/main/java/com/starrocks/server/CatalogMgr.java # fe/fe-core/src/main/java/com/starrocks/server/GlobalStateMgr.java # fe/fe-core/src/main/java/com/starrocks/server/HiveTableFactory.java # fe/fe-core/src/main/java/com/starrocks/server/HudiTableFactory.java # fe/fe-core/src/main/java/com/starrocks/server/IcebergTableFactory.java # fe/fe-core/src/main/java/com/starrocks/server/LocalMetastore.java # fe/fe-core/src/main/java/com/starrocks/server/MetadataMgr.java # fe/fe-core/src/main/java/com/starrocks/server/NodeMgr.java # fe/fe-core/src/main/java/com/starrocks/server/OlapTableFactory.java # fe/fe-core/src/main/java/com/starrocks/server/SharedDataStorageVolumeMgr.java # fe/fe-core/src/main/java/com/starrocks/server/StorageVolumeMgr.java # fe/fe-core/src/main/java/com/starrocks/server/WarehouseManager.java # fe/fe-core/src/main/java/com/starrocks/service/FrontendServiceImpl.java # fe/fe-core/src/main/java/com/starrocks/service/InformationSchemaDataSource.java # fe/fe-core/src/main/java/com/starrocks/sql/DeletePlanner.java # fe/fe-core/src/main/java/com/starrocks/sql/Explain.java # fe/fe-core/src/main/java/com/starrocks/sql/ExplainAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/InsertPlanner.java # fe/fe-core/src/main/java/com/starrocks/sql/LoadPlanner.java # fe/fe-core/src/main/java/com/starrocks/sql/StatementPlanner.java # fe/fe-core/src/main/java/com/starrocks/sql/UpdatePlanner.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AggregationAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AlterRoutineLoadAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AlterTableClauseAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AlterTableStatementAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AnalyzeStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/Analyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AnalyzerUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AstToSQLBuilder.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AstToStringBuilder.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/Authorizer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AuthorizerStmtVisitor.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/BackupRestoreAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/CTASAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/CancelAlterTableStatementAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/CreateRoutineLoadAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/CreateTableAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/CreateTableLikeAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/DecimalV3FunctionAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/DeleteAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/DictionaryAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/DropStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ExportStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ExpressionAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/FeNameFormat.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/FunctionAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/InsertAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/LoadStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/MaterializedViewAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/PlannerMetaLocker.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/PolymorphicFunctionAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/QueryAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/RecoverPartitionAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/RecoverTableAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/RefreshTableStatementAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ResourceGroupAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/SelectAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/SetStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ShowAlterStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ShowStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ShowTabletStmtAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/TruncateTableAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/UpdateAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ViewAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/analyzer/WarehouseAnalyzer.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/AbstractBackupStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/AddFieldClause.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/AlterRoutineLoadStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/AlterUserStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/AnalyzeStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/AstVisitor.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/BackupStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/BaseCreateAlterUserStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/BaseGrantRevokePrivilegeStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CancelBackupStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ColumnDef.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateFunctionStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateMaterializedViewStatement.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateMaterializedViewStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateRoutineLoadStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateTableAsSelectStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateUserStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/DataDescription.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/DmlStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/DropFunctionStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/DropPartitionClause.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ExportStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/FileTableFunctionRelation.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/IndexDef.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/InsertStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/IntervalLiteral.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ListPartitionDesc.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/MVColumnItem.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/QueryStatement.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/RefreshMaterializedViewStatement.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/RestoreStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ShowAnalyzeJobStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ShowAnalyzeStatusStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ShowBasicStatsMetaStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ShowHistogramStatsMetaStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/StatementBase.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/TableRelation.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/UnitIdentifier.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/UserAuthOption.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/UserIdentity.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/ValuesRelation.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/pipe/ShowPipeStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/ast/warehouse/ShowWarehousesStmt.java # fe/fe-core/src/main/java/com/starrocks/sql/common/DebugOperatorTracer.java # fe/fe-core/src/main/java/com/starrocks/sql/common/Generator.java # fe/fe-core/src/main/java/com/starrocks/sql/common/ListPartitionDiffer.java # fe/fe-core/src/main/java/com/starrocks/sql/common/MetaUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PListCell.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PRangeCell.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PRangeCellPlus.java # fe/fe-core/src/main/java/com/starrocks/sql/common/ParserErrorMsg.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PartitionDiff.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PartitionDiffResult.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PartitionDiffer.java # fe/fe-core/src/main/java/com/starrocks/sql/common/PermutationGenerator.java # fe/fe-core/src/main/java/com/starrocks/sql/common/RangePartitionDiffer.java # fe/fe-core/src/main/java/com/starrocks/sql/common/SqlWithIdUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/common/SyncPartitionUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/common/TimeUnitUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/CTEUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/LogicalPlanPrinter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/MaterializationContext.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/MaterializedViewOptimizer.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/MvRewriteContext.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/MvRewritePreprocessor.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/OptExpression.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/OptExpressionVisitor.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/Optimizer.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/OptimizerContext.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/OptimizerTraceUtil.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/UKFKConstraintsCollector.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/Utils.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/base/ColumnRefSet.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/base/LogicalProperty.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/base/SortProperty.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/function/MetaFunctions.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/Operator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/OperatorType.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/OperatorVisitor.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/UKFKConstraints.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalAggregationOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalAssertOneRowOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalCTEAnchorOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalCTEConsumeOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalCTEProduceOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalFilterOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalIcebergMetadataScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalIcebergScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalJoinOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalLimitOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalMetaScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalOlapScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalProjectOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalSetOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalTableFunctionOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalTopNOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalUnionOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalWindowOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalHashAggregateOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalIcebergMetadataScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalIcebergScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalMetaScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalOlapScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalScanOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalTopNOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalUnionOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalWindowOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/ConstantOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/DictionaryGetOperator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/OptExternalPartitionPruner.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/OptOlapPartitionPruner.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/PartitionColPredicateEvaluator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/PartitionColPredicateExtractor.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ReplaceColumnRefRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorEvaluator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarOperatorFunctions.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/ScalarRangePredicateExtractor.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/scalar/ReduceCastRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/RuleSet.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/RuleSetType.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/RuleType.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/implementation/IcebergScanImplementationRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/implementation/NestLoopJoinImplementationRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/implementation/TopNImplementationRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/implementation/WindowImplementationRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/join/JoinOrder.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/join/JoinReorderFactory.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/join/ReorderJoinRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/mv/MaterializedViewRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/EliminateAggRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/ExternalScanPartitionPruneRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/GroupByCountDistinctRewriteRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/JoinCommutativityRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/ListPartitionPruner.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/MaterializedViewTransparentRewriteRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/MergeLimitDirectRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/MergeProjectWithChildRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PartitionPruneRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PruneHDFSScanColumnRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PushDownAggToMetaScanRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PushDownFlatJsonMetaToMetaScanRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PushDownLimitRankingWindowRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PushDownPredicateRankingWindowRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PushDownPredicateScanRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/RewriteSimpleAggToHDFSScanRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/RewriteSimpleAggToMetaScanRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/SeparateProjectRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/SplitAggregateRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/SplitScanORToUnionRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/AggregateFunctionRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/AggregatedMaterializedViewPushDownRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/AggregatedMaterializedViewRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/AndRangePredicate.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/BestMvSelector.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/ColumnRangePredicate.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/EquationRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MVColumnPruner.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MVPartitionPruner.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MVTransparentState.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MVUnionRewriteMode.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MaterializedViewRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvPartitionCompensator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewriteStrategy.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvUtils.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/OptExpressionDuplicator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/PredicateExtractor.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/compensation/MVCompensationBuilder.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/compensation/OptCompensator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/CountRewriteEquivalent.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/DateTruncEquivalent.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/EquivalentShuttleContext.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/HLLRewriteEquivalent.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/IRewriteEquivalent.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/RewriteEquivalent.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/rule/AggregateJoinPushDownRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/rule/BaseMaterializedViewRewriteRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/AddDecodeNodeForDictStringRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/DataCachePopulateRewriteRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/ExchangeSortToMergeRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/PreAggregateTurnOnRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/ScalarOperatorsReuseRule.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/lowcardinality/DecodeCollector.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/pdagg/AggregatePushDownContext.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/pdagg/PushDownAggregateCollector.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/pdagg/PushDownAggregateRewriter.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/CacheDictManager.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/CachedStatisticStorage.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/ColumnBasicStatsCacheLoader.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/ColumnHistogramStatsCacheLoader.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/StatisticStorage.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/Statistics.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/StatisticsCalculator.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/statistics/StatisticsEstimateCoefficient.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/task/PrepareCollectMetaTask.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/task/RewriteTreeTask.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/transformer/QueryTransformer.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/transformer/RelationTransformer.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/transformer/WindowTransformer.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/validate/InputDependenciesChecker.java # fe/fe-core/src/main/java/com/starrocks/sql/optimizer/validate/TypeChecker.java # fe/fe-core/src/main/java/com/starrocks/sql/parser/AstBuilder.java # fe/fe-core/src/main/java/com/starrocks/sql/parser/SqlParser.java # fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocks.g4 # fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocksLex.g4 # fe/fe-core/src/main/java/com/starrocks/sql/parser/SyntaxSugars.java # fe/fe-core/src/main/java/com/starrocks/sql/plan/ExecPlan.java # fe/fe-core/src/main/java/com/starrocks/sql/plan/PlanFragmentBuilder.java # fe/fe-core/src/main/java/com/starrocks/sql/plan/ScalarOperatorToExpr.java # fe/fe-core/src/main/java/com/starrocks/sql/util/TablePlus.java # fe/fe-core/src/main/java/com/starrocks/staros/StarMgrServer.java # fe/fe-core/src/main/java/com/starrocks/statistic/AnalyzeMgr.java # fe/fe-core/src/main/java/com/starrocks/statistic/BasicStatsMeta.java # fe/fe-core/src/main/java/com/starrocks/statistic/ColumnStatsMeta.java # fe/fe-core/src/main/java/com/starrocks/statistic/ExternalBasicStatsMeta.java # fe/fe-core/src/main/java/com/starrocks/statistic/ExternalFullStatisticsCollectJob.java # fe/fe-core/src/main/java/com/starrocks/statistic/HistogramStatisticsCollectJob.java # fe/fe-core/src/main/java/com/starrocks/statistic/NativeAnalyzeJob.java # fe/fe-core/src/main/java/com/starrocks/statistic/NativeAnalyzeStatus.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticExecutor.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticSQLBuilder.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticUtils.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticsCollectJob.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticsCollectJobFactory.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticsCollectionTrigger.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatisticsMetaManager.java # fe/fe-core/src/main/java/com/starrocks/statistic/StatsConstants.java # fe/fe-core/src/main/java/com/starrocks/statistic/sample/SampleInfo.java # fe/fe-core/src/main/java/com/starrocks/statistic/sample/TabletSampleManager.java # fe/fe-core/src/main/java/com/starrocks/statistic/sample/TabletStats.java # fe/fe-core/src/main/java/com/starrocks/system/Backend.java # fe/fe-core/src/main/java/com/starrocks/system/BackendHbResponse.java # fe/fe-core/src/main/java/com/starrocks/system/BackendResourceStat.java # fe/fe-core/src/main/java/com/starrocks/system/ComputeNode.java # fe/fe-core/src/main/java/com/starrocks/system/Frontend.java # fe/fe-core/src/main/java/com/starrocks/system/FrontendHbResponse.java # fe/fe-core/src/main/java/com/starrocks/system/HeartbeatMgr.java # fe/fe-core/src/main/java/com/starrocks/system/HeartbeatResponse.java # fe/fe-core/src/main/java/com/starrocks/system/NodeSelector.java # fe/fe-core/src/main/java/com/starrocks/system/SystemInfoService.java # fe/fe-core/src/main/java/com/starrocks/task/AlterReplicaTask.java # fe/fe-core/src/main/java/com/starrocks/task/CreateReplicaTask.java # fe/fe-core/src/main/java/com/starrocks/task/ExportExportingTask.java # fe/fe-core/src/main/java/com/starrocks/task/ExportPendingTask.java # fe/fe-core/src/main/java/com/starrocks/task/PublishVersionTask.java # fe/fe-core/src/main/java/com/starrocks/task/RemoteSnapshotTask.java # fe/fe-core/src/main/java/com/starrocks/transaction/AbstractTxnStateChangeCallback.java # fe/fe-core/src/main/java/com/starrocks/transaction/DatabaseTransactionMgr.java # fe/fe-core/src/main/java/com/starrocks/transaction/GlobalTransactionMgr.java # fe/fe-core/src/main/java/com/starrocks/transaction/GtidGenerator.java # fe/fe-core/src/main/java/com/starrocks/transaction/IllegalTransactionParameterException.java # fe/fe-core/src/main/java/com/starrocks/transaction/InsertTxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/transaction/LakeTableTxnLogApplier.java # fe/fe-core/src/main/java/com/starrocks/transaction/LakeTableTxnStateListener.java # fe/fe-core/src/main/java/com/starrocks/transaction/OlapTableTxnLogApplier.java # fe/fe-core/src/main/java/com/starrocks/transaction/OlapTableTxnStateListener.java # fe/fe-core/src/main/java/com/starrocks/transaction/PartitionCommitInfo.java # fe/fe-core/src/main/java/com/starrocks/transaction/PublishVersionDaemon.java # fe/fe-core/src/main/java/com/starrocks/transaction/TableCommitInfo.java # fe/fe-core/src/main/java/com/starrocks/transaction/TransactionChecker.java # fe/fe-core/src/main/java/com/starrocks/transaction/TransactionCommitFailedException.java # fe/fe-core/src/main/java/com/starrocks/transaction/TransactionException.java # fe/fe-core/src/main/java/com/starrocks/transaction/TransactionState.java # fe/fe-core/src/main/java/com/starrocks/transaction/TransactionStateBatch.java # fe/fe-core/src/main/java/com/starrocks/transaction/TxnCommitAttachment.java # fe/fe-core/src/main/java/com/starrocks/transaction/TxnStateChangeCallback.java # fe/fe-core/src/main/java/com/starrocks/transaction/UpdateDbUsedDataQuotaDaemon.java # fe/fe-core/src/main/java/com/starrocks/warehouse/DefaultWarehouse.java # fe/fe-core/src/main/java/com/starrocks/warehouse/WarehouseProcDir.java # fe/fe-core/src/main/java/org/apache/iceberg/DeleteFileIndex.java # fe/fe-core/src/main/java/org/apache/iceberg/StarRocksIcebergTableScan.java # fe/fe-core/src/test/java/com/starrocks/alter/AlterJobV2Test.java # fe/fe-core/src/test/java/com/starrocks/alter/AlterTableTest.java # fe/fe-core/src/test/java/com/starrocks/alter/AlterTest.java # fe/fe-core/src/test/java/com/starrocks/alter/BatchRollupJobTest.java # fe/fe-core/src/test/java/com/starrocks/alter/CompactionHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/alter/LakeTableAlterDataCachePartitionDurationTest.java # fe/fe-core/src/test/java/com/starrocks/alter/LakeTableAlterMetaJobTest.java # fe/fe-core/src/test/java/com/starrocks/alter/LakeTableAsyncFastSchemaChangeJobTest.java # fe/fe-core/src/test/java/com/starrocks/alter/LakeTableSchemaChangeJobTest.java # fe/fe-core/src/test/java/com/starrocks/alter/MaterializedViewHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/alter/OnlineOptimizeJobV2Test.java # fe/fe-core/src/test/java/com/starrocks/alter/OptimizeJobV2BuilderTest.java # fe/fe-core/src/test/java/com/starrocks/alter/OptimizeJobV2Test.java # fe/fe-core/src/test/java/com/starrocks/alter/RollupJobV2Test.java # fe/fe-core/src/test/java/com/starrocks/alter/SchemaChangeHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/alter/SchemaChangeJobV2Test.java # fe/fe-core/src/test/java/com/starrocks/alter/SystemHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/AccessTestUtil.java # fe/fe-core/src/test/java/com/starrocks/analysis/AlterUserStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CTASAutoTabletTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CancelLoadStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ColumnDefTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ColumnPositionTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateAnalyzeJobTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateDbStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateRoutineLoadStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateSyncMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateTableAutoTabletTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateTableWithPartitionTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/CreateUserStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/DropMaterializedViewStmtNewPlannerTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/DropMaterializedViewStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/FailPointStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/GINIndexTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/IndexDefTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/InstallPluginStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/LoadStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/MVColumnBitmapUnionPatternTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/MaterializedViewAutoTabletTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ModifyBackendClauseTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ModifyBrokerClauseTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ModifyFrontendAddressClauseTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/RefreshMaterializedViewStatementTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/RefreshMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ResourceGroupStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/RestrictOpMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/RuntimeFilterTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/SelectStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/SetCatalogStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/SetPassVarTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/SetStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/SetUserPropertyVarTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowCatalogsStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowCharsetStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowCreateMaterializedViewStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowCreateRoutineLoadStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowCreateViewStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowDbStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowDeleteTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowEnginesStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowLoadStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowLoadWarningsStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowRestoreStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/ShowTransactionStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/SubmitTaskStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/UseCatalogStmtTest.java # fe/fe-core/src/test/java/com/starrocks/analysis/UseMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/authentication/AuthenticationManagerTest.java # fe/fe-core/src/test/java/com/starrocks/authentication/AuthenticationProviderFactoryTest.java # fe/fe-core/src/test/java/com/starrocks/authentication/PlainPasswordAuthenticationProviderTest.java # fe/fe-core/src/test/java/com/starrocks/authentication/UserPropertyTest.java # fe/fe-core/src/test/java/com/starrocks/backup/BackupHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/backup/BackupJobMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/backup/BackupJobPrimaryKeyTest.java # fe/fe-core/src/test/java/com/starrocks/backup/BackupJobTest.java # fe/fe-core/src/test/java/com/starrocks/backup/CatalogMocker.java # fe/fe-core/src/test/java/com/starrocks/backup/RestoreJobMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/backup/RestoreJobPrimaryKeyTest.java # fe/fe-core/src/test/java/com/starrocks/backup/RestoreJobTest.java # fe/fe-core/src/test/java/com/starrocks/benchmark/MVPartitionCompensateOptBench.java # fe/fe-core/src/test/java/com/starrocks/benchmark/MvPreProcessorWithSSBBench.java # fe/fe-core/src/test/java/com/starrocks/benchmark/MvRefreshConcurrencyTest.java # fe/fe-core/src/test/java/com/starrocks/binlog/BinlogManagerTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/AdminStmtTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/BackendTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/BrokerMgrTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CatalogRecycleBinLakeTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CatalogRecycleBinTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CatalogUtilsTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ColocateTableIndexTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ColocateTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ColumnTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CreateTableLikeTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CreateTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CreateTableWithLocationTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/CreateViewTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/DatabaseTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/DictionaryMgrTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/DropPartitionTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/DynamicPartitionTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ExpressionRangePartitionInfoTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/FakeEditLog.java # fe/fe-core/src/test/java/com/starrocks/catalog/ForeignKeyConstraintTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/GlobalFunctionMgrTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/GlobalStateMgrTestUtil.java # fe/fe-core/src/test/java/com/starrocks/catalog/HiveResourceTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/HiveTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/HudiResourceTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/HudiTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/IcebergResourceTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/IcebergTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/InfoSchemaDbTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/JDBCTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ListPartitionInfoTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/MVPartitionExprResolverTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/MaterializedIndexTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/MaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/MetadataViewerTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/OlapTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/PhysicalPartitionImplTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ReplaceLakePartitionTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/ResourceMgrTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/SparkResourceTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/StorageCoolDownTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/StorageMediumInferTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/TableFunctionTableTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/TabletStatMgrTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/TempPartitionTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/system/sys/SysFeLocksTest.java # fe/fe-core/src/test/java/com/starrocks/catalog/system/sys/SysFeMemoryUsageTest.java # fe/fe-core/src/test/java/com/starrocks/clone/ColocateTableBalancerTest.java # fe/fe-core/src/test/java/com/starrocks/clone/DiskAndTabletLoadReBalancerTest.java # fe/fe-core/src/test/java/com/starrocks/clone/DynamicPartitionSchedulerTest.java # fe/fe-core/src/test/java/com/starrocks/clone/TabletSchedCtxTest.java # fe/fe-core/src/test/java/com/starrocks/clone/TabletSchedulerTest.java # fe/fe-core/src/test/java/com/starrocks/cluster/SystemInfoServiceTest.java # fe/fe-core/src/test/java/com/starrocks/common/ConfigTest.java # fe/fe-core/src/test/java/com/starrocks/common/MarkDownParserTest.java # fe/fe-core/src/test/java/com/starrocks/common/PropertyAnalyzerTest.java # fe/fe-core/src/test/java/com/starrocks/common/lock/AutoCloseableLockerTest.java # fe/fe-core/src/test/java/com/starrocks/common/lock/DeadLockTest.java # fe/fe-core/src/test/java/com/starrocks/common/lock/TestLockException.java # fe/fe-core/src/test/java/com/starrocks/common/lock/TestLockInterface.java # fe/fe-core/src/test/java/com/starrocks/common/proc/CurrentGlobalQueryStatisticsProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/CurrentQueryStatisticsProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/DbsProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/LakeTabletsProcNodeTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/LocalTabletsProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/PartitionsProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/StatisticProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/proc/TablesProcDirTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/AutoInferUtilTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/BrokerUtilTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/KafkaUtilTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/ProfileManagerTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/ProfilingExecPlanTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/SmallFileMgrTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/TimeUtilsTest.java # fe/fe-core/src/test/java/com/starrocks/common/util/UnitTestUtil.java # fe/fe-core/src/test/java/com/starrocks/common/util/concurrent/QueryableReentrantLockTest.java # fe/fe-core/src/test/java/com/starrocks/connector/CatalogConnectorMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/HiveMetastoreApiConverterTest.java # fe/fe-core/src/test/java/com/starrocks/connector/PartitionUtilTest.java # fe/fe-core/src/test/java/com/starrocks/connector/RemoteFileOperationsTest.java # fe/fe-core/src/test/java/com/starrocks/connector/RemoteScanRangeLocationsTest.java # fe/fe-core/src/test/java/com/starrocks/connector/analyzer/SimpleExpressionAnalyzer.java # fe/fe-core/src/test/java/com/starrocks/connector/delta/CachingDeltaLakeMetastoreTest.java # fe/fe-core/src/test/java/com/starrocks/connector/delta/DeltaLakeConnectorTest.java # fe/fe-core/src/test/java/com/starrocks/connector/delta/DeltaLakeMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/elasticsearch/EsShardPartitionsTest.java # fe/fe-core/src/test/java/com/starrocks/connector/elasticsearch/QueryBuildersTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/CachingHiveMetastoreTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/HiveConnectorTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/HiveMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/HiveMetastoreOperationsTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/HiveMetastoreTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/HiveStatisticsProviderTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/HiveViewTest.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/MockedHiveMetadata.java # fe/fe-core/src/test/java/com/starrocks/connector/hive/ReplayMetadataMgr.java # fe/fe-core/src/test/java/com/starrocks/connector/hudi/HudiMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/iceberg/IcebergApiConverterTest.java # fe/fe-core/src/test/java/com/starrocks/connector/iceberg/IcebergMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/iceberg/MockIcebergMetadata.java # fe/fe-core/src/test/java/com/starrocks/connector/iceberg/cost/IcebergStatisticProviderTest.java # fe/fe-core/src/test/java/com/starrocks/connector/jdbc/MockedJDBCMetadata.java # fe/fe-core/src/test/java/com/starrocks/connector/jdbc/MysqlSchemaResolverTest.java # fe/fe-core/src/test/java/com/starrocks/connector/kudu/KuduMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/kudu/KuduPredicateConverterTest.java # fe/fe-core/src/test/java/com/starrocks/connector/odps/MockedBase.java # fe/fe-core/src/test/java/com/starrocks/connector/odps/OdpsMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/odps/OdpsTableTest.java # fe/fe-core/src/test/java/com/starrocks/connector/paimon/PaimonConnectorTest.java # fe/fe-core/src/test/java/com/starrocks/connector/paimon/PaimonMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/connector/parser/trino/TrinoFunctionTransformTest.java # fe/fe-core/src/test/java/com/starrocks/connector/parser/trino/TrinoParserNotSupportTest.java # fe/fe-core/src/test/java/com/starrocks/connector/parser/trino/TrinoQueryTest.java # fe/fe-core/src/test/java/com/starrocks/connector/parser/trino/TrinoTestBase.java # fe/fe-core/src/test/java/com/starrocks/connector/unified/UnifiedMetadataTest.java # fe/fe-core/src/test/java/com/starrocks/consistency/ConsistencyCheckerTest.java # fe/fe-core/src/test/java/com/starrocks/consistency/MetaRecoveryDaemonTest.java # fe/fe-core/src/test/java/com/starrocks/credential/CloudConfigurationFactoryTest.java # fe/fe-core/src/test/java/com/starrocks/external/starrocks/TableMetaSyncerTest.java # fe/fe-core/src/test/java/com/starrocks/fs/HdfsUtilTest.java # fe/fe-core/src/test/java/com/starrocks/fs/TestHdfsFsManager.java # fe/fe-core/src/test/java/com/starrocks/fs/WildcardURITest.java # fe/fe-core/src/test/java/com/starrocks/ha/BDBHATest.java # fe/fe-core/src/test/java/com/starrocks/http/BadHttpRequestTest.java # fe/fe-core/src/test/java/com/starrocks/http/ExecuteSqlActionTest.java # fe/fe-core/src/test/java/com/starrocks/http/LoadActionTest.java # fe/fe-core/src/test/java/com/starrocks/http/QueryDumpActionTest.java # fe/fe-core/src/test/java/com/starrocks/http/RestBaseResultTest.java # fe/fe-core/src/test/java/com/starrocks/http/ShowDataActionTest.java # fe/fe-core/src/test/java/com/starrocks/http/ShowMetaInfoActionTest.java # fe/fe-core/src/test/java/com/starrocks/http/StarRocksHttpTestCase.java # fe/fe-core/src/test/java/com/starrocks/http/TableQueryPlanActionTest.java # fe/fe-core/src/test/java/com/starrocks/http/TransactionLoadActionTest.java # fe/fe-core/src/test/java/com/starrocks/journal/bdbje/BDBEnvironmentTest.java # fe/fe-core/src/test/java/com/starrocks/lake/AlterTest.java # fe/fe-core/src/test/java/com/starrocks/lake/CreateLakeTableTest.java # fe/fe-core/src/test/java/com/starrocks/lake/LakeMaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/lake/LakeTableHelperTest.java # fe/fe-core/src/test/java/com/starrocks/lake/StarMgrMetaSyncerTest.java # fe/fe-core/src/test/java/com/starrocks/lake/StarOSAgent2ndTest.java # fe/fe-core/src/test/java/com/starrocks/lake/StarOSAgentTest.java # fe/fe-core/src/test/java/com/starrocks/lake/UtilsTest.java # fe/fe-core/src/test/java/com/starrocks/lake/compaction/CompactionJobTest.java # fe/fe-core/src/test/java/com/starrocks/lake/compaction/CompactionMgrTest.java # fe/fe-core/src/test/java/com/starrocks/lake/compaction/CompactionSchedulerTest.java # fe/fe-core/src/test/java/com/starrocks/lake/compaction/CompactionTxnCommitAttachmentTest.java # fe/fe-core/src/test/java/com/starrocks/lake/delete/DeleteTest.java # fe/fe-core/src/test/java/com/starrocks/lake/qe/ShowExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/lake/qe/scheduler/DefaultSharedDataWorkerProviderTest.java # fe/fe-core/src/test/java/com/starrocks/leader/LeaderImplTest.java # fe/fe-core/src/test/java/com/starrocks/leader/ReportHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/load/BrokerFileGroupTest.java # fe/fe-core/src/test/java/com/starrocks/load/DeleteHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/load/DeletePruneTest.java # fe/fe-core/src/test/java/com/starrocks/load/ExportCheckerTest.java # fe/fe-core/src/test/java/com/starrocks/load/ExportMgrTest.java # fe/fe-core/src/test/java/com/starrocks/load/InsertOverwriteJobManagerTest.java # fe/fe-core/src/test/java/com/starrocks/load/InsertOverwriteJobRunnerTest.java # fe/fe-core/src/test/java/com/starrocks/load/InsertOverwriteJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/LoadPlannerTest.java # fe/fe-core/src/test/java/com/starrocks/load/LoadTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/BrokerLoadJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/BrokerLoadPendingTaskTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/InsertLoadJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/LoadJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/LoadMgrTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/SparkEtlJobHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/SparkLoadJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/SparkLoadPendingTaskTest.java # fe/fe-core/src/test/java/com/starrocks/load/loadv2/SparkRepositoryTest.java # fe/fe-core/src/test/java/com/starrocks/load/pipe/PipeManagerTest.java # fe/fe-core/src/test/java/com/starrocks/load/pipe/filelist/FileListRepoTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/KafkaProgressTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/KafkaRoutineLoadJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/KafkaTaskInfoTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/RoutineLoadJobMetaTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/RoutineLoadJobTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/RoutineLoadManagerTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/RoutineLoadSchedulerTest.java # fe/fe-core/src/test/java/com/starrocks/load/routineload/RoutineLoadTaskSchedulerTest.java # fe/fe-core/src/test/java/com/starrocks/load/streamload/ShowStreamLoadTest.java # fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadManagerTest.java # fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadTaskTest.java # fe/fe-core/src/test/java/com/starrocks/mysql/MysqlHandshakePacketTest.java # fe/fe-core/src/test/java/com/starrocks/persist/ColumnRenameTest.java # fe/fe-core/src/test/java/com/starrocks/persist/CreateInsertOverwriteJobLogTest.java # fe/fe-core/src/test/java/com/starrocks/persist/EditLogTest.java # fe/fe-core/src/test/java/com/starrocks/persist/OperationTypeTest.java # fe/fe-core/src/test/java/com/starrocks/persist/RecyclePartitionInfoTest.java # fe/fe-core/src/test/java/com/starrocks/persist/RenameMaterializedViewLogTest.java # fe/fe-core/src/test/java/com/starrocks/persist/metablock/SRMetaBlockV1Test.java # fe/fe-core/src/test/java/com/starrocks/persist/metablock/SRMetaBlockV2Test.java # fe/fe-core/src/test/java/com/starrocks/planner/FileScanNodeTest.java # fe/fe-core/src/test/java/com/starrocks/planner/HudiScanNodeTest.java # fe/fe-core/src/test/java/com/starrocks/planner/IcebergMetadataScanNodeTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewAggPushDownRewriteTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewAggRollupTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewLowCardTPCHTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewManualTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewRewriteWithSSBTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewTPCHTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewTestBase.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewTextBasedRewriteTPCHTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewWithMultiStageTest.java # fe/fe-core/src/test/java/com/starrocks/planner/MaterializedViewWithPartitionTest.java # fe/fe-core/src/test/java/com/starrocks/planner/OlapTableSinkTest.java # fe/fe-core/src/test/java/com/starrocks/planner/OlapTableSinkTest2.java # fe/fe-core/src/test/java/com/starrocks/planner/StreamLoadPlannerTest.java # fe/fe-core/src/test/java/com/starrocks/planner/StreamLoadScanNodeTest.java # fe/fe-core/src/test/java/com/starrocks/planner/TableFunctionTableSinkTest.java # fe/fe-core/src/test/java/com/starrocks/planner/TablePruningTest.java # fe/fe-core/src/test/java/com/starrocks/planner/TablePruningTestBase.java # fe/fe-core/src/test/java/com/starrocks/planner/mv/MVMetaVersionRepairerTest.java # fe/fe-core/src/test/java/com/starrocks/plugin/PluginMgrTest.java # fe/fe-core/src/test/java/com/starrocks/plugin/PluginZipTest.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/BeRestartTest.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/BeTabletManager.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/BeTxnManager.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/LocationLabeledTableBalanceTest.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/LocationMismatchRepairTest.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/PseudoBackend.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/PseudoCluster.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/PseudoClusterTest.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/PseudoFrontend.java # fe/fe-core/src/test/java/com/starrocks/pseudocluster/ReplicaMinReadableVersionTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ColocatedBackendSelectorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ConnectContextTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ConnectProcessorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/CoordinatorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ExecuteExceptionHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ExportHandleTest.java # fe/fe-core/src/test/java/com/starrocks/qe/HDFSBackendSelectorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/RBACExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/SetExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ShowExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/ShowTableMockMeta.java # fe/fe-core/src/test/java/com/starrocks/qe/ShowTablesTest.java # fe/fe-core/src/test/java/com/starrocks/qe/StmtExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/qe/VariableMgrTest.java # fe/fe-core/src/test/java/com/starrocks/qe/scheduler/DefaultWorkerProviderTest.java # fe/fe-core/src/test/java/com/starrocks/qe/scheduler/GetNextTest.java # fe/fe-core/src/test/java/com/starrocks/qe/scheduler/QueryQueueManagerTest.java # fe/fe-core/src/test/java/com/starrocks/qe/scheduler/SchedulerTestBase.java # fe/fe-core/src/test/java/com/starrocks/qe/scheduler/StartSchedulingTest.java # fe/fe-core/src/test/java/com/starrocks/replication/ReplicationJobTest.java # fe/fe-core/src/test/java/com/starrocks/replication/ReplicationMgrTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/MVRefreshTestBase.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PCTRefreshListPartitionOlapTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessorHiveTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessorIcebergTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessorJdbcTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessorOlapPart2Test.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessorOlapTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshProcessorPaimonTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/PartitionBasedMvRefreshTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/TaskRunFIFOQueueTest.java # fe/fe-core/src/test/java/com/starrocks/scheduler/mv/MVMaintenanceJobTest.java # fe/fe-core/src/test/java/com/starrocks/server/CatalogLevelTest.java # fe/fe-core/src/test/java/com/starrocks/server/CatalogMgrTest.java # fe/fe-core/src/test/java/com/starrocks/server/ConcurrentDDLTest.java # fe/fe-core/src/test/java/com/starrocks/server/GlobalStateMgrTest.java # fe/fe-core/src/test/java/com/starrocks/server/LocalMetaStoreTest.java # fe/fe-core/src/test/java/com/starrocks/server/MVRepairHandlerTest.java # fe/fe-core/src/test/java/com/starrocks/server/MetadataMgrTest.java # fe/fe-core/src/test/java/com/starrocks/server/NodeMgrTest.java # fe/fe-core/src/test/java/com/starrocks/server/SharedDataStorageVolumeMgrTest.java # fe/fe-core/src/test/java/com/starrocks/server/WarehouseManagerTest.java # fe/fe-core/src/test/java/com/starrocks/service/FrontendOptionsTest.java # fe/fe-core/src/test/java/com/starrocks/service/FrontendServiceImplTest.java # fe/fe-core/src/test/java/com/starrocks/service/LakeInformationSchemaDataSourceTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AlterDbRenameAnalyzerTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeAggregateTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeBackupRestoreTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeCreateAnalyzeJobTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeCreateTableTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeDropTableTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeFunctionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeInsertTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/AnalyzeStmtTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/CTASAnalyzerTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/ExternalDbTablePrivTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/MaterializedViewAnalyzerTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/PrivilegeCheckerTest.java # fe/fe-core/src/test/java/com/starrocks/sql/analyzer/PrivilegeStmtAnalyzerV2Test.java # fe/fe-core/src/test/java/com/starrocks/sql/ast/CreateFunctionStmtTest.java # fe/fe-core/src/test/java/com/starrocks/sql/ast/DropFunctionStmtTest.java # fe/fe-core/src/test/java/com/starrocks/sql/ast/ExecuteAsStmtTest.java # fe/fe-core/src/test/java/com/starrocks/sql/ast/StructFieldDescTest.java # fe/fe-core/src/test/java/com/starrocks/sql/common/MetaUtilTest.java # fe/fe-core/src/test/java/com/starrocks/sql/common/SqlWithIdUtilsTest.java # fe/fe-core/src/test/java/com/starrocks/sql/common/SyncPartitionUtilsTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/MVRewriteTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/OptimizerTaskTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/SelectStmtWithCaseWhenTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/UtilsTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/operator/ColumnFilterConverterTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/operator/operator/OperatorEqualsTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/JoinPredicatePushdownTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/PredicateReorderRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/scalar/FoldConstantsRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rewrite/scalar/ReduceCastRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/mv/MaterializedViewRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/DistributionPrunerRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/PartitionPruneRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/PruneHDFSScanColumnRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MVRewriteWithSchemaChangeTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRefreshAndRewriteIcebergTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRefreshAndRewriteJDBCTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRefreshTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewriteHiveTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewriteListPartitionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewritePartialPartitionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewritePartitionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewritePreprocessorTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewriteTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewriteTestBase.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvRewriteUnionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvTransparentRewriteWithHiveTableTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvTransparentRewriteWithOlapTableTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvTransparentUnionRewriteHiveTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvUtilsTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/PredicateSplitTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/statistics/CachedStatisticStorageTest.java # fe/fe-core/src/test/java/com/starrocks/sql/optimizer/statistics/StatisticsCalculatorTest.java # fe/fe-core/src/test/java/com/starrocks/sql/parser/ParserTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/AggregatePushDownTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/AggregateTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/CTEPlanTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/ConnectorPlanTestBase.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/DataCachePlanTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/DistributedEnvPlanTestBase.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/DistributedEnvPlanWithCostTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/DistributedEnvTPCDSPlanTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/ExpressionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/ExternalTableTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/FilterUnusedColumnTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/GroupingSetTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/GroupingSetsTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/InsertPlanTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/JoinTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/JsonTypeTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/LimitTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/LowCardinalityArrayTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/LowCardinalityTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/LowCardinalityTest2.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/MockTpchStatisticStorage.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/MultiJoinReorderTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/NestLoopJoinTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/PlanFragmentWithCostTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/PlanTestBase.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/PlanTestNoneDBBase.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/PredicatePushDownTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/PruneComplexSubfieldTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/PruneUKFKJoinRuleTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/RemoveAggTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/ReplayFromDumpTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/ScanTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/SetTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/ShortCircuitTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/SkewJoinTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/SplitScanToUnionTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/TPCDS1TTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/TPCDSPushAggTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/TPCHPlanTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/TPCHPlanWithHistogramCostTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/UDFTest.java # fe/fe-core/src/test/java/com/starrocks/sql/plan/WindowTest.java # fe/fe-core/src/test/java/com/starrocks/staros/StarMgrServerTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/AnalyzeMgrTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/BasicStatsMetaTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/CacheLoaderTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/MockHistogramStatisticStorage.java # fe/fe-core/src/test/java/com/starrocks/statistic/StatisticExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/StatisticsCollectJobTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/StatisticsCollectionTriggerTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/StatisticsExecutorTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/StatisticsSQLTest.java # fe/fe-core/src/test/java/com/starrocks/statistic/sample/SampleInfoTest.java # fe/fe-core/src/test/java/com/starrocks/system/BackendHbResponseTest.java # fe/fe-core/src/test/java/com/starrocks/system/BackendResourceStatTest.java # fe/fe-core/src/test/java/com/starrocks/system/ComputeNodeTest.java # fe/fe-core/src/test/java/com/starrocks/system/SystemInfoServiceTest.java # fe/fe-core/src/test/java/com/starrocks/task/AgentTaskTest.java # fe/fe-core/src/test/java/com/starrocks/transaction/DatabaseTransactionMgrTest.java # fe/fe-core/src/test/java/com/starrocks/transaction/GlobalTransactionMgrTest.java # fe/fe-core/src/test/java/com/starrocks/transaction/LakePublishBatchTest.java # fe/fe-core/src/test/java/com/starrocks/transaction/LakeTableTestHelper.java # fe/fe-core/src/test/java/com/starrocks/transaction/LakeTableTxnLogApplierTest.java # fe/fe-core/src/test/java/com/starrocks/transaction/TransactionStateBatchTest.java # fe/fe-core/src/test/java/com/starrocks/utframe/MockJournal.java # fe/fe-core/src/test/java/com/starrocks/utframe/MockedBackend.java # fe/fe-core/src/test/java/com/starrocks/utframe/MockedFrontend.java # fe/fe-core/src/test/java/com/starrocks/utframe/StarRocksAssert.java # fe/fe-core/src/test/java/com/starrocks/utframe/TestWithFeService.java # fe/fe-core/src/test/java/com/starrocks/utframe/UtFrameUtils.java # fe/fe-core/src/test/resources/sql/materialized-view/tpch-hive/q1.sql # fe/fe-core/src/test/resources/sql/materialized-view/tpch/q1.sql # fe/fe-core/src/test/resources/sql/query_dump/deep_join_cost.json # fe/fe-core/src/test/resources/sql/query_dump/distinct_constant.json # fe/fe-core/src/test/resources/sql/query_dump/force_rule_based_mv_rewrite.json # fe/fe-core/src/test/resources/sql/query_dump/force_rule_based_mv_rewrite_drinks.json # fe/fe-core/src/test/resources/sql/query_dump/force_rule_based_mv_rewrite_month.json # fe/fe-core/src/test/resources/sql/query_dump/force_rule_based_mv_rewrite_year.json # fe/fe-core/src/test/resources/sql/query_dump/join_init_error.json # fe/fe-core/src/test/resources/sql/query_dump/materialized-view/count_star_rewrite.json # fe/fe-core/src/test/resources/sql/query_dump/materialized-view/mv_rewrite_with_dict_opt1.json # fe/fe-core/src/test/resources/sql/query_dump/nested_view_with_cte.json # fe/fe-core/src/test/resources/sql/query_dump/no_cte_operator_test.json # fe/fe-core/src/test/resources/sql/query_dump/normalize_non_trivial_project.json # fe/fe-core/src/test/resources/sql/query_dump/prune_table_npe.json # fe/fe-core/src/test/resources/sql/query_dump/query_cache_misuse_exogenous_runtime_filter.json # fe/fe-core/src/test/resources/sql/query_dump/query_cache_set_operator.json # fe/fe-core/src/test/resources/sql/query_dump/shared_data_query_test.json # fe/fe-core/src/test/resources/sql/query_dump/split_order_by.json # fe/fe-core/src/test/resources/sql/query_dump/topn_push_down_union.json # fe/fe-core/src/test/resources/sql/query_dump/view_delta.json # fe/fe-core/src/test/resources/sql/scheduler/external/hive/tpch/q1.sql # fe/fe-core/src/test/resources/sql/subquery/in-subquery.sql # fe/fe-core/src/test/resources/sql/subquery/scalar-subquery.sql # fe/fe-core/src/test/resources/sql/tpcds_constraints/AddUniqueKeys.sql # fe/pom.xml # fe/spark-dpp/src/main/java/com/starrocks/load/loadv2/dpp/SparkDpp.java # fe/spark-dpp/src/main/java/com/starrocks/load/loadv2/etl/EtlJobConfig.java # fe/starrocks_intellij_style.xml # fs_brokers/apache_hdfs_broker/src/broker-core/pom.xml # fs_brokers/apache_hdfs_broker/src/pom.xml # gensrc/proto/data.proto # gensrc/proto/descriptors.proto # gensrc/proto/internal_service.proto # gensrc/proto/lake_service.proto # gensrc/proto/lake_types.proto # gensrc/proto/olap_file.proto # gensrc/proto/tablet_schema.proto # gensrc/proto/types.proto # gensrc/script/functions.py # gensrc/thrift/AgentService.thrift # gensrc/thrift/DataSinks.thrift # gensrc/thrift/Descriptors.thrift # gensrc/thrift/FrontendService.thrift # gensrc/thrift/HeartbeatService.thrift # gensrc/thrift/InternalService.thrift # gensrc/thrift/PlanNodes.thrift # gensrc/thrift/Planner.thrift # gensrc/thrift/StatusCode.thrift # gensrc/thrift/Types.thrift # java-extensions/hadoop-ext/src/main/java/com/starrocks/connector/share/iceberg/SerializableTable.java # java-extensions/hive-reader/src/main/java/com/starrocks/hive/reader/HiveScannerFactory.java # java-extensions/hudi-reader/src/main/java/com/starrocks/hudi/reader/HudiSliceScannerFactory.java # java-extensions/iceberg-metadata-reader/pom.xml # java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergMetadataColumnValue.java # java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergMetadataScanner.java # java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergMetadataScannerFactory.java # java-extensions/jni-connector/src/main/java/com/starrocks/jni/connector/ScannerFactory.java # java-extensions/kudu-reader/src/main/java/com/starrocks/kudu/reader/KuduSplitScannerFactory.java # java-extensions/odps-reader/src/main/java/com/starrocks/odps/reader/OdpsSplitScannerFactory.java # java-extensions/paimon-reader/src/main/java/com/starrocks/paimon/reader/PaimonSplitScannerFactory.java # run-be-ut.sh # test/lib/__init__.py # test/lib/sr_sql_lib.py # test/requirements.txt # test/sql/test_analyze_statistics/R/test_analyze_hive_stats # test/sql/test_analyze_statistics/T/test_analyze_hive_stats # test/sql/test_array/R/test_array # test/sql/test_auto_increment/R/test_auto_increment # test/sql/test_auto_increment/T/test_auto_increment # test/sql/test_automatic_bucket/R/test_automatic_partition # test/sql/test_automatic_bucket/T/test_automatic_partition # test/sql/test_automatic_partition/R/test_automatic_partition_fail # test/sql/test_automatic_partition/R/test_automatic_partition_list # test/sql/test_automatic_partition/R/test_insert_overwrite # test/sql/test_column_rename/R/test_column_rename2 # test/sql/test_deltalake/R/test_deltalake_collect_stats # test/sql/test_deltalake/R/test_deltalake_trace # test/sql/test_deltalake/T/test_deltalake_collect_stats # test/sql/test_deltalake/T/test_deltalake_trace # test/sql/test_dictionary/R/test_dictionary # test/sql/test_dictionary/T/test_dictionary # test/sql/test_dml/R/test_update # test/sql/test_dml/T/test_update # test/sql/test_drop_partition/R/test_drop_partition # test/sql/test_drop_partition/T/test_drop_partition # test/sql/test_external_file/R/test_parquet_read_range # test/sql/test_external_file/R/test_parquet_struct_in_struct # test/sql/test_external_file/T/test_parquet_read_range # test/sql/test_external_file/T/test_parquet_struct_in_struct # test/sql/test_files/R/csv_format # test/sql/test_files/T/csv_format # test/sql/test_function/R/test_math # test/sql/test_function/R/test_regex # test/sql/test_function/T/test_math # test/sql/test_iceberg/R/test_iceberg_catalog # test/sql/test_iceberg/R/test_iceberg_distributed_plan # test/sql/test_iceberg/R/test_iceberg_identifier_metrics_cache # test/sql/test_iceberg/R/test_iceberg_logical_metadata_table # test/sql/test_iceberg/T/test_iceberg_catalog # test/sql/test_iceberg/T/test_iceberg_distributed_plan # test/sql/test_iceberg/T/test_iceberg_identifier_metrics_cache # test/sql/test_iceberg/T/test_iceberg_logical_metadata_table # test/sql/test_index/R/test_ngram_bloom_filter # test/sql/test_index/T/test_ngram_bloom_filter # test/sql/test_information_schema/R/test_loads # test/sql/test_information_schema/R/test_task_run_status # test/sql/test_information_schema/T/test_task_run_status # test/sql/test_inverted_index/R/test_inverted_index # test/sql/test_inverted_index/T/test_inverted_index # test/sql/test_list_partition/R/test_add_list_partition # test/sql/test_list_partition/R/test_list_partition_cardinality # test/sql/test_list_partition/T/test_add_list_partition # test/sql/test_list_partition/T/test_list_partition_cardinality # test/sql/test_materialized_column/R/test_generated_column_rewrite # test/sql/test_materialized_column/R/test_materialized_column # test/sql/test_materialized_column/T/test_generated_column_rewrite # test/sql/test_materialized_column/T/test_materialized_column # test/sql/test_materialized_view/R/test_materialized_view_agg_pushdown_rewrite # test/sql/test_materialized_view/R/test_materialized_view_rewrite # test/sql/test_materialized_view/R/test_materialized_view_union # test/sql/test_materialized_view/R/test_mv_iceberg_rewrite # test/sql/test_materialized_view/R/test_mv_join_derivabllity_rewrite # test/sql/test_materialized_view/R/test_mv_or_predicate_rewrite # test/sql/test_materialized_view/R/test_mv_partition_compensate_hive # test/sql/test_materialized_view/R/test_mv_partition_compensate_iceberg_part1 # test/sql/test_materialized_view/R/test_mv_partition_compensate_iceberg_part2 # test/sql/test_materialized_view/R/test_mv_partition_compensate_mysql # test/sql/test_materialized_view/R/test_mv_partition_compensate_olap # test/sql/test_materialized_view/R/test_show_materialized_view # test/sql/test_materialized_view/T/test_materialized_view_rewrite # test/sql/test_materialized_view/T/test_materialized_view_union # test/sql/test_materialized_view/T/test_mv_iceberg_rewrite # test/sql/test_materialized_view/T/test_mv_join_derivabllity_rewrite # test/sql/test_materialized_view/T/test_mv_or_predicate_rewrite # test/sql/test_materialized_view/T/test_mv_partition_compensate_hive # test/sql/test_materialized_view/T/test_mv_partition_compensate_iceberg_part1 # test/sql/test_materialized_view/T/test_mv_partition_compensate_iceberg_part2 # test/sql/test_materialized_view/T/test_mv_partition_compensate_mysql # test/sql/test_materialized_view/T/test_mv_partition_compensate_olap # test/sql/test_materialized_view/T/test_show_materialized_view # test/sql/test_materialized_view_refresh/R/test_mv_refresh_list_partitions_basic # test/sql/test_materialized_view_refresh/R/test_mv_refresh_list_partitions_partial_refresh # test/sql/test_materialized_view_refresh/R/test_mv_refresh_list_partitions_with_nullable # test/sql/test_materialized_view_refresh/R/test_mv_refresh_with_mv_reuse # test/sql/test_materialized_view_refresh/R/test_mv_refresh_with_time_slice # test/sql/test_materialized_view_refresh/R/test_mv_refresh_with_union # test/sql/test_materialized_view_refresh/T/test_mv_refresh_list_partitions_basic # test/sql/test_materialized_view_refresh/T/test_mv_refresh_list_partitions_partial_refresh # test/sql/test_materialized_view_refresh/T/test_mv_refresh_list_partitions_with_nullable # test/sql/test_materialized_view_refresh/T/test_mv_refresh_with_mv_reuse # test/sql/test_materialized_view_refresh/T/test_mv_refresh_with_time_slice # test/sql/test_materialized_view_refresh/T/test_mv_refresh_with_union # test/sql/test_nest_loop_join/R/test_nest_loop_join # test/sql/test_nest_loop_join/T/test_nest_loop_join # test/sql/test_partition_by_expr/R/test_expr_from_unixtime_prune_partition # test/sql/test_partition_by_expr/R/test_expr_str2date # test/sql/test_partition_by_expr/R/test_expr_substr # test/sql/test_partition_by_expr/T/test_expr_from_unixtime_prune_partition # test/sql/test_partition_by_expr/T/test_expr_str2date # test/sql/test_partition_by_expr/T/test_expr_substr # test/sql/test_preparestatement/R/test_driver_prepare # test/sql/test_preparestatement/T/test_driver_prepare # test/sql/test_profile/T/test_load_channel_profile_analysis.sh # test/sql/test_scan/test_pushdown_or_predicate/R/test_index_and_filter_on_or_predicate # test/sql/test_scan/test_pushdown_or_predicate/T/test_index_and_filter_on_or_predicate # test/sql/test_spill/R/test_spill_nl_join # test/sql/test_spill/T/test_spill_nl_join # test/sql/test_task/R/test_drop # test/sql/test_task/R/test_periodical_task # test/sql/test_task/T/test_drop # test/sql/test_task/T/test_periodical_task # test/sql/test_transparent_mv/R/test_transparent_mv_hive # test/sql/test_transparent_mv/R/test_transparent_mv_iceberg_part1 # test/sql/test_transparent_mv/R/test_transparent_mv_iceberg_part2 # test/sql/test_transparent_mv/R/test_transparent_mv_mysql # test/sql/test_transparent_mv/R/test_transparent_mv_union_iceberg # test/sql/test_transparent_mv/T/test_transparent_mv_hive # test/sql/test_transparent_mv/T/test_transparent_mv_iceberg_part1 # test/sql/test_transparent_mv/T/test_transparent_mv_iceberg_part2 # test/sql/test_transparent_mv/T/test_transparent_mv_mysql # test/sql/test_transparent_mv/T/test_transparent_mv_union_iceberg # test/test_sql_cases.py # thirdparty/build-thirdparty.sh # thirdparty/download-thirdparty.sh # thirdparty/starlet-artifacts-version.sh # thirdparty/vars-aarch64.sh # thirdparty/vars-ubuntu22-aarch64.sh # thirdparty/vars-ubuntu22-x86_64.sh # thirdparty/vars-x86_64.sh # thirdparty/vars.sh # tools/stream_load/README.md # trivy.yaml --- .github/CODEOWNERS | 136 ++ .github/PULL_REQUEST_TEMPLATE.md | 8 + .github/workflows/ci-comment-tools.yml | 29 + .github/workflows/ci-merged-sonarcloud-fe.yml | 8 + .github/workflows/ci-merged.yml | 42 + .github/workflows/ci-pipeline-branch.yml | 12 + .github/workflows/ci-pipeline.yml | 304 ++- .github/workflows/ci-report.yml | 129 ++ .github/workflows/ci-sync.yml | 22 + .github/workflows/inspection-pipeline.yml | 128 ++ .github/workflows/pr-checker.yml | 20 + .github/workflows/releasenotes404.yaml | 32 + .gitignore | 4 + .trivyignore | 5 + README.md | 42 + be/.gitignore | 4 + be/CMakeLists.txt | 263 +++ be/cmake_modules/FindClangTidy.cmake | 22 + be/cmake_modules/FindGlibcVersion.cmake | 25 + be/extension/python-udf/src/flight_server.py | 155 ++ be/src/agent/agent_task.cpp | 31 + be/src/agent/finish_task.cpp | 13 + be/src/agent/heartbeat_server.cpp | 17 + be/src/agent/publish_version.cpp | 17 + be/src/agent/report_task.cpp | 4 + be/src/agent/task_worker_pool.cpp | 5 + be/src/agent/utils.cpp | 34 + be/src/agent/utils.h | 7 + be/src/bench/CMakeLists.txt | 5 + be/src/bench/bit_copy.h | 86 + be/src/bench/bit_unpack_bench.cpp | 350 ++++ be/src/bench/block_cache_bench.cpp | 21 + be/src/bench/chunks_sorter_bench.cpp | 20 + be/src/bench/csv_reader_bench.cpp | 8 + be/src/bench/get_dict_codes_bench.cpp | 4 + be/src/bench/mem_equal_bench.cpp | 145 ++ be/src/bench/orc_column_reader_bench.cpp | 10 +- be/src/bench/parquet_dict_decode_bench.cpp | 13 + be/src/bench/persistent_index_bench.cpp | 18 +- be/src/bench/runtime_filter_bench.cpp | 14 + be/src/bench/shuffle_chunk_bench.cpp | 189 ++ be/src/block_cache/CMakeLists.txt | 6 + be/src/block_cache/block_cache.cpp | 23 + be/src/block_cache/block_cache.h | 15 + be/src/block_cache/cache_options.h | 19 + be/src/block_cache/datacache_utils.cpp | 30 + be/src/block_cache/datacache_utils.h | 10 +- be/src/block_cache/disk_space_monitor.cpp | 12 + be/src/block_cache/kv_cache.h | 9 + be/src/block_cache/starcache_wrapper.cpp | 29 + be/src/block_cache/starcache_wrapper.h | 10 + be/src/column/adaptive_nullable_column.cpp | 43 + be/src/column/adaptive_nullable_column.h | 22 + be/src/column/array_column.h | 9 + be/src/column/array_view_column.h | 9 + be/src/column/binary_column.cpp | 107 + be/src/column/binary_column.h | 25 + be/src/column/bytes.h | 8 + be/src/column/chunk.cpp | 12 + be/src/column/chunk.h | 13 + be/src/column/column.cpp | 4 + be/src/column/column.h | 53 + be/src/column/column_builder.h | 4 + be/src/column/column_hash.h | 18 + be/src/column/column_helper.cpp | 40 + be/src/column/column_helper.h | 15 + be/src/column/column_viewer.cpp | 16 + be/src/column/const_column.cpp | 4 + be/src/column/const_column.h | 26 + be/src/column/datum.h | 7 + be/src/column/field.h | 81 + be/src/column/fixed_length_column_base.cpp | 18 + be/src/column/fixed_length_column_base.h | 25 + be/src/column/hash_set.h | 4 + be/src/column/json_column.cpp | 13 + be/src/column/json_column.h | 4 + be/src/column/map_column.h | 10 + be/src/column/nullable_column.cpp | 26 + be/src/column/nullable_column.h | 23 + be/src/column/object_column.cpp | 11 + be/src/column/object_column.h | 21 + be/src/column/schema.cpp | 7 + be/src/column/struct_column.cpp | 11 + be/src/column/struct_column.h | 7 + be/src/column/vectorized_fwd.h | 24 + be/src/common/config.h | 151 ++ be/src/common/daemon.cpp | 56 + be/src/common/format_ip.h | 86 + be/src/common/logconfig.cpp | 3 + be/src/common/logging.h | 6 + be/src/common/status.cpp | 5 + be/src/common/status.h | 10 + be/src/common/vlog_cntl.h | 46 + be/src/connector/CMakeLists.txt | 4 + be/src/connector/connector.cpp | 16 + be/src/connector/connector.h | 8 + .../deletion_vector/deletion_vector.cpp | 170 ++ .../deletion_vector/deletion_vector.h | 57 + be/src/connector/hive_connector.cpp | 120 ++ be/src/connector/hive_connector.h | 32 + be/src/connector/lake_connector.cpp | 124 ++ be/src/connector/lake_connector.h | 32 + be/src/exec/CMakeLists.txt | 12 + be/src/exec/aggregate/agg_hash_map.h | 147 ++ be/src/exec/aggregate/agg_hash_set.h | 424 ++++ be/src/exec/aggregate/aggregate_base_node.cpp | 3 + be/src/exec/aggregator.cpp | 223 ++ be/src/exec/aggregator.h | 99 + be/src/exec/analytor.cpp | 98 + be/src/exec/analytor.h | 49 + be/src/exec/arrow_flight_batch_reader.cpp | 45 + be/src/exec/arrow_flight_batch_reader.h | 34 + be/src/exec/arrow_to_starrocks_converter.cpp | 17 + be/src/exec/arrow_to_starrocks_converter.h | 7 + be/src/exec/capture_version_node.cpp | 6 + be/src/exec/chunks_sorter.cpp | 4 + be/src/exec/chunks_sorter.h | 28 + be/src/exec/chunks_sorter_full_sort.h | 12 + be/src/exec/chunks_sorter_heap_sort.h | 6 + be/src/exec/chunks_sorter_topn.h | 34 + be/src/exec/connector_scan_node.cpp | 6 + be/src/exec/csv_scanner.cpp | 12 + be/src/exec/csv_scanner.h | 8 + be/src/exec/data_sink.cpp | 5 + be/src/exec/data_sink.h | 23 + be/src/exec/dictionary_cache_writer.h | 3 + be/src/exec/es/es_predicate.cpp | 6 + be/src/exec/es/es_scan_reader.cpp | 5 + be/src/exec/except_hash_set.cpp | 9 + be/src/exec/except_hash_set.h | 4 + be/src/exec/exec_node.h | 57 + be/src/exec/file_scanner.cpp | 4 + be/src/exec/hash_join_components.cpp | 751 +++++++ be/src/exec/hash_join_components.h | 168 ++ be/src/exec/hash_join_node.cpp | 23 + be/src/exec/hash_join_node.h | 11 + be/src/exec/hash_joiner.cpp | 181 ++ be/src/exec/hash_joiner.h | 108 + be/src/exec/hdfs_scanner.cpp | 101 + be/src/exec/hdfs_scanner.h | 77 + be/src/exec/hdfs_scanner_orc.cpp | 21 + be/src/exec/hdfs_scanner_parquet.cpp | 48 + be/src/exec/hdfs_scanner_text.cpp | 4 + .../exec/iceberg/iceberg_delete_builder.cpp | 276 +++ be/src/exec/iceberg/iceberg_delete_builder.h | 35 + be/src/exec/intersect_hash_set.cpp | 16 + be/src/exec/intersect_hash_set.h | 4 + be/src/exec/jdbc_scanner.cpp | 11 + be/src/exec/jdbc_scanner.h | 28 + be/src/exec/jni_scanner.cpp | 23 + be/src/exec/jni_scanner.h | 7 + be/src/exec/join_hash_map.cpp | 37 + be/src/exec/join_hash_map.h | 48 + be/src/exec/join_hash_map.tpp | 44 + be/src/exec/json_scanner.cpp | 43 + be/src/exec/json_scanner.h | 8 + be/src/exec/local_file_writer.cpp | 18 + be/src/exec/olap_common.cpp | 93 + be/src/exec/olap_common.h | 22 + be/src/exec/olap_scan_node.cpp | 86 + be/src/exec/olap_scan_node.h | 15 + be/src/exec/olap_scan_prepare.cpp | 770 +++++++ be/src/exec/olap_scan_prepare.h | 159 ++ be/src/exec/olap_utils.h | 34 + be/src/exec/orc_scanner.cpp | 6 + be/src/exec/parquet_reader.cpp | 4 + be/src/exec/parquet_reader.h | 9 + be/src/exec/parquet_scanner.cpp | 35 + be/src/exec/partition/chunks_partitioner.cpp | 19 + be/src/exec/partition/chunks_partitioner.h | 21 + be/src/exec/partition/partition_hash_map.h | 11 + .../exec/partition/partition_hash_variant.cpp | 10 + .../exec/partition/partition_hash_variant.h | 5 + .../aggregate_blocking_sink_operator.h | 15 + .../aggregate_blocking_source_operator.h | 8 + ...ggregate_distinct_blocking_sink_operator.h | 15 + ...regate_distinct_blocking_source_operator.h | 8 + ...gregate_distinct_streaming_sink_operator.h | 24 + ...egate_distinct_streaming_source_operator.h | 11 + .../aggregate_streaming_sink_operator.h | 26 + .../aggregate_streaming_source_operator.h | 11 + ...sorted_aggregate_streaming_sink_operator.h | 10 + ...rted_aggregate_streaming_source_operator.h | 9 + ...illable_aggregate_blocking_sink_operator.h | 25 + ...lable_aggregate_blocking_source_operator.h | 18 + ...ble_aggregate_distinct_blocking_operator.h | 38 + .../pipeline/audit_statistics_reporter.cpp | 18 + .../exec/pipeline/audit_statistics_reporter.h | 4 + .../exec/pipeline/chunk_accumulate_operator.h | 4 + .../exec/pipeline/context_with_dependency.h | 4 + .../exchange/exchange_sink_operator.cpp | 17 + .../exchange/local_exchange_sink_operator.h | 5 + .../exchange/local_exchange_source_operator.h | 12 + .../exchange/mem_limited_chunk_queue.cpp | 3 + .../multi_cast_local_exchange_sink_operator.h | 5 + ...ulti_cast_local_exchange_source_operator.h | 5 + be/src/exec/pipeline/exchange/sink_buffer.cpp | 134 ++ be/src/exec/pipeline/exchange/sink_buffer.h | 51 + be/src/exec/pipeline/exec_state_reporter.cpp | 34 + be/src/exec/pipeline/fragment_context.cpp | 55 + be/src/exec/pipeline/fragment_context.h | 20 + be/src/exec/pipeline/fragment_executor.cpp | 208 ++ be/src/exec/pipeline/fragment_executor.h | 5 + .../exec/pipeline/hash_partition_context.cpp | 10 + be/src/exec/pipeline/hash_partition_context.h | 4 + .../hashjoin/hash_join_build_operator.cpp | 32 + .../hashjoin/hash_join_build_operator.h | 18 + .../hashjoin/hash_join_probe_operator.cpp | 39 + .../hashjoin/hash_join_probe_operator.h | 8 + .../exec/pipeline/hashjoin/hash_joiner_fwd.h | 31 + .../spillable_hash_join_build_operator.cpp | 95 + .../spillable_hash_join_build_operator.h | 25 + .../spillable_hash_join_probe_operator.cpp | 34 + .../spillable_hash_join_probe_operator.h | 12 + be/src/exec/pipeline/limit_operator.cpp | 24 + be/src/exec/pipeline/limit_operator.h | 5 + .../pipeline/nljoin/nljoin_build_operator.h | 4 + .../exec/pipeline/nljoin/nljoin_context.cpp | 8 + be/src/exec/pipeline/nljoin/nljoin_context.h | 10 + .../pipeline/nljoin/nljoin_probe_operator.cpp | 24 + .../pipeline/nljoin/nljoin_probe_operator.h | 12 + .../nljoin/spillable_nljoin_probe_operator.h | 4 + be/src/exec/pipeline/operator.cpp | 50 + be/src/exec/pipeline/operator.h | 11 + be/src/exec/pipeline/pipeline.h | 9 + be/src/exec/pipeline/pipeline_driver.cpp | 16 + be/src/exec/pipeline/pipeline_driver.h | 20 + be/src/exec/pipeline/pipeline_fwd.h | 9 + be/src/exec/pipeline/query_context.cpp | 64 + be/src/exec/pipeline/query_context.h | 69 + be/src/exec/pipeline/result_sink_operator.cpp | 49 + be/src/exec/pipeline/result_sink_operator.h | 37 + be/src/exec/pipeline/runtime_filter_types.h | 63 + be/src/exec/pipeline/scan/chunk_source.h | 4 + .../pipeline/scan/connector_scan_operator.cpp | 33 + .../pipeline/scan/connector_scan_operator.h | 11 + .../exec/pipeline/scan/meta_scan_operator.cpp | 11 + .../exec/pipeline/scan/meta_scan_operator.h | 4 + .../scan/meta_scan_prepare_operator.cpp | 8 + be/src/exec/pipeline/scan/morsel.cpp | 117 ++ be/src/exec/pipeline/scan/morsel.h | 65 + .../exec/pipeline/scan/olap_chunk_source.cpp | 179 ++ be/src/exec/pipeline/scan/olap_chunk_source.h | 33 + .../exec/pipeline/scan/olap_scan_context.cpp | 40 + be/src/exec/pipeline/scan/olap_scan_context.h | 8 + .../exec/pipeline/scan/olap_scan_operator.cpp | 5 + .../exec/pipeline/scan/olap_scan_operator.h | 4 + be/src/exec/pipeline/scan/scan_operator.cpp | 23 + be/src/exec/pipeline/scan/scan_operator.h | 65 + .../pipeline/scan/schema_scan_operator.cpp | 3 + .../exec/pipeline/scan/schema_scan_operator.h | 4 + be/src/exec/pipeline/select_operator.cpp | 34 + be/src/exec/pipeline/select_operator.h | 28 + .../sort/local_partition_topn_context.cpp | 286 +++ .../sort/local_partition_topn_context.h | 134 ++ be/src/exec/pipeline/sort/sort_context.cpp | 8 + be/src/exec/pipeline/sort/sort_context.h | 14 + be/src/exec/pipeline/stream_epoch_manager.h | 13 + be/src/exec/pipeline/stream_pipeline_driver.h | 9 + .../exec/pipeline/table_function_operator.h | 18 + be/src/exec/query_cache/cache_manager.h | 4 + be/src/exec/query_cache/cache_operator.cpp | 138 ++ be/src/exec/query_cache/cache_operator.h | 4 + be/src/exec/query_cache/cache_param.h | 4 + be/src/exec/query_cache/multilane_operator.h | 32 + be/src/exec/scan_node.cpp | 22 + be/src/exec/scan_node.h | 4 + be/src/exec/schema_scan_node.cpp | 4 + be/src/exec/select_node.cpp | 20 + be/src/exec/select_node.h | 9 + be/src/exec/sorted_streaming_aggregator.cpp | 41 + be/src/exec/sorted_streaming_aggregator.h | 9 + be/src/exec/sorting/compare_column.cpp | 4 + be/src/exec/sorting/merge.h | 34 + be/src/exec/sorting/merge_column.cpp | 33 + be/src/exec/sorting/sort_permute.h | 4 + be/src/exec/sorting/sorting.h | 5 + be/src/exec/spill/common.h | 8 + be/src/exec/spill/mem_table.cpp | 4 + be/src/exec/spill/mem_table.h | 15 + be/src/exec/spill/spiller.h | 8 + .../exec/stream/aggregate/agg_group_state.cpp | 9 + .../exec/stream/aggregate/agg_group_state.h | 29 + .../exec/stream/aggregate/agg_state_data.cpp | 4 + be/src/exec/stream/aggregate/agg_state_data.h | 21 + .../aggregate/stream_aggregate_operator.h | 14 + .../exec/stream/aggregate/stream_aggregator.h | 48 + .../exec/stream/scan/stream_scan_operator.h | 30 + be/src/exec/stream/state/mem_state_table.cpp | 45 + be/src/exec/stream/state/mem_state_table.h | 27 + be/src/exec/stream/state/state_table.h | 25 + be/src/exec/tablet_info.cpp | 56 + be/src/exec/tablet_info.h | 13 + be/src/exec/tablet_scanner.cpp | 29 + be/src/exec/tablet_scanner.h | 4 + be/src/exec/tablet_sink.cpp | 40 + be/src/exec/tablet_sink.h | 4 + be/src/exec/tablet_sink_index_channel.cpp | 12 + be/src/exec/tablet_sink_index_channel.h | 15 + be/src/exec/tablet_sink_sender.cpp | 4 + be/src/exec/topn_node.cpp | 27 + be/src/exec/topn_node.h | 5 + be/src/exec/union_node.h | 17 + be/src/exec/write_combined_txn_log.h | 4 + be/src/exprs/CMakeLists.txt | 34 + be/src/exprs/agg/agg_state_merge.h | 90 + be/src/exprs/agg/agg_state_union.h | 84 + be/src/exprs/agg/aggregate.h | 56 + be/src/exprs/agg/aggregate_factory.h | 6 + be/src/exprs/agg/aggregate_state_allocator.h | 112 + be/src/exprs/agg/approx_top_k.h | 8 + be/src/exprs/agg/array_agg.h | 30 + be/src/exprs/agg/array_union_agg.h | 14 + be/src/exprs/agg/avg.h | 11 + be/src/exprs/agg/bitmap_agg.h | 4 + be/src/exprs/agg/count.h | 8 + be/src/exprs/agg/distinct.h | 158 ++ be/src/exprs/agg/ds_hll_count_distinct.h | 240 +++ .../exprs/agg/factory/aggregate_factory.cpp | 56 + .../exprs/agg/factory/aggregate_factory.hpp | 55 + .../exprs/agg/factory/aggregate_resolver.hpp | 7 + .../agg/factory/aggregate_resolver_approx.cpp | 6 + .../agg/factory/aggregate_resolver_avg.cpp | 32 + .../aggregate_resolver_hypothesis_testing.cpp | 26 + .../factory/aggregate_resolver_minmaxany.cpp | 9 + .../agg/factory/aggregate_resolver_others.cpp | 23 + be/src/exprs/agg/group_concat.h | 4 + .../exprs/agg/helpers/serialize_helpers.hpp | 258 +++ be/src/exprs/agg/hll_ndv.h | 37 + be/src/exprs/agg/hll_union.h | 21 + be/src/exprs/agg/hll_union_count.h | 32 + be/src/exprs/agg/hypothesis_testing_common.h | 63 + be/src/exprs/agg/java_udaf_function.h | 8 + be/src/exprs/agg/mann_whitney.h | 355 ++++ be/src/exprs/agg/map_agg.h | 160 ++ be/src/exprs/agg/nullable_aggregate.h | 16 + be/src/exprs/agg/percentile_approx.h | 21 + be/src/exprs/agg/percentile_cont.h | 275 ++- be/src/exprs/agg/percentile_union.h | 26 + be/src/exprs/agg/sum.h | 4 + be/src/exprs/agg/window.h | 8 + be/src/exprs/agg_state_function.h | 95 + be/src/exprs/arithmetic_expr.cpp | 58 + be/src/exprs/arithmetic_operation.h | 48 + be/src/exprs/array_element_expr.cpp | 4 + be/src/exprs/array_functions.tpp | 4 + be/src/exprs/array_map_expr.cpp | 3 + be/src/exprs/arrow_function_call.cpp | 135 ++ be/src/exprs/arrow_function_call.h | 47 + be/src/exprs/binary_predicate.cpp | 33 + be/src/exprs/bitmap_functions.cpp | 5 + be/src/exprs/builtin_functions.h | 6 + be/src/exprs/case_expr.cpp | 18 + be/src/exprs/cast_expr.cpp | 56 + be/src/exprs/cast_expr.h | 41 + be/src/exprs/cast_expr_struct.cpp | 133 ++ be/src/exprs/compound_predicate.cpp | 35 + be/src/exprs/debug_expr.cpp | 4 + be/src/exprs/debug_expr.h | 4 + be/src/exprs/decimal_binary_function.h | 8 + be/src/exprs/expr.cpp | 57 + be/src/exprs/expr.h | 64 + be/src/exprs/expr_context.cpp | 9 + be/src/exprs/expr_context.h | 23 + be/src/exprs/function_call_expr.cpp | 68 + be/src/exprs/function_call_expr.h | 28 + be/src/exprs/function_context.cpp | 5 + be/src/exprs/function_context.h | 37 + be/src/exprs/function_helper.cpp | 62 + be/src/exprs/function_helper.h | 22 + be/src/exprs/in_const_predicate.hpp | 24 + be/src/exprs/inet_aton.cpp | 48 + be/src/exprs/java_function_call_expr.cpp | 11 + be/src/exprs/java_function_call_expr.h | 6 + be/src/exprs/jit/jit_expr.cpp | 3 + be/src/exprs/json_functions.h | 26 + be/src/exprs/like_predicate.cpp | 4 + be/src/exprs/literal.cpp | 19 + be/src/exprs/literal.h | 8 + be/src/exprs/locate.cpp | 4 + be/src/exprs/map_apply_expr.cpp | 3 + be/src/exprs/map_functions.cpp | 4 + be/src/exprs/math_functions.cpp | 113 + be/src/exprs/math_functions.h | 12 + be/src/exprs/min_max_predicate.h | 150 ++ be/src/exprs/percentile_functions.cpp | 39 + be/src/exprs/regexp_split.cpp | 115 ++ be/src/exprs/regexp_split.h | 44 + be/src/exprs/runtime_filter_bank.cpp | 28 + be/src/exprs/runtime_filter_bank.h | 14 + be/src/exprs/split.cpp | 4 + be/src/exprs/string_functions.cpp | 230 +++ be/src/exprs/string_functions.h | 24 + be/src/exprs/table_function/generate_series.h | 12 + .../exprs/table_function/java_udtf_function.h | 9 + be/src/exprs/table_function/json_each.h | 12 + be/src/exprs/table_function/list_rowsets.cpp | 4 + be/src/exprs/table_function/list_rowsets.h | 12 + be/src/exprs/table_function/multi_unnest.h | 12 + .../exprs/table_function/subdivide_bitmap.h | 17 + be/src/exprs/table_function/table_function.h | 13 + be/src/exprs/table_function/unnest.h | 12 + be/src/exprs/unary_function.h | 3 + be/src/exprs/utility_functions.cpp | 69 + be/src/exprs/utility_functions.h | 9 + be/src/formats/CMakeLists.txt | 10 + be/src/formats/csv/json_converter.h | 6 + .../orc/apache-orc/c++/include/orc/Common.hh | 45 + .../formats/orc/apache-orc/c++/src/Int128.cc | 4 + .../orc/apache-orc/c++/src/Statistics.hh | 5 + be/src/formats/orc/orc_chunk_reader.cpp | 10 + be/src/formats/parquet/chunk_writer.cpp | 15 + be/src/formats/parquet/chunk_writer.h | 33 + .../formats/parquet/column_chunk_reader.cpp | 42 + be/src/formats/parquet/column_chunk_reader.h | 38 + .../formats/parquet/column_chunk_writer.cpp | 6 + be/src/formats/parquet/column_chunk_writer.h | 11 + be/src/formats/parquet/column_converter.cpp | 35 + be/src/formats/parquet/column_converter.h | 14 + .../formats/parquet/column_read_order_ctx.cpp | 10 + .../formats/parquet/column_read_order_ctx.h | 9 + be/src/formats/parquet/column_reader.cpp | 33 + be/src/formats/parquet/column_reader.h | 115 ++ .../formats/parquet/column_reader_factory.cpp | 266 +++ .../formats/parquet/column_reader_factory.h | 46 + .../formats/parquet/complex_column_reader.cpp | 354 ++++ .../formats/parquet/complex_column_reader.h | 222 ++ be/src/formats/parquet/encoding.cpp | 8 + be/src/formats/parquet/encoding.h | 15 + be/src/formats/parquet/encoding_dict.h | 26 + be/src/formats/parquet/file_reader.cpp | 328 +++ be/src/formats/parquet/file_reader.h | 78 + be/src/formats/parquet/file_writer.cpp | 28 + be/src/formats/parquet/file_writer.h | 46 + be/src/formats/parquet/group_reader.cpp | 226 ++ be/src/formats/parquet/group_reader.h | 76 + be/src/formats/parquet/level_builder.cpp | 23 + be/src/formats/parquet/level_builder.h | 26 + be/src/formats/parquet/level_codec.cpp | 7 + be/src/formats/parquet/level_codec.h | 13 + be/src/formats/parquet/meta_helper.cpp | 24 + be/src/formats/parquet/meta_helper.h | 43 + be/src/formats/parquet/metadata.cpp | 169 ++ be/src/formats/parquet/metadata.h | 48 + be/src/formats/parquet/page_index_reader.cpp | 21 + be/src/formats/parquet/page_index_reader.h | 34 + be/src/formats/parquet/page_reader.cpp | 11 + be/src/formats/parquet/page_reader.h | 10 + .../formats/parquet/parquet_file_writer.cpp | 38 + be/src/formats/parquet/parquet_file_writer.h | 55 + .../formats/parquet/scalar_column_reader.cpp | 420 ++++ be/src/formats/parquet/scalar_column_reader.h | 157 ++ be/src/formats/parquet/schema.cpp | 10 + be/src/formats/parquet/schema.h | 8 + be/src/formats/parquet/statistics_helper.cpp | 67 +- be/src/formats/parquet/statistics_helper.h | 27 +- .../formats/parquet/stored_column_reader.cpp | 25 + be/src/formats/parquet/stored_column_reader.h | 34 + .../stored_column_reader_with_index.cpp | 12 + .../parquet/stored_column_reader_with_index.h | 26 + be/src/formats/parquet/utils.cpp | 46 + be/src/formats/parquet/utils.h | 18 + .../parquet/zone_map_filter_evaluator.h | 102 + be/src/fs/CMakeLists.txt | 13 + be/src/fs/fs.cpp | 33 + be/src/fs/fs.h | 45 + be/src/fs/fs_broker.cpp | 22 + be/src/fs/fs_s3.cpp | 169 ++ be/src/fs/fs_s3.h | 94 + be/src/fs/fs_starlet.cpp | 4 + be/src/fs/hdfs/fs_hdfs.cpp | 28 + be/src/fs/s3/poco_common.cpp | 139 ++ be/src/fs/s3/poco_common.h | 119 ++ be/src/fs/s3/poco_http_client.cpp | 206 ++ be/src/fs/s3/poco_http_client.h | 52 + be/src/fs/s3/poco_http_client_factory.cpp | 44 + be/src/fs/s3/poco_http_client_factory.h | 41 + be/src/fs/s3/pool_base.h | 130 ++ be/src/gen_cpp/CMakeLists.txt | 3 + be/src/geo/wkt_parse.cpp | 4 + be/src/geo/wkt_yacc.y | 12 + be/src/gutil/CMakeLists.txt | 5 + be/src/gutil/strings/join.h | 4 + be/src/http/action/checksum_action.cpp | 3 + be/src/http/action/datacache_action.cpp | 3 + be/src/http/action/memory_metrics_action.cpp | 3 + be/src/http/action/metrics_action.h | 6 + be/src/http/action/stream_load.cpp | 73 + be/src/http/action/stream_load.h | 9 + be/src/http/action/update_config_action.cpp | 16 + be/src/http/default_path_handlers.cpp | 3 + be/src/http/download_action.cpp | 3 + be/src/http/http_client.h | 7 + be/src/http/http_common.h | 11 + be/src/io/cache_input_stream.cpp | 7 + be/src/io/cache_input_stream.h | 9 + be/src/io/cache_select_input_stream.hpp | 11 +- be/src/io/direct_s3_output_stream.cpp | 20 + be/src/io/s3_input_stream.cpp | 84 + be/src/io/s3_input_stream.h | 25 + be/src/io/s3_output_stream.cpp | 12 + be/src/io/s3_zero_copy_iostream.h | 51 + be/src/runtime/CMakeLists.txt | 34 + be/src/runtime/agg_state_desc.cpp | 124 ++ be/src/runtime/agg_state_desc.h | 114 + be/src/runtime/arrow_result_writer.cpp | 85 + be/src/runtime/arrow_result_writer.h | 62 + .../runtime/batch_write/batch_write_mgr.cpp | 227 ++ be/src/runtime/batch_write/batch_write_mgr.h | 67 + .../runtime/batch_write/batch_write_util.cpp | 105 + be/src/runtime/batch_write/batch_write_util.h | 64 + .../batch_write/isomorphic_batch_write.cpp | 464 +++++ .../batch_write/isomorphic_batch_write.h | 89 + be/src/runtime/broker_mgr.cpp | 14 + be/src/runtime/buffer_control_block.cpp | 134 ++ be/src/runtime/buffer_control_block.h | 46 + .../runtime/buffer_control_result_writer.cpp | 63 + be/src/runtime/buffer_control_result_writer.h | 48 + be/src/runtime/chunk_cursor.h | 4 + be/src/runtime/customized_result_writer.cpp | 19 + be/src/runtime/customized_result_writer.h | 19 + be/src/runtime/data_stream_mgr.h | 4 + be/src/runtime/data_stream_sender.cpp | 15 + be/src/runtime/data_stream_sender.h | 3 + be/src/runtime/descriptors.cpp | 99 + be/src/runtime/descriptors.h | 40 + be/src/runtime/exec_env.cpp | 88 + be/src/runtime/exec_env.h | 36 + be/src/runtime/file_result_writer.h | 5 + be/src/runtime/fragment_mgr.cpp | 59 + be/src/runtime/fragment_mgr.h | 27 + be/src/runtime/global_dict/miscs.cpp | 4 + be/src/runtime/global_dict/parser.cpp | 4 + be/src/runtime/global_dict/parser.h | 17 + be/src/runtime/global_variables.cpp | 27 + be/src/runtime/global_variables.h | 48 + be/src/runtime/http_result_writer.cpp | 14 + be/src/runtime/http_result_writer.h | 20 + be/src/runtime/lake_snapshot_loader.cpp | 3 + be/src/runtime/lake_tablets_channel.cpp | 132 ++ be/src/runtime/load_channel.cpp | 81 + be/src/runtime/load_channel.h | 17 + be/src/runtime/load_path_mgr.cpp | 3 + be/src/runtime/local_tablets_channel.cpp | 189 ++ be/src/runtime/local_tablets_channel.h | 30 + be/src/runtime/mem_pool.h | 29 + be/src/runtime/memory/allocator.h | 72 + be/src/runtime/memory/column_allocator.cpp | 21 + be/src/runtime/memory/column_allocator.h | 82 + be/src/runtime/memory/counting_allocator.h | 180 ++ be/src/runtime/memory/mem_hook_allocator.h | 45 + be/src/runtime/memory/roaring_hook.cpp | 73 + be/src/runtime/memory/roaring_hook.h | 32 + be/src/runtime/metadata_result_writer.cpp | 24 + be/src/runtime/metadata_result_writer.h | 18 + be/src/runtime/mysql_result_writer.cpp | 28 + be/src/runtime/mysql_result_writer.h | 20 + be/src/runtime/plan_fragment_executor.cpp | 10 + be/src/runtime/query_statistics.cpp | 68 + be/src/runtime/query_statistics.h | 34 + be/src/runtime/result_buffer_mgr.cpp | 24 + be/src/runtime/result_buffer_mgr.h | 23 + be/src/runtime/result_queue_mgr.h | 8 + be/src/runtime/result_sink.cpp | 4 + be/src/runtime/result_sink.h | 8 + be/src/runtime/result_writer.h | 27 + be/src/runtime/runtime_filter_worker.cpp | 84 + be/src/runtime/runtime_filter_worker.h | 20 + be/src/runtime/runtime_state.cpp | 28 + be/src/runtime/runtime_state.h | 51 + be/src/runtime/schema_table_sink.cpp | 4 + be/src/runtime/small_file_mgr.h | 18 + be/src/runtime/snapshot_loader.cpp | 13 + be/src/runtime/statistic_result_writer.cpp | 71 + be/src/runtime/statistic_result_writer.h | 26 + .../stream_load/stream_load_context.cpp | 24 + .../runtime/stream_load/stream_load_context.h | 23 + .../runtime/stream_load/stream_load_pipe.cpp | 51 + be/src/runtime/stream_load/stream_load_pipe.h | 63 + .../time_bounded_stream_load_pipe.cpp | 44 + .../time_bounded_stream_load_pipe.h | 67 + be/src/runtime/stream_load/transaction_mgr.h | 4 + be/src/runtime/table_function_table_sink.cpp | 12 + be/src/runtime/table_function_table_sink.h | 4 + be/src/runtime/tablets_channel.h | 14 + be/src/runtime/time_types.h | 4 + be/src/runtime/types.cpp | 8 + be/src/runtime/types.h | 5 + be/src/runtime/user_function_cache.cpp | 20 + be/src/runtime/user_function_cache.h | 7 + be/src/runtime/variable_result_writer.cpp | 19 + be/src/runtime/variable_result_writer.h | 16 + be/src/script/CMakeLists.txt | 5 + be/src/script/script.cpp | 25 + be/src/serde/column_array_serde.cpp | 20 + be/src/service/CMakeLists.txt | 4 + be/src/service/internal_service.cpp | 58 + be/src/service/internal_service.h | 12 + be/src/service/mem_hook.cpp | 183 ++ be/src/service/service_be/CMakeLists.txt | 4 + .../service_be/arrow_flight_sql_service.cpp | 96 + .../service_be/arrow_flight_sql_service.h | 45 + .../service/service_be/internal_service.cpp | 3 + be/src/service/service_be/internal_service.h | 3 + be/src/service/service_be/lake_service.cpp | 76 + be/src/service/service_be/lake_service.h | 5 + be/src/service/service_be/starrocks_be.cpp | 140 ++ be/src/service/staros_worker.cpp | 12 + be/src/service/staros_worker.h | 8 + be/src/service/starrocks_main.cpp | 19 + be/src/simd/multi_version.h | 39 + be/src/simd/simd.h | 134 ++ be/src/starrocks_format/CMakeLists.txt | 82 + be/src/starrocks_format/starrocks_lib.cpp | 84 + be/src/starrocks_format/starrocks_lib.h | 27 + be/src/storage/CMakeLists.txt | 53 + be/src/storage/aggregate_iterator.cpp | 8 + be/src/storage/aggregate_type.cpp | 21 + be/src/storage/aggregate_type.h | 6 + be/src/storage/async_delta_writer.cpp | 4 + be/src/storage/base_tablet.h | 10 + be/src/storage/chunk_aggregator.cpp | 16 + be/src/storage/chunk_helper.cpp | 494 +++++ be/src/storage/chunk_helper.h | 85 + be/src/storage/chunk_iterator.cpp | 8 + be/src/storage/chunk_iterator.h | 28 + be/src/storage/column_aggregate_func.cpp | 84 + be/src/storage/column_aggregate_func.h | 9 + be/src/storage/column_and_predicate.cpp | 80 + be/src/storage/column_and_predicate.h | 58 + be/src/storage/column_expr_predicate.h | 30 + be/src/storage/column_in_predicate.cpp | 137 ++ be/src/storage/column_not_in_predicate.cpp | 35 + be/src/storage/column_null_predicate.cpp | 27 + be/src/storage/column_operator_predicate.h | 5 + be/src/storage/column_or_predicate.cpp | 16 + be/src/storage/column_or_predicate.h | 9 + be/src/storage/column_predicate.h | 47 + be/src/storage/column_predicate_cmp.cpp | 108 + .../storage/column_predicate_dict_conjuct.cpp | 4 + be/src/storage/column_predicate_rewriter.cpp | 474 +++++ be/src/storage/column_predicate_rewriter.h | 101 + be/src/storage/compaction.cpp | 16 + be/src/storage/compaction_manager.h | 7 + be/src/storage/compaction_task.cpp | 16 + be/src/storage/compaction_task.h | 8 + be/src/storage/compaction_utils.cpp | 8 + be/src/storage/compaction_utils.h | 4 + be/src/storage/delta_writer.cpp | 59 + be/src/storage/delta_writer.h | 89 + be/src/storage/horizontal_compaction_task.cpp | 6 + be/src/storage/index/index_descriptor.h | 58 + .../clucene/clucene_inverted_reader.cpp | 162 ++ .../clucene/clucene_inverted_reader.h | 86 + .../inverted/clucene/clucene_inverted_util.h | 41 + .../clucene/clucene_inverted_writer.cpp | 260 +++ .../clucene/clucene_inverted_writer.h | 54 + .../index/inverted/clucene/clucene_plugin.cpp | 31 + .../index/inverted/clucene/clucene_plugin.h | 53 + .../clucene/clucene_roaring_hit_collector.h | 29 + .../index/inverted/clucene/match_operator.cpp | 73 + .../index/inverted/clucene/match_operator.h | 122 ++ .../index/inverted/inverted_index_common.h | 66 + .../inverted/inverted_index_iterator.cpp | 38 + .../index/inverted/inverted_index_iterator.h | 53 + .../index/inverted/inverted_index_option.cpp | 84 + .../index/inverted/inverted_index_option.h | 38 + .../storage/index/inverted/inverted_plugin.h | 36 + .../inverted/inverted_plugin_factory.cpp | 30 + .../index/inverted/inverted_plugin_factory.h | 27 + .../storage/index/inverted/inverted_reader.h | 61 + .../storage/index/inverted/inverted_writer.h | 44 + .../index/vector/empty_index_reader.cpp | 17 + .../storage/index/vector/empty_index_reader.h | 43 + .../index/vector/tenann/del_id_filter.cpp | 52 + .../index/vector/tenann/del_id_filter.h | 54 + .../vector/tenann/tenann_index_builder.cpp | 184 ++ .../vector/tenann/tenann_index_builder.h | 60 + .../vector/tenann/tenann_index_utils.cpp | 125 ++ .../index/vector/tenann/tenann_index_utils.h | 48 + .../index/vector/tenann_index_reader.cpp | 100 + .../index/vector/tenann_index_reader.h | 49 + .../index/vector/vector_index_builder.cpp | 29 + .../index/vector/vector_index_builder.h | 80 + .../vector/vector_index_builder_factory.cpp | 37 + .../vector/vector_index_builder_factory.h | 38 + .../index/vector/vector_index_reader.h | 62 + .../vector/vector_index_reader_factory.cpp | 46 + .../vector/vector_index_reader_factory.h | 32 + .../index/vector/vector_index_writer.cpp | 142 ++ .../index/vector/vector_index_writer.h | 81 + .../index/vector/vector_search_option.h | 57 + be/src/storage/lake/async_delta_writer.cpp | 20 + be/src/storage/lake/async_delta_writer.h | 8 + be/src/storage/lake/delta_writer.cpp | 34 + be/src/storage/lake/delta_writer.h | 7 + be/src/storage/lake/general_tablet_writer.cpp | 38 + .../lake/horizontal_compaction_task.cpp | 6 + be/src/storage/lake/lake_delvec_loader.cpp | 47 + be/src/storage/lake/lake_delvec_loader.h | 44 + be/src/storage/lake/lake_primary_index.cpp | 5 + ...imary_key_compaction_conflict_resolver.cpp | 11 + ...primary_key_compaction_conflict_resolver.h | 16 + be/src/storage/lake/location_provider.h | 16 + be/src/storage/lake/meta_file.cpp | 17 + be/src/storage/lake/meta_file.h | 4 + be/src/storage/lake/metacache.h | 5 + be/src/storage/lake/pk_tablet_writer.cpp | 9 + be/src/storage/lake/rowset.cpp | 96 + be/src/storage/lake/rowset.h | 37 + be/src/storage/lake/schema_change.cpp | 68 + .../lake/starlet_location_provider.cpp | 18 + .../storage/lake/starlet_location_provider.h | 9 + be/src/storage/lake/tablet.cpp | 46 + be/src/storage/lake/tablet.h | 76 + be/src/storage/lake/tablet_manager.cpp | 135 ++ be/src/storage/lake/tablet_manager.h | 70 + be/src/storage/lake/tablet_reader.cpp | 39 + be/src/storage/lake/tablet_reader.h | 22 + be/src/storage/lake/tablet_writer.h | 17 + be/src/storage/lake/transactions.cpp | 67 + be/src/storage/lake/transactions.h | 9 + be/src/storage/lake/txn_log_applier.cpp | 4 + be/src/storage/lake/update_manager.cpp | 25 + be/src/storage/lake/update_manager.h | 11 + be/src/storage/lake/vacuum.cpp | 18 + be/src/storage/lake/versioned_tablet.cpp | 14 + be/src/storage/lake/versioned_tablet.h | 9 + .../storage/lake/vertical_compaction_task.cpp | 6 + be/src/storage/local_primary_key_recover.cpp | 13 + be/src/storage/memtable.cpp | 41 + be/src/storage/memtable.h | 53 + be/src/storage/memtable_flush_executor.cpp | 30 + be/src/storage/memtable_flush_executor.h | 12 + be/src/storage/merge_iterator.cpp | 8 + be/src/storage/meta_reader.cpp | 73 + be/src/storage/meta_reader.h | 15 + be/src/storage/metadata_util.cpp | 55 +- be/src/storage/olap_common.h | 28 + be/src/storage/olap_meta_reader.cpp | 9 + be/src/storage/olap_runtime_range_pruner.h | 15 + be/src/storage/olap_runtime_range_pruner.hpp | 92 + be/src/storage/options.h | 12 + be/src/storage/persistent_index.cpp | 4 + be/src/storage/predicate_parser.cpp | 126 ++ be/src/storage/predicate_parser.h | 71 + .../storage/predicate_tree/predicate_tree.cpp | 445 ++++ .../storage/predicate_tree/predicate_tree.h | 82 + .../storage/predicate_tree/predicate_tree.hpp | 6 + .../predicate_tree/predicate_tree_fwd.h | 4 + be/src/storage/primary_index.cpp | 16 + be/src/storage/projection_iterator.cpp | 8 + be/src/storage/protobuf_file.cpp | 36 + be/src/storage/protobuf_file.h | 19 + be/src/storage/range.h | 39 + be/src/storage/roaring2range.h | 15 + be/src/storage/row_source_mask.cpp | 8 + be/src/storage/rowset/array_column_iterator.h | 34 + be/src/storage/rowset/array_column_writer.cpp | 60 + be/src/storage/rowset/base_rowset.h | 17 + be/src/storage/rowset/binary_dict_page.h | 16 + be/src/storage/rowset/binary_plain_page.h | 14 + be/src/storage/rowset/binary_prefix_page.cpp | 16 + be/src/storage/rowset/binary_prefix_page.h | 12 + .../storage/rowset/bitmap_index_evaluator.cpp | 471 +++++ .../storage/rowset/bitmap_index_evaluator.h | 79 + be/src/storage/rowset/bitmap_range_iterator.h | 40 + be/src/storage/rowset/bitshuffle_page.h | 18 + be/src/storage/rowset/cast_column_iterator.h | 5 + be/src/storage/rowset/column_iterator.h | 40 + .../rowset/column_iterator_decorator.h | 10 + be/src/storage/rowset/column_reader.cpp | 88 + be/src/storage/rowset/column_reader.h | 43 + be/src/storage/rowset/column_writer.cpp | 5 + be/src/storage/rowset/column_writer.h | 13 + be/src/storage/rowset/data_sample.cpp | 342 +++ be/src/storage/rowset/data_sample.h | 124 ++ .../rowset/default_value_column_iterator.cpp | 5 + .../rowset/default_value_column_iterator.h | 34 + .../storage/rowset/fill_subfield_iterator.h | 12 + .../storage/rowset/frame_of_reference_page.h | 20 + .../horizontal_update_rowset_writer.cpp | 28 + .../storage/rowset/indexed_column_reader.cpp | 6 + be/src/storage/rowset/indexed_column_reader.h | 4 + .../storage/rowset/json_column_iterator.cpp | 59 + be/src/storage/rowset/map_column_iterator.h | 16 + be/src/storage/rowset/ordinal_page_index.cpp | 8 + be/src/storage/rowset/ordinal_page_index.h | 4 + be/src/storage/rowset/page_decoder.h | 28 + be/src/storage/rowset/parsed_page.cpp | 42 + be/src/storage/rowset/parsed_page.h | 5 + be/src/storage/rowset/plain_page.h | 20 + be/src/storage/rowset/rle_page.h | 16 + be/src/storage/rowset/rowid_column_iterator.h | 32 + be/src/storage/rowset/rowset.cpp | 103 + be/src/storage/rowset/rowset.h | 23 + be/src/storage/rowset/rowset_meta.cpp | 23 + be/src/storage/rowset/rowset_meta.h | 16 + be/src/storage/rowset/rowset_options.h | 18 + be/src/storage/rowset/rowset_writer.cpp | 237 +++ be/src/storage/rowset/rowset_writer.h | 14 + be/src/storage/rowset/rowset_writer_context.h | 5 + .../storage/rowset/scalar_column_iterator.cpp | 86 + .../storage/rowset/scalar_column_iterator.h | 48 + be/src/storage/rowset/segment.cpp | 49 + be/src/storage/rowset/segment.h | 25 + be/src/storage/rowset/segment_iterator.cpp | 839 ++++++++ be/src/storage/rowset/segment_options.h | 28 + be/src/storage/rowset/segment_rewriter.cpp | 3 + be/src/storage/rowset/segment_rewriter.h | 3 + be/src/storage/rowset/segment_writer.cpp | 24 + .../storage/rowset/struct_column_iterator.cpp | 22 + be/src/storage/rowset_update_state.cpp | 13 + be/src/storage/schema_change.cpp | 10 + be/src/storage/schema_change_utils.cpp | 7 + be/src/storage/schema_change_utils.h | 4 + be/src/storage/segment_flush_executor.cpp | 28 + be/src/storage/segment_flush_executor.h | 23 + be/src/storage/segment_replicate_executor.cpp | 76 + be/src/storage/segment_replicate_executor.h | 31 + be/src/storage/snapshot_manager.cpp | 5 + be/src/storage/table_reader.cpp | 16 + be/src/storage/table_reader.h | 14 + be/src/storage/tablet.cpp | 93 + be/src/storage/tablet.h | 79 + be/src/storage/tablet_index.cpp | 5 + be/src/storage/tablet_manager.h | 8 + be/src/storage/tablet_meta.h | 26 + be/src/storage/tablet_reader.cpp | 26 + be/src/storage/tablet_reader.h | 10 + be/src/storage/tablet_reader_params.h | 18 + be/src/storage/tablet_schema.cpp | 56 + be/src/storage/tablet_schema.h | 18 + be/src/storage/tablet_updates.cpp | 179 ++ be/src/storage/tablet_updates.h | 26 + be/src/storage/txn_manager.cpp | 3 + be/src/storage/txn_manager.h | 44 + be/src/storage/types.cpp | 7 + be/src/storage/union_iterator.cpp | 8 + be/src/storage/vertical_compaction_task.cpp | 6 + be/src/storage/zone_map_detail.h | 11 + be/src/testutil/column_test_helper.h | 4 + be/src/testutil/exprs_test_helper.h | 15 + be/src/testutil/init_test_env.h | 10 + be/src/testutil/schema_test_helper.cpp | 43 + be/src/testutil/schema_test_helper.h | 8 + be/src/types/CMakeLists.txt | 10 + be/src/types/bitmap_value.cpp | 4 + be/src/types/bitmap_value.h | 8 + be/src/types/bitmap_value_detail.h | 24 + be/src/types/checker/type_checker.cpp | 317 +++ be/src/types/checker/type_checker.h | 102 + be/src/types/constexpr.h | 6 + be/src/types/hll.cpp | 65 + be/src/types/hll.h | 7 + be/src/types/hll_sketch.cpp | 127 ++ be/src/types/hll_sketch.h | 143 ++ be/src/types/large_int_value.cpp | 47 + be/src/types/large_int_value.h | 63 + be/src/types/logical_type_infra.h | 5 + be/src/types/timestamp_value.cpp | 17 + be/src/types/timestamp_value.h | 4 + be/src/types/type_checker_manager.cpp | 66 + be/src/types/type_checker_manager.h | 40 + be/src/udf/CMakeLists.txt | 15 +- be/src/udf/java/java_data_converter.h | 5 + be/src/udf/java/java_udf.h | 16 + be/src/udf/python/callstub.cpp | 188 ++ be/src/udf/python/callstub.h | 57 + be/src/udf/python/env.cpp | 250 +++ be/src/udf/python/env.h | 167 ++ be/src/udf/udf_call_stub.cpp | 124 ++ be/src/udf/udf_call_stub.h | 55 + be/src/util/CMakeLists.txt | 11 + be/src/util/arrow/row_batch.cpp | 12 + be/src/util/arrow/row_batch.h | 13 + .../util/arrow/starrocks_column_to_arrow.cpp | 26 + be/src/util/arrow/starrocks_column_to_arrow.h | 7 + be/src/util/arrow/utils.h | 11 + be/src/util/base85.cpp | 77 + be/src/util/base85.h | 23 + be/src/util/bit_packing.h | 3 + be/src/util/bit_packing_adapter.h | 160 ++ be/src/util/bit_packing_simd.h | 484 +++++ be/src/util/bit_stream_utils.h | 5 + be/src/util/bit_stream_utils.inline.h | 20 + be/src/util/bitmap_intersect.h | 3 + be/src/util/brpc_stub_cache.h | 50 + be/src/util/c_string.h | 4 + be/src/util/cpu_info.h | 15 + be/src/util/debug/query_trace_impl.h | 4 + be/src/util/decimal_types.h | 19 + be/src/util/failpoint/fail_point.cpp | 4 + be/src/util/filesystem_util.cc | 19 + be/src/util/hdfs_util.cpp | 7 + be/src/util/int96.cpp | 4 + .../internal_service_recoverable_stub.cpp | 171 ++ .../util/internal_service_recoverable_stub.h | 94 + be/src/util/json_converter.h | 5 + be/src/util/lru_cache.cpp | 6 + be/src/util/lru_cache.h | 6 + be/src/util/misc.cpp | 7 + be/src/util/mysql_row_buffer.cpp | 4 + be/src/util/phmap/phmap.h | 4 + be/src/util/raw_container.h | 31 + be/src/util/rle_encoding.h | 76 + be/src/util/starrocks_metrics.h | 4 + be/src/util/system_metrics.cpp | 120 ++ be/src/util/system_metrics.h | 23 + be/src/util/threadpool.h | 22 + be/src/util/thrift_rpc_helper.cpp | 58 + be/src/util/thrift_rpc_helper.h | 23 + be/src/util/thrift_util.h | 35 + be/src/util/timezone_hsscan.h | 4 + be/src/util/uid_util.cpp | 25 + be/src/util/uid_util.h | 5 + be/test/CMakeLists.txt | 96 + be/test/agent/agent_task_test.cpp | 34 + be/test/agent/heartbeat_server_test.cpp | 19 + be/test/block_cache/block_cache_test.cpp | 17 + be/test/block_cache/datacache_utils_test.cpp | 26 + .../block_cache/disk_space_monitor_test.cpp | 90 + be/test/column/avx_numeric_column.h | 4 + be/test/column/avx_numeric_column_test.cpp | 24 + be/test/column/binary_column_test.cpp | 30 + be/test/column/field_test.cpp | 51 + be/test/column/fixed_length_column_test.cpp | 8 + be/test/column/object_column_test.cpp | 4 + be/test/column/timestamp_value_test.cpp | 9 + .../deletion_vector/deletion_vector_test.cpp | 65 + be/test/exec/agg_hash_map_test.cpp | 9 + be/test/exec/chunks_sorter_test.cpp | 9 + be/test/exec/column_value_range_test.cpp | 44 + be/test/exec/hdfs_scan_node_test.cpp | 10 + be/test/exec/hdfs_scanner_test.cpp | 25 + be/test/exec/join_hash_map_test.cpp | 12 + be/test/exec/lake_meta_scanner_test.cpp | 11 + be/test/exec/olap_scan_prepare_test.cpp | 280 +++ be/test/exec/parquet_scanner_test.cpp | 9 + .../pipeline/mem_limited_chunk_queue_test.cpp | 4 + .../workgroup/pipeline_executor_set_test.cpp | 80 + be/test/exprs/agg/aggregate_test.cpp | 251 +++ be/test/exprs/array_functions_test.cpp | 8 + be/test/exprs/cast_expr_test.cpp | 121 ++ be/test/exprs/like_test.cpp | 4 + be/test/exprs/min_max_predicate_test.cpp | 238 +++ .../string_fn_money_format_decimal_test.cpp | 7 + be/test/exprs/string_fn_test.cpp | 375 ++++ be/test/exprs/time_functions_test.cpp | 28 + be/test/formats/csv/string_converter_test.cpp | 5 + .../formats/csv/varbinary_converter_test.cpp | 4 + be/test/formats/orc/orc_chunk_reader_test.cpp | 95 + be/test/formats/orc/utils_test.cpp | 137 ++ .../formats/parquet/column_converter_test.cpp | 6 + be/test/formats/parquet/file_reader_test.cpp | 642 ++++++ be/test/formats/parquet/file_writer_test.cpp | 6 + be/test/formats/parquet/group_reader_test.cpp | 84 + ...berg_schema_evolution_file_reader_test.cpp | 114 + be/test/formats/parquet/page_index_test.cpp | 221 ++ be/test/formats/parquet/parquet_cli_reader.h | 35 + .../parquet/parquet_file_writer_test.cpp | 7 + be/test/formats/parquet/parquet_ut_base.cpp | 26 + be/test/formats/parquet/parquet_ut_base.h | 10 + .../file_read_test_filter_row_group_1.parquet | Bin 0 -> 2934 bytes .../file_read_test_filter_row_group_2.parquet | Bin 0 -> 2928 bytes be/test/fs/fs_posix_test.cpp | 8 + be/test/fs/fs_s3_test.cpp | 42 + be/test/fs/fs_test.cpp | 10 + be/test/fs/poco_http_client_test.cpp | 200 ++ .../http/action/update_config_action_test.cpp | 69 + be/test/http/stream_load_test.cpp | 157 ++ be/test/io/cache_input_stream_test.cpp | 17 + be/test/io/s3_input_stream_test.cpp | 42 + be/test/io/s3_output_stream_test.cpp | 12 + be/test/runtime/agg_state_desc_test.cpp | 59 + .../batch_write/batch_write_mgr_test.cpp | 376 ++++ .../batch_write/batch_write_util_test.cpp | 65 + .../isomorphic_batch_write_test.cpp | 315 +++ be/test/runtime/decimalv3_test.cpp | 4 + be/test/runtime/lake_tablets_channel_test.cpp | 415 ++++ be/test/runtime/large_int_value_test.cpp | 10 + be/test/runtime/load_channel_test.cpp | 9 + .../runtime/local_tablets_channel_test.cpp | 24 + .../memory/counting_allocator_test.cpp | 80 + be/test/runtime/stream_load_pipe_test.cpp | 82 + .../time_bounded_stream_load_pipe_test.cpp | 115 ++ be/test/runtime/type_descriptor_test.cpp | 16 + be/test/serde/column_array_serde_test.cpp | 8 + be/test/service/lake_service_test.cpp | 196 ++ be/test/storage/aggregate_iterator_test.cpp | 8 + be/test/storage/base_compaction_test.cpp | 11 + be/test/storage/chunk_helper_test.cpp | 122 ++ be/test/storage/column_and_predicate_test.cpp | 121 ++ be/test/storage/column_or_predicate_test.cpp | 76 + be/test/storage/column_predicate_test.cpp | 80 + .../storage/conjunctive_predicates_test.cpp | 64 + be/test/storage/delta_column_group_test.cpp | 6 + be/test/storage/index/vector_index_test.cpp | 160 ++ be/test/storage/index/vector_search_test.cpp | 184 ++ .../storage/lake/alter_tablet_meta_test.cpp | 3 + .../storage/lake/async_delta_writer_test.cpp | 6 + .../auto_increment_partial_update_test.cpp | 24 + .../storage/lake/compaction_policy_test.cpp | 6 + be/test/storage/lake/compaction_task_test.cpp | 16 + .../storage/lake/condition_update_test.cpp | 20 + be/test/storage/lake/delta_writer_test.cpp | 36 + .../lake_primary_key_consistency_test.cpp | 20 + be/test/storage/lake/lake_scan_node_test.cpp | 10 + be/test/storage/lake/meta_file_test.cpp | 21 + be/test/storage/lake/partial_update_test.cpp | 116 ++ .../lake/primary_key_compaction_task_test.cpp | 88 + .../storage/lake/primary_key_publish_test.cpp | 199 ++ .../lake/replication_txn_manager_test.cpp | 22 + be/test/storage/lake/rowset_test.cpp | 5 + be/test/storage/lake/schema_change_test.cpp | 61 + .../lake/starlet_location_provider_test.cpp | 96 + be/test/storage/lake/tablet_manager_test.cpp | 73 + be/test/storage/lake/tablet_writer_test.cpp | 26 + be/test/storage/lake/test_util.h | 10 + be/test/storage/meta_reader_test.cpp | 8 + be/test/storage/metadata_util_test.cpp | 147 ++ .../olap_runtime_range_pruner_test.cpp | 167 ++ be/test/storage/projection_iterator_test.cpp | 9 + .../storage/publish_version_manager_test.cpp | 3 + be/test/storage/publish_version_task_test.cpp | 3 + be/test/storage/roaring2range_test.cpp | 47 + be/test/storage/rows_mapper_test.cpp | 18 + .../rowset/column_reader_writer_test.cpp | 4 + be/test/storage/rowset/data_sample_test.cpp | 265 +++ .../default_value_column_iterator_test.cpp | 4 + .../rowset/frame_of_reference_page_test.cpp | 7 + be/test/storage/rowset/rle_page_test.cpp | 4 + .../storage/rowset/segment_rewriter_test.cpp | 3 + be/test/storage/rowset/segment_test.cpp | 4 + be/test/storage/rowset_update_state_test.cpp | 48 + be/test/storage/tablet_index_test.cpp | 111 + be/test/storage/tablet_updates_test.cpp | 24 + .../engine_storage_migration_task_test.cpp | 28 + be/test/storage/union_iterator_test.cpp | 10 + be/test/types/bitmap_value_test.cpp | 20 + be/test/types/type_checker_test.cpp | 489 +++++ .../arrow/starrocks_column_to_arrow_test.cpp | 5 + be/test/util/base85_test.cpp | 35 + be/test/util/bit_packing_simd_test.cpp | 102 + be/test/util/bit_stream_utils_test.cpp | 4 + be/test/util/brpc_stub_cache_test.cpp | 18 + ...internal_service_recoverable_stub_test.cpp | 66 + be/test/util/mysql_row_buffer_test.cpp | 5 + be/test/util/raw_container_test.cpp | 38 + be/test/util/threadpool_test.cpp | 7 + bin/common.sh | 3 + bin/show_be_version.sh | 3 + bin/start_backend.sh | 6 + bin/start_fe.sh | 17 + bin/stop_be.sh | 17 + build.sh | 193 ++ contrib/starrocks-python-client/README.md | 33 + contrib/starrocks-python-client/setup.py | 7 + .../starrocks/__init__.py | 4 + .../starrocks/alembic.py | 28 + .../starrocks/dialect.py | 23 + .../test/test_suite.py | 13 + docker/dockerfiles/Dockerhub-README.md | 99 + docker/dockerfiles/dev-env/dev-env.Dockerfile | 8 + .../toolchains/toolchains-centos7.Dockerfile | 83 + .../toolchains/toolchains-ubuntu.Dockerfile | 15 + .../aarch64/CentOS-Base-Local-List.repo | 22 + .../aarch64/yum-base-mirrorlist.txt | 7 + .../aarch64/yum-extras-mirrorlist.txt | 7 + .../aarch64/yum-updates-mirrorlist.txt | 7 + .../x86_64/CentOS-Base-Local-List.repo | 19 + .../x86_64/yum-base-mirrorlist.txt | 7 + .../x86_64/yum-extras-mirrorlist.txt | 7 + .../x86_64/yum-updates-mirrorlist.txt | 7 + .../current.json | 5 + .../management/FE_configuration.md | 42 + .../resource_management/query_queues.md | 6 + .../resource_management/resource_group.md | 6 +- .../en/data_source/catalog/iceberg_catalog.md | 93 + .../build_starrocks_on_ubuntu.md | 4 + docs/en/ecosystem_release/flink_connector.md | 43 + docs/en/ecosystem_release/kafka_connector.md | 4 + docs/en/ecosystem_release/spark_connector.md | 14 + .../integrations/BI_integrations/Metabase.md | 5 + docs/en/introduction/Architecture.md | 4 + docs/en/loading/Kafka-connector-starrocks.md | 65 + docs/en/quick_start/hudi.md | 4 + docs/en/release_notes/release-2.5.md | 41 + docs/en/release_notes/release-3.0.md | 70 + docs/en/release_notes/release-3.1.md | 660 ++++++ docs/en/release_notes/release-3.2.md | 322 +++ docs/en/release_notes/release-3.3.md | 530 +++++ docs/en/sql-reference/System_limit.md | 3 + docs/en/sql-reference/System_variable.md | 21 + .../sql-reference/sql-functions/Python_UDF.md | 146 ++ .../aggregate-functions/any_value.md | 4 + .../approx_count_distinct.md | 4 + .../approx_count_distinct_hll_sketch.md | 30 + .../aggregate-functions/approx_top_k.md | 4 + .../sql-functions/aggregate-functions/avg.md | 4 + .../sql-functions/aggregate-functions/corr.md | 4 + .../aggregate-functions/count.md | 4 + .../aggregate-functions/count_if.md | 4 + .../aggregate-functions/covar_pop.md | 4 + .../aggregate-functions/covar_samp.md | 4 + .../aggregate-functions/group_concat.md | 4 + .../aggregate-functions/grouping.md | 4 + .../aggregate-functions/grouping_id.md | 4 + .../aggregate-functions/hll_raw_agg.md | 4 + .../aggregate-functions/hll_union.md | 4 + .../aggregate-functions/hll_union_agg.md | 4 + .../mann_whitney_u_test.md | 125 ++ .../sql-functions/aggregate-functions/max.md | 4 + .../aggregate-functions/max_by.md | 4 + .../sql-functions/aggregate-functions/min.md | 4 + .../aggregate-functions/min_by.md | 4 + .../multi_distinct_count.md | 4 + .../aggregate-functions/multi_distinct_sum.md | 4 + .../aggregate-functions/percentile_approx.md | 4 + .../aggregate-functions/percentile_cont.md | 4 + .../aggregate-functions/percentile_disc.md | 4 + .../aggregate-functions/percentile_disc_lc.md | 91 + .../aggregate-functions/retention.md | 4 + .../sql-functions/aggregate-functions/std.md | 4 + .../aggregate-functions/stddev.md | 4 + .../aggregate-functions/stddev_samp.md | 4 + .../sql-functions/aggregate-functions/sum.md | 4 + .../aggregate-functions/var_samp.md | 4 + .../aggregate-functions/variance.md | 4 + .../aggregate-functions/window_funnel.md | 4 + .../array-functions/all_match.md | 4 + .../array-functions/any_match.md | 4 + .../array-functions/array_agg.md | 4 + .../array-functions/array_append.md | 4 + .../array-functions/array_avg.md | 4 + .../array-functions/array_concat.md | 4 + .../array-functions/array_contains.md | 4 + .../array-functions/array_contains_all.md | 4 + .../array-functions/array_contains_seq.md | 4 + .../array-functions/array_cum_sum.md | 4 + .../array-functions/array_difference.md | 4 + .../array-functions/array_distinct.md | 4 + .../array-functions/array_filter.md | 4 + .../array-functions/array_generate.md | 4 + .../array-functions/array_intersect.md | 4 + .../array-functions/array_join.md | 4 + .../array-functions/array_length.md | 4 + .../array-functions/array_map.md | 4 + .../array-functions/array_max.md | 4 + .../array-functions/array_min.md | 4 + .../array-functions/array_position.md | 4 + .../array-functions/array_remove.md | 4 + .../array-functions/array_slice.md | 4 + .../array-functions/array_sort.md | 4 + .../array-functions/array_sortby.md | 4 + .../array-functions/array_sum.md | 4 + .../array-functions/array_to_bitmap.md | 4 + .../array-functions/array_unique_agg.md | 4 + .../array-functions/arrays_overlap.md | 4 + .../array-functions/cardinality.md | 4 + .../array-functions/element_at.md | 4 + .../sql-functions/array-functions/reverse.md | 4 + .../sql-functions/array-functions/unnest.md | 4 + .../binary-functions/from_binary.md | 4 + .../binary-functions/to_binary.md | 4 + .../bit-functions/bit_shift_left.md | 4 + .../bit-functions/bit_shift_right.md | 4 + .../bit-functions/bit_shift_right_logical.md | 4 + .../sql-functions/bit-functions/bitand.md | 4 + .../sql-functions/bit-functions/bitnot.md | 4 + .../sql-functions/bit-functions/bitor.md | 4 + .../sql-functions/bit-functions/bitxor.md | 4 + .../bitmap-functions/base64_to_bitmap.md | 4 + .../bitmap-functions/bitmap_agg.md | 4 + .../bitmap-functions/bitmap_and.md | 4 + .../bitmap-functions/bitmap_andnot.md | 4 + .../bitmap-functions/bitmap_contains.md | 4 + .../bitmap-functions/bitmap_count.md | 4 + .../bitmap-functions/bitmap_empty.md | 4 + .../bitmap-functions/bitmap_from_binary.md | 4 + .../bitmap-functions/bitmap_from_string.md | 4 + .../bitmap-functions/bitmap_has_any.md | 4 + .../bitmap-functions/bitmap_hash.md | 4 + .../bitmap-functions/bitmap_intersect.md | 4 + .../bitmap-functions/bitmap_max.md | 4 + .../bitmap-functions/bitmap_min.md | 4 + .../bitmap-functions/bitmap_or.md | 4 + .../bitmap-functions/bitmap_remove.md | 4 + .../bitmap_subset_in_range.md | 4 + .../bitmap-functions/bitmap_subset_limit.md | 4 + .../bitmap-functions/bitmap_to_array.md | 4 + .../bitmap-functions/bitmap_to_base64.md | 4 + .../bitmap-functions/bitmap_to_binary.md | 4 + .../bitmap-functions/bitmap_to_string.md | 4 + .../bitmap-functions/bitmap_union.md | 4 + .../bitmap-functions/bitmap_union_count.md | 4 + .../bitmap-functions/bitmap_union_int.md | 4 + .../bitmap-functions/bitmap_xor.md | 4 + .../bitmap-functions/intersect_count.md | 4 + .../bitmap-functions/sub_bitmap.md | 4 + .../bitmap-functions/subdivide_bitmap.md | 4 + .../bitmap-functions/to_bitmap.md | 4 + .../bitmap-functions/unnest_bitmap.md | 4 + docs/en/sql-reference/sql-functions/cast.md | 4 + .../condition-functions/case_when.md | 4 + .../condition-functions/coalesce.md | 4 + .../sql-functions/condition-functions/if.md | 4 + .../condition-functions/ifnull.md | 4 + .../condition-functions/nullif.md | 4 + .../crytographic-functions/aes_decrypt.md | 4 + .../crytographic-functions/aes_encrypt.md | 4 + .../base64_decode_binary.md | 4 + .../base64_decode_string.md | 4 + .../crytographic-functions/from_base64.md | 4 + .../crytographic-functions/sm3.md | 4 + .../crytographic-functions/to_base64.md | 4 + .../date-time-functions/add_months.md | 4 + .../date-time-functions/convert_tz.md | 4 + .../date-time-functions/curdate.md | 4 + .../date-time-functions/current_timestamp.md | 4 + .../date-time-functions/curtime.md | 4 + .../sql-functions/date-time-functions/date.md | 4 + .../date-time-functions/date_add.md | 4 + .../date-time-functions/date_diff.md | 4 + .../date-time-functions/date_format.md | 4 + .../date-time-functions/date_slice.md | 4 + .../date-time-functions/date_sub.md | 4 + .../date-time-functions/date_trunc.md | 4 + .../date-time-functions/datediff.md | 4 + .../sql-functions/date-time-functions/day.md | 4 + .../date-time-functions/day_of_week_iso.md | 4 + .../date-time-functions/dayname.md | 4 + .../date-time-functions/dayofmonth.md | 4 + .../date-time-functions/dayofweek.md | 4 + .../date-time-functions/dayofyear.md | 4 + .../date-time-functions/days_add.md | 4 + .../date-time-functions/days_diff.md | 4 + .../date-time-functions/days_sub.md | 4 + .../date-time-functions/from_days.md | 4 + .../date-time-functions/from_unixtime.md | 4 + .../sql-functions/date-time-functions/hour.md | 4 + .../date-time-functions/hours_add.md | 4 + .../date-time-functions/hours_diff.md | 4 + .../date-time-functions/hours_sub.md | 4 + .../date-time-functions/jodatime_format.md | 4 + .../date-time-functions/last_day.md | 4 + .../date-time-functions/makedate.md | 4 + .../date-time-functions/microseconds_add.md | 4 + .../date-time-functions/microseconds_sub.md | 4 + .../date-time-functions/milliseconds_diff.md | 4 + .../date-time-functions/minute.md | 4 + .../date-time-functions/minutes_add.md | 4 + .../date-time-functions/minutes_diff.md | 4 + .../date-time-functions/minutes_sub.md | 4 + .../date-time-functions/month.md | 4 + .../date-time-functions/monthname.md | 4 + .../date-time-functions/months_add.md | 4 + .../date-time-functions/months_diff.md | 4 + .../date-time-functions/months_sub.md | 4 + .../date-time-functions/next_day.md | 4 + .../sql-functions/date-time-functions/now.md | 4 + .../date-time-functions/previous_day.md | 4 + .../date-time-functions/quarter.md | 4 + .../date-time-functions/second.md | 4 + .../date-time-functions/seconds_diff.md | 4 + .../date-time-functions/seconds_sub.md | 4 + .../date-time-functions/str2date.md | 4 + .../date-time-functions/str_to_date.md | 4 + .../date-time-functions/str_to_jodatime.md | 4 + .../date-time-functions/time_slice.md | 4 + .../date-time-functions/time_to_sec.md | 4 + .../date-time-functions/timediff.md | 4 + .../date-time-functions/timestamp.md | 4 + .../date-time-functions/timestampadd.md | 4 + .../date-time-functions/timestampdiff.md | 4 + .../date-time-functions/to_date.md | 4 + .../date-time-functions/to_days.md | 4 + .../date-time-functions/to_iso8601.md | 4 + .../date-time-functions/to_tera_date.md | 4 + .../date-time-functions/to_tera_timestamp.md | 4 + .../date-time-functions/unix_timestamp.md | 4 + .../date-time-functions/utc_time.md | 4 + .../date-time-functions/utc_timestamp.md | 4 + .../sql-functions/date-time-functions/week.md | 4 + .../date-time-functions/week_iso.md | 4 + .../date-time-functions/weekofyear.md | 4 + .../date-time-functions/weeks_add.md | 4 + .../date-time-functions/weeks_diff.md | 4 + .../date-time-functions/weeks_sub.md | 4 + .../sql-functions/date-time-functions/year.md | 4 + .../date-time-functions/years_diff.md | 4 + .../date-time-functions/years_sub.md | 4 + .../date-time-functions/yearweek.md | 4 + .../dict-functions/dict_mapping.md | 4 + .../hash-functions/murmur_hash3_32.md | 4 + .../hash-functions/xx_hash3_128.md | 4 + .../hash-functions/xx_hash3_64.md | 4 + .../json-constructor-functions/json_array.md | 4 + .../json-constructor-functions/json_object.md | 4 + .../json-constructor-functions/parse_json.md | 4 + .../arrow-function.md | 4 + .../cast.md | 4 + .../get_json_bool.md | 4 + .../get_json_double.md | 4 + .../get_json_int.md | 4 + .../get_json_string.md | 4 + .../json_each.md | 4 + .../json_exists.md | 4 + .../json_keys.md | 4 + .../json_length.md | 4 + .../json_query.md | 4 + .../json_string.md | 4 + .../to_json.md | 4 + .../like-predicate-functions/like.md | 4 + .../like-predicate-functions/regexp.md | 4 + .../regexp_extract.md | 4 + .../regexp_extract_all.md | 4 + .../regexp_replace.md | 4 + .../map-functions/cardinality.md | 4 + .../map-functions/distinct_map_keys.md | 4 + .../sql-functions/map-functions/element_at.md | 4 + .../sql-functions/map-functions/map_apply.md | 4 + .../sql-functions/map-functions/map_concat.md | 4 + .../sql-functions/map-functions/map_filter.md | 4 + .../map-functions/map_from_arrays.md | 4 + .../sql-functions/map-functions/map_keys.md | 4 + .../sql-functions/map-functions/map_size.md | 4 + .../sql-functions/map-functions/map_values.md | 4 + .../map-functions/transform_keys.md | 4 + .../map-functions/transform_values.md | 4 + .../sql-functions/math-functions/abs.md | 4 + .../sql-functions/math-functions/acos.md | 4 + .../sql-functions/math-functions/asin.md | 4 + .../sql-functions/math-functions/atan.md | 4 + .../sql-functions/math-functions/atan2.md | 4 + .../sql-functions/math-functions/bin.md | 4 + .../sql-functions/math-functions/cbrt.md | 4 + .../sql-functions/math-functions/ceil.md | 4 + .../sql-functions/math-functions/ceiling.md | 4 + .../sql-functions/math-functions/conv.md | 4 + .../sql-functions/math-functions/cos.md | 4 + .../math-functions/cos_similarity.md | 4 + .../math-functions/cos_similarity_norm.md | 4 + .../sql-functions/math-functions/cosh.md | 4 + .../sql-functions/math-functions/cot.md | 4 + .../sql-functions/math-functions/degrees.md | 4 + .../sql-functions/math-functions/divide.md | 4 + .../sql-functions/math-functions/e.md | 4 + .../sql-functions/math-functions/exp.md | 4 + .../sql-functions/math-functions/floor.md | 4 + .../sql-functions/math-functions/fmod.md | 4 + .../sql-functions/math-functions/greatest.md | 4 + .../sql-functions/math-functions/least.md | 4 + .../sql-functions/math-functions/ln.md | 4 + .../sql-functions/math-functions/log.md | 4 + .../sql-functions/math-functions/log10.md | 4 + .../sql-functions/math-functions/log2.md | 4 + .../sql-functions/math-functions/mod.md | 4 + .../sql-functions/math-functions/multiply.md | 4 + .../sql-functions/math-functions/negative.md | 4 + .../sql-functions/math-functions/pi.md | 4 + .../sql-functions/math-functions/pmod.md | 4 + .../sql-functions/math-functions/positive.md | 4 + .../sql-functions/math-functions/pow.md | 4 + .../sql-functions/math-functions/radians.md | 4 + .../sql-functions/math-functions/rand.md | 3 + .../sql-functions/math-functions/round.md | 4 + .../sql-functions/math-functions/sign.md | 4 + .../sql-functions/math-functions/sin.md | 4 + .../sql-functions/math-functions/sinh.md | 4 + .../sql-functions/math-functions/sqrt.md | 4 + .../sql-functions/math-functions/square.md | 4 + .../sql-functions/math-functions/tan.md | 4 + .../sql-functions/math-functions/tanh.md | 4 + .../sql-functions/math-functions/truncate.md | 4 + .../percentile_approx_raw.md | 4 + .../percentile-functions/percentile_empty.md | 4 + .../percentile-functions/percentile_hash.md | 4 + .../percentile-functions/percentile_union.md | 4 + .../scalar-functions/hll_cardinality.md | 4 + .../scalar-functions/hll_empty.md | 4 + .../scalar-functions/hll_hash.md | 4 + .../spatial-functions/st_astext.md | 4 + .../spatial-functions/st_circle.md | 4 + .../spatial-functions/st_contains.md | 4 + .../spatial-functions/st_distance_sphere.md | 4 + .../spatial-functions/st_geometryfromtext.md | 4 + .../spatial-functions/st_linefromtext.md | 4 + .../spatial-functions/st_point.md | 4 + .../spatial-functions/st_polygon.md | 4 + .../sql-functions/spatial-functions/st_x.md | 4 + .../sql-functions/spatial-functions/st_y.md | 4 + .../append_trailing_char_if_absent.md | 4 + .../sql-functions/string-functions/ascii.md | 4 + .../sql-functions/string-functions/char.md | 4 + .../string-functions/char_length.md | 4 + .../string-functions/character_length.md | 4 + .../sql-functions/string-functions/concat.md | 4 + .../string-functions/concat_ws.md | 4 + .../sql-functions/string-functions/crc32.md | 4 + .../string-functions/ends_with.md | 4 + .../string-functions/find_in_set.md | 4 + .../string-functions/group_concat.md | 4 + .../sql-functions/string-functions/hex.md | 4 + .../string-functions/hex_decode_binary.md | 4 + .../string-functions/hex_decode_string.md | 4 + .../string-functions/inet_aton.md | 39 + .../sql-functions/string-functions/instr.md | 4 + .../sql-functions/string-functions/lcase.md | 4 + .../sql-functions/string-functions/left.md | 4 + .../sql-functions/string-functions/length.md | 4 + .../sql-functions/string-functions/locate.md | 4 + .../sql-functions/string-functions/lower.md | 4 + .../sql-functions/string-functions/lpad.md | 4 + .../sql-functions/string-functions/ltrim.md | 4 + .../string-functions/money_format.md | 4 + .../string-functions/ngram_search.md | 4 + .../string-functions/null_or_empty.md | 4 + .../string-functions/parse_url.md | 4 + .../string-functions/regexp_split.md | 59 + .../sql-functions/string-functions/repeat.md | 4 + .../sql-functions/string-functions/replace.md | 4 + .../sql-functions/string-functions/reverse.md | 4 + .../sql-functions/string-functions/right.md | 4 + .../sql-functions/string-functions/rpad.md | 4 + .../sql-functions/string-functions/rtrim.md | 4 + .../sql-functions/string-functions/space.md | 4 + .../sql-functions/string-functions/split.md | 4 + .../string-functions/split_part.md | 4 + .../string-functions/starts_with.md | 4 + .../string-functions/str_to_map.md | 4 + .../sql-functions/string-functions/strcmp.md | 4 + .../sql-functions/string-functions/strleft.md | 4 + .../string-functions/strright.md | 4 + .../string-functions/substring.md | 4 + .../string-functions/substring_index.md | 4 + .../string-functions/translate.md | 4 + .../sql-functions/string-functions/trim.md | 4 + .../sql-functions/string-functions/ucase.md | 4 + .../sql-functions/string-functions/unhex.md | 4 + .../sql-functions/string-functions/upper.md | 4 + .../string-functions/url_decode.md | 4 + .../string-functions/url_encode.md | 4 + .../string-functions/url_extract_host.md | 4 + .../string-functions/url_extract_parameter.md | 4 + .../struct-functions/named_struct.md | 4 + .../sql-functions/struct-functions/row.md | 4 + .../sql-functions/table-functions/files.md | 4 + .../table-functions/generate_series.md | 4 + .../sql-functions/utility-functions/bar.md | 40 + .../utility-functions/catalog.md | 4 + .../utility-functions/current_role.md | 4 + .../utility-functions/current_version.md | 4 + .../utility-functions/database.md | 4 + .../utility-functions/equiwidth_bucket.md | 39 + .../utility-functions/get_query_profile.md | 4 + .../utility-functions/host_name.md | 4 + .../utility-functions/is_role_in_session.md | 4 + .../utility-functions/isnotnull.md | 4 + .../sql-functions/utility-functions/isnull.md | 4 + .../utility-functions/last_query_id.md | 4 + .../sql-functions/utility-functions/sleep.md | 4 + .../sql-functions/utility-functions/uuid.md | 4 + .../utility-functions/uuid_numeric.md | 4 + .../utility-functions/version.md | 4 + .../sql-statements/Database/SHOW_DATA.md | 4 + .../Function/CREATE_FUNCTION.md | 17 + .../table_bucket_part_index/ALTER_TABLE.md | 31 + docs/en/sql-reference/template_for_config.md | 17 + .../expression_partitioning.md | 8 + docs/en/table_design/indexes/Bitmap_index.md | 4 + docs/translation/.env.sample | 3 + docs/translation/.gitignore | 5 + docs/translation/README.md | 167 ++ docs/translation/en-to-zh-configs/config.yaml | 24 + .../en-to-zh-configs/evaluation_prompt.txt | 9 + .../en-to-zh-configs/human_prompt.txt | 51 + .../en-to-zh-configs/language_dicts/en.yaml | 137 ++ .../en-to-zh-configs/language_dicts/zh.yaml | 139 ++ .../en-to-zh-configs/system_prompt.txt | 68 + .../translation/scripts/en-to-zh.translate.sh | 4 + .../translation/scripts/zh-to-en.translate.sh | 4 + docs/translation/translation.Dockerfile | 9 + docs/translation/zh-to-en-configs/config.yaml | 24 + .../zh-to-en-configs/evaluation_prompt.txt | 9 + .../zh-to-en-configs/human_prompt.txt | 51 + .../zh-to-en-configs/language_dicts/en.yaml | 137 ++ .../zh-to-en-configs/language_dicts/zh.yaml | 139 ++ .../zh-to-en-configs/system_prompt.txt | 68 + .../management/FE_configuration.md | 18 + .../resource_management/query_queues.md | 6 + .../zh/data_source/catalog/iceberg_catalog.md | 52 + .../deployment/environment_configurations.md | 4 + .../build_starrocks_on_ubuntu.md | 4 + docs/zh/ecosystem_release/flink_connector.md | 43 + docs/zh/ecosystem_release/kafka_connector.md | 4 + docs/zh/ecosystem_release/spark_connector.md | 14 + docs/zh/introduction/what_is_starrocks.md | 4 + docs/zh/loading/Kafka-connector-starrocks.md | 63 + docs/zh/quick_start/helm.md | 220 ++ docs/zh/release_notes/release-2.5.md | 41 + docs/zh/release_notes/release-3.0.md | 61 + docs/zh/release_notes/release-3.1.md | 660 ++++++ docs/zh/release_notes/release-3.2.md | 311 +++ docs/zh/release_notes/release-3.3.md | 531 +++++ docs/zh/sql-reference/System_variable.md | 22 + .../sql-reference/sql-functions/Python_UDF.md | 143 ++ .../aggregate-functions/any_value.md | 4 + .../approx_count_distinct.md | 4 + .../aggregate-functions/approx_top_k.md | 4 + .../sql-functions/aggregate-functions/avg.md | 4 + .../sql-functions/aggregate-functions/corr.md | 4 + .../aggregate-functions/count.md | 4 + .../aggregate-functions/count_if.md | 4 + .../aggregate-functions/covar_pop.md | 4 + .../aggregate-functions/covar_samp.md | 4 + .../aggregate-functions/group_concat.md | 4 + .../aggregate-functions/grouping.md | 4 + .../aggregate-functions/grouping_id.md | 4 + .../aggregate-functions/hll_raw_agg.md | 4 + .../aggregate-functions/hll_union.md | 4 + .../aggregate-functions/hll_union_agg.md | 4 + .../mann_whitney_u_test.md | 129 ++ .../sql-functions/aggregate-functions/max.md | 4 + .../aggregate-functions/max_by.md | 4 + .../sql-functions/aggregate-functions/min.md | 4 + .../aggregate-functions/min_by.md | 4 + .../multi_distinct_count.md | 4 + .../aggregate-functions/multi_distinct_sum.md | 4 + .../aggregate-functions/percentile_approx.md | 4 + .../aggregate-functions/percentile_cont.md | 4 + .../aggregate-functions/percentile_disc.md | 4 + .../aggregate-functions/percentile_disc_lc.md | 96 + .../aggregate-functions/retention.md | 4 + .../sql-functions/aggregate-functions/std.md | 4 + .../aggregate-functions/stddev.md | 4 + .../aggregate-functions/stddev_samp.md | 4 + .../sql-functions/aggregate-functions/sum.md | 4 + .../aggregate-functions/var_samp.md | 4 + .../aggregate-functions/variance.md | 4 + .../aggregate-functions/window_funnel.md | 4 + .../array-functions/all_match.md | 4 + .../array-functions/any_match.md | 4 + .../array-functions/array_agg.md | 4 + .../array-functions/array_append.md | 4 + .../array-functions/array_avg.md | 4 + .../array-functions/array_concat.md | 4 + .../array-functions/array_contains.md | 4 + .../array-functions/array_contains_all.md | 4 + .../array-functions/array_cum_sum.md | 4 + .../array-functions/array_difference.md | 4 + .../array-functions/array_distinct.md | 4 + .../array-functions/array_filter.md | 4 + .../array-functions/array_generate.md | 4 + .../array-functions/array_intersect.md | 4 + .../array-functions/array_join.md | 4 + .../array-functions/array_length.md | 4 + .../array-functions/array_map.md | 4 + .../array-functions/array_max.md | 4 + .../array-functions/array_min.md | 4 + .../array-functions/array_position.md | 4 + .../array-functions/array_remove.md | 4 + .../array-functions/array_slice.md | 4 + .../array-functions/array_sort.md | 4 + .../array-functions/array_sortby.md | 4 + .../array-functions/array_sum.md | 4 + .../array-functions/array_to_bitmap.md | 4 + .../array-functions/array_unique_agg.md | 4 + .../array-functions/arrays_overlap.md | 4 + .../array-functions/cardinality.md | 4 + .../array-functions/element_at.md | 4 + .../sql-functions/array-functions/reverse.md | 4 + .../sql-functions/array-functions/unnest.md | 4 + .../binary-functions/from_binary.md | 4 + .../binary-functions/to_binary.md | 4 + .../bit-functions/bit_shift_left.md | 4 + .../bit-functions/bit_shift_right.md | 4 + .../bit-functions/bit_shift_right_logical.md | 4 + .../sql-functions/bit-functions/bitand.md | 4 + .../sql-functions/bit-functions/bitnot.md | 4 + .../sql-functions/bit-functions/bitor.md | 4 + .../sql-functions/bit-functions/bitxor.md | 4 + .../bitmap-functions/base64_to_bitmap.md | 4 + .../bitmap-functions/bitmap_agg.md | 4 + .../bitmap-functions/bitmap_and.md | 4 + .../bitmap-functions/bitmap_andnot.md | 4 + .../bitmap-functions/bitmap_contains.md | 4 + .../bitmap-functions/bitmap_count.md | 4 + .../bitmap-functions/bitmap_empty.md | 4 + .../bitmap-functions/bitmap_from_binary.md | 4 + .../bitmap-functions/bitmap_from_string.md | 4 + .../bitmap-functions/bitmap_has_any.md | 4 + .../bitmap-functions/bitmap_hash.md | 4 + .../bitmap-functions/bitmap_intersect.md | 4 + .../bitmap-functions/bitmap_max.md | 4 + .../bitmap-functions/bitmap_min.md | 4 + .../bitmap-functions/bitmap_or.md | 4 + .../bitmap-functions/bitmap_remove.md | 4 + .../bitmap_subset_in_range.md | 4 + .../bitmap-functions/bitmap_subset_limit.md | 4 + .../bitmap-functions/bitmap_to_array.md | 4 + .../bitmap-functions/bitmap_to_base64.md | 4 + .../bitmap-functions/bitmap_to_binary.md | 4 + .../bitmap-functions/bitmap_to_string.md | 4 + .../bitmap-functions/bitmap_union.md | 4 + .../bitmap-functions/bitmap_union_count.md | 4 + .../bitmap-functions/bitmap_union_int.md | 4 + .../bitmap-functions/bitmap_xor.md | 4 + .../bitmap-functions/intersect_count.md | 4 + .../bitmap-functions/sub_bitmap.md | 4 + .../bitmap-functions/subdivide_bitmap.md | 4 + .../bitmap-functions/to_bitmap.md | 4 + .../bitmap-functions/unnest_bitmap.md | 4 + docs/zh/sql-reference/sql-functions/cast.md | 4 + .../condition-functions/case_when.md | 4 + .../condition-functions/coalesce.md | 4 + .../sql-functions/condition-functions/if.md | 4 + .../condition-functions/ifnull.md | 4 + .../condition-functions/nullif.md | 4 + .../crytographic-functions/aes_decrypt.md | 4 + .../crytographic-functions/aes_encrypt.md | 4 + .../base64_decode_binary.md | 4 + .../base64_decode_string.md | 4 + .../crytographic-functions/from_base64.md | 4 + .../crytographic-functions/md5.md | 4 + .../crytographic-functions/md5sum.md | 4 + .../crytographic-functions/md5sum_numeric.md | 4 + .../crytographic-functions/sha2.md | 4 + .../crytographic-functions/sm3.md | 4 + .../crytographic-functions/to_base64.md | 4 + .../date-time-functions/add_months.md | 4 + .../date-time-functions/convert_tz.md | 4 + .../date-time-functions/curdate.md | 4 + .../date-time-functions/current_timestamp.md | 4 + .../date-time-functions/curtime.md | 4 + .../sql-functions/date-time-functions/date.md | 4 + .../date-time-functions/date_add.md | 4 + .../date-time-functions/date_diff.md | 4 + .../date-time-functions/date_format.md | 4 + .../date-time-functions/date_slice.md | 4 + .../date-time-functions/date_sub.md | 4 + .../date-time-functions/date_trunc.md | 4 + .../date-time-functions/datediff.md | 4 + .../sql-functions/date-time-functions/day.md | 4 + .../date-time-functions/day_of_week_iso.md | 4 + .../date-time-functions/dayname.md | 4 + .../date-time-functions/dayofmonth.md | 4 + .../date-time-functions/dayofweek.md | 4 + .../date-time-functions/dayofyear.md | 4 + .../date-time-functions/days_add.md | 4 + .../date-time-functions/days_diff.md | 4 + .../date-time-functions/days_sub.md | 4 + .../date-time-functions/from_days.md | 4 + .../date-time-functions/from_unixtime.md | 4 + .../sql-functions/date-time-functions/hour.md | 4 + .../date-time-functions/hours_add.md | 4 + .../date-time-functions/hours_diff.md | 4 + .../date-time-functions/hours_sub.md | 4 + .../date-time-functions/jodatime_format.md | 4 + .../date-time-functions/last_day.md | 4 + .../date-time-functions/makedate.md | 4 + .../date-time-functions/microseconds_add.md | 4 + .../date-time-functions/microseconds_sub.md | 4 + .../date-time-functions/milliseconds_diff.md | 4 + .../date-time-functions/minute.md | 4 + .../date-time-functions/minutes_add.md | 4 + .../date-time-functions/minutes_diff.md | 4 + .../date-time-functions/minutes_sub.md | 4 + .../date-time-functions/month.md | 4 + .../date-time-functions/monthname.md | 4 + .../date-time-functions/months_add.md | 4 + .../date-time-functions/months_diff.md | 4 + .../date-time-functions/months_sub.md | 4 + .../date-time-functions/next_day.md | 4 + .../sql-functions/date-time-functions/now.md | 4 + .../date-time-functions/previous_day.md | 4 + .../date-time-functions/quarter.md | 4 + .../date-time-functions/second.md | 4 + .../date-time-functions/seconds_add.md | 4 + .../date-time-functions/seconds_diff.md | 4 + .../date-time-functions/seconds_sub.md | 4 + .../date-time-functions/str2date.md | 4 + .../date-time-functions/str_to_date.md | 4 + .../date-time-functions/str_to_jodatime.md | 4 + .../date-time-functions/time_slice.md | 4 + .../date-time-functions/time_to_sec.md | 4 + .../date-time-functions/timediff.md | 4 + .../date-time-functions/timestamp.md | 4 + .../date-time-functions/timestampadd.md | 4 + .../date-time-functions/timestampdiff.md | 4 + .../date-time-functions/to_date.md | 4 + .../date-time-functions/to_days.md | 4 + .../date-time-functions/to_iso8601.md | 4 + .../date-time-functions/to_tera_date.md | 4 + .../date-time-functions/to_tera_timestamp.md | 4 + .../date-time-functions/unix_timestamp.md | 4 + .../date-time-functions/utc_timestamp.md | 4 + .../sql-functions/date-time-functions/week.md | 4 + .../date-time-functions/week_iso.md | 4 + .../date-time-functions/weekofyear.md | 4 + .../date-time-functions/weeks_add.md | 4 + .../date-time-functions/weeks_diff.md | 4 + .../date-time-functions/weeks_sub.md | 4 + .../sql-functions/date-time-functions/year.md | 4 + .../date-time-functions/years_add.md | 4 + .../date-time-functions/years_diff.md | 4 + .../date-time-functions/years_sub.md | 4 + .../date-time-functions/yearweek.md | 4 + .../dict-functions/dict_mapping.md | 4 + .../hash-functions/murmur_hash3_32.md | 4 + .../hash-functions/xx_hash3_128.md | 4 + .../hash-functions/xx_hash3_64.md | 4 + .../json-constructor-functions/json_array.md | 4 + .../json-constructor-functions/json_object.md | 4 + .../json-constructor-functions/parse_json.md | 4 + .../arrow-function.md | 4 + .../cast.md | 4 + .../get_json_bool.md | 4 + .../get_json_double.md | 4 + .../get_json_int.md | 4 + .../get_json_string.md | 4 + .../json_each.md | 4 + .../json_exists.md | 4 + .../json_keys.md | 4 + .../json_length.md | 4 + .../json_string.md | 4 + .../to_json.md | 4 + .../like-predicate-functions/like.md | 4 + .../like-predicate-functions/regexp.md | 4 + .../regexp_extract.md | 4 + .../regexp_extract_all.md | 4 + .../regexp_replace.md | 4 + .../map-functions/cardinality.md | 4 + .../map-functions/distinct_map_keys.md | 4 + .../sql-functions/map-functions/element_at.md | 4 + .../sql-functions/map-functions/map_apply.md | 4 + .../sql-functions/map-functions/map_concat.md | 4 + .../sql-functions/map-functions/map_filter.md | 4 + .../map-functions/map_from_arrays.md | 4 + .../sql-functions/map-functions/map_keys.md | 4 + .../sql-functions/map-functions/map_size.md | 4 + .../sql-functions/map-functions/map_values.md | 4 + .../map-functions/transform_keys.md | 4 + .../map-functions/transform_values.md | 4 + .../sql-functions/math-functions/abs.md | 4 + .../sql-functions/math-functions/acos.md | 4 + .../sql-functions/math-functions/asin.md | 4 + .../sql-functions/math-functions/atan.md | 4 + .../sql-functions/math-functions/atan2.md | 4 + .../sql-functions/math-functions/bin.md | 4 + .../sql-functions/math-functions/cbrt.md | 4 + .../sql-functions/math-functions/ceil.md | 4 + .../sql-functions/math-functions/ceiling.md | 4 + .../sql-functions/math-functions/conv.md | 4 + .../sql-functions/math-functions/cos.md | 4 + .../math-functions/cos_similarity.md | 4 + .../math-functions/cos_similarity_norm.md | 4 + .../sql-functions/math-functions/cosh.md | 4 + .../sql-functions/math-functions/cot.md | 4 + .../sql-functions/math-functions/degrees.md | 4 + .../sql-functions/math-functions/divide.md | 4 + .../sql-functions/math-functions/e.md | 4 + .../sql-functions/math-functions/exp.md | 4 + .../sql-functions/math-functions/floor.md | 4 + .../sql-functions/math-functions/fmod.md | 4 + .../sql-functions/math-functions/greatest.md | 4 + .../sql-functions/math-functions/least.md | 4 + .../sql-functions/math-functions/ln.md | 4 + .../sql-functions/math-functions/log.md | 4 + .../sql-functions/math-functions/log10.md | 4 + .../sql-functions/math-functions/log2.md | 4 + .../sql-functions/math-functions/mod.md | 4 + .../sql-functions/math-functions/multiply.md | 4 + .../sql-functions/math-functions/negative.md | 4 + .../sql-functions/math-functions/pi.md | 4 + .../sql-functions/math-functions/pmod.md | 4 + .../sql-functions/math-functions/positive.md | 4 + .../sql-functions/math-functions/pow.md | 4 + .../sql-functions/math-functions/radians.md | 4 + .../sql-functions/math-functions/rand.md | 3 + .../sql-functions/math-functions/round.md | 4 + .../sql-functions/math-functions/sign.md | 4 + .../sql-functions/math-functions/sin.md | 4 + .../sql-functions/math-functions/sinh.md | 4 + .../sql-functions/math-functions/sqrt.md | 4 + .../sql-functions/math-functions/square.md | 4 + .../sql-functions/math-functions/tan.md | 4 + .../sql-functions/math-functions/tanh.md | 4 + .../sql-functions/math-functions/truncate.md | 4 + .../percentile_approx_raw.md | 4 + .../percentile-functions/percentile_empty.md | 4 + .../percentile-functions/percentile_hash.md | 4 + .../percentile-functions/percentile_union.md | 4 + .../scalar-functions/hll_cardinality.md | 4 + .../scalar-functions/hll_empty.md | 4 + .../scalar-functions/hll_hash.md | 4 + .../spatial-functions/st_astext.md | 4 + .../spatial-functions/st_circle.md | 4 + .../spatial-functions/st_contains.md | 4 + .../spatial-functions/st_distance_sphere.md | 4 + .../spatial-functions/st_geometryfromtext.md | 4 + .../spatial-functions/st_linefromtext.md | 4 + .../spatial-functions/st_point.md | 4 + .../spatial-functions/st_polygon.md | 4 + .../sql-functions/spatial-functions/st_x.md | 4 + .../sql-functions/spatial-functions/st_y.md | 4 + .../append_trailing_char_if_absent.md | 4 + .../sql-functions/string-functions/ascii.md | 4 + .../sql-functions/string-functions/char.md | 4 + .../string-functions/char_length.md | 4 + .../string-functions/character_length.md | 4 + .../sql-functions/string-functions/concat.md | 4 + .../string-functions/concat_ws.md | 4 + .../sql-functions/string-functions/crc32.md | 4 + .../string-functions/ends_with.md | 4 + .../string-functions/find_in_set.md | 4 + .../string-functions/group_concat.md | 4 + .../sql-functions/string-functions/hex.md | 4 + .../string-functions/hex_decode_binary.md | 4 + .../string-functions/hex_decode_string.md | 4 + .../string-functions/inet_aton.md | 44 + .../sql-functions/string-functions/instr.md | 4 + .../sql-functions/string-functions/lcase.md | 4 + .../sql-functions/string-functions/left.md | 4 + .../sql-functions/string-functions/length.md | 4 + .../sql-functions/string-functions/locate.md | 4 + .../sql-functions/string-functions/lower.md | 4 + .../sql-functions/string-functions/lpad.md | 4 + .../sql-functions/string-functions/ltrim.md | 4 + .../string-functions/money_format.md | 4 + .../string-functions/ngram_search.md | 4 + .../string-functions/null_or_empty.md | 4 + .../string-functions/parse_url.md | 4 + .../string-functions/regexp_split.md | 59 + .../sql-functions/string-functions/repeat.md | 4 + .../sql-functions/string-functions/replace.md | 4 + .../sql-functions/string-functions/reverse.md | 4 + .../sql-functions/string-functions/right.md | 4 + .../sql-functions/string-functions/rpad.md | 4 + .../sql-functions/string-functions/rtrim.md | 4 + .../sql-functions/string-functions/space.md | 4 + .../sql-functions/string-functions/split.md | 4 + .../string-functions/split_part.md | 4 + .../string-functions/starts_with.md | 4 + .../string-functions/str_to_map.md | 4 + .../sql-functions/string-functions/strleft.md | 4 + .../string-functions/strright.md | 4 + .../string-functions/substring.md | 4 + .../string-functions/substring_index.md | 4 + .../string-functions/translate.md | 4 + .../sql-functions/string-functions/trim.md | 4 + .../sql-functions/string-functions/ucase.md | 4 + .../sql-functions/string-functions/unhex.md | 4 + .../sql-functions/string-functions/upper.md | 4 + .../string-functions/url_decode.md | 4 + .../string-functions/url_encode.md | 4 + .../string-functions/url_extract_host.md | 4 + .../string-functions/url_extract_parameter.md | 4 + .../struct-functions/named_struct.md | 4 + .../sql-functions/struct-functions/row.md | 4 + .../sql-functions/table-functions/files.md | 4 + .../table-functions/generate_series.md | 4 + .../sql-functions/utility-functions/bar.md | 39 + .../utility-functions/catalog.md | 4 + .../utility-functions/current_role.md | 4 + .../utility-functions/current_version.md | 4 + .../utility-functions/database.md | 4 + .../utility-functions/equiwidth_bucket.md | 39 + .../utility-functions/get_query_profile.md | 4 + .../utility-functions/host_name.md | 4 + .../utility-functions/is_role_in_session.md | 4 + .../sql-functions/utility-functions/isnull.md | 4 + .../utility-functions/last_query_id.md | 4 + .../sql-functions/utility-functions/sleep.md | 4 + .../sql-functions/utility-functions/uuid.md | 4 + .../utility-functions/uuid_numeric.md | 4 + .../utility-functions/version.md | 4 + .../Function/CREATE_FUNCTION.md | 13 + .../ALTER_MATERIALIZED_VIEW.md | 4 + .../table_bucket_part_index/ALTER_TABLE.md | 31 + .../table_bucket_part_index/SELECT.md | 3 + docs/zh/sql-reference/template_for_config.md | 13 + .../expression_partitioning.md | 8 + env.sh | 3 + fe/fe-core/pom.xml | 156 ++ .../main/java/com/starrocks/StarRocksFE.java | 30 + .../com/starrocks/alter/AlterHandler.java | 9 + .../com/starrocks/alter/AlterJobExecutor.java | 161 ++ .../java/com/starrocks/alter/AlterJobMgr.java | 145 ++ .../java/com/starrocks/alter/AlterJobV2.java | 47 + .../starrocks/alter/AlterJobV2Builder.java | 89 + .../starrocks/alter/AlterMVJobExecutor.java | 54 + .../java/com/starrocks/alter/AlterOpType.java | 6 + .../starrocks/alter/CompactionHandler.java | 26 + .../com/starrocks/alter/LakeRollupJob.java | 744 +++++++ .../alter/LakeTableAlterJobV2Builder.java | 22 + .../alter/LakeTableAlterMetaJob.java | 3 + .../alter/LakeTableAlterMetaJobBase.java | 149 ++ .../alter/LakeTableRollupBuilder.java | 123 ++ .../alter/LakeTableSchemaChangeJob.java | 62 + .../alter/LakeTableSchemaChangeJobBase.java | 173 ++ .../alter/MaterializedViewHandler.java | 166 ++ .../alter/OlapTableAlterJobV2Builder.java | 8 + .../alter/OlapTableRollupJobBuilder.java | 134 ++ .../starrocks/alter/OnlineOptimizeJobV2.java | 220 ++ .../com/starrocks/alter/OptimizeJobV2.java | 96 + .../starrocks/alter/OptimizeJobV2Builder.java | 8 + .../java/com/starrocks/alter/RollupJobV2.java | 236 +++ .../starrocks/alter/SchemaChangeHandler.java | 181 ++ .../starrocks/alter/SchemaChangeJobV2.java | 119 ++ .../com/starrocks/alter/SystemHandler.java | 18 + .../java/com/starrocks/analysis/Analyzer.java | 8 + .../analysis/BloomFilterIndexUtil.java | 7 + .../starrocks/analysis/DescriptorTable.java | 6 + .../com/starrocks/analysis/DictQueryExpr.java | 3 + .../starrocks/analysis/FunctionCallExpr.java | 4 + .../com/starrocks/analysis/FunctionName.java | 9 + .../java/com/starrocks/analysis/HintNode.java | 4 + .../starrocks/analysis/InvertedIndexUtil.java | 30 + .../com/starrocks/analysis/JoinOperator.java | 32 + .../com/starrocks/analysis/LabelName.java | 7 + .../com/starrocks/analysis/OutFileClause.java | 8 + .../com/starrocks/analysis/ParseNode.java | 8 + .../java/com/starrocks/analysis/SortInfo.java | 16 + .../com/starrocks/analysis/TableName.java | 28 + .../starrocks/analysis/VarBinaryLiteral.java | 3 + .../starrocks/analysis/VectorIndexUtil.java | 142 ++ .../authentication/AuthenticationMgr.java | 42 + .../AuthenticationProvider.java | 12 + .../KerberosAuthenticationProvider.java | 23 + .../LDAPAuthProviderForNative.java | 18 + .../PlainPasswordAuthenticationProvider.java | 56 + .../authentication/UserPropertyInfo.java | 14 + .../authorization/AccessControlProvider.java | 73 + .../authorization/AccessController.java | 202 ++ .../authorization/AccessDeniedException.java | 57 + .../starrocks/authorization/ActionSet.java | 66 + .../authorization/AuthorizationMgr.java | 1782 ++++++++++++++++ .../authorization/AuthorizationProvider.java | 95 + .../authorization/CatalogPEntryObject.java | 156 ++ .../authorization/ColumnPrivilege.java | 276 +++ .../authorization/DbPEntryObject.java | 212 ++ .../DefaultAuthorizationProvider.java | 253 +++ .../ExternalAccessController.java | 17 + .../ForwardCompatiblePEntryObject.java | 68 + .../authorization/FunctionPEntryObject.java | 183 ++ .../GlobalFunctionPEntryObject.java | 135 ++ .../MaterializedViewPEntryObject.java | 69 + .../authorization/NativeAccessController.java | 413 ++++ .../starrocks/authorization/ObjectType.java | 140 ++ .../starrocks/authorization/PEntryObject.java | 82 + .../authorization/PipePEntryObject.java | 246 +++ .../authorization/PolicyFCEntryObject.java | 18 + .../PrivObjNotFoundException.java | 23 + .../PrivilegeBuiltinConstants.java | 65 + .../authorization/PrivilegeCollectionV2.java | 297 +++ .../authorization/PrivilegeEntry.java | 68 + .../authorization/PrivilegeException.java | 23 + .../authorization/PrivilegeType.java | 141 ++ .../ResourceGroupPEntryObject.java | 128 ++ .../authorization/ResourcePEntryObject.java | 130 ++ .../RolePrivilegeCollectionV2.java | 154 ++ .../SecurityPolicyRewriteRule.java | 93 + .../StorageVolumePEntryObject.java | 131 ++ .../authorization/TablePEntryObject.java | 297 +++ .../authorization/UserPEntryObject.java | 139 ++ .../UserPrivilegeCollectionV2.java | 64 + .../authorization/ViewPEntryObject.java | 70 + .../WarehouseFCPEntryObject.java | 18 + .../authorization/WarehousePEntryObject.java | 128 ++ .../ranger/AccessTypeConverter.java | 20 + .../ranger/ObjectTypeConverter.java | 20 + .../ranger/RangerAccessController.java | 122 ++ .../ranger/RangerAccessResourceBuilder.java | 99 + .../ranger/RangerStarRocksAccessRequest.java | 62 + .../ranger/hive/HiveAccessType.java | 19 + .../hive/RangerHiveAccessController.java | 135 ++ .../ranger/hive/RangerHiveResource.java | 42 + .../RangerStarRocksAccessController.java | 465 +++++ .../starrocks/RangerStarRocksResource.java | 63 + .../com/starrocks/backup/BackupHandler.java | 298 +++ .../java/com/starrocks/backup/BackupJob.java | 68 + .../com/starrocks/backup/BackupJobInfo.java | 40 + .../java/com/starrocks/backup/BackupMeta.java | 42 + .../com/starrocks/backup/BlobStorage.java | 32 + .../java/com/starrocks/backup/RestoreJob.java | 478 +++++ .../starrocks/backup/mv/MVRestoreUpdater.java | 24 + .../com/starrocks/binlog/BinlogManager.java | 57 + .../starrocks/catalog/AggregateFunction.java | 40 + .../com/starrocks/catalog/AggregateType.java | 28 + .../java/com/starrocks/catalog/Catalog.java | 7 + .../starrocks/catalog/CatalogRecycleBin.java | 8 + .../com/starrocks/catalog/CatalogUtils.java | 16 + .../starrocks/catalog/ColocateTableIndex.java | 43 + .../java/com/starrocks/catalog/Column.java | 116 ++ .../java/com/starrocks/catalog/Database.java | 187 ++ .../com/starrocks/catalog/DeltaLakeTable.java | 49 + .../com/starrocks/catalog/Dictionary.java | 3 + .../com/starrocks/catalog/DictionaryMgr.java | 107 + .../starrocks/catalog/DistributionInfo.java | 7 + .../starrocks/catalog/ExternalOlapTable.java | 38 + .../java/com/starrocks/catalog/FileTable.java | 11 + .../java/com/starrocks/catalog/Function.java | 72 + .../com/starrocks/catalog/FunctionSet.java | 210 ++ .../starrocks/catalog/GlobalFunctionMgr.java | 104 + .../java/com/starrocks/catalog/HiveTable.java | 62 + .../java/com/starrocks/catalog/HudiTable.java | 35 + .../com/starrocks/catalog/IcebergTable.java | 125 ++ .../com/starrocks/catalog/IcebergView.java | 5 + .../java/com/starrocks/catalog/Index.java | 37 + .../com/starrocks/catalog/IndexParams.java | 234 +++ .../java/com/starrocks/catalog/JDBCTable.java | 14 + .../java/com/starrocks/catalog/KuduTable.java | 23 + .../starrocks/catalog/ListPartitionInfo.java | 32 + .../starrocks/catalog/MaterializedIndex.java | 45 + .../starrocks/catalog/MaterializedView.java | 496 +++++ .../com/starrocks/catalog/MetadataViewer.java | 28 + .../catalog/MvBaseTableUpdateInfo.java | 34 + .../starrocks/catalog/MvRefreshArbiter.java | 37 + .../com/starrocks/catalog/MvUpdateInfo.java | 8 + .../com/starrocks/catalog/MysqlTable.java | 18 + .../java/com/starrocks/catalog/OdpsTable.java | 16 + .../java/com/starrocks/catalog/OlapTable.java | 254 +++ .../com/starrocks/catalog/PaimonTable.java | 16 + .../java/com/starrocks/catalog/Partition.java | 278 +++ .../starrocks/catalog/PhysicalPartition.java | 489 +++++ .../catalog/ResourceGroupClassifier.java | 4 + .../starrocks/catalog/ResourceGroupMgr.java | 16 + .../com/starrocks/catalog/ResourceMgr.java | 7 + .../com/starrocks/catalog/ScalarFunction.java | 135 ++ .../com/starrocks/catalog/StructField.java | 19 + .../java/com/starrocks/catalog/Table.java | 98 + .../starrocks/catalog/TableFunctionTable.java | 201 ++ .../com/starrocks/catalog/TableProperty.java | 36 + .../catalog/TabletInvertedIndex.java | 35 + .../com/starrocks/catalog/TabletStatMgr.java | 48 + .../com/starrocks/catalog/TempPartitions.java | 5 + .../main/java/com/starrocks/catalog/Type.java | 65 + .../main/java/com/starrocks/catalog/View.java | 16 + .../combinator/AggStateCombinator.java | 112 + .../catalog/combinator/AggStateDesc.java | 202 ++ .../combinator/AggStateMergeCombinator.java | 110 + .../combinator/AggStateUnionCombinator.java | 111 + .../catalog/combinator/AggStateUtils.java | 232 +++ .../constraint/ForeignKeyConstraint.java | 50 + .../catalog/constraint/UniqueConstraint.java | 10 + .../catalog/mv/MVTimelinessArbiter.java | 139 ++ .../mv/MVTimelinessListPartitionArbiter.java | 71 + .../mv/MVTimelinessNonPartitionArbiter.java | 9 + .../mv/MVTimelinessRangePartitionArbiter.java | 79 + .../information/TaskRunsSystemTable.java | 7 + .../system/information/TasksSystemTable.java | 7 + .../catalog/system/sys/GrantsTo.java | 44 + .../catalog/system/sys/RoleEdges.java | 9 + .../catalog/system/sys/SysFeLocks.java | 44 + .../catalog/system/sys/SysFeMemoryUsage.java | 8 + .../system/sys/SysObjectDependencies.java | 17 + .../clone/ColocateTableBalancer.java | 21 + .../clone/DiskAndTabletLoadReBalancer.java | 110 + .../clone/DynamicPartitionScheduler.java | 126 ++ .../clone/PartitionTTLScheduler.java | 303 +++ .../clone/SchedulerRuntimeInfoCollector.java | 91 + .../com/starrocks/clone/TabletChecker.java | 43 + .../com/starrocks/clone/TabletSchedCtx.java | 45 + .../com/starrocks/clone/TabletScheduler.java | 67 + .../common/AlreadyExistsException.java | 4 + .../starrocks/common/AnalysisException.java | 4 + .../common/AuthenticationException.java | 4 + .../java/com/starrocks/common/Config.java | 221 ++ .../java/com/starrocks/common/ConfigBase.java | 80 + .../com/starrocks/common/DdlException.java | 4 + .../java/com/starrocks/common/ErrorCode.java | 39 + .../com/starrocks/common/ErrorReport.java | 13 + .../com/starrocks/common/FeConstants.java | 10 + .../starrocks/common/InvertedIndexParams.java | 16 + .../com/starrocks/common/LoadException.java | 4 + .../com/starrocks/common/MarkDownParser.java | 16 + .../common/MetaNotFoundException.java | 4 + .../common/NgramBfIndexParamsKey.java | 13 + .../common/NoAliveBackendException.java | 4 + .../common/NotImplementedException.java | 4 + .../starrocks/common/StarRocksException.java | 81 + .../java/com/starrocks/common/StatusOr.java | 51 + .../starrocks/common/TimeoutException.java | 4 + .../com/starrocks/common/TraceManager.java | 85 + .../starrocks/common/VectorIndexParams.java | 177 ++ .../starrocks/common/VectorSearchOptions.java | 120 ++ .../com/starrocks/common/io/DeepCopy.java | 9 + .../com/starrocks/common/io/ParamsKey.java | 15 + .../common/proc/BackendsProcDir.java | 9 + .../common/proc/ComputeNodeProcDir.java | 8 + .../com/starrocks/common/proc/DbsProcDir.java | 20 + .../common/proc/EsPartitionsProcDir.java | 16 + .../starrocks/common/proc/EsShardProcDir.java | 8 + .../proc/HMSTablePartitionsProcDir.java | 24 + .../common/proc/IndexInfoProcDir.java | 16 + .../starrocks/common/proc/IndicesProcDir.java | 16 + .../starrocks/common/proc/JobsDbProcDir.java | 8 + .../common/proc/LakeTabletsProcDir.java | 16 + .../common/proc/LocalTabletsProcDir.java | 8 + .../common/proc/PartitionsProcDir.java | 22 + .../com/starrocks/common/proc/ProcUtils.java | 4 + .../common/proc/ReplicasProcNode.java | 9 + .../common/proc/StatisticProcDir.java | 20 + .../starrocks/common/proc/TableProcDir.java | 8 + .../starrocks/common/proc/TablesProcDir.java | 26 + .../com/starrocks/common/profile/Tracer.java | 4 + .../starrocks/common/profile/TracerImpl.java | 4 + .../com/starrocks/common/profile/Tracers.java | 4 + .../com/starrocks/common/profile/Var.java | 4 + .../starrocks/common/profile/VarTracer.java | 12 + .../com/starrocks/common/util/ArrowUtil.java | 49 + .../starrocks/common/util/AutoInferUtil.java | 8 + .../com/starrocks/common/util/BrokerUtil.java | 151 ++ .../com/starrocks/common/util/Daemon.java | 15 + .../common/util/DynamicPartitionUtil.java | 131 ++ .../com/starrocks/common/util/KafkaUtil.java | 44 + .../com/starrocks/common/util/ParseUtil.java | 11 + .../starrocks/common/util/ProfileManager.java | 53 + .../common/util/PropertyAnalyzer.java | 85 + .../com/starrocks/common/util/PulsarUtil.java | 36 + .../starrocks/common/util/SmallFileMgr.java | 12 + .../com/starrocks/common/util/TimeUtils.java | 48 + .../java/com/starrocks/common/util/Util.java | 6 + .../common/util/concurrent/LockUtils.java | 173 ++ .../QueryableReentrantReadWriteLock.java | 188 ++ .../concurrent/lock/AutoCloseableLock.java | 21 + .../common/util/concurrent/lock/Locker.java | 259 +++ .../starrocks/connector/AsyncTaskQueue.java | 314 +++ .../starrocks/connector/BranchOptions.java | 52 + .../connector/CachingRemoteFileIO.java | 17 + .../connector/CatalogConnectorMetadata.java | 101 + .../starrocks/connector/ConnectorFactory.java | 4 + .../ConnectorMetadatRequestContext.java | 42 + .../connector/ConnectorMetadata.java | 128 ++ .../connector/ConnectorPartitionTraits.java | 48 + .../connector/ConnectorProperties.java | 43 + .../connector/ConnectorScanRangeSource.java | 30 + .../connector/ConnectorTableInfo.java | 7 + .../connector/ConnectorTableVersion.java | 35 + .../DirectoryBasedUpdateArbitrator.java | 44 + .../connector/GetRemoteFilesParams.java | 208 ++ .../HMSPartitionBasedRemoteInfoSource.java | 133 ++ .../connector/HivePartitionDataInfo.java | 33 + .../connector/MetaPreparationItem.java | 30 + .../ObjectBasedUpdateArbitrator.java | 59 + .../starrocks/connector/PartitionInfo.java | 18 + .../starrocks/connector/PartitionUtil.java | 124 ++ .../com/starrocks/connector/PointerType.java | 26 + .../connector/PredicateSearchKey.java | 7 + .../com/starrocks/connector/RemoteFileIO.java | 12 + .../starrocks/connector/RemoteFileInfo.java | 31 + .../RemoteFileInfoDefaultSource.java | 38 + .../connector/RemoteFileInfoSource.java | 32 + .../connector/RemoteFileOperations.java | 139 ++ .../connector/RemoteFileScanContext.java | 56 + .../starrocks/connector/RemotePathKey.java | 49 + .../connector/TableUpdateArbitrator.java | 79 + .../connector/TableVersionRange.java | 82 + .../com/starrocks/connector/TagOptions.java | 39 + .../delta/DeltaConnectorScanRangeSource.java | 146 ++ .../delta/DeltaLakeCacheUpdateProcessor.java | 4 + .../connector/delta/DeltaLakeMetadata.java | 190 ++ .../delta/DeltaLakeMetadataFactory.java | 17 + .../connector/delta/DeltaRemoteFileInfo.java | 29 + .../starrocks/connector/delta/DeltaUtils.java | 4 + .../connector/delta/FileScanTask.java | 26 + .../connector/delta/ScanFileUtils.java | 16 + .../connector/elasticsearch/EsRepository.java | 7 + .../connector/hive/CachingHiveMetastore.java | 26 + .../hive/ConnectorTableMetadataProcessor.java | 20 + .../hive/HiveCacheUpdateProcessor.java | 146 ++ .../connector/hive/HiveCommitter.java | 50 + .../connector/hive/HiveConnector.java | 5 + .../hive/HiveConnectorScanRangeSource.java | 412 ++++ .../connector/hive/HiveMetadata.java | 212 ++ .../connector/hive/HiveMetadataFactory.java | 27 + .../connector/hive/HiveMetastore.java | 16 + .../hive/HiveMetastoreApiConverter.java | 16 + .../hive/HiveMetastoreOperations.java | 67 + .../connector/hive/HiveRemoteFileIO.java | 22 + .../hive/HiveStatisticsProvider.java | 74 + .../connector/hive/HiveWriteUtils.java | 9 + .../starrocks/connector/hive/Partition.java | 12 + .../connector/hive/RemoteFileInputFormat.java | 12 + .../connector/hudi/HudiConnector.java | 13 + .../hudi/HudiConnectorScanRangeSource.java | 153 ++ .../connector/hudi/HudiMetadata.java | 97 + .../connector/hudi/HudiMetadataFactory.java | 26 + .../connector/hudi/HudiRemoteFileIO.java | 89 + .../iceberg/CachingIcebergCatalog.java | 179 ++ .../iceberg/IcebergAlterTableExecutor.java | 246 +++ .../iceberg/IcebergApiConverter.java | 37 + .../connector/iceberg/IcebergCatalog.java | 201 ++ .../connector/iceberg/IcebergConnector.java | 17 + .../IcebergConnectorScanRangeSource.java | 359 ++++ .../iceberg/IcebergDeleteSchema.java | 57 + .../iceberg/IcebergGetRemoteFilesParams.java | 61 + .../connector/iceberg/IcebergMORParams.java | 95 + .../connector/iceberg/IcebergMetaSpec.java | 18 + .../connector/iceberg/IcebergMetaSplit.java | 32 + .../connector/iceberg/IcebergMetadata.java | 591 ++++++ .../iceberg/IcebergPartitionUtils.java | 165 ++ .../iceberg/IcebergRemoteFileInfo.java | 30 + .../IcebergRemoteFileInfoSourceKey.java | 64 + .../iceberg/IcebergRemoteSourceTrigger.java | 136 ++ .../iceberg/IcebergTableOperation.java | 31 + .../QueueIcebergRemoteFileInfoSource.java | 51 + .../cost/IcebergStatisticProvider.java | 32 + .../iceberg/glue/IcebergGlueCatalog.java | 8 + .../iceberg/hadoop/IcebergHadoopCatalog.java | 8 + .../iceberg/hive/IcebergHiveCatalog.java | 8 + .../iceberg/rest/IcebergRESTCatalog.java | 112 + .../iceberg/rest/OAuth2SecurityConfig.java | 126 ++ .../rest/OAuth2SecurityProperties.java | 50 + .../connector/iceberg/rest/SecurityEnum.java | 19 + .../connector/jdbc/JDBCMetadata.java | 19 + .../connector/jdbc/MysqlSchemaResolver.java | 5 + .../connector/kudu/KuduMetadata.java | 33 + .../kudu/KuduPredicateConverter.java | 4 + .../AbstractMetadataTableFactory.java | 21 + .../metadata/MetadataCollectJob.java | 5 + .../connector/metadata/MetadataExecutor.java | 4 + .../connector/metadata/MetadataTable.java | 50 + .../MetadataTableFactoryProvider.java | 27 + .../connector/metadata/MetadataTableType.java | 11 + .../metadata/TableMetaConnector.java | 7 + .../connector/metadata/TableMetaMetadata.java | 40 + .../metadata/iceberg/IcebergFilesTable.java | 93 + .../metadata/iceberg/IcebergHistoryTable.java | 70 + .../iceberg/IcebergManifestsTable.java | 87 + .../IcebergMetadataLogEntriesTable.java | 72 + .../iceberg/IcebergMetadataTableFactory.java | 52 + .../iceberg/IcebergPartitionsTable.java | 99 + .../metadata/iceberg/IcebergRefsTable.java | 73 + .../iceberg/IcebergSnapshotsTable.java | 74 + .../iceberg/LogicalIcebergMetadataTable.java | 37 + .../connector/odps/OdpsMetadata.java | 57 + .../connector/paimon/PaimonConnector.java | 17 + .../connector/paimon/PaimonMetadata.java | 70 + .../connector/parser/trino/AstBuilder.java | 67 + .../parser/trino/TrinoParserUtils.java | 8 + .../CachedPartitionTraits.java | 24 + .../partitiontraits/DefaultTraits.java | 38 + .../DeltaLakePartitionTraits.java | 6 + .../partitiontraits/HivePartitionTraits.java | 10 + .../partitiontraits/HudiPartitionTraits.java | 10 + .../IcebergPartitionTraits.java | 33 + .../partitiontraits/JDBCPartitionTraits.java | 6 + .../partitiontraits/KuduPartitionTraits.java | 6 + .../partitiontraits/OdpsPartitionTraits.java | 6 + .../partitiontraits/OlapPartitionTraits.java | 29 + .../PaimonPartitionTraits.java | 3 + .../statistics/ConnectorAnalyzeTask.java | 195 ++ .../statistics/ConnectorAnalyzeTaskQueue.java | 128 ++ .../ConnectorColumnStatsCacheLoader.java | 4 + .../statistics/ConnectorTableColumnStats.java | 19 + .../ConnectorTableTriggerAnalyzeMgr.java | 105 + .../connector/statistics/StatisticsUtils.java | 82 + .../connector/unified/UnifiedMetadata.java | 64 + .../consistency/CheckConsistencyJob.java | 35 + .../consistency/ConsistencyChecker.java | 256 +++ .../starrocks/consistency/LockChecker.java | 49 + .../consistency/MetaRecoveryDaemon.java | 29 + .../credential/CloudConfigurationFactory.java | 18 + .../datacache/DataCacheSelectExecutor.java | 12 + .../main/java/com/starrocks/fs/HdfsUtil.java | 123 ++ .../com/starrocks/fs/hdfs/HdfsFsManager.java | 304 +++ .../com/starrocks/fs/hdfs/HdfsService.java | 56 + .../com/starrocks/fs/hdfs/WildcardURI.java | 12 + .../src/main/java/com/starrocks/ha/BDBHA.java | 15 + .../java/com/starrocks/ha/HAProtocol.java | 5 + .../java/com/starrocks/ha/LeaderInfo.java | 10 + .../java/com/starrocks/http/BaseAction.java | 9 + .../starrocks/http/HttpConnectProcessor.java | 8 + .../java/com/starrocks/http/HttpServer.java | 17 + .../starrocks/http/action/WebBaseAction.java | 8 + .../http/meta/ColocateMetaService.java | 15 + .../http/meta/GlobalDictMetaService.java | 7 + .../com/starrocks/http/meta/MetaService.java | 8 + .../http/rest/BootstrapFinishAction.java | 63 + .../starrocks/http/rest/CancelStreamLoad.java | 12 + .../http/rest/CheckDecommissionAction.java | 15 + .../starrocks/http/rest/GetDdlStmtAction.java | 21 + .../http/rest/GetLoadInfoAction.java | 8 + .../starrocks/http/rest/GetLogFileAction.java | 8 + .../http/rest/GetStreamLoadState.java | 4 + .../com/starrocks/http/rest/LoadAction.java | 74 + .../http/rest/MetaReplayerCheckAction.java | 7 + .../starrocks/http/rest/MetricsAction.java | 7 + .../starrocks/http/rest/MigrationAction.java | 34 + .../starrocks/http/rest/RestBaseAction.java | 138 ++ .../starrocks/http/rest/RestBaseResult.java | 60 + .../starrocks/http/rest/RowCountAction.java | 19 + .../starrocks/http/rest/SetConfigAction.java | 7 + .../starrocks/http/rest/ShowDataAction.java | 11 + .../http/rest/ShowMetaInfoAction.java | 11 + .../starrocks/http/rest/ShowProcAction.java | 7 + .../com/starrocks/http/rest/StopFeAction.java | 8 + .../http/rest/StorageTypeCheckAction.java | 23 + .../http/rest/StreamLoadMetaAction.java | 177 ++ .../http/rest/SyncCloudTableMetaAction.java | 7 + .../http/rest/TableQueryPlanAction.java | 22 + .../http/rest/TableRowCountAction.java | 22 + .../http/rest/TableSchemaAction.java | 22 + .../http/rest/TransactionLoadAction.java | 70 + .../starrocks/http/rest/TriggerAction.java | 15 + .../BypassWriteTransactionHandler.java | 63 + .../TransactionOperationHandler.java | 8 + .../TransactionWithChannelHandler.java | 12 + .../TransactionWithoutChannelHandler.java | 41 + .../http/rest/v2/RestBaseResultV2.java | 150 ++ .../http/rest/v2/TableBaseAction.java | 122 ++ .../http/rest/v2/TablePartitionAction.java | 94 + .../http/rest/v2/TableSchemaAction.java | 56 + .../starrocks/http/rest/v2/vo/ColumnView.java | 421 ++++ .../http/rest/v2/vo/DistributionInfoView.java | 92 + .../starrocks/http/rest/v2/vo/IndexView.java | 118 ++ .../rest/v2/vo/MaterializedIndexMetaView.java | 82 + .../http/rest/v2/vo/PartitionInfoView.java | 302 +++ .../http/rest/v2/vo/TableSchemaView.java | 263 +++ .../starrocks/http/rest/v2/vo/TabletView.java | 80 + .../http/rest/v2/vo/package-info.java | 21 + .../journal/CheckpointException.java | 21 + .../starrocks/journal/CheckpointWorker.java | 192 ++ .../journal/GlobalStateCheckpointWorker.java | 74 + .../com/starrocks/journal/JournalEntity.java | 220 ++ .../journal/StarMgrCheckpointWorker.java | 46 + .../com/starrocks/journal/bdbje/BDBTool.java | 6 + .../starrocks/journal/bdbje/Timestamp.java | 11 + .../starrocks/lake/LakeMaterializedView.java | 21 + .../java/com/starrocks/lake/LakeTable.java | 42 + .../com/starrocks/lake/LakeTableHelper.java | 45 + .../com/starrocks/lake/StarMgrMetaSyncer.java | 89 + .../java/com/starrocks/lake/StarOSAgent.java | 75 + .../com/starrocks/lake/TxnInfoHelper.java | 4 + .../main/java/com/starrocks/lake/Utils.java | 44 + .../starrocks/lake/backup/LakeBackupJob.java | 4 + .../starrocks/lake/backup/LakeRestoreJob.java | 31 + .../lake/compaction/CompactionMgr.java | 4 + .../lake/compaction/CompactionScheduler.java | 60 + .../CompactionTxnCommitAttachment.java | 6 + .../starrocks/lake/delete/LakeDeleteJob.java | 16 + .../lake/vacuum/AutovacuumDaemon.java | 24 + .../leader/CheckpointController.java | 472 +++++ .../java/com/starrocks/leader/LeaderImpl.java | 105 + .../java/com/starrocks/leader/MetaHelper.java | 33 + .../com/starrocks/leader/ReportHandler.java | 475 +++++ .../starrocks/listener/LoadJobMVListener.java | 13 + .../listener/LoadJobStatsListener.java | 4 + .../com/starrocks/load/BrokerFileGroup.java | 13 + .../java/com/starrocks/load/DeleteInfo.java | 12 + .../java/com/starrocks/load/DeleteJob.java | 12 + .../java/com/starrocks/load/DeleteMgr.java | 39 + .../java/com/starrocks/load/EtlStatus.java | 3 + .../com/starrocks/load/ExportChecker.java | 8 + .../java/com/starrocks/load/ExportJob.java | 102 + .../java/com/starrocks/load/ExportMgr.java | 31 + .../starrocks/load/InsertOverwriteJob.java | 33 + .../starrocks/load/InsertOverwriteJobMgr.java | 4 + .../load/InsertOverwriteJobRunner.java | 116 ++ .../main/java/com/starrocks/load/Load.java | 95 + .../com/starrocks/load/OlapDeleteJob.java | 29 + .../com/starrocks/load/PartitionUtils.java | 121 ++ .../com/starrocks/load/TabletDeleteInfo.java | 13 + .../load/batchwrite/BatchWriteId.java | 54 + .../load/batchwrite/BatchWriteMgr.java | 226 ++ .../CoordinatorBackendAssigner.java | 56 + .../CoordinatorBackendAssignerImpl.java | 864 ++++++++ .../load/batchwrite/IsomorphicBatchWrite.java | 264 +++ .../load/batchwrite/LoadExecuteCallback.java | 28 + .../load/batchwrite/LoadExecutor.java | 323 +++ .../RequestCoordinatorBackendResult.java | 32 + .../load/batchwrite/RequestLoadResult.java | 29 + .../starrocks/load/batchwrite/TableId.java | 67 + .../starrocks/load/loadv2/BrokerLoadJob.java | 39 + .../load/loadv2/BrokerLoadPendingTask.java | 12 + .../starrocks/load/loadv2/BulkLoadJob.java | 68 + .../starrocks/load/loadv2/InsertLoadJob.java | 70 + .../com/starrocks/load/loadv2/LoadJob.java | 41 + .../load/loadv2/LoadJobFinalOperation.java | 6 + .../load/loadv2/LoadLoadingTask.java | 13 + .../com/starrocks/load/loadv2/LoadMgr.java | 56 + .../com/starrocks/load/loadv2/LoadTask.java | 12 + .../load/loadv2/LoadsHistorySyncer.java | 10 + .../loadv2/ManualLoadTxnCommitAttachment.java | 6 + .../loadv2/MiniLoadTxnCommitAttachment.java | 6 + .../load/loadv2/SparkEtlJobHandler.java | 36 + .../starrocks/load/loadv2/SparkLoadJob.java | 77 + .../load/loadv2/SparkLoadPendingTask.java | 104 + .../load/loadv2/SparkRepository.java | 24 + .../starrocks/load/pipe/FilePipeSource.java | 12 + .../java/com/starrocks/load/pipe/Pipe.java | 40 + .../com/starrocks/load/pipe/PipeListener.java | 8 + .../com/starrocks/load/pipe/PipeManager.java | 4 + .../load/pipe/filelist/FileListTableRepo.java | 8 + .../load/pipe/filelist/RepoCreator.java | 11 + .../load/routineload/KafkaProgress.java | 8 + .../load/routineload/KafkaRoutineLoadJob.java | 58 + .../load/routineload/KafkaTaskInfo.java | 24 + .../routineload/PulsarRoutineLoadJob.java | 49 + .../load/routineload/PulsarTaskInfo.java | 24 + .../RLTaskTxnCommitAttachment.java | 6 + .../RoutineLoadFunctionalExprProvider.java | 8 + .../load/routineload/RoutineLoadJob.java | 161 ++ .../load/routineload/RoutineLoadMgr.java | 51 + .../routineload/RoutineLoadScheduler.java | 20 + .../load/routineload/RoutineLoadTaskInfo.java | 23 + .../routineload/RoutineLoadTaskScheduler.java | 8 + .../StreamLoadFunctionalExprProvider.java | 6 + .../load/streamload/StreamLoadHttpHeader.java | 77 + .../load/streamload/StreamLoadInfo.java | 143 ++ .../load/streamload/StreamLoadKvParams.java | 376 ++++ .../load/streamload/StreamLoadMgr.java | 114 + .../load/streamload/StreamLoadParams.java | 64 + .../load/streamload/StreamLoadTask.java | 112 + .../streamload/StreamLoadThriftParams.java | 194 ++ .../StreamLoadTxnCommitAttachment.java | 12 + .../metric/MaterializedViewMetricsEntity.java | 51 + .../java/com/starrocks/metric/MetricRepo.java | 66 + .../com/starrocks/monitor/jvm/JvmStats.java | 15 + .../starrocks/mv/MVMetaVersionRepairer.java | 91 + .../com/starrocks/mv/MVRepairHandler.java | 15 + .../mv/analyzer/MVPartitionExprResolver.java | 80 + .../analyzer/MVPartitionSlotRefResolver.java | 17 + .../starrocks/mysql/privilege/Password.java | 13 + .../starrocks/persist/BackendTabletsInfo.java | 9 + .../persist/CreateInsertOverwriteJobLog.java | 18 + .../com/starrocks/persist/CreateUserInfo.java | 7 + .../com/starrocks/persist/DatabaseInfo.java | 14 + .../starrocks/persist/DropPartitionInfo.java | 3 + .../starrocks/persist/DropPartitionsInfo.java | 124 ++ .../java/com/starrocks/persist/EditLog.java | 219 ++ .../com/starrocks/persist/MetaCleaner.java | 4 + .../persist/ModifyPartitionInfo.java | 15 + .../com/starrocks/persist/OperationType.java | 85 + .../PhysicalPartitionPersistInfoV2.java | 12 + .../com/starrocks/persist/RecoverInfo.java | 12 + .../persist/RolePrivilegeCollectionInfo.java | 7 + .../java/com/starrocks/persist/TableInfo.java | 9 + .../persist/UserPrivilegeCollectionInfo.java | 7 + .../com/starrocks/persist/gson/GsonUtils.java | 35 + .../starrocks/planner/AggregationNode.java | 19 + .../starrocks/planner/AnalyticEvalNode.java | 8 + .../com/starrocks/planner/BinlogScanNode.java | 27 + .../starrocks/planner/DeltaLakeScanNode.java | 95 + .../com/starrocks/planner/EsScanNode.java | 23 + .../com/starrocks/planner/ExchangeNode.java | 11 + .../com/starrocks/planner/ExportSink.java | 11 + .../com/starrocks/planner/FileScanNode.java | 87 + .../starrocks/planner/FileTableScanNode.java | 17 + .../starrocks/planner/FragmentNormalizer.java | 43 + .../planner/HashDistributionPruner.java | 16 + .../com/starrocks/planner/HashJoinNode.java | 30 + .../com/starrocks/planner/HdfsScanNode.java | 40 + .../com/starrocks/planner/HiveTableSink.java | 6 + .../com/starrocks/planner/HudiScanNode.java | 20 + .../planner/IcebergMetadataScanNode.java | 73 + .../starrocks/planner/IcebergScanNode.java | 212 ++ .../starrocks/planner/IcebergTableSink.java | 36 + .../com/starrocks/planner/JDBCScanNode.java | 15 + .../java/com/starrocks/planner/JoinNode.java | 19 + .../com/starrocks/planner/KuduScanNode.java | 28 + .../com/starrocks/planner/LoadScanNode.java | 16 + .../com/starrocks/planner/MetaScanNode.java | 38 + .../com/starrocks/planner/MysqlScanNode.java | 15 + .../com/starrocks/planner/MysqlTableSink.java | 5 + .../com/starrocks/planner/OdpsScanNode.java | 28 + .../com/starrocks/planner/OlapScanNode.java | 236 +++ .../com/starrocks/planner/OlapTableSink.java | 120 ++ .../com/starrocks/planner/PaimonScanNode.java | 31 + .../com/starrocks/planner/PlanFragment.java | 22 + .../java/com/starrocks/planner/PlanNode.java | 49 + .../com/starrocks/planner/ProjectNode.java | 11 + .../com/starrocks/planner/RepeatNode.java | 22 + .../planner/RuntimeFilterPushDownContext.java | 5 + .../java/com/starrocks/planner/ScanNode.java | 23 + .../com/starrocks/planner/SchemaScanNode.java | 11 + .../com/starrocks/planner/SelectNode.java | 58 + .../starrocks/planner/SetOperationNode.java | 9 + .../java/com/starrocks/planner/SortNode.java | 84 + .../starrocks/planner/StreamLoadPlanner.java | 8 + .../starrocks/planner/StreamLoadScanNode.java | 102 + .../starrocks/planner/TableFunctionNode.java | 8 + .../starrocks/plugin/BuiltinPluginLoader.java | 12 + .../starrocks/plugin/DynamicPluginLoader.java | 35 + .../com/starrocks/plugin/PluginException.java | 6 + .../com/starrocks/plugin/PluginLoader.java | 25 + .../java/com/starrocks/plugin/PluginMgr.java | 38 + .../java/com/starrocks/plugin/PluginZip.java | 36 + .../com/starrocks/qe/BackendSelector.java | 7 + .../qe/ColocatedBackendSelector.java | 12 + .../java/com/starrocks/qe/ConnectContext.java | 88 + .../com/starrocks/qe/ConnectProcessor.java | 16 + .../com/starrocks/qe/ConnectScheduler.java | 68 + .../starrocks/qe/CoordinatorPreprocessor.java | 24 + .../com/starrocks/qe/DDLStmtExecutor.java | 47 + .../com/starrocks/qe/DefaultCoordinator.java | 205 ++ .../starrocks/qe/ExecuteExceptionHandler.java | 17 + .../starrocks/qe/ExecuteScriptExecutor.java | 36 + .../com/starrocks/qe/HDFSBackendSelector.java | 105 + .../com/starrocks/qe/LeaderOpExecutor.java | 12 + .../starrocks/qe/NormalBackendSelector.java | 8 + .../java/com/starrocks/qe/QeProcessor.java | 10 + .../com/starrocks/qe/QeProcessorImpl.java | 17 + .../com/starrocks/qe/QueryQueueManager.java | 28 + .../com/starrocks/qe/QueryStateException.java | 7 + .../com/starrocks/qe/QueryStatisticsInfo.java | 23 + .../java/com/starrocks/qe/ResultReceiver.java | 46 + .../com/starrocks/qe/SessionVariable.java | 551 +++++ .../starrocks/qe/SetDefaultRoleExecutor.java | 10 + .../com/starrocks/qe/SetRoleExecutor.java | 21 + .../starrocks/qe/ShortCircuitExecutor.java | 21 + .../qe/ShortCircuitHybridExecutor.java | 16 + .../java/com/starrocks/qe/ShowExecutor.java | 221 ++ .../qe/ShowMaterializedViewStatus.java | 4 + .../java/com/starrocks/qe/StmtExecutor.java | 522 +++++ .../starrocks/qe/feedback/NodeExecStats.java | 139 ++ .../qe/feedback/OperatorTuningGuides.java | 152 ++ .../qe/feedback/PlanAdvisorExecutor.java | 107 + .../qe/feedback/PlanTuningAdvisor.java | 122 ++ .../qe/feedback/PlanTuningCacheKey.java | 73 + .../feedback/analyzer/JoinTuningAnalyzer.java | 107 + .../feedback/analyzer/PlanTuningAnalyzer.java | 48 + .../analyzer/StreamingAggTuningAnalyzer.java | 110 + .../qe/feedback/guide/JoinTuningGuide.java | 100 + .../LeftChildEstimationErrorTuningGuide.java | 122 ++ .../RightChildEstimationErrorTuningGuide.java | 230 +++ .../guide/StreamingAggTuningGuide.java | 59 + .../qe/feedback/guide/TuningGuide.java | 37 + .../qe/feedback/skeleton/BlockingAggNode.java | 60 + .../feedback/skeleton/DistributionNode.java | 58 + .../qe/feedback/skeleton/JoinNode.java | 63 + .../qe/feedback/skeleton/ScanNode.java | 69 + .../qe/feedback/skeleton/SkeletonBuilder.java | 188 ++ .../qe/feedback/skeleton/SkeletonNode.java | 131 ++ .../feedback/skeleton/StreamingAggNode.java | 60 + .../starrocks/qe/scheduler/Coordinator.java | 52 + .../com/starrocks/qe/scheduler/Deployer.java | 30 + .../qe/scheduler/FeExecuteCoordinator.java | 4 + .../qe/scheduler/QueryRuntimeProfile.java | 14 + .../qe/scheduler/SchedulerException.java | 6 + .../scheduler/TFragmentInstanceFactory.java | 37 + .../assignment/BackendSelectorFactory.java | 22 + .../FragmentAssignmentStrategy.java | 10 + .../FragmentAssignmentStrategyFactory.java | 4 + .../LocalFragmentAssignmentStrategy.java | 63 + .../RemoteFragmentAssignmentStrategy.java | 12 + .../dag/AllAtOnceExecutionSchedule.java | 89 + .../qe/scheduler/dag/ExecutionDAG.java | 4 + .../qe/scheduler/dag/ExecutionSchedule.java | 14 + .../qe/scheduler/dag/FragmentInstance.java | 54 + .../dag/FragmentInstanceExecState.java | 27 + .../starrocks/qe/scheduler/dag/JobSpec.java | 28 + .../dag/PhasedExecutionSchedule.java | 61 + .../scheduler/dag/ScheduleNextTurnRunner.java | 8 + .../qe/scheduler/slot/GlobalSlotProvider.java | 9 + .../starrocks/replication/ReplicationJob.java | 43 + .../starrocks/replication/ReplicationMgr.java | 8 + .../ReplicationTxnCommitAttachment.java | 6 + .../java/com/starrocks/rpc/BrpcProxy.java | 6 + .../com/starrocks/rpc/PBackendService.java | 12 + .../com/starrocks/scheduler/Constants.java | 4 + .../scheduler/DataCacheSelectProcessor.java | 20 + .../starrocks/scheduler/MVActiveChecker.java | 9 + .../starrocks/scheduler/MvTaskRunContext.java | 33 + .../PartitionBasedMvRefreshProcessor.java | 255 +++ .../scheduler/TableSnapshotInfo.java | 5 + .../scheduler/TableWithPartitions.java | 17 + .../com/starrocks/scheduler/TaskManager.java | 16 + .../java/com/starrocks/scheduler/TaskRun.java | 8 + .../starrocks/scheduler/TaskRunManager.java | 17 + .../scheduler/history/TableKeeper.java | 19 + .../scheduler/mv/MVMaintenanceJob.java | 16 + .../scheduler/mv/MVMaintenanceTask.java | 4 + .../scheduler/mv/MVPCTMetaRepairer.java | 145 ++ .../mv/MVPCTRefreshListPartitioner.java | 327 +++ .../mv/MVPCTRefreshNonPartitioner.java | 17 + .../scheduler/mv/MVPCTRefreshPartitioner.java | 79 + .../scheduler/mv/MVPCTRefreshPlanBuilder.java | 141 ++ .../mv/MVPCTRefreshRangePartitioner.java | 198 ++ .../starrocks/scheduler/mv/MVTraceUtils.java | 4 + .../scheduler/mv/MVVersionManager.java | 20 + .../mv/TxnBasedEpochCoordinator.java | 16 + .../java/com/starrocks/server/CatalogMgr.java | 49 + .../com/starrocks/server/GlobalStateMgr.java | 421 ++++ .../starrocks/server/HiveTableFactory.java | 5 + .../starrocks/server/HudiTableFactory.java | 5 + .../starrocks/server/IcebergTableFactory.java | 5 + .../com/starrocks/server/LocalMetastore.java | 1156 +++++++++++ .../com/starrocks/server/MetadataMgr.java | 202 ++ .../java/com/starrocks/server/NodeMgr.java | 76 + .../starrocks/server/OlapTableFactory.java | 29 + .../server/SharedDataStorageVolumeMgr.java | 8 + .../starrocks/server/StorageVolumeMgr.java | 6 + .../starrocks/server/WarehouseManager.java | 19 + .../service/FrontendServiceImpl.java | 493 +++++ .../service/InformationSchemaDataSource.java | 65 + .../sql/ArrowFlightSqlConnectContext.java | 200 ++ .../sql/ArrowFlightSqlConnectProcessor.java | 142 ++ .../flight/sql/ArrowFlightSqlService.java | 113 + .../flight/sql/ArrowFlightSqlServiceImpl.java | 473 +++++ .../sql/auth/ArrowFlightSqlAuthenticator.java | 75 + .../ArrowFlightSqlCredentialValidator.java | 61 + .../session/ArrowFlightSqlSessionManager.java | 75 + .../sql/session/ArrowFlightSqlTokenInfo.java | 43 + .../session/ArrowFlightSqlTokenManager.java | 87 + .../java/com/starrocks/sql/DeletePlanner.java | 15 + .../main/java/com/starrocks/sql/Explain.java | 18 + .../com/starrocks/sql/ExplainAnalyzer.java | 85 + .../java/com/starrocks/sql/InsertPlanner.java | 91 + .../java/com/starrocks/sql/LoadPlanner.java | 59 + .../com/starrocks/sql/RankingWindowUtils.java | 136 ++ .../com/starrocks/sql/StatementPlanner.java | 131 ++ .../java/com/starrocks/sql/UpdatePlanner.java | 10 + .../sql/analyzer/AggregationAnalyzer.java | 4 + .../analyzer/AlterRoutineLoadAnalyzer.java | 8 + .../analyzer/AlterTableClauseAnalyzer.java | 138 ++ .../analyzer/AlterTableStatementAnalyzer.java | 14 + .../sql/analyzer/AnalyzeStmtAnalyzer.java | 71 + .../com/starrocks/sql/analyzer/Analyzer.java | 71 + .../starrocks/sql/analyzer/AnalyzerUtils.java | 150 ++ .../sql/analyzer/AstToSQLBuilder.java | 25 + .../sql/analyzer/AstToStringBuilder.java | 110 + .../sql/analyzer/AuthenticationAnalyzer.java | 167 ++ .../sql/analyzer/AuthorizationAnalyzer.java | 510 +++++ .../starrocks/sql/analyzer/Authorizer.java | 19 + .../sql/analyzer/AuthorizerStmtVisitor.java | 169 ++ .../sql/analyzer/BackupRestoreAnalyzer.java | 122 ++ .../starrocks/sql/analyzer/CTASAnalyzer.java | 18 + .../CancelAlterTableStatementAnalyzer.java | 9 + .../sql/analyzer/CreateFunctionAnalyzer.java | 554 +++++ .../analyzer/CreateRoutineLoadAnalyzer.java | 8 + .../sql/analyzer/CreateTableAnalyzer.java | 136 ++ .../sql/analyzer/CreateTableLikeAnalyzer.java | 20 + .../analyzer/DecimalV3FunctionAnalyzer.java | 87 + .../sql/analyzer/DeleteAnalyzer.java | 47 + .../sql/analyzer/DictionaryAnalyzer.java | 3 + .../sql/analyzer/DropStmtAnalyzer.java | 25 + .../sql/analyzer/ExportStmtAnalyzer.java | 4 + .../sql/analyzer/ExpressionAnalyzer.java | 60 + .../starrocks/sql/analyzer/FeNameFormat.java | 19 + .../sql/analyzer/FunctionAnalyzer.java | 649 ++++++ .../sql/analyzer/InsertAnalyzer.java | 333 +++ .../sql/analyzer/LoadStmtAnalyzer.java | 15 + .../analyzer/MaterializedViewAnalyzer.java | 619 ++++++ .../sql/analyzer/PlannerMetaLocker.java | 23 + .../analyzer/PolymorphicFunctionAnalyzer.java | 55 + .../starrocks/sql/analyzer/QueryAnalyzer.java | 244 +++ .../analyzer/RecoverPartitionAnalyzer.java | 7 + .../sql/analyzer/RecoverTableAnalyzer.java | 7 + .../RefreshTableStatementAnalyzer.java | 7 + .../sql/analyzer/ResourceGroupAnalyzer.java | 4 + .../sql/analyzer/SelectAnalyzer.java | 10 + .../sql/analyzer/SetStmtAnalyzer.java | 16 + .../sql/analyzer/ShowAlterStmtAnalyzer.java | 8 + .../sql/analyzer/ShowStmtAnalyzer.java | 36 + .../sql/analyzer/ShowTabletStmtAnalyzer.java | 14 + .../sql/analyzer/TruncateTableAnalyzer.java | 7 + .../sql/analyzer/UpdateAnalyzer.java | 33 + .../starrocks/sql/analyzer/ViewAnalyzer.java | 15 + .../sql/analyzer/WarehouseAnalyzer.java | 17 + .../starrocks/sql/ast/AbstractBackupStmt.java | 108 + .../com/starrocks/sql/ast/AddFieldClause.java | 3 + .../sql/ast/AlterRoutineLoadStmt.java | 47 + .../sql/ast/AlterTableOperationClause.java | 55 + .../com/starrocks/sql/ast/AlterUserStmt.java | 11 + .../com/starrocks/sql/ast/AnalyzeStmt.java | 31 + .../com/starrocks/sql/ast/AstVisitor.java | 68 + .../com/starrocks/sql/ast/BackupStmt.java | 19 + .../sql/ast/BaseCreateAlterUserStmt.java | 31 + .../sql/ast/BaseGrantRevokePrivilegeStmt.java | 7 + .../starrocks/sql/ast/CancelBackupStmt.java | 26 + .../com/starrocks/sql/ast/CatalogRef.java | 80 + .../java/com/starrocks/sql/ast/ColumnDef.java | 102 + .../starrocks/sql/ast/CreateFunctionStmt.java | 119 ++ .../ast/CreateMaterializedViewStatement.java | 57 + .../sql/ast/CreateMaterializedViewStmt.java | 119 ++ .../sql/ast/CreateOrReplaceBranchClause.java | 62 + .../sql/ast/CreateOrReplaceTagClause.java | 62 + .../sql/ast/CreateRoutineLoadStmt.java | 42 + .../sql/ast/CreateTableAsSelectStmt.java | 8 + .../com/starrocks/sql/ast/CreateUserStmt.java | 26 + .../starrocks/sql/ast/DataDescription.java | 22 + .../java/com/starrocks/sql/ast/DmlStmt.java | 48 + .../starrocks/sql/ast/DropBranchClause.java | 43 + .../starrocks/sql/ast/DropFunctionStmt.java | 21 + .../sql/ast/DropPartitionClause.java | 67 + .../com/starrocks/sql/ast/DropTagClause.java | 43 + .../com/starrocks/sql/ast/ExportStmt.java | 12 + .../sql/ast/FileTableFunctionRelation.java | 25 + .../com/starrocks/sql/ast/FunctionRef.java | 90 + .../java/com/starrocks/sql/ast/IndexDef.java | 23 + .../com/starrocks/sql/ast/InsertStmt.java | 83 + .../starrocks/sql/ast/IntervalLiteral.java | 8 + .../starrocks/sql/ast/ListPartitionDesc.java | 77 + .../com/starrocks/sql/ast/MVColumnItem.java | 27 + .../com/starrocks/sql/ast/QueryPeriod.java | 59 + .../com/starrocks/sql/ast/QueryStatement.java | 16 + .../ast/RefreshMaterializedViewStatement.java | 19 + .../com/starrocks/sql/ast/RestoreStmt.java | 19 + .../starrocks/sql/ast/ShowAnalyzeJobStmt.java | 7 + .../sql/ast/ShowAnalyzeStatusStmt.java | 14 + .../sql/ast/ShowBasicStatsMetaStmt.java | 15 + .../sql/ast/ShowHistogramStatsMetaStmt.java | 15 + .../com/starrocks/sql/ast/StatementBase.java | 16 + .../com/starrocks/sql/ast/TableRelation.java | 53 + .../starrocks/sql/ast/TableSampleClause.java | 143 ++ .../com/starrocks/sql/ast/UnitIdentifier.java | 8 + .../com/starrocks/sql/ast/UserAuthOption.java | 3 + .../com/starrocks/sql/ast/UserIdentity.java | 13 + .../com/starrocks/sql/ast/ValuesRelation.java | 29 + .../sql/ast/feedback/AddPlanAdvisorStmt.java | 39 + .../ast/feedback/ClearPlanAdvisorStmt.java | 30 + .../sql/ast/feedback/DelPlanAdvisorStmt.java | 37 + .../sql/ast/feedback/PlanAdvisorStmt.java | 31 + .../sql/ast/feedback/ShowPlanAdvisorStmt.java | 30 + .../starrocks/sql/ast/pipe/ShowPipeStmt.java | 4 + .../sql/ast/warehouse/AlterWarehouseStmt.java | 67 + .../sql/ast/warehouse/ShowWarehousesStmt.java | 4 + .../sql/common/DebugOperatorTracer.java | 47 + .../com/starrocks/sql/common/Generator.java | 12 + .../sql/common/ListPartitionDiffer.java | 160 ++ .../com/starrocks/sql/common/MetaUtils.java | 69 + .../com/starrocks/sql/common/PListCell.java | 39 + .../com/starrocks/sql/common/PRangeCell.java | 25 + .../starrocks/sql/common/PRangeCellPlus.java | 26 + .../starrocks/sql/common/ParserErrorMsg.java | 27 + .../starrocks/sql/common/PartitionDiff.java | 69 + .../sql/common/PartitionDiffResult.java | 22 + .../starrocks/sql/common/PartitionDiffer.java | 78 + .../sql/common/PermutationGenerator.java | 9 + .../sql/common/RangePartitionDiffer.java | 213 ++ .../starrocks/sql/common/SqlWithIdUtils.java | 8 + .../sql/common/SyncPartitionUtils.java | 48 + .../starrocks/sql/common/TimeUnitUtils.java | 27 + .../com/starrocks/sql/optimizer/CTEUtils.java | 14 + .../sql/optimizer/LogicalPlanPrinter.java | 8 + .../sql/optimizer/MaterializationContext.java | 143 ++ .../optimizer/MaterializedViewOptimizer.java | 31 + .../sql/optimizer/MvRewriteContext.java | 7 + .../sql/optimizer/MvRewritePreprocessor.java | 28 + .../sql/optimizer/OptExpression.java | 50 + .../sql/optimizer/OptExpressionVisitor.java | 7 + .../starrocks/sql/optimizer/Optimizer.java | 177 ++ .../sql/optimizer/OptimizerContext.java | 20 + .../sql/optimizer/OptimizerTraceUtil.java | 16 + .../optimizer/UKFKConstraintsCollector.java | 177 ++ .../com/starrocks/sql/optimizer/Utils.java | 18 + .../sql/optimizer/base/ColumnRefSet.java | 4 + .../sql/optimizer/base/LogicalProperty.java | 5 + .../sql/optimizer/base/SortProperty.java | 4 + .../sql/optimizer/function/MetaFunctions.java | 47 + .../sql/optimizer/operator/OpRuleBit.java | 33 + .../sql/optimizer/operator/Operator.java | 108 + .../sql/optimizer/operator/OperatorType.java | 8 + .../optimizer/operator/OperatorVisitor.java | 22 + .../optimizer/operator/UKFKConstraints.java | 78 + .../logical/LogicalAggregationOperator.java | 45 + .../logical/LogicalAssertOneRowOperator.java | 20 + .../logical/LogicalCTEAnchorOperator.java | 16 + .../logical/LogicalCTEConsumeOperator.java | 16 + .../logical/LogicalCTEProduceOperator.java | 19 + .../logical/LogicalFilterOperator.java | 16 + ...icalIcebergEqualityDeleteScanOperator.java | 123 ++ .../LogicalIcebergMetadataScanOperator.java | 46 + .../logical/LogicalIcebergScanOperator.java | 91 + .../operator/logical/LogicalJoinOperator.java | 22 + .../logical/LogicalLimitOperator.java | 20 + .../logical/LogicalMetaScanOperator.java | 46 + .../logical/LogicalOlapScanOperator.java | 85 + .../logical/LogicalProjectOperator.java | 18 + .../operator/logical/LogicalScanOperator.java | 73 + .../operator/logical/LogicalSetOperator.java | 16 + .../logical/LogicalTableFunctionOperator.java | 20 + .../operator/logical/LogicalTopNOperator.java | 99 + .../logical/LogicalUnionOperator.java | 35 + .../logical/LogicalWindowOperator.java | 47 + .../PhysicalHashAggregateOperator.java | 40 + ...icalIcebergEqualityDeleteScanOperator.java | 79 + .../PhysicalIcebergMetadataScanOperator.java | 8 + .../physical/PhysicalIcebergScanOperator.java | 33 + .../physical/PhysicalMetaScanOperator.java | 24 + .../physical/PhysicalOlapScanOperator.java | 76 + .../physical/PhysicalScanOperator.java | 39 + .../physical/PhysicalTopNOperator.java | 45 + .../physical/PhysicalUnionOperator.java | 25 + .../physical/PhysicalWindowOperator.java | 31 + .../operator/scalar/ConstantOperator.java | 6 + .../scalar/DictionaryGetOperator.java | 3 + .../scalar/OperatorFunctionChecker.java | 65 + .../optimizer/property/DomainProperty.java | 171 ++ .../property/DomainPropertyDeriver.java | 198 ++ .../optimizer/property/RangeExtractor.java | 344 ++++ .../optimizer/property/ReplaceShuttle.java | 61 + .../rewrite/OptExternalPartitionPruner.java | 93 + .../rewrite/OptOlapPartitionPruner.java | 116 ++ .../PartitionColPredicateEvaluator.java | 13 + .../PartitionColPredicateExtractor.java | 10 + .../rewrite/ReplaceColumnRefRewriter.java | 27 + .../rewrite/ScalarOperatorEvaluator.java | 25 + .../rewrite/ScalarOperatorFunctions.java | 34 + .../ScalarRangePredicateExtractor.java | 33 + .../rewrite/TableScanPredicateExtractor.java | 176 ++ .../rewrite/scalar/ReduceCastRule.java | 38 + .../starrocks/sql/optimizer/rule/RuleSet.java | 47 + .../sql/optimizer/rule/RuleSetType.java | 5 + .../sql/optimizer/rule/RuleType.java | 28 + ...gEqualityDeleteScanImplementationRule.java | 44 + .../IcebergScanImplementationRule.java | 5 + .../NestLoopJoinImplementationRule.java | 10 + .../TopNImplementationRule.java | 6 + .../WindowImplementationRule.java | 4 + .../sql/optimizer/rule/join/JoinOrder.java | 4 + .../rule/join/JoinReorderFactory.java | 39 + .../optimizer/rule/join/ReorderJoinRule.java | 22 + .../rule/mv/MaterializedViewRule.java | 4 + .../rule/transformation/EliminateAggRule.java | 56 + .../ExternalScanPartitionPruneRule.java | 21 + .../GroupByCountDistinctRewriteRule.java | 54 + .../IcebergEqualityDeleteRewriteRule.java | 347 ++++ .../IcebergPartitionsTableRewriteRule.java | 116 ++ .../transformation/JoinCommutativityRule.java | 4 + .../transformation/ListPartitionPruner.java | 123 ++ ...aterializedViewTransparentRewriteRule.java | 21 + .../transformation/MergeLimitDirectRule.java | 5 + .../MergeProjectWithChildRule.java | 13 + .../OnPredicateMoveAroundRule.java | 291 +++ .../transformation/PartitionPruneRule.java | 24 + .../PruneHDFSScanColumnRule.java | 15 + .../PruneUKFKGroupByKeysRule.java | 139 ++ .../PullUpScanPredicateRule.java | 270 +++ .../PushDownAggToMetaScanRule.java | 63 + .../PushDownFlatJsonMetaToMetaScanRule.java | 7 + .../PushDownLimitRankingWindowRule.java | 140 ++ .../PushDownPredicateRankingWindowRule.java | 160 ++ .../PushDownPredicateScanRule.java | 12 + .../RewriteSimpleAggToHDFSScanRule.java | 5 + .../RewriteSimpleAggToMetaScanRule.java | 7 + .../RewriteToVectorPlanRule.java | 296 +++ .../transformation/SeparateProjectRule.java | 6 + .../transformation/SplitAggregateRule.java | 8 + .../SplitScanORToUnionRule.java | 7 + .../AggregateFunctionRewriter.java | 111 + ...gatedMaterializedViewPushDownRewriter.java | 155 ++ .../AggregatedMaterializedViewRewriter.java | 140 ++ .../AggregatedTimeSeriesRewriter.java | 754 +++++++ .../materialization/AndRangePredicate.java | 11 + .../materialization/BestMvSelector.java | 14 + .../materialization/ColumnRangePredicate.java | 33 + .../materialization/EquationRewriter.java | 49 + .../materialization/MVColumnPruner.java | 4 + .../materialization/MVPartitionPruner.java | 37 + .../materialization/MVTransparentState.java | 15 + .../materialization/MVUnionRewriteMode.java | 64 + .../MaterializedViewRewriter.java | 142 ++ .../MvPartitionCompensator.java | 95 + .../materialization/MvRewriteStrategy.java | 3 + .../materialization/MvUtils.java | 186 ++ .../OptExpressionDuplicator.java | 37 + .../materialization/PredicateExtractor.java | 11 + .../common/AggregateFunctionRollupUtils.java | 192 ++ .../common/AggregatePushDownUtils.java | 373 ++++ .../compensation/MVCompensationBuilder.java | 177 ++ .../compensation/OptCompensator.java | 159 ++ .../equivalent/AggStateRewriteEquivalent.java | 212 ++ .../equivalent/CountRewriteEquivalent.java | 13 + .../equivalent/DateTruncEquivalent.java | 45 + .../equivalent/EquivalentShuttleContext.java | 41 + .../equivalent/HLLRewriteEquivalent.java | 7 + .../equivalent/IRewriteEquivalent.java | 9 + .../equivalent/RewriteEquivalent.java | 33 + .../rule/AggregateJoinPushDownRule.java | 21 + .../rule/AggregateTimeSeriesRule.java | 58 + .../rule/BaseMaterializedViewRewriteRule.java | 46 + .../partition/PartitionSelector.java | 661 ++++++ .../tree/AddDecodeNodeForDictStringRule.java | 45 + .../rule/tree/ApplyTuningGuideRule.java | 134 ++ .../tree/DataCachePopulateRewriteRule.java | 8 + .../rule/tree/ExchangeSortToMergeRule.java | 12 + .../MarkParentRequiredDistributionRule.java | 129 ++ .../rule/tree/PreAggregateTurnOnRule.java | 57 + .../rule/tree/ScalarOperatorsReuseRule.java | 39 + .../tree/lowcardinality/DecodeCollector.java | 24 + .../tree/pdagg/AggregatePushDownContext.java | 95 + .../pdagg/PushDownAggregateCollector.java | 247 +++ .../tree/pdagg/PushDownAggregateRewriter.java | 69 + .../statistics/CacheDictManager.java | 5 + .../statistics/CachedStatisticStorage.java | 113 + .../ColumnBasicStatsCacheLoader.java | 26 + .../ColumnHistogramStatsCacheLoader.java | 6 + .../statistics/StatisticStorage.java | 16 + .../sql/optimizer/statistics/Statistics.java | 11 + .../statistics/StatisticsCalculator.java | 173 ++ .../StatisticsEstimateCoefficient.java | 7 + .../task/PrepareCollectMetaTask.java | 5 + .../optimizer/task/RewriteDownTopTask.java | 41 + .../sql/optimizer/task/RewriteTreeTask.java | 15 + .../transformer/QueryTransformer.java | 7 + .../transformer/RelationTransformer.java | 98 + .../transformer/WindowTransformer.java | 19 + .../validate/InputDependenciesChecker.java | 7 + .../sql/optimizer/validate/TypeChecker.java | 36 + .../com/starrocks/sql/parser/AstBuilder.java | 1002 +++++++++ .../com/starrocks/sql/parser/SqlParser.java | 21 + .../com/starrocks/sql/parser/StarRocks.g4 | 314 +++ .../com/starrocks/sql/parser/StarRocksLex.g4 | 53 + .../starrocks/sql/parser/SyntaxSugars.java | 14 + .../java/com/starrocks/sql/plan/ExecPlan.java | 20 + .../sql/plan/PlanFragmentBuilder.java | 411 ++++ .../sql/plan/ScalarOperatorToExpr.java | 3 + .../com/starrocks/sql/util/TablePlus.java | 4 + .../com/starrocks/staros/StarMgrServer.java | 81 + .../com/starrocks/statistic/AnalyzeMgr.java | 86 + .../starrocks/statistic/BasicStatsMeta.java | 5 + .../starrocks/statistic/ColumnStatsMeta.java | 44 + .../statistic/ExternalBasicStatsMeta.java | 14 + .../ExternalFullStatisticsCollectJob.java | 4 + .../ExternalSampleStatisticsCollectJob.java | 47 + .../HistogramStatisticsCollectJob.java | 63 + .../statistic/HyperStatisticsCollectJob.java | 186 ++ .../starrocks/statistic/NativeAnalyzeJob.java | 12 + .../statistic/NativeAnalyzeStatus.java | 27 + .../statistic/StatisticExecutor.java | 82 + .../statistic/StatisticSQLBuilder.java | 16 + .../starrocks/statistic/StatisticUtils.java | 182 ++ .../statistic/StatisticsCollectJob.java | 6 + .../StatisticsCollectJobFactory.java | 209 ++ .../StatisticsCollectionTrigger.java | 8 + .../statistic/StatisticsMetaManager.java | 39 + .../starrocks/statistic/StatsConstants.java | 13 + .../statistic/base/ColumnClassifier.java | 103 + .../starrocks/statistic/base/ColumnStats.java | 71 + .../base/ComplexTypeColumnStats.java | 60 + .../statistic/base/PartitionSampler.java | 160 ++ .../base/PrimitiveTypeColumnStats.java | 77 + .../statistic/base/SubFieldColumnStats.java | 88 + .../statistic/base/TabletSampler.java | 71 + .../statistic/hyper/ConstQueryJob.java | 79 + .../statistic/hyper/FullQueryJob.java | 63 + .../statistic/hyper/HyperQueryJob.java | 276 +++ .../statistic/hyper/HyperStatisticSQLs.java | 172 ++ .../statistic/hyper/MetaQueryJob.java | 150 ++ .../statistic/hyper/SampleQueryJob.java | 58 + .../statistic/sample/SampleInfo.java | 49 + .../statistic/sample/TabletSampleManager.java | 51 + .../statistic/sample/TabletStats.java | 9 + .../java/com/starrocks/system/Backend.java | 4 + .../starrocks/system/BackendHbResponse.java | 51 + .../starrocks/system/BackendResourceStat.java | 4 + .../com/starrocks/system/ComputeNode.java | 211 ++ .../java/com/starrocks/system/Frontend.java | 103 + .../starrocks/system/FrontendHbResponse.java | 25 + .../com/starrocks/system/HeartbeatMgr.java | 58 + .../starrocks/system/HeartbeatResponse.java | 4 + .../com/starrocks/system/NodeSelector.java | 16 + .../starrocks/system/SystemInfoService.java | 25 + .../com/starrocks/task/AlterReplicaTask.java | 29 + .../com/starrocks/task/CreateReplicaTask.java | 11 + .../starrocks/task/ExportExportingTask.java | 24 + .../com/starrocks/task/ExportPendingTask.java | 4 + .../starrocks/task/PublishVersionTask.java | 41 + .../starrocks/task/RemoteSnapshotTask.java | 3 + .../starrocks/task/TabletTaskExecutor.java | 446 ++++ .../AbstractTxnStateChangeCallback.java | 16 + .../transaction/DatabaseTransactionMgr.java | 371 ++++ .../transaction/GlobalTransactionMgr.java | 142 ++ .../starrocks/transaction/GtidGenerator.java | 4 + .../IllegalTransactionParameterException.java | 6 + .../InsertTxnCommitAttachment.java | 6 + .../transaction/LakeTableTxnLogApplier.java | 21 + .../LakeTableTxnStateListener.java | 9 + .../transaction/OlapTableTxnLogApplier.java | 12 + .../OlapTableTxnStateListener.java | 46 + .../transaction/PartitionCommitInfo.java | 41 + .../transaction/PublishVersionDaemon.java | 171 ++ .../transaction/TableCommitInfo.java | 8 + .../transaction/TransactionChecker.java | 20 + .../TransactionCommitFailedException.java | 4 + .../transaction/TransactionException.java | 6 + .../transaction/TransactionState.java | 84 + .../transaction/TransactionStateBatch.java | 10 + .../transaction/TxnCommitAttachment.java | 20 + .../transaction/TxnStateChangeCallback.java | 16 + .../UpdateDbUsedDataQuotaDaemon.java | 4 + .../starrocks/warehouse/DefaultWarehouse.java | 4 + .../starrocks/warehouse/WarehouseProcDir.java | 4 + .../org/apache/iceberg/DeleteFileIndex.java | 4 + .../iceberg/StarRocksIcebergTableScan.java | 88 + .../com/starrocks/alter/AlterJobV2Test.java | 132 ++ .../com/starrocks/alter/AlterTableTest.java | 303 +++ .../java/com/starrocks/alter/AlterTest.java | 1528 ++++++++++++++ .../starrocks/alter/BatchRollupJobTest.java | 20 + .../alter/CompactionHandlerTest.java | 35 + .../starrocks/alter/LakeRollupJobTest.java | 159 ++ .../alter/LakeSyncMaterializedViewTest.java | 639 ++++++ ...leAlterDataCachePartitionDurationTest.java | 38 + .../alter/LakeTableAlterMetaJobTest.java | 56 + ...LakeTableAsyncFastSchemaChangeJobTest.java | 71 + .../alter/LakeTableSchemaChangeJobTest.java | 111 + .../alter/MaterializedViewHandlerTest.java | 40 + .../alter/OnlineOptimizeJobV2Test.java | 61 + .../alter/OptimizeJobV2BuilderTest.java | 17 + .../starrocks/alter/OptimizeJobV2Test.java | 64 + .../com/starrocks/alter/RollupJobV2Test.java | 104 + .../alter/SchemaChangeHandlerTest.java | 178 ++ .../alter/SchemaChangeJobV2Test.java | 115 ++ .../starrocks/alter/SystemHandlerTest.java | 28 + .../starrocks/analysis/AccessTestUtil.java | 93 + .../starrocks/analysis/AlterUserStmtTest.java | 36 + .../analysis/CTASAutoTabletTest.java | 22 + .../analysis/CancelLoadStmtTest.java | 8 + .../com/starrocks/analysis/ColumnDefTest.java | 145 ++ .../analysis/ColumnPositionTest.java | 3 + .../analysis/CreateAnalyzeJobTest.java | 12 + .../starrocks/analysis/CreateDbStmtTest.java | 4 + .../analysis/CreateMaterializedViewTest.java | 650 ++++++ .../analysis/CreateRoutineLoadStmtTest.java | 8 + .../CreateSyncMaterializedViewTest.java | 98 + .../analysis/CreateTableAutoTabletTest.java | 80 + .../CreateTableWithPartitionTest.java | 224 ++ .../analysis/CreateUserStmtTest.java | 36 + ...ropMaterializedViewStmtNewPlannerTest.java | 4 + .../DropMaterializedViewStmtTest.java | 4 + .../starrocks/analysis/FailPointStmtTest.java | 3 + .../com/starrocks/analysis/GINIndexTest.java | 29 + .../com/starrocks/analysis/IndexDefTest.java | 6 + .../analysis/InstallPluginStmtTest.java | 8 + .../com/starrocks/analysis/LoadStmtTest.java | 10 + .../MVColumnBitmapUnionPatternTest.java | 3 + .../MaterializedViewAutoTabletTest.java | 18 + .../analysis/ModifyBackendClauseTest.java | 3 + .../analysis/ModifyBrokerClauseTest.java | 3 + .../ModifyFrontendAddressClauseTest.java | 3 + .../RefreshMaterializedViewStatementTest.java | 42 + .../analysis/RefreshMaterializedViewTest.java | 218 ++ .../analysis/ResourceGroupStmtTest.java | 17 + .../RestrictOpMaterializedViewTest.java | 3 + .../starrocks/analysis/RuntimeFilterTest.java | 18 + .../starrocks/analysis/SelectStmtTest.java | 43 + .../analysis/SetCatalogStmtTest.java | 5 + .../starrocks/analysis/SetPassVarTest.java | 24 + .../com/starrocks/analysis/SetStmtTest.java | 16 + .../analysis/SetUserPropertyVarTest.java | 12 + .../analysis/ShowCatalogsStmtTest.java | 7 + .../analysis/ShowCharsetStmtTest.java | 7 + .../ShowCreateMaterializedViewStmtTest.java | 12 + .../ShowCreateRoutineLoadStmtTest.java | 3 + .../analysis/ShowCreateViewStmtTest.java | 20 + .../starrocks/analysis/ShowDbStmtTest.java | 10 + .../starrocks/analysis/ShowDeleteTest.java | 10 + .../analysis/ShowEnginesStmtTest.java | 8 + .../starrocks/analysis/ShowLoadStmtTest.java | 12 + .../analysis/ShowLoadWarningsStmtTest.java | 12 + .../analysis/ShowRestoreStmtTest.java | 8 + .../analysis/ShowTransactionStmtTest.java | 12 + .../analysis/SubmitTaskStmtTest.java | 3 + .../analysis/UseCatalogStmtTest.java | 5 + .../analysis/UseMaterializedViewTest.java | 20 + .../starrocks/analysis/VectorIndexTest.java | 225 ++ .../AuthenticationManagerTest.java | 7 + .../AuthenticationProviderFactoryTest.java | 11 + ...ainPasswordAuthenticationProviderTest.java | 40 + .../authentication/UserPropertyTest.java | 7 + .../authorization/AccessControlTest.java | 116 ++ .../authorization/ActionSetTest.java | 113 + .../authorization/AuthorizationMgrTest.java | 1834 +++++++++++++++++ .../starrocks/authorization/IdGenerator.java | 29 + .../authorization/InvalidateObjectTest.java | 190 ++ .../PrivilegeCollectionTest.java | 367 ++++ .../authorization/RBACMockedMetadataMgr.java | 124 ++ .../RolePrivilegeCollectionTest.java | 59 + .../ranger/RangerInterfaceTest.java | 260 +++ .../ranger/RangerResourceTest.java | 85 + .../starrocks/backup/BackupHandlerTest.java | 354 ++++ .../backup/BackupJobMaterializedViewTest.java | 77 + .../backup/BackupJobPrimaryKeyTest.java | 61 + .../com/starrocks/backup/BackupJobTest.java | 70 + .../com/starrocks/backup/CatalogMocker.java | 76 + .../RestoreJobMaterializedViewTest.java | 69 + .../backup/RestoreJobPrimaryKeyTest.java | 8 + .../com/starrocks/backup/RestoreJobTest.java | 263 +++ .../MVPartitionCompensateOptBench.java | 7 + .../benchmark/MvPreProcessorWithSSBBench.java | 3 + .../benchmark/MvRefreshConcurrencyTest.java | 6 + .../starrocks/binlog/BinlogManagerTest.java | 22 + .../com/starrocks/catalog/AdminStmtTest.java | 15 + .../starrocks/catalog/AggStateDescTest.java | 60 + .../com/starrocks/catalog/BackendTest.java | 4 + .../com/starrocks/catalog/BrokerMgrTest.java | 10 + .../CatalogRecycleBinLakeTableTest.java | 61 + .../catalog/CatalogRecycleBinTest.java | 49 + .../starrocks/catalog/CatalogUtilsTest.java | 11 + .../catalog/ColocateTableIndexTest.java | 137 ++ .../starrocks/catalog/ColocateTableTest.java | 15 + .../com/starrocks/catalog/ColumnTest.java | 4 + .../catalog/CreateTableLikeTest.java | 191 ++ .../starrocks/catalog/CreateTableTest.java | 111 + .../catalog/CreateTableWithAggStateTest.java | 393 ++++ .../catalog/CreateTableWithLocationTest.java | 232 +++ .../com/starrocks/catalog/CreateViewTest.java | 12 + .../com/starrocks/catalog/DatabaseTest.java | 73 + .../starrocks/catalog/DictionaryMgrTest.java | 3 + .../starrocks/catalog/DropPartitionTest.java | 191 ++ .../DropPartitionWithExprListTest.java | 743 +++++++ .../DropPartitionWithExprRangeTest.java | 436 ++++ .../catalog/DynamicPartitionTableTest.java | 329 +++ .../ExpressionRangePartitionInfoTest.java | 242 +++ .../com/starrocks/catalog/FakeEditLog.java | 11 + .../catalog/ForeignKeyConstraintTest.java | 28 + .../catalog/GlobalFunctionMgrTest.java | 90 +- .../catalog/GlobalStateMgrTestUtil.java | 35 + .../starrocks/catalog/HiveResourceTest.java | 8 + .../com/starrocks/catalog/HiveTableTest.java | 5 + .../starrocks/catalog/HudiResourceTest.java | 8 + .../com/starrocks/catalog/HudiTableTest.java | 5 + .../catalog/IcebergResourceTest.java | 12 + .../starrocks/catalog/IcebergTableTest.java | 5 + .../starrocks/catalog/InfoSchemaDbTest.java | 43 + .../com/starrocks/catalog/JDBCTableTest.java | 4 + .../catalog/ListPartitionInfoTest.java | 22 + .../catalog/MVPartitionExprResolverTest.java | 155 ++ .../catalog/MaterializedIndexTest.java | 10 + .../catalog/MaterializedViewTest.java | 466 +++++ .../starrocks/catalog/MetadataViewerTest.java | 10 + .../com/starrocks/catalog/OlapTableTest.java | 44 + .../catalog/PhysicalPartitionImplTest.java | 17 + .../catalog/ReplaceLakePartitionTest.java | 24 + .../starrocks/catalog/ResourceMgrTest.java | 45 + .../starrocks/catalog/SparkResourceTest.java | 20 + .../catalog/StorageCoolDownTest.java | 20 + .../catalog/StorageMediumInferTest.java | 32 + .../catalog/TableFunctionTableTest.java | 30 + .../starrocks/catalog/TabletStatMgrTest.java | 61 + .../starrocks/catalog/TempPartitionTest.java | 17 + .../combinator/AggStateCombinatorTest.java | 1156 +++++++++++ .../catalog/system/sys/SysFeLocksTest.java | 55 + .../system/sys/SysFeMemoryUsageTest.java | 8 + .../clone/ColocateTableBalancerTest.java | 255 +++ .../DiskAndTabletLoadReBalancerTest.java | 173 ++ .../clone/DynamicPartitionSchedulerTest.java | 444 ++++ .../starrocks/clone/TabletSchedCtxTest.java | 25 + .../starrocks/clone/TabletSchedulerTest.java | 20 + .../cluster/SystemInfoServiceTest.java | 27 + .../java/com/starrocks/common/ConfigTest.java | 71 + .../starrocks/common/MarkDownParserTest.java | 29 + .../common/PropertyAnalyzerTest.java | 4 + .../starrocks/common/TraceManagerTest.java | 95 + .../common/lock/AutoCloseableLockerTest.java | 8 + .../starrocks/common/lock/DeadLockTest.java | 4 + .../common/lock/TestLockException.java | 13 + .../common/lock/TestLockInterface.java | 107 + ...rrentGlobalQueryStatisticsProcDirTest.java | 16 + .../CurrentQueryStatisticsProcDirTest.java | 18 + .../starrocks/common/proc/DbsProcDirTest.java | 48 + .../common/proc/LakeTabletsProcNodeTest.java | 17 + .../common/proc/LocalTabletsProcDirTest.java | 8 + .../common/proc/PartitionsProcDirTest.java | 9 + .../common/proc/StatisticProcDirTest.java | 3 + .../common/proc/TablesProcDirTest.java | 44 + .../common/util/AutoInferUtilTest.java | 8 + .../starrocks/common/util/BrokerUtilTest.java | 56 + .../starrocks/common/util/KafkaUtilTest.java | 28 + .../common/util/ProfileManagerTest.java | 3 + .../common/util/ProfilingExecPlanTest.java | 5 + .../common/util/SmallFileMgrTest.java | 4 + .../starrocks/common/util/TimeUtilsTest.java | 43 + .../starrocks/common/util/UnitTestUtil.java | 8 + .../QueryableReentrantLockTest.java | 8 + .../starrocks/connector/AlterTableTest.java | 319 +++ .../connector/AsyncTaskQueueTest.java | 129 ++ .../CatalogConnectorMetadataTest.java | 46 + .../DirectoryBasedUpdateArbitratorTest.java | 202 ++ ...HMSPartitionBasedRemoteInfoSourceTest.java | 80 + .../HiveMetastoreApiConverterTest.java | 25 + .../ObjectBasedUpdateArbitratorTest.java | 208 ++ .../connector/PartitionUtilTest.java | 13 + .../connector/RemoteFileOperationsTest.java | 191 ++ .../RemoteScanRangeLocationsTest.java | 23 + .../connector/TableUpdateArbitratorTest.java | 112 + .../analyzer/SimpleExpressionAnalyzer.java | 3 + .../delta/CachingDeltaLakeMetastoreTest.java | 5 + .../delta/DeltaLakeConnectorTest.java | 22 + .../delta/DeltaLakeMetadataTest.java | 16 + .../elasticsearch/EsShardPartitionsTest.java | 5 + .../elasticsearch/QueryBuildersTest.java | 3 + .../hive/CachingHiveMetastoreTest.java | 17 + .../connector/hive/HiveConnectorTest.java | 5 + .../connector/hive/HiveMetadataTest.java | 172 ++ .../hive/HiveMetastoreOperationsTest.java | 159 ++ .../connector/hive/HiveMetastoreTest.java | 17 + .../hive/HiveStatisticsProviderTest.java | 26 + .../connector/hive/HiveViewTest.java | 10 + .../connector/hive/MockedHiveMetadata.java | 417 ++++ .../connector/hive/ReplayMetadataMgr.java | 41 + .../connector/hudi/HudiMetadataTest.java | 17 + .../iceberg/CachingIcebergCatalogTest.java | 106 + .../iceberg/IcebergApiConverterTest.java | 14 + .../iceberg/IcebergMetadataTest.java | 311 +++ .../connector/iceberg/MIcebergTable.java | 28 + .../connector/iceberg/MIcebergTableMeta.java | 174 ++ .../iceberg/MockIcebergMetadata.java | 89 + .../cost/IcebergStatisticProviderTest.java | 19 + .../rest/OAuth2SecurityConfigTest.java | 69 + .../connector/jdbc/MockedJDBCMetadata.java | 8 + .../jdbc/MysqlSchemaResolverTest.java | 62 + .../connector/kudu/KuduMetadataTest.java | 29 + .../kudu/KuduPredicateConverterTest.java | 20 + .../starrocks/connector/odps/MockedBase.java | 13 + .../connector/odps/OdpsMetadataTest.java | 30 + .../connector/odps/OdpsTableTest.java | 10 + .../connector/paimon/PaimonConnectorTest.java | 5 + .../connector/paimon/PaimonMetadataTest.java | 41 + .../trino/TrinoDialectDowngradeTest.java | 38 + .../trino/TrinoFunctionTransformTest.java | 12 + .../parser/trino/TrinoInsertTest.java | 69 + .../trino/TrinoParserNotSupportTest.java | 7 + .../parser/trino/TrinoQueryTest.java | 4 + .../connector/parser/trino/TrinoTestBase.java | 11 + .../ConnectorAnalyzeTaskQueueTest.java | 101 + .../statistics/ConnectorAnalyzeTaskTest.java | 224 ++ .../unified/UnifiedMetadataTest.java | 304 +++ .../consistency/ConsistencyCheckerTest.java | 19 + .../consistency/MetaRecoveryDaemonTest.java | 56 + .../CloudConfigurationFactoryTest.java | 27 + .../starrocks/TableMetaSyncerTest.java | 9 + .../java/com/starrocks/fs/HdfsUtilTest.java | 14 + .../com/starrocks/fs/TestHdfsFsManager.java | 30 + .../com/starrocks/fs/WildcardURITest.java | 8 + .../test/java/com/starrocks/ha/BDBHATest.java | 7 + .../starrocks/http/BadHttpRequestTest.java | 8 + .../starrocks/http/ExecuteSqlActionTest.java | 11 + .../com/starrocks/http/LoadActionTest.java | 111 + .../starrocks/http/QueryDumpActionTest.java | 4 + .../starrocks/http/RestBaseResultTest.java | 41 + .../starrocks/http/ShowDataActionTest.java | 10 + .../http/ShowMetaInfoActionTest.java | 34 + .../starrocks/http/StarRocksHttpTestCase.java | 135 ++ .../http/StreamLoadMetaActionTest.java | 236 +++ .../http/TableQueryPlanActionTest.java | 17 + .../http/TransactionLoadActionTest.java | 81 + .../rest/v2/TablePartitionActionTest.java | 517 +++++ .../http/rest/v2/TableSchemaActionTest.java | 525 +++++ .../journal/bdbje/BDBEnvironmentTest.java | 11 + .../java/com/starrocks/lake/AlterTest.java | 124 ++ .../starrocks/lake/CreateLakeTableTest.java | 58 + .../lake/LakeMaterializedViewTest.java | 154 ++ .../starrocks/lake/LakeTableHelperTest.java | 28 + .../starrocks/lake/StarMgrMetaSyncerTest.java | 11 + .../starrocks/lake/StarOSAgent2ndTest.java | 23 + .../com/starrocks/lake/StarOSAgentTest.java | 28 + .../java/com/starrocks/lake/UtilsTest.java | 14 + .../lake/compaction/CompactionJobTest.java | 15 + .../lake/compaction/CompactionMgrTest.java | 26 + .../compaction/CompactionSchedulerTest.java | 8 + .../CompactionTxnCommitAttachmentTest.java | 15 + .../com/starrocks/lake/delete/DeleteTest.java | 42 + .../starrocks/lake/qe/ShowExecutorTest.java | 8 + .../DefaultSharedDataWorkerProviderTest.java | 16 + .../com/starrocks/leader/LeaderImplTest.java | 24 + .../starrocks/leader/ReportHandlerTest.java | 68 + .../starrocks/load/BrokerFileGroupTest.java | 36 + .../com/starrocks/load/DeleteHandlerTest.java | 98 + .../com/starrocks/load/DeletePruneTest.java | 61 + .../com/starrocks/load/ExportCheckerTest.java | 8 + .../com/starrocks/load/ExportMgrTest.java | 10 + .../load/InsertOverwriteJobManagerTest.java | 12 + .../load/InsertOverwriteJobRunnerTest.java | 26 + .../load/InsertOverwriteJobTest.java | 8 + .../com/starrocks/load/LoadPlannerTest.java | 12 + .../java/com/starrocks/load/LoadTest.java | 16 + .../starrocks/load/PartitionUtilsTest.java | 55 + .../load/batchwrite/BatchWriteMgrTest.java | 196 ++ .../load/batchwrite/BatchWriteTestBase.java | 108 + .../CoordinatorBackendAssignerTest.java | 277 +++ .../batchwrite/IsomorphicBatchWriteTest.java | 307 +++ .../load/batchwrite/LoadExecutorTest.java | 390 ++++ .../load/loadv2/BrokerLoadJobTest.java | 63 + .../loadv2/BrokerLoadPendingTaskTest.java | 8 + .../load/loadv2/InsertLoadJobTest.java | 9 + .../starrocks/load/loadv2/LoadJobTest.java | 4 + .../starrocks/load/loadv2/LoadMgrTest.java | 61 + .../load/loadv2/SparkEtlJobHandlerTest.java | 26 + .../load/loadv2/SparkLoadJobTest.java | 100 + .../load/loadv2/SparkLoadPendingTaskTest.java | 50 + .../load/loadv2/SparkRepositoryTest.java | 44 + .../starrocks/load/pipe/PipeManagerTest.java | 43 + .../load/pipe/filelist/FileListRepoTest.java | 9 + .../load/routineload/KafkaProgressTest.java | 12 + .../routineload/KafkaRoutineLoadJobTest.java | 55 + .../load/routineload/KafkaTaskInfoTest.java | 12 + .../routineload/RoutineLoadJobMetaTest.java | 16 + .../load/routineload/RoutineLoadJobTest.java | 56 + .../routineload/RoutineLoadManagerTest.java | 56 + .../routineload/RoutineLoadSchedulerTest.java | 7 + .../RoutineLoadTaskSchedulerTest.java | 34 + .../load/streamload/ShowStreamLoadTest.java | 4 + .../streamload/StreamLoadHttpHeaderTest.java | 40 + .../load/streamload/StreamLoadInfoTest.java | 94 + .../streamload/StreamLoadKvParamsTest.java | 357 ++++ .../streamload/StreamLoadManagerTest.java | 50 + .../streamload/StreamLoadParamsTestBase.java | 315 +++ .../load/streamload/StreamLoadTaskTest.java | 22 + .../StreamLoadThriftParamsTest.java | 302 +++ .../mysql/MysqlHandshakePacketTest.java | 4 + .../starrocks/persist/ColumnRenameTest.java | 17 + .../CreateInsertOverwriteJobLogTest.java | 4 + .../persist/DropPartitionsInfoTest.java | 91 + .../com/starrocks/persist/EditLogTest.java | 3 + .../starrocks/persist/OperationTypeTest.java | 63 + .../persist/RecyclePartitionInfoTest.java | 4 + .../RenameMaterializedViewLogTest.java | 7 + .../persist/metablock/SRMetaBlockV1Test.java | 3 + .../persist/metablock/SRMetaBlockV2Test.java | 3 + .../starrocks/planner/FileScanNodeTest.java | 24 + .../starrocks/planner/HudiScanNodeTest.java | 3 + .../planner/IcebergMetadataScanNodeTest.java | 32 + ...aterializedViewAggPushDownRewriteTest.java | 59 + .../MaterializedViewAggRollupTest.java | 4 + .../MaterializedViewLowCardTPCHTest.java | 6 + .../planner/MaterializedViewManualTest.java | 42 + .../MaterializedViewRewriteWithSSBTest.java | 3 + .../planner/MaterializedViewTPCHTest.java | 13 + .../planner/MaterializedViewTest.java | 789 +++++++ .../planner/MaterializedViewTestBase.java | 13 + ...erializedViewTextBasedRewriteTPCHTest.java | 6 + .../MaterializedViewWithMultiStageTest.java | 3 + .../MaterializedViewWithPartitionTest.java | 4 + .../starrocks/planner/OlapTableSinkTest.java | 107 + .../starrocks/planner/OlapTableSinkTest2.java | 28 + .../OnPredicateMoveAroundRuleTest.java | 228 ++ .../planner/StreamLoadPlannerTest.java | 43 + .../planner/StreamLoadScanNodeTest.java | 73 + .../planner/TableFunctionTableSinkTest.java | 3 + .../starrocks/planner/TablePruningTest.java | 15 + .../planner/TablePruningTestBase.java | 4 + .../starrocks/planner/VectorIndexTest.java | 121 ++ .../planner/mv/MVMetaVersionRepairerTest.java | 36 + .../com/starrocks/plugin/PluginMgrTest.java | 12 + .../com/starrocks/plugin/PluginZipTest.java | 16 + .../pseudocluster/BeRestartTest.java | 4 + .../pseudocluster/BeTabletManager.java | 12 + .../starrocks/pseudocluster/BeTxnManager.java | 13 + .../LocationLabeledTableBalanceTest.java | 22 + .../LocationMismatchRepairTest.java | 140 ++ .../pseudocluster/PseudoBackend.java | 34 + .../pseudocluster/PseudoCluster.java | 30 + .../pseudocluster/PseudoClusterTest.java | 16 + .../pseudocluster/PseudoFrontend.java | 9 + .../ReplicaMinReadableVersionTest.java | 4 + .../qe/ColocatedBackendSelectorTest.java | 24 + .../com/starrocks/qe/ConnectContextTest.java | 69 + .../starrocks/qe/ConnectProcessorTest.java | 7 + .../com/starrocks/qe/CoordinatorTest.java | 5 + .../qe/ExecuteExceptionHandlerTest.java | 17 + .../com/starrocks/qe/ExportHandleTest.java | 9 + .../starrocks/qe/HDFSBackendSelectorTest.java | 87 + .../com/starrocks/qe/KillQueryHandleTest.java | 221 ++ .../com/starrocks/qe/RBACExecutorTest.java | 25 + .../com/starrocks/qe/SetExecutorTest.java | 8 + .../com/starrocks/qe/ShowExecutorTest.java | 366 ++++ .../com/starrocks/qe/ShowTableMockMeta.java | 10 + .../java/com/starrocks/qe/ShowTablesTest.java | 6 + .../com/starrocks/qe/StmtExecutorTest.java | 46 + .../com/starrocks/qe/VariableMgrTest.java | 14 + .../analyzer/PlanTuningAnalyzerTest.java | 146 ++ ...ftChildEstimationErrorTuningGuideTest.java | 74 + ...htChildEstimationErrorTuningGuideTest.java | 247 +++ .../scheduler/DefaultWorkerProviderTest.java | 16 + .../starrocks/qe/scheduler/GetNextTest.java | 12 + .../scheduler/IncrementalDeployHiveTest.java | 149 ++ .../qe/scheduler/QueryQueueManagerTest.java | 312 +++ .../qe/scheduler/SchedulerTestBase.java | 4 + .../qe/scheduler/StartSchedulingTest.java | 16 + .../replication/ReplicationJobTest.java | 61 + .../replication/ReplicationMgrTest.java | 35 + .../scheduler/MVRefreshTestBase.java | 13 + .../PCTRefreshListPartitionOlapTest.java | 927 +++++++++ ...titionBasedMvRefreshProcessorHiveTest.java | 387 ++++ ...ionBasedMvRefreshProcessorIcebergTest.java | 388 ++++ ...titionBasedMvRefreshProcessorJdbcTest.java | 62 + ...nBasedMvRefreshProcessorOlapPart2Test.java | 83 + ...titionBasedMvRefreshProcessorOlapTest.java | 455 ++++ ...tionBasedMvRefreshProcessorPaimonTest.java | 15 + .../PartitionBasedMvRefreshTest.java | 261 +++ .../scheduler/TaskRunFIFOQueueTest.java | 6 + .../scheduler/mv/MVMaintenanceJobTest.java | 4 + .../starrocks/server/CatalogLevelTest.java | 7 + .../com/starrocks/server/CatalogMgrTest.java | 13 + .../starrocks/server/ConcurrentDDLTest.java | 52 + .../starrocks/server/GlobalStateMgrTest.java | 15 + .../starrocks/server/LocalMetaStoreTest.java | 103 + .../starrocks/server/MVRepairHandlerTest.java | 4 + .../com/starrocks/server/MetadataMgrTest.java | 27 + .../com/starrocks/server/NodeMgrTest.java | 4 + .../SharedDataStorageVolumeMgrTest.java | 3 + .../server/WarehouseManagerTest.java | 49 + .../service/ArrowFlightSqlJDBCTest.java | 108 + .../service/FrontendOptionsTest.java | 3 + .../service/FrontendServiceImplTest.java | 601 ++++++ .../LakeInformationSchemaDataSourceTest.java | 3 + .../flight/sql/ArrowFlightSqlServiceTest.java | 70 + .../analyzer/AlterDbRenameAnalyzerTest.java | 6 + .../sql/analyzer/AnalyzeAggregateTest.java | 6 + .../analyzer/AnalyzeBackupRestoreTest.java | 152 ++ .../analyzer/AnalyzeCreateAnalyzeJobTest.java | 23 + .../sql/analyzer/AnalyzeCreateTableTest.java | 16 + .../sql/analyzer/AnalyzeDropTableTest.java | 29 + .../sql/analyzer/AnalyzeFunctionTest.java | 4 + .../sql/analyzer/AnalyzeInsertTest.java | 59 + .../sql/analyzer/AnalyzeStmtTest.java | 87 + .../sql/analyzer/CTASAnalyzerTest.java | 12 + .../CreateFunctionStmtAnalyzerTest.java | 215 ++ .../sql/analyzer/ExternalDbTablePrivTest.java | 9 + .../MaterializedViewAnalyzerTest.java | 60 + .../sql/analyzer/PrivilegeCheckerTest.java | 169 ++ .../analyzer/PrivilegeStmtAnalyzerV2Test.java | 22 + .../sql/ast/CreateFunctionStmtTest.java | 110 + .../sql/ast/DropFunctionStmtTest.java | 14 + .../starrocks/sql/ast/ExecuteAsStmtTest.java | 5 + .../sql/ast/StructFieldDescTest.java | 13 + .../sql/ast/TableSampleClauseTest.java | 39 + .../starrocks/sql/common/MetaUtilTest.java | 27 + .../sql/common/PermutationGeneratorTest.java | 42 + .../sql/common/SqlWithIdUtilsTest.java | 12 + .../sql/common/SyncPartitionUtilsTest.java | 117 ++ .../sql/optimizer/MVRewriteTest.java | 130 ++ .../sql/optimizer/OptimizerTaskTest.java | 109 + .../optimizer/ScanPredicateExprReuseTest.java | 319 +++ .../optimizer/SelectStmtWithCaseWhenTest.java | 11 + .../starrocks/sql/optimizer/UtilsTest.java | 16 + .../operator/ColumnFilterConverterTest.java | 4 + .../operator/operator/OperatorEqualsTest.java | 7 + .../rewrite/JoinPredicatePushdownTest.java | 20 + .../rewrite/PredicateReorderRuleTest.java | 18 + .../rewrite/scalar/FoldConstantsRuleTest.java | 7 + .../rewrite/scalar/ReduceCastRuleTest.java | 14 + .../rule/mv/MaterializedViewRuleTest.java | 28 + .../DistributionPrunerRuleTest.java | 15 + .../PartitionPruneRuleTest.java | 38 + .../PruneHDFSScanColumnRuleTest.java | 16 + .../MVRewriteWithSchemaChangeTest.java | 12 + .../MvRefreshAndRewriteIcebergTest.java | 1718 +++++++++++++++ .../MvRefreshAndRewriteJDBCTest.java | 218 ++ .../materialization/MvRefreshTest.java | 142 ++ .../materialization/MvRewriteHiveTest.java | 33 + .../MvRewriteListPartitionTest.java | 19 + .../MvRewritePartialPartitionTest.java | 4 + .../MvRewritePartitionTest.java | 9 + .../MvRewritePreprocessorTest.java | 7 + .../materialization/MvRewriteTest.java | 61 + .../materialization/MvRewriteTestBase.java | 27 + .../materialization/MvRewriteUnionTest.java | 19 + .../MvTimeSeriesRewriteWithHiveTest.java | 60 + .../MvTimeSeriesRewriteWithOlapTest.java | 441 ++++ ...MvTransparentRewriteWithHiveTableTest.java | 9 + ...MvTransparentRewriteWithOlapTableTest.java | 92 + .../MvTransparentUnionRewriteHiveTest.java | 24 + .../materialization/MvUtilsTest.java | 27 + .../materialization/PredicateSplitTest.java | 40 + ...arkParentRequiredDistributionRuleTest.java | 66 + .../CachedStatisticStorageTest.java | 42 + .../statistics/StatisticsCalculatorTest.java | 360 ++++ .../com/starrocks/sql/parser/ParserTest.java | 21 + .../sql/plan/AggregatePushDownTest.java | 38 + .../plan/AggregatePushDownWithCostTest.java | 339 +++ .../com/starrocks/sql/plan/AggregateTest.java | 55 + .../sql/plan/AggregateWithUKFKTest.java | 545 +++++ .../com/starrocks/sql/plan/CTEPlanTest.java | 24 + .../sql/plan/ConnectorPlanTestBase.java | 14 + .../starrocks/sql/plan/DataCachePlanTest.java | 49 + .../sql/plan/DistributedEnvPlanTestBase.java | 42 + .../plan/DistributedEnvPlanWithCostTest.java | 15 + .../sql/plan/DistributedEnvTPCDSPlanTest.java | 16 + .../starrocks/sql/plan/ExpressionTest.java | 48 + .../starrocks/sql/plan/ExternalTableTest.java | 9 + .../sql/plan/FilterUnusedColumnTest.java | 185 ++ .../starrocks/sql/plan/GroupingSetTest.java | 4 + .../starrocks/sql/plan/GroupingSetsTest.java | 4 + .../plan/IcebergEqualityDeletePlanTest.java | 651 ++++++ .../starrocks/sql/plan/InsertPlanTest.java | 11 + .../java/com/starrocks/sql/plan/JoinTest.java | 13 + .../com/starrocks/sql/plan/JsonTypeTest.java | 16 + .../com/starrocks/sql/plan/LimitTest.java | 5 + .../sql/plan/LowCardinalityArrayTest.java | 5 + .../sql/plan/LowCardinalityTest.java | 46 + .../sql/plan/LowCardinalityTest2.java | 42 + .../sql/plan/MockTpchStatisticStorage.java | 37 + .../sql/plan/MultiJoinReorderTest.java | 12 + .../starrocks/sql/plan/NestLoopJoinTest.java | 23 + .../sql/plan/PlanFragmentWithCostTest.java | 138 ++ .../com/starrocks/sql/plan/PlanTestBase.java | 32 + .../sql/plan/PlanTestNoneDBBase.java | 25 + .../sql/plan/PlanWithCostTestBase.java | 139 ++ .../sql/plan/PredicatePushDownTest.java | 4 + .../sql/plan/PruneComplexSubfieldTest.java | 21 + .../sql/plan/PruneUKFKJoinRuleTest.java | 25 + .../com/starrocks/sql/plan/RemoveAggTest.java | 4 + .../sql/plan/ReplayFromDumpTest.java | 65 + .../java/com/starrocks/sql/plan/ScanTest.java | 49 + .../sql/plan/SelectUsingAliasTest.java | 271 +++ .../java/com/starrocks/sql/plan/SetTest.java | 3 + .../starrocks/sql/plan/ShortCircuitTest.java | 8 + .../com/starrocks/sql/plan/SkewJoinTest.java | 25 + .../sql/plan/SplitScanToUnionTest.java | 19 + .../com/starrocks/sql/plan/TPCDS1TTest.java | 29 + .../sql/plan/TPCDSAggregateWithUKFKTest.java | 227 ++ .../starrocks/sql/plan/TPCDSPushAggTest.java | 133 ++ .../com/starrocks/sql/plan/TPCHPlanTest.java | 4 + .../plan/TPCHPlanWithHistogramCostTest.java | 25 + .../java/com/starrocks/sql/plan/UDFTest.java | 10 + .../com/starrocks/sql/plan/WindowTest.java | 243 +++ .../starrocks/staros/StarMgrServerTest.java | 8 + .../starrocks/statistic/AnalyzeMgrTest.java | 15 + .../statistic/BasicStatsMetaTest.java | 5 + .../starrocks/statistic/CacheLoaderTest.java | 18 + .../MockHistogramStatisticStorage.java | 4 + .../statistic/StatisticExecutorTest.java | 9 + .../statistic/StatisticsCollectJobTest.java | 431 ++++ .../StatisticsCollectionTriggerTest.java | 8 + .../statistic/StatisticsExecutorTest.java | 28 + .../statistic/StatisticsSQLTest.java | 46 + .../statistic/hyper/HyperJobTest.java | 238 +++ .../statistic/sample/SampleInfoTest.java | 5 + .../system/BackendHbResponseTest.java | 53 + .../system/BackendResourceStatTest.java | 34 + .../com/starrocks/system/ComputeNodeTest.java | 470 +++++ .../system/SystemInfoServiceTest.java | 4 + .../com/starrocks/task/AgentTaskTest.java | 10 + .../DatabaseTransactionMgrTest.java | 68 + .../transaction/GlobalTransactionMgrTest.java | 176 ++ .../transaction/GtidGeneratorTest.java | 109 + .../transaction/LakePublishBatchTest.java | 51 + .../transaction/LakeTableTestHelper.java | 12 + .../LakeTableTxnLogApplierTest.java | 26 + .../TransactionStateBatchTest.java | 8 + .../com/starrocks/utframe/MockJournal.java | 8 + .../com/starrocks/utframe/MockedBackend.java | 13 + .../com/starrocks/utframe/MockedFrontend.java | 9 + .../starrocks/utframe/StarRocksAssert.java | 367 ++++ .../starrocks/utframe/TestWithFeService.java | 4 + .../com/starrocks/utframe/UtFrameUtils.java | 367 ++++ .../resources/conf/config_mutable.properties | 1 + .../sql/materialized-view/tpch-hive/q1.sql | 8 + .../sql/materialized-view/tpch/q1.sql | 5 + ...agg-pushdown-disable_on_broadcast_join.sql | 566 +++++ .../agg-pushdown-enable_on_broadcast_join.sql | 567 +++++ ...agg-pushdown-disable_on_broadcast_join.sql | 316 +++ ...eagg-pushdown-enable_on_broadcast_join.sql | 315 +++ .../sql/query_dump/deep_join_cost.json | 4 + .../sql/query_dump/distinct_constant.json | 6 +- .../force_rule_based_mv_rewrite.json | 4 + .../force_rule_based_mv_rewrite_drinks.json | 4 + .../force_rule_based_mv_rewrite_month.json | 4 + .../force_rule_based_mv_rewrite_year.json | 4 + .../sql/query_dump/join_init_error.json | 4 + .../materialized-view/count_star_rewrite.json | 4 + .../mv_rewrite_with_dict_opt1.json | 4 + .../sql/query_dump/nested_view_with_cte.json | 4 + .../sql/query_dump/no_cte_operator_test.json | 6 +- .../normalize_non_trivial_project.json | 6 +- .../sql/query_dump/prune_table_npe.json | 4 + ...cache_misuse_exogenous_runtime_filter.json | 4 + .../query_dump/query_cache_set_operator.json | 4 + .../query_dump/shared_data_query_test.json | 4 + .../sql/query_dump/split_order_by.json | 4 + .../sql/query_dump/topn_push_down_union.json | 4 + .../resources/sql/query_dump/view_delta.json | 4 + .../sql/scheduler/external/hive/tpch/q1.sql | 34 + .../resources/sql/subquery/in-subquery.sql | 12 +- .../sql/subquery/scalar-subquery.sql | 118 +- .../sql/tpcds_constraints/AddUniqueKeys.sql | 4 + fe/pom.xml | 94 + .../starrocks/load/loadv2/dpp/SparkDpp.java | 12 + .../load/loadv2/etl/EtlJobConfig.java | 19 + fe/starrocks_intellij_style.xml | 4 + .../src/broker-core/pom.xml | 7 + fs_brokers/apache_hdfs_broker/src/pom.xml | 14 + gensrc/proto/data.proto | 37 + gensrc/proto/descriptors.proto | 4 + gensrc/proto/internal_service.proto | 42 + gensrc/proto/lake_service.proto | 15 + gensrc/proto/lake_types.proto | 4 + gensrc/proto/olap_file.proto | 10 + gensrc/proto/tablet_schema.proto | 19 + gensrc/proto/types.proto | 24 + gensrc/script/functions.py | 34 + gensrc/thrift/AgentService.thrift | 16 + gensrc/thrift/DataSinks.thrift | 9 + gensrc/thrift/Descriptors.thrift | 35 + gensrc/thrift/FrontendService.thrift | 177 ++ gensrc/thrift/HeartbeatService.thrift | 5 + gensrc/thrift/InternalService.thrift | 34 + gensrc/thrift/PlanNodes.thrift | 108 + gensrc/thrift/Planner.thrift | 4 + gensrc/thrift/StatusCode.thrift | 5 + gensrc/thrift/Types.thrift | 49 +- .../share/iceberg/IcebergPartitionUtils.java | 55 + .../share/iceberg/SerializableTable.java | 12 + .../hive/reader/HiveScannerFactory.java | 4 + .../hudi/reader/HudiSliceScannerFactory.java | 4 + .../iceberg-metadata-reader/pom.xml | 15 + .../AbstractIcebergMetadataScanner.java | 124 ++ .../iceberg/IcebergFilesTableScanner.java | 178 ++ .../iceberg/IcebergHistoryTableScanner.java | 84 + .../iceberg/IcebergManifestsTableScanner.java | 126 ++ .../iceberg/IcebergMetadataColumnValue.java | 68 +- .../IcebergMetadataLogEntriesScanner.java | 116 ++ .../iceberg/IcebergMetadataScanner.java | 70 + .../IcebergMetadataScannerFactory.java | 35 + .../IcebergPartitionsTableScanner.java | 181 ++ .../iceberg/IcebergRefsTableScanner.java | 87 + .../iceberg/IcebergSnapshotsTableScanner.java | 118 ++ .../jni/connector/ScannerFactory.java | 4 + .../kudu/reader/KuduSplitScannerFactory.java | 4 + .../odps/reader/OdpsSplitScannerFactory.java | 4 + .../reader/PaimonSplitScannerFactory.java | 4 + run-be-ut.sh | 27 + test/lib/__init__.py | 4 + test/lib/arrow_sql_lib.py | 46 + test/lib/sr_sql_lib.py | 100 + test/requirements.txt | 6 + test/sql/test_across_engine/R/test_connection | 21 + test/sql/test_across_engine/R/test_sink | 273 +++ .../sql/test_across_engine/R/test_sink_nested | 199 ++ .../R/test_sink_partitioned | 351 ++++ test/sql/test_across_engine/T/test_connection | 11 + test/sql/test_across_engine/T/test_sink | 95 + .../sql/test_across_engine/T/test_sink_nested | 114 + .../T/test_sink_partitioned | 173 ++ .../data/nested_lists.parquet | Bin 0 -> 881 bytes .../data/nested_maps.parquet | Bin 0 -> 1324 bytes .../data/nested_structs.parquet | Bin 0 -> 27502 bytes .../data/tpch_lineitem.parquet | Bin 0 -> 362801 bytes test/sql/test_agg/R/test_agg_set_prefetch | 39 + test/sql/test_agg/R/test_tinyint_agg | 21 + test/sql/test_agg/T/test_agg_set_prefetch | 18 + test/sql/test_agg/T/test_tinyint_agg | 11 + test/sql/test_agg_function/R/test_hll | 119 ++ .../R/test_hll_sketch_count.sql | 75 + .../test_agg_function/R/test_lc_percentile | 149 ++ .../sql/test_agg_function/R/test_mann_whitney | 247 +++ test/sql/test_agg_function/R/test_map_agg | 195 ++ .../test_agg_function/R/test_percentile_union | 21 + test/sql/test_agg_function/T/test_hll | 28 + .../T/test_hll_sketch_count.sql | 35 + .../test_agg_function/T/test_lc_percentile | 57 + .../sql/test_agg_function/T/test_mann_whitney | 155 ++ test/sql/test_agg_function/T/test_map_agg | 74 + .../test_agg_function/T/test_percentile_union | 14 + .../test_agg_state_ds_hll_count_distinct.sql | 100 + .../R/test_agg_state_table_basic.sql | 215 ++ ...est_agg_state_table_with_all_functions.sql | 935 +++++++++ .../R/test_agg_state_with_async_mv.sql | 179 ++ .../R/test_agg_state_with_sync_mv.sql | 172 ++ .../test_agg_state_ds_hll_count_distinct.sql | 57 + .../T/test_agg_state_table_basic.sql | 129 ++ ...est_agg_state_table_with_all_functions.sql | 924 +++++++++ .../T/test_agg_state_with_async_mv.sql | 162 ++ .../T/test_agg_state_with_sync_mv.sql | 153 ++ .../R/test_analyze_hive_stats | 19 + .../T/test_analyze_hive_stats | 19 + test/sql/test_array/R/test_array | 6 + test/sql/test_arrow/R/test_arrow | 39 + test/sql/test_arrow/T/test_arrow | 22 + .../test_auto_increment/R/test_auto_increment | 40 +- .../test_auto_increment/T/test_auto_increment | 26 + .../R/test_automatic_partition | 141 ++ .../T/test_automatic_partition | 13 + .../R/test_automatic_partition_fail | 4 + .../R/test_automatic_partition_list | 13 + .../R/test_insert_overwrite | 8 + .../R/test_multi_expr | 649 ++++++ .../T/test_multi_expr | 214 ++ test/sql/test_cast/R/test_cast_json_to_struct | 49 + test/sql/test_cast/T/test_cast_json_to_struct | 14 + .../test_column_rename/R/test_column_rename2 | 3 + .../test_column_rename/T/test_column_rename | 114 + .../test_column_rename/T/test_column_rename2 | 61 + .../R/test_deltalake_collect_stats | 11 + test/sql/test_deltalake/R/test_deltalake_dv | 25 + .../R/test_deltalake_scan_ranges | 320 +++ .../sql/test_deltalake/R/test_deltalake_trace | 6 + .../T/test_deltalake_collect_stats | 9 + test/sql/test_deltalake/T/test_deltalake_dv | 15 + .../T/test_deltalake_scan_ranges | 99 + .../sql/test_deltalake/T/test_deltalake_trace | 4 + test/sql/test_dictionary/R/test_dictionary | 8 + test/sql/test_dictionary/T/test_dictionary | 8 + test/sql/test_dml/R/test_update | 30 +- test/sql/test_dml/T/test_update | 15 +- .../test_drop_partition/R/test_drop_partition | 90 + .../test_drop_partition_list_table_with_where | 123 ++ ...test_drop_partition_range_table_with_where | 136 ++ .../test_drop_partition/T/test_drop_partition | 30 + .../test_drop_partition_list_table_with_where | 58 + ...test_drop_partition_range_table_with_where | 68 + .../test_dynamic_overwrite/R/test_overwrite | 125 ++ .../test_dynamic_overwrite/T/test_overwrite | 51 + .../R/test_scan_predicate_expr_reuse | 201 ++ .../T/test_scan_predicate_expr_reuse | 64 + .../R/test_parquet_read_range | 26 + .../R/test_parquet_struct_in_struct | 14 + .../T/test_parquet_read_range | 17 + .../T/test_parquet_struct_in_struct | 6 + test/sql/test_feedback/R/test_agg_feedback | 143 ++ .../R/test_external_table_join_feedback | 67 + test/sql/test_feedback/R/test_join_feedback | 67 + test/sql/test_feedback/T/test_agg_feedback | 58 + .../T/test_external_table_join_feedback | 32 + test/sql/test_feedback/T/test_join_feedback | 31 + test/sql/test_files/R/csv_format | 23 + test/sql/test_files/R/test_insert_properties | 150 ++ test/sql/test_files/R/test_orc_files_merge | 115 ++ test/sql/test_files/R/test_orc_struct | 36 + .../sql/test_files/R/test_parquet_files_merge | 115 ++ test/sql/test_files/T/csv_format | 18 + test/sql/test_files/T/test_insert_properties | 97 + test/sql/test_files/T/test_orc_files_merge | 59 + test/sql/test_files/T/test_orc_struct | 15 + .../sql/test_files/T/test_parquet_files_merge | 59 + .../sql/test_files/csv_format/invalid_int.csv | 3 + test/sql/test_files/orc_format/basic_type.orc | Bin 0 -> 1027 bytes .../orc_format/basic_type_k2k5k7.orc | Bin 0 -> 434 bytes .../orc_format/struct_mix.snappy.orc | Bin 0 -> 17196 bytes .../parquet_format/basic_type_k2k5k7.parquet | Bin 0 -> 836 bytes test/sql/test_function/R/test_math | 50 + test/sql/test_function/R/test_regex | 27 + test/sql/test_function/R/test_synopse | 29 + test/sql/test_function/T/test_math | 26 +- test/sql/test_function/T/test_synopse | 4 + test/sql/test_gtid/R/test_gtid | 612 ++++++ test/sql/test_gtid/T/test_gtid | 167 ++ test/sql/test_hive/R/test_hive_analyze | 54 + test/sql/test_hive/R/test_hive_scan_ranges | 65 + test/sql/test_hive/T/test_hive_analyze | 25 + test/sql/test_hive/T/test_hive_scan_ranges | 31 + test/sql/test_iceberg/R/test_iceberg_catalog | 19 +- .../R/test_iceberg_distributed_plan | 6 + .../R/test_iceberg_identifier_metrics_cache | 6 + .../R/test_iceberg_logical_metadata_table | 6 + test/sql/test_iceberg/R/test_metadata_table | 131 ++ test/sql/test_iceberg/R/test_table_operation | 62 + test/sql/test_iceberg/R/test_timetravel | 113 + test/sql/test_iceberg/R/test_write_null | 26 + test/sql/test_iceberg/T/test_iceberg_catalog | 7 + .../T/test_iceberg_distributed_plan | 4 + .../T/test_iceberg_identifier_metrics_cache | 4 + .../T/test_iceberg_logical_metadata_table | 4 + test/sql/test_iceberg/T/test_metadata_table | 50 + test/sql/test_iceberg/T/test_table_operation | 38 + test/sql/test_iceberg/T/test_timetravel | 38 + test/sql/test_iceberg/T/test_write_null | 12 + test/sql/test_index/R/test_ngram_bloom_filter | 18 + test/sql/test_index/T/test_ngram_bloom_filter | 6 +- test/sql/test_information_schema/R/test_loads | 8 + .../R/test_task_run_status | 30 + .../T/test_task_run_status | 14 + .../test_insert_empty/R/test_insert_by_name | 126 ++ .../test_insert_empty/R/test_insert_timeout | 63 + .../test_insert_empty/T/test_insert_by_name | 46 + .../test_insert_empty/T/test_insert_timeout | 33 + .../test_inverted_index/R/test_inverted_index | 12 + .../test_inverted_index/T/test_inverted_index | 4 + .../test_join/R/test_predicate_move_around | 826 ++++++++ .../test_join/T/test_predicate_move_around | 190 ++ test/sql/test_lake_rollup/R/test_lake_rollup | 38 + test/sql/test_lake_rollup/T/test_lake_rollup | 23 + .../sql/test_lake_sync_mv/R/test_lake_sync_mv | 38 + .../R/test_lake_sync_mv_rewrite | 51 + .../sql/test_lake_sync_mv/T/test_lake_sync_mv | 23 + .../T/test_lake_sync_mv_rewrite | 38 + .../R/test_add_list_partition | 83 + .../R/test_list_partition_cardinality | 4 + .../T/test_add_list_partition | 39 +- .../T/test_list_partition_cardinality | 4 + .../R/test_generated_column_rewrite | 8 + .../R/test_materialized_column | 8 + .../T/test_generated_column_rewrite | 6 + .../T/test_materialized_column | 4 + ...est_materialized_view_agg_pushdown_rewrite | 11 + ...erialized_view_incremental_refresh_on_hive | 105 + .../R/test_materialized_view_rewrite | 20 + .../R/test_materialized_view_union | 20 + .../R/test_mv_iceberg_rewrite | 12 + .../R/test_mv_join_derivabllity_rewrite | 80 + .../R/test_mv_or_predicate_rewrite | 36 + .../R/test_mv_partition_compensate_hive | 10 + ...test_mv_partition_compensate_iceberg_part1 | 38 + ...test_mv_partition_compensate_iceberg_part2 | 48 + .../R/test_mv_partition_compensate_mysql | 6 + .../R/test_mv_partition_compensate_olap | 4 + .../R/test_refresh_mv_with_different_dbs | 71 + .../R/test_show_materialized_view | 18 +- ...erialized_view_incremental_refresh_on_hive | 66 + .../T/test_materialized_view_rewrite | 20 + .../T/test_materialized_view_union | 20 + .../T/test_mv_iceberg_rewrite | 6 + .../T/test_mv_join_derivabllity_rewrite | 80 + .../T/test_mv_or_predicate_rewrite | 36 + .../T/test_mv_partition_compensate_hive | 8 + ...test_mv_partition_compensate_iceberg_part1 | 28 + ...test_mv_partition_compensate_iceberg_part2 | 34 + .../T/test_mv_partition_compensate_mysql | 4 + .../T/test_mv_partition_compensate_olap | 4 + .../T/test_refresh_mv_with_different_dbs | 46 + .../T/test_show_materialized_view | 10 +- .../R/test_mv_refresh_list_partitions_basic | 40 + ...mv_refresh_list_partitions_partial_refresh | 45 + ...t_mv_refresh_list_partitions_with_nullable | 41 + .../R/test_mv_refresh_with_mv_reuse | 68 + .../R/test_mv_refresh_with_time_slice | 14 +- .../R/test_mv_refresh_with_union | 24 + .../R/test_mv_skip_partition_cache_iceberg | 173 ++ .../T/test_mv_refresh_list_partitions_basic | 22 + ...mv_refresh_list_partitions_partial_refresh | 25 + ...t_mv_refresh_list_partitions_with_nullable | 16 + .../T/test_mv_refresh_with_mv_reuse | 45 +- .../T/test_mv_refresh_with_time_slice | 14 +- .../T/test_mv_refresh_with_union | 24 + .../T/test_mv_skip_partition_cache_iceberg | 75 + .../R/test_mv_rewrite_with_date_trunc_rollup | 349 ++++ .../R/test_mv_rewrite_with_time_series | 263 +++ ...test_mv_rewrite_with_time_series_multi_mvs | 270 +++ .../T/test_mv_rewrite_with_date_trunc_rollup | 110 + .../T/test_mv_rewrite_with_time_series | 101 + ...test_mv_rewrite_with_time_series_multi_mvs | 129 ++ test/sql/test_meta_scan/R/test_meta_scan | 538 +++++ test/sql/test_meta_scan/T/test_meta_scan | 225 ++ .../test_nest_loop_join/R/test_nest_loop_join | 4 + .../test_nest_loop_join/T/test_nest_loop_join | 4 + .../R/test_expr_from_unixtime_prune_partition | 8 + .../R/test_expr_str2date | 4 + .../test_partition_by_expr/R/test_expr_substr | 4 + .../T/test_expr_from_unixtime_prune_partition | 8 + .../T/test_expr_str2date | 4 + .../test_partition_by_expr/T/test_expr_substr | 4 + .../R/test_driver_prepare | 29 + .../T/test_driver_prepare | 28 + .../T/test_load_channel_profile_analysis.sh | 4 + test/sql/test_query_cache/R/test_query_cache | 426 ++++ .../R/test_query_cache_shard_data | 426 ++++ test/sql/test_query_cache/T/test_query_cache | 399 ++++ .../T/test_query_cache_shard_data | 395 ++++ test/sql/test_rbac/R/test_view_privilege | 32 + test/sql/test_rbac/T/test_view_privilege | 14 + .../test_scan/R/test_schema_scan_asan_crash | 15 + test/sql/test_scan/R/test_table_sample | 92 + .../test_scan/T/test_schema_scan_asan_crash | 9 + test/sql/test_scan/T/test_table_sample | 50 + .../R/test_index_and_filter_on_or_predicate | 294 +++ .../T/test_index_and_filter_on_or_predicate | 207 ++ .../sql/test_sink/R/test_fault_injection_hdfs | 260 +++ test/sql/test_sink/R/test_fault_injection_oss | 286 +++ .../sql/test_sink/T/test_fault_injection_hdfs | 167 ++ test/sql/test_sink/T/test_fault_injection_oss | 192 ++ test/sql/test_spill/R/test_spill_nl_join | 6 + test/sql/test_spill/T/test_spill_nl_join | 4 + test/sql/test_task/R/test_drop | 4 + test/sql/test_task/R/test_periodical_task | 9 + test/sql/test_task/T/test_drop | 4 + test/sql/test_task/T/test_periodical_task | 10 + ...t_mv_with_multi_partition_columns_iceberg1 | 462 +++++ ...t_mv_with_multi_partition_columns_iceberg2 | 681 ++++++ .../R/test_transparent_mv_hive | 4 + .../R/test_transparent_mv_iceberg_part1 | 6 + .../R/test_transparent_mv_iceberg_part2 | 10 + .../R/test_transparent_mv_mysql | 6 + .../R/test_transparent_mv_olap_part1 | 820 ++++++++ .../R/test_transparent_mv_union_iceberg | 74 + ...t_mv_with_multi_partition_columns_iceberg1 | 292 +++ ...t_mv_with_multi_partition_columns_iceberg2 | 223 ++ .../T/test_transparent_mv_hive | 4 + .../T/test_transparent_mv_iceberg_part1 | 4 + .../T/test_transparent_mv_iceberg_part2 | 8 + .../T/test_transparent_mv_mysql | 4 + .../T/test_transparent_mv_olap_part1 | 268 +++ .../T/test_transparent_mv_union_iceberg | 17 + test/sql/test_udf/R/test_python_udf | 288 +++ test/sql/test_udf/T/test_python_udf | 249 +++ .../sql/test_vector_index/R/test_vector_index | 91 + .../sql/test_vector_index/T/test_vector_index | 45 + .../R/test_window_pre_agg_with_rank | 96 + .../T/test_window_pre_agg_with_rank | 79 + test/test_sql_cases.py | 4 + thirdparty/build-thirdparty.sh | 170 ++ thirdparty/download-thirdparty.sh | 90 + thirdparty/patches/avro-1.10.2.c.gcc14.patch | 13 + thirdparty/patches/breakpad-2022.07.12.patch | 12 + thirdparty/patches/clucene-gcc14.patch | 12 + .../mariadb-connector-c-3.1.14-gcc14.patch | 13 + thirdparty/patches/poco-1.12.5-ca.patch | 162 ++ .../patches/poco-1.12.5-keep-alive.patch | 27 + .../patches/poco-1.12.5-zero-copy.patch | 143 ++ thirdparty/patches/rapidjson-gcc14.patch | 45 + thirdparty/patches/rocksdb-6.22.1-gcc14.patch | 151 ++ .../rocksdb-6.22.1-metadata-header.patch | 84 + thirdparty/patches/sasl2-gcc14.patch | 26 + thirdparty/starlet-artifacts-version.sh | 4 + thirdparty/vars-aarch64.sh | 7 + thirdparty/vars-ubuntu22-aarch64.sh | 7 + thirdparty/vars-ubuntu22-x86_64.sh | 7 + thirdparty/vars-x86_64.sh | 7 + thirdparty/vars.sh | 58 + tools/benchmark/table_sample.sh | 84 + tools/stream_load/README.md | 4 + trivy.yaml | 9 + 3907 files changed, 217918 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/releasenotes404.yaml create mode 100644 be/cmake_modules/FindGlibcVersion.cmake create mode 100644 be/extension/python-udf/src/flight_server.py create mode 100644 be/src/bench/bit_copy.h create mode 100644 be/src/bench/bit_unpack_bench.cpp create mode 100644 be/src/bench/mem_equal_bench.cpp create mode 100644 be/src/common/format_ip.h create mode 100644 be/src/common/vlog_cntl.h create mode 100644 be/src/connector/deletion_vector/deletion_vector.cpp create mode 100644 be/src/connector/deletion_vector/deletion_vector.h create mode 100644 be/src/exec/arrow_flight_batch_reader.cpp create mode 100644 be/src/exec/arrow_flight_batch_reader.h create mode 100644 be/src/exec/pipeline/hashjoin/hash_joiner_fwd.h create mode 100644 be/src/exprs/agg/agg_state_merge.h create mode 100644 be/src/exprs/agg/agg_state_union.h create mode 100644 be/src/exprs/agg/aggregate_state_allocator.h create mode 100644 be/src/exprs/agg/ds_hll_count_distinct.h create mode 100644 be/src/exprs/agg/factory/aggregate_resolver_hypothesis_testing.cpp create mode 100644 be/src/exprs/agg/helpers/serialize_helpers.hpp create mode 100644 be/src/exprs/agg/hypothesis_testing_common.h create mode 100644 be/src/exprs/agg/mann_whitney.h create mode 100644 be/src/exprs/agg/map_agg.h create mode 100644 be/src/exprs/agg_state_function.h create mode 100644 be/src/exprs/arrow_function_call.cpp create mode 100644 be/src/exprs/arrow_function_call.h create mode 100644 be/src/exprs/cast_expr_struct.cpp create mode 100644 be/src/exprs/inet_aton.cpp create mode 100644 be/src/exprs/min_max_predicate.h create mode 100644 be/src/exprs/regexp_split.cpp create mode 100644 be/src/exprs/regexp_split.h create mode 100644 be/src/formats/parquet/column_reader_factory.cpp create mode 100644 be/src/formats/parquet/column_reader_factory.h create mode 100644 be/src/formats/parquet/complex_column_reader.cpp create mode 100644 be/src/formats/parquet/complex_column_reader.h create mode 100644 be/src/formats/parquet/scalar_column_reader.cpp create mode 100644 be/src/formats/parquet/scalar_column_reader.h create mode 100644 be/src/formats/parquet/zone_map_filter_evaluator.h create mode 100644 be/src/fs/s3/poco_common.cpp create mode 100644 be/src/fs/s3/poco_common.h create mode 100644 be/src/fs/s3/poco_http_client.cpp create mode 100644 be/src/fs/s3/poco_http_client.h create mode 100644 be/src/fs/s3/poco_http_client_factory.cpp create mode 100644 be/src/fs/s3/poco_http_client_factory.h create mode 100644 be/src/fs/s3/pool_base.h create mode 100644 be/src/io/s3_zero_copy_iostream.h create mode 100644 be/src/runtime/agg_state_desc.cpp create mode 100644 be/src/runtime/agg_state_desc.h create mode 100644 be/src/runtime/arrow_result_writer.cpp create mode 100644 be/src/runtime/arrow_result_writer.h create mode 100644 be/src/runtime/batch_write/batch_write_mgr.cpp create mode 100644 be/src/runtime/batch_write/batch_write_mgr.h create mode 100644 be/src/runtime/batch_write/batch_write_util.cpp create mode 100644 be/src/runtime/batch_write/batch_write_util.h create mode 100644 be/src/runtime/batch_write/isomorphic_batch_write.cpp create mode 100644 be/src/runtime/batch_write/isomorphic_batch_write.h create mode 100644 be/src/runtime/buffer_control_result_writer.cpp create mode 100644 be/src/runtime/buffer_control_result_writer.h create mode 100644 be/src/runtime/global_variables.cpp create mode 100644 be/src/runtime/global_variables.h create mode 100644 be/src/runtime/memory/allocator.h create mode 100644 be/src/runtime/memory/column_allocator.cpp create mode 100644 be/src/runtime/memory/column_allocator.h create mode 100644 be/src/runtime/memory/counting_allocator.h create mode 100644 be/src/runtime/memory/mem_hook_allocator.h create mode 100644 be/src/runtime/memory/roaring_hook.cpp create mode 100644 be/src/runtime/memory/roaring_hook.h create mode 100644 be/src/runtime/stream_load/time_bounded_stream_load_pipe.cpp create mode 100644 be/src/runtime/stream_load/time_bounded_stream_load_pipe.h create mode 100644 be/src/service/service_be/arrow_flight_sql_service.cpp create mode 100644 be/src/service/service_be/arrow_flight_sql_service.h create mode 100644 be/src/simd/multi_version.h create mode 100644 be/src/starrocks_format/CMakeLists.txt create mode 100644 be/src/starrocks_format/starrocks_lib.cpp create mode 100644 be/src/starrocks_format/starrocks_lib.h create mode 100644 be/src/storage/column_and_predicate.cpp create mode 100644 be/src/storage/column_and_predicate.h create mode 100644 be/src/storage/index/index_descriptor.h create mode 100644 be/src/storage/index/inverted/clucene/clucene_inverted_reader.cpp create mode 100644 be/src/storage/index/inverted/clucene/clucene_inverted_reader.h create mode 100644 be/src/storage/index/inverted/clucene/clucene_inverted_util.h create mode 100644 be/src/storage/index/inverted/clucene/clucene_inverted_writer.cpp create mode 100644 be/src/storage/index/inverted/clucene/clucene_inverted_writer.h create mode 100644 be/src/storage/index/inverted/clucene/clucene_plugin.cpp create mode 100644 be/src/storage/index/inverted/clucene/clucene_plugin.h create mode 100644 be/src/storage/index/inverted/clucene/clucene_roaring_hit_collector.h create mode 100644 be/src/storage/index/inverted/clucene/match_operator.cpp create mode 100644 be/src/storage/index/inverted/clucene/match_operator.h create mode 100644 be/src/storage/index/inverted/inverted_index_common.h create mode 100644 be/src/storage/index/inverted/inverted_index_iterator.cpp create mode 100644 be/src/storage/index/inverted/inverted_index_iterator.h create mode 100644 be/src/storage/index/inverted/inverted_index_option.cpp create mode 100644 be/src/storage/index/inverted/inverted_index_option.h create mode 100644 be/src/storage/index/inverted/inverted_plugin.h create mode 100644 be/src/storage/index/inverted/inverted_plugin_factory.cpp create mode 100644 be/src/storage/index/inverted/inverted_plugin_factory.h create mode 100644 be/src/storage/index/inverted/inverted_reader.h create mode 100644 be/src/storage/index/inverted/inverted_writer.h create mode 100644 be/src/storage/index/vector/empty_index_reader.cpp create mode 100644 be/src/storage/index/vector/empty_index_reader.h create mode 100644 be/src/storage/index/vector/tenann/del_id_filter.cpp create mode 100644 be/src/storage/index/vector/tenann/del_id_filter.h create mode 100644 be/src/storage/index/vector/tenann/tenann_index_builder.cpp create mode 100644 be/src/storage/index/vector/tenann/tenann_index_builder.h create mode 100644 be/src/storage/index/vector/tenann/tenann_index_utils.cpp create mode 100644 be/src/storage/index/vector/tenann/tenann_index_utils.h create mode 100644 be/src/storage/index/vector/tenann_index_reader.cpp create mode 100644 be/src/storage/index/vector/tenann_index_reader.h create mode 100644 be/src/storage/index/vector/vector_index_builder.cpp create mode 100644 be/src/storage/index/vector/vector_index_builder.h create mode 100644 be/src/storage/index/vector/vector_index_builder_factory.cpp create mode 100644 be/src/storage/index/vector/vector_index_builder_factory.h create mode 100644 be/src/storage/index/vector/vector_index_reader.h create mode 100644 be/src/storage/index/vector/vector_index_reader_factory.cpp create mode 100644 be/src/storage/index/vector/vector_index_reader_factory.h create mode 100644 be/src/storage/index/vector/vector_index_writer.cpp create mode 100644 be/src/storage/index/vector/vector_index_writer.h create mode 100644 be/src/storage/index/vector/vector_search_option.h create mode 100644 be/src/storage/lake/lake_delvec_loader.cpp create mode 100644 be/src/storage/lake/lake_delvec_loader.h create mode 100644 be/src/storage/rowset/bitmap_index_evaluator.cpp create mode 100644 be/src/storage/rowset/bitmap_index_evaluator.h create mode 100644 be/src/storage/rowset/data_sample.cpp create mode 100644 be/src/storage/rowset/data_sample.h create mode 100644 be/src/types/checker/type_checker.cpp create mode 100644 be/src/types/checker/type_checker.h create mode 100644 be/src/types/hll_sketch.cpp create mode 100644 be/src/types/hll_sketch.h create mode 100644 be/src/types/large_int_value.cpp create mode 100644 be/src/types/large_int_value.h create mode 100644 be/src/types/type_checker_manager.cpp create mode 100644 be/src/types/type_checker_manager.h create mode 100644 be/src/udf/python/callstub.cpp create mode 100644 be/src/udf/python/callstub.h create mode 100644 be/src/udf/python/env.cpp create mode 100644 be/src/udf/python/env.h create mode 100644 be/src/udf/udf_call_stub.cpp create mode 100644 be/src/udf/udf_call_stub.h create mode 100644 be/src/util/base85.cpp create mode 100644 be/src/util/base85.h create mode 100644 be/src/util/bit_packing_adapter.h create mode 100644 be/src/util/bit_packing_simd.h create mode 100644 be/src/util/internal_service_recoverable_stub.cpp create mode 100644 be/src/util/internal_service_recoverable_stub.h create mode 100644 be/test/connector/deletion_vector/deletion_vector_test.cpp create mode 100644 be/test/exec/olap_scan_prepare_test.cpp create mode 100644 be/test/exec/workgroup/pipeline_executor_set_test.cpp create mode 100644 be/test/exprs/min_max_predicate_test.cpp create mode 100644 be/test/formats/orc/utils_test.cpp create mode 100644 be/test/formats/parquet/test_data/file_read_test_filter_row_group_1.parquet create mode 100644 be/test/formats/parquet/test_data/file_read_test_filter_row_group_2.parquet create mode 100644 be/test/fs/poco_http_client_test.cpp create mode 100644 be/test/http/action/update_config_action_test.cpp create mode 100644 be/test/runtime/agg_state_desc_test.cpp create mode 100644 be/test/runtime/batch_write/batch_write_mgr_test.cpp create mode 100644 be/test/runtime/batch_write/batch_write_util_test.cpp create mode 100644 be/test/runtime/batch_write/isomorphic_batch_write_test.cpp create mode 100644 be/test/runtime/memory/counting_allocator_test.cpp create mode 100644 be/test/runtime/time_bounded_stream_load_pipe_test.cpp create mode 100644 be/test/storage/column_and_predicate_test.cpp create mode 100644 be/test/storage/column_or_predicate_test.cpp create mode 100644 be/test/storage/index/vector_index_test.cpp create mode 100644 be/test/storage/index/vector_search_test.cpp create mode 100644 be/test/storage/lake/starlet_location_provider_test.cpp create mode 100644 be/test/storage/metadata_util_test.cpp create mode 100644 be/test/storage/olap_runtime_range_pruner_test.cpp create mode 100644 be/test/storage/rowset/data_sample_test.cpp create mode 100644 be/test/types/type_checker_test.cpp create mode 100644 be/test/util/base85_test.cpp create mode 100644 be/test/util/bit_packing_simd_test.cpp create mode 100644 be/test/util/internal_service_recoverable_stub_test.cpp create mode 100644 be/test/util/raw_container_test.cpp create mode 100644 contrib/starrocks-python-client/starrocks/alembic.py create mode 100644 docker/dockerfiles/Dockerhub-README.md create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/aarch64/CentOS-Base-Local-List.repo create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/aarch64/yum-base-mirrorlist.txt create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/aarch64/yum-extras-mirrorlist.txt create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/aarch64/yum-updates-mirrorlist.txt create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/x86_64/CentOS-Base-Local-List.repo create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/x86_64/yum-base-mirrorlist.txt create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/x86_64/yum-extras-mirrorlist.txt create mode 100644 docker/dockerfiles/toolchains/yum-mirrorlist/x86_64/yum-updates-mirrorlist.txt create mode 100644 docs/en/release_notes/release-3.1.md create mode 100644 docs/en/release_notes/release-3.3.md create mode 100644 docs/en/sql-reference/sql-functions/Python_UDF.md create mode 100644 docs/en/sql-reference/sql-functions/aggregate-functions/approx_count_distinct_hll_sketch.md create mode 100644 docs/en/sql-reference/sql-functions/aggregate-functions/mann_whitney_u_test.md create mode 100644 docs/en/sql-reference/sql-functions/aggregate-functions/percentile_disc_lc.md create mode 100644 docs/en/sql-reference/sql-functions/string-functions/inet_aton.md create mode 100644 docs/en/sql-reference/sql-functions/string-functions/regexp_split.md create mode 100644 docs/en/sql-reference/sql-functions/utility-functions/bar.md create mode 100644 docs/en/sql-reference/sql-functions/utility-functions/equiwidth_bucket.md create mode 100644 docs/translation/.env.sample create mode 100644 docs/translation/.gitignore create mode 100644 docs/translation/README.md create mode 100644 docs/translation/en-to-zh-configs/config.yaml create mode 100644 docs/translation/en-to-zh-configs/evaluation_prompt.txt create mode 100644 docs/translation/en-to-zh-configs/human_prompt.txt create mode 100644 docs/translation/en-to-zh-configs/language_dicts/en.yaml create mode 100644 docs/translation/en-to-zh-configs/language_dicts/zh.yaml create mode 100644 docs/translation/en-to-zh-configs/system_prompt.txt create mode 100755 docs/translation/scripts/en-to-zh.translate.sh create mode 100755 docs/translation/scripts/zh-to-en.translate.sh create mode 100644 docs/translation/translation.Dockerfile create mode 100644 docs/translation/zh-to-en-configs/config.yaml create mode 100644 docs/translation/zh-to-en-configs/evaluation_prompt.txt create mode 100644 docs/translation/zh-to-en-configs/human_prompt.txt create mode 100644 docs/translation/zh-to-en-configs/language_dicts/en.yaml create mode 100644 docs/translation/zh-to-en-configs/language_dicts/zh.yaml create mode 100644 docs/translation/zh-to-en-configs/system_prompt.txt create mode 100644 docs/zh/release_notes/release-3.1.md create mode 100644 docs/zh/release_notes/release-3.3.md create mode 100644 docs/zh/sql-reference/sql-functions/Python_UDF.md create mode 100644 docs/zh/sql-reference/sql-functions/aggregate-functions/mann_whitney_u_test.md create mode 100644 docs/zh/sql-reference/sql-functions/aggregate-functions/percentile_disc_lc.md create mode 100644 docs/zh/sql-reference/sql-functions/string-functions/inet_aton.md create mode 100644 docs/zh/sql-reference/sql-functions/string-functions/regexp_split.md create mode 100644 docs/zh/sql-reference/sql-functions/utility-functions/bar.md create mode 100644 docs/zh/sql-reference/sql-functions/utility-functions/equiwidth_bucket.md create mode 100644 fe/fe-core/src/main/java/com/starrocks/alter/LakeRollupJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/alter/LakeTableRollupBuilder.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/alter/LakeTableSchemaChangeJobBase.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/alter/OlapTableRollupJobBuilder.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/analysis/VectorIndexUtil.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/AccessControlProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/AccessController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/AccessDeniedException.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ActionSet.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/AuthorizationMgr.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/AuthorizationProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/CatalogPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ColumnPrivilege.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/DbPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/DefaultAuthorizationProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ExternalAccessController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ForwardCompatiblePEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/FunctionPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/GlobalFunctionPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/MaterializedViewPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/NativeAccessController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ObjectType.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PipePEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PolicyFCEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PrivObjNotFoundException.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PrivilegeBuiltinConstants.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PrivilegeCollectionV2.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PrivilegeEntry.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PrivilegeException.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/PrivilegeType.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ResourceGroupPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ResourcePEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/RolePrivilegeCollectionV2.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/SecurityPolicyRewriteRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/StorageVolumePEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/TablePEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/UserPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/UserPrivilegeCollectionV2.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ViewPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/WarehouseFCPEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/WarehousePEntryObject.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/AccessTypeConverter.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/ObjectTypeConverter.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/RangerAccessController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/RangerAccessResourceBuilder.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/RangerStarRocksAccessRequest.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/hive/HiveAccessType.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/hive/RangerHiveAccessController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/hive/RangerHiveResource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/starrocks/RangerStarRocksAccessController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/authorization/ranger/starrocks/RangerStarRocksResource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/catalog/IndexParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/catalog/combinator/AggStateCombinator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/catalog/combinator/AggStateDesc.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/catalog/combinator/AggStateMergeCombinator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/catalog/combinator/AggStateUnionCombinator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/catalog/combinator/AggStateUtils.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/clone/PartitionTTLScheduler.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/clone/SchedulerRuntimeInfoCollector.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/common/StarRocksException.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/common/StatusOr.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/common/VectorIndexParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/common/VectorSearchOptions.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/common/util/ArrowUtil.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/common/util/concurrent/LockUtils.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/AsyncTaskQueue.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/BranchOptions.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/ConnectorMetadatRequestContext.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/ConnectorProperties.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/ConnectorScanRangeSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/ConnectorTableVersion.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/DirectoryBasedUpdateArbitrator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/GetRemoteFilesParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/HMSPartitionBasedRemoteInfoSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/HivePartitionDataInfo.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/ObjectBasedUpdateArbitrator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/PointerType.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/RemoteFileInfoDefaultSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/RemoteFileInfoSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/RemoteFileScanContext.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/TableUpdateArbitrator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/TableVersionRange.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/TagOptions.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/delta/DeltaConnectorScanRangeSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/delta/DeltaRemoteFileInfo.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/hive/HiveConnectorScanRangeSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/hudi/HudiConnectorScanRangeSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergConnectorScanRangeSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergDeleteSchema.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergGetRemoteFilesParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergMORParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergRemoteFileInfo.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergRemoteFileInfoSourceKey.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergRemoteSourceTrigger.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/IcebergTableOperation.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/QueueIcebergRemoteFileInfoSource.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/rest/OAuth2SecurityConfig.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/rest/OAuth2SecurityProperties.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/iceberg/rest/SecurityEnum.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/AbstractMetadataTableFactory.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/MetadataTableFactoryProvider.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergFilesTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergHistoryTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergManifestsTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergMetadataLogEntriesTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergMetadataTableFactory.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergPartitionsTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergRefsTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/metadata/iceberg/IcebergSnapshotsTable.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/statistics/ConnectorAnalyzeTask.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/statistics/ConnectorAnalyzeTaskQueue.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/connector/statistics/ConnectorTableTriggerAnalyzeMgr.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/StreamLoadMetaAction.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/RestBaseResultV2.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/TableBaseAction.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/TablePartitionAction.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/TableSchemaAction.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/ColumnView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/DistributionInfoView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/IndexView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/MaterializedIndexMetaView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/PartitionInfoView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/TableSchemaView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/TabletView.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/http/rest/v2/vo/package-info.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/journal/CheckpointException.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/journal/CheckpointWorker.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/journal/GlobalStateCheckpointWorker.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/journal/StarMgrCheckpointWorker.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/leader/CheckpointController.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/BatchWriteId.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/BatchWriteMgr.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/CoordinatorBackendAssigner.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/CoordinatorBackendAssignerImpl.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/IsomorphicBatchWrite.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/LoadExecuteCallback.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/LoadExecutor.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/RequestCoordinatorBackendResult.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/RequestLoadResult.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/batchwrite/TableId.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadHttpHeader.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadKvParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/load/streamload/StreamLoadThriftParams.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/persist/DropPartitionsInfo.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/NodeExecStats.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/OperatorTuningGuides.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/PlanAdvisorExecutor.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/PlanTuningAdvisor.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/PlanTuningCacheKey.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/analyzer/JoinTuningAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/analyzer/PlanTuningAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/analyzer/StreamingAggTuningAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/guide/JoinTuningGuide.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/guide/LeftChildEstimationErrorTuningGuide.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/guide/RightChildEstimationErrorTuningGuide.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/guide/StreamingAggTuningGuide.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/guide/TuningGuide.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/BlockingAggNode.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/DistributionNode.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/JoinNode.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/ScanNode.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/SkeletonBuilder.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/SkeletonNode.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/qe/feedback/skeleton/StreamingAggNode.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/scheduler/mv/MVPCTMetaRepairer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/ArrowFlightSqlConnectContext.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/ArrowFlightSqlConnectProcessor.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/ArrowFlightSqlService.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/ArrowFlightSqlServiceImpl.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/auth/ArrowFlightSqlAuthenticator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/auth/ArrowFlightSqlCredentialValidator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/session/ArrowFlightSqlSessionManager.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/session/ArrowFlightSqlTokenInfo.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/service/arrow/flight/sql/session/ArrowFlightSqlTokenManager.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/RankingWindowUtils.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AuthenticationAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/analyzer/AuthorizationAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/analyzer/CreateFunctionAnalyzer.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/AlterTableOperationClause.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/CatalogRef.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateOrReplaceBranchClause.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/CreateOrReplaceTagClause.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/DropBranchClause.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/DropTagClause.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/FunctionRef.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/QueryPeriod.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/TableSampleClause.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/feedback/AddPlanAdvisorStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/feedback/ClearPlanAdvisorStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/feedback/DelPlanAdvisorStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/feedback/PlanAdvisorStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/feedback/ShowPlanAdvisorStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/ast/warehouse/AlterWarehouseStmt.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/OpRuleBit.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/logical/LogicalIcebergEqualityDeleteScanOperator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/physical/PhysicalIcebergEqualityDeleteScanOperator.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/operator/scalar/OperatorFunctionChecker.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/property/DomainProperty.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/property/DomainPropertyDeriver.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/property/RangeExtractor.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/property/ReplaceShuttle.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rewrite/TableScanPredicateExtractor.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/implementation/IcebergEqualityDeleteScanImplementationRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/IcebergEqualityDeleteRewriteRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/IcebergPartitionsTableRewriteRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/OnPredicateMoveAroundRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PruneUKFKGroupByKeysRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/PullUpScanPredicateRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/RewriteToVectorPlanRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/AggregatedTimeSeriesRewriter.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/common/AggregateFunctionRollupUtils.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/common/AggregatePushDownUtils.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/equivalent/AggStateRewriteEquivalent.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/materialization/rule/AggregateTimeSeriesRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/transformation/partition/PartitionSelector.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/ApplyTuningGuideRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/rule/tree/MarkParentRequiredDistributionRule.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/sql/optimizer/task/RewriteDownTopTask.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/ExternalSampleStatisticsCollectJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/HyperStatisticsCollectJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/ColumnClassifier.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/ColumnStats.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/ComplexTypeColumnStats.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/PartitionSampler.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/PrimitiveTypeColumnStats.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/SubFieldColumnStats.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/base/TabletSampler.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/hyper/ConstQueryJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/hyper/FullQueryJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/hyper/HyperQueryJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/hyper/HyperStatisticSQLs.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/hyper/MetaQueryJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/statistic/hyper/SampleQueryJob.java create mode 100644 fe/fe-core/src/main/java/com/starrocks/task/TabletTaskExecutor.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/alter/LakeRollupJobTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/alter/LakeSyncMaterializedViewTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/analysis/VectorIndexTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/AccessControlTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/ActionSetTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/AuthorizationMgrTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/IdGenerator.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/InvalidateObjectTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/PrivilegeCollectionTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/RBACMockedMetadataMgr.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/RolePrivilegeCollectionTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/ranger/RangerInterfaceTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/authorization/ranger/RangerResourceTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/catalog/AggStateDescTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/catalog/CreateTableWithAggStateTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/catalog/DropPartitionWithExprListTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/catalog/DropPartitionWithExprRangeTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/catalog/combinator/AggStateCombinatorTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/common/TraceManagerTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/AlterTableTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/AsyncTaskQueueTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/DirectoryBasedUpdateArbitratorTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/HMSPartitionBasedRemoteInfoSourceTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/ObjectBasedUpdateArbitratorTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/TableUpdateArbitratorTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/iceberg/CachingIcebergCatalogTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/iceberg/MIcebergTable.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/iceberg/MIcebergTableMeta.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/iceberg/rest/OAuth2SecurityConfigTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/parser/trino/TrinoDialectDowngradeTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/parser/trino/TrinoInsertTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/statistics/ConnectorAnalyzeTaskQueueTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/connector/statistics/ConnectorAnalyzeTaskTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/http/StreamLoadMetaActionTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/http/rest/v2/TablePartitionActionTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/http/rest/v2/TableSchemaActionTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/PartitionUtilsTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/batchwrite/BatchWriteMgrTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/batchwrite/BatchWriteTestBase.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/batchwrite/CoordinatorBackendAssignerTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/batchwrite/IsomorphicBatchWriteTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/batchwrite/LoadExecutorTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadHttpHeaderTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadInfoTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadKvParamsTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadParamsTestBase.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/load/streamload/StreamLoadThriftParamsTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/persist/DropPartitionsInfoTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/planner/OnPredicateMoveAroundRuleTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/planner/VectorIndexTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/qe/KillQueryHandleTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/qe/feedback/analyzer/PlanTuningAnalyzerTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/qe/feedback/guide/LeftChildEstimationErrorTuningGuideTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/qe/feedback/guide/RightChildEstimationErrorTuningGuideTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/qe/scheduler/IncrementalDeployHiveTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/service/ArrowFlightSqlJDBCTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/service/arrow/flight/sql/ArrowFlightSqlServiceTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/analyzer/CreateFunctionStmtAnalyzerTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/ast/TableSampleClauseTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/common/PermutationGeneratorTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/optimizer/ScanPredicateExprReuseTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvTimeSeriesRewriteWithHiveTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/transformation/materialization/MvTimeSeriesRewriteWithOlapTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/optimizer/rule/tree/MarkParentRequiredDistributionRuleTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/plan/AggregatePushDownWithCostTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/plan/AggregateWithUKFKTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/plan/IcebergEqualityDeletePlanTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/plan/PlanWithCostTestBase.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/plan/SelectUsingAliasTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/sql/plan/TPCDSAggregateWithUKFKTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/statistic/hyper/HyperJobTest.java create mode 100644 fe/fe-core/src/test/java/com/starrocks/transaction/GtidGeneratorTest.java create mode 100644 fe/fe-core/src/test/resources/conf/config_mutable.properties create mode 100644 fe/fe-core/src/test/resources/sql/optimized-plan/agg-pushdown-disable_on_broadcast_join.sql create mode 100644 fe/fe-core/src/test/resources/sql/optimized-plan/agg-pushdown-enable_on_broadcast_join.sql create mode 100644 fe/fe-core/src/test/resources/sql/optimized-plan/preagg-pushdown-disable_on_broadcast_join.sql create mode 100644 fe/fe-core/src/test/resources/sql/optimized-plan/preagg-pushdown-enable_on_broadcast_join.sql create mode 100644 java-extensions/hadoop-ext/src/main/java/com/starrocks/connector/share/iceberg/IcebergPartitionUtils.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/AbstractIcebergMetadataScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergFilesTableScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergHistoryTableScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergManifestsTableScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergMetadataLogEntriesScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergPartitionsTableScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergRefsTableScanner.java create mode 100644 java-extensions/iceberg-metadata-reader/src/main/java/com/starrocks/connector/iceberg/IcebergSnapshotsTableScanner.java create mode 100644 test/lib/arrow_sql_lib.py create mode 100644 test/sql/test_across_engine/R/test_connection create mode 100644 test/sql/test_across_engine/R/test_sink create mode 100644 test/sql/test_across_engine/R/test_sink_nested create mode 100644 test/sql/test_across_engine/R/test_sink_partitioned create mode 100644 test/sql/test_across_engine/T/test_connection create mode 100644 test/sql/test_across_engine/T/test_sink create mode 100644 test/sql/test_across_engine/T/test_sink_nested create mode 100644 test/sql/test_across_engine/T/test_sink_partitioned create mode 100644 test/sql/test_across_engine/data/nested_lists.parquet create mode 100644 test/sql/test_across_engine/data/nested_maps.parquet create mode 100644 test/sql/test_across_engine/data/nested_structs.parquet create mode 100644 test/sql/test_across_engine/data/tpch_lineitem.parquet create mode 100644 test/sql/test_agg/R/test_agg_set_prefetch create mode 100644 test/sql/test_agg/R/test_tinyint_agg create mode 100644 test/sql/test_agg/T/test_agg_set_prefetch create mode 100644 test/sql/test_agg/T/test_tinyint_agg create mode 100644 test/sql/test_agg_function/R/test_hll create mode 100644 test/sql/test_agg_function/R/test_hll_sketch_count.sql create mode 100644 test/sql/test_agg_function/R/test_lc_percentile create mode 100644 test/sql/test_agg_function/R/test_mann_whitney create mode 100644 test/sql/test_agg_function/R/test_map_agg create mode 100644 test/sql/test_agg_function/R/test_percentile_union create mode 100644 test/sql/test_agg_function/T/test_hll create mode 100644 test/sql/test_agg_function/T/test_hll_sketch_count.sql create mode 100644 test/sql/test_agg_function/T/test_lc_percentile create mode 100644 test/sql/test_agg_function/T/test_mann_whitney create mode 100644 test/sql/test_agg_function/T/test_map_agg create mode 100644 test/sql/test_agg_function/T/test_percentile_union create mode 100644 test/sql/test_agg_state/R/test_agg_state_ds_hll_count_distinct.sql create mode 100644 test/sql/test_agg_state/R/test_agg_state_table_basic.sql create mode 100644 test/sql/test_agg_state/R/test_agg_state_table_with_all_functions.sql create mode 100644 test/sql/test_agg_state/R/test_agg_state_with_async_mv.sql create mode 100644 test/sql/test_agg_state/R/test_agg_state_with_sync_mv.sql create mode 100644 test/sql/test_agg_state/T/test_agg_state_ds_hll_count_distinct.sql create mode 100644 test/sql/test_agg_state/T/test_agg_state_table_basic.sql create mode 100644 test/sql/test_agg_state/T/test_agg_state_table_with_all_functions.sql create mode 100644 test/sql/test_agg_state/T/test_agg_state_with_async_mv.sql create mode 100644 test/sql/test_agg_state/T/test_agg_state_with_sync_mv.sql create mode 100644 test/sql/test_arrow/R/test_arrow create mode 100644 test/sql/test_arrow/T/test_arrow create mode 100644 test/sql/test_automatic_partition/R/test_multi_expr create mode 100644 test/sql/test_automatic_partition/T/test_multi_expr create mode 100644 test/sql/test_cast/R/test_cast_json_to_struct create mode 100644 test/sql/test_cast/T/test_cast_json_to_struct create mode 100644 test/sql/test_column_rename/T/test_column_rename create mode 100644 test/sql/test_column_rename/T/test_column_rename2 create mode 100644 test/sql/test_deltalake/R/test_deltalake_dv create mode 100644 test/sql/test_deltalake/R/test_deltalake_scan_ranges create mode 100644 test/sql/test_deltalake/T/test_deltalake_dv create mode 100644 test/sql/test_deltalake/T/test_deltalake_scan_ranges create mode 100644 test/sql/test_drop_partition/R/test_drop_partition_list_table_with_where create mode 100644 test/sql/test_drop_partition/R/test_drop_partition_range_table_with_where create mode 100644 test/sql/test_drop_partition/T/test_drop_partition_list_table_with_where create mode 100644 test/sql/test_drop_partition/T/test_drop_partition_range_table_with_where create mode 100644 test/sql/test_dynamic_overwrite/R/test_overwrite create mode 100644 test/sql/test_dynamic_overwrite/T/test_overwrite create mode 100644 test/sql/test_expr_reuese/R/test_scan_predicate_expr_reuse create mode 100644 test/sql/test_expr_reuese/T/test_scan_predicate_expr_reuse create mode 100644 test/sql/test_feedback/R/test_agg_feedback create mode 100644 test/sql/test_feedback/R/test_external_table_join_feedback create mode 100644 test/sql/test_feedback/R/test_join_feedback create mode 100644 test/sql/test_feedback/T/test_agg_feedback create mode 100644 test/sql/test_feedback/T/test_external_table_join_feedback create mode 100644 test/sql/test_feedback/T/test_join_feedback create mode 100644 test/sql/test_files/R/test_insert_properties create mode 100644 test/sql/test_files/R/test_orc_files_merge create mode 100644 test/sql/test_files/R/test_orc_struct create mode 100644 test/sql/test_files/R/test_parquet_files_merge create mode 100644 test/sql/test_files/T/test_insert_properties create mode 100644 test/sql/test_files/T/test_orc_files_merge create mode 100644 test/sql/test_files/T/test_orc_struct create mode 100644 test/sql/test_files/T/test_parquet_files_merge create mode 100644 test/sql/test_files/csv_format/invalid_int.csv create mode 100644 test/sql/test_files/orc_format/basic_type.orc create mode 100644 test/sql/test_files/orc_format/basic_type_k2k5k7.orc create mode 100644 test/sql/test_files/orc_format/struct_mix.snappy.orc create mode 100644 test/sql/test_files/parquet_format/basic_type_k2k5k7.parquet create mode 100644 test/sql/test_function/R/test_synopse create mode 100644 test/sql/test_function/T/test_synopse create mode 100644 test/sql/test_gtid/R/test_gtid create mode 100644 test/sql/test_gtid/T/test_gtid create mode 100644 test/sql/test_hive/R/test_hive_analyze create mode 100644 test/sql/test_hive/R/test_hive_scan_ranges create mode 100644 test/sql/test_hive/T/test_hive_analyze create mode 100644 test/sql/test_hive/T/test_hive_scan_ranges create mode 100644 test/sql/test_iceberg/R/test_metadata_table create mode 100644 test/sql/test_iceberg/R/test_table_operation create mode 100644 test/sql/test_iceberg/R/test_timetravel create mode 100644 test/sql/test_iceberg/R/test_write_null create mode 100644 test/sql/test_iceberg/T/test_metadata_table create mode 100644 test/sql/test_iceberg/T/test_table_operation create mode 100644 test/sql/test_iceberg/T/test_timetravel create mode 100644 test/sql/test_iceberg/T/test_write_null create mode 100644 test/sql/test_insert_empty/R/test_insert_by_name create mode 100644 test/sql/test_insert_empty/R/test_insert_timeout create mode 100644 test/sql/test_insert_empty/T/test_insert_by_name create mode 100644 test/sql/test_insert_empty/T/test_insert_timeout create mode 100644 test/sql/test_join/R/test_predicate_move_around create mode 100644 test/sql/test_join/T/test_predicate_move_around create mode 100644 test/sql/test_lake_rollup/R/test_lake_rollup create mode 100644 test/sql/test_lake_rollup/T/test_lake_rollup create mode 100644 test/sql/test_lake_sync_mv/R/test_lake_sync_mv create mode 100644 test/sql/test_lake_sync_mv/R/test_lake_sync_mv_rewrite create mode 100644 test/sql/test_lake_sync_mv/T/test_lake_sync_mv create mode 100644 test/sql/test_lake_sync_mv/T/test_lake_sync_mv_rewrite create mode 100644 test/sql/test_materialized_view/R/test_materialized_view_incremental_refresh_on_hive create mode 100644 test/sql/test_materialized_view/R/test_refresh_mv_with_different_dbs create mode 100644 test/sql/test_materialized_view/T/test_materialized_view_incremental_refresh_on_hive create mode 100644 test/sql/test_materialized_view/T/test_refresh_mv_with_different_dbs create mode 100644 test/sql/test_materialized_view_refresh/R/test_mv_skip_partition_cache_iceberg create mode 100644 test/sql/test_materialized_view_refresh/T/test_mv_skip_partition_cache_iceberg create mode 100644 test/sql/test_materialized_view_rewrite/R/test_mv_rewrite_with_date_trunc_rollup create mode 100644 test/sql/test_materialized_view_rewrite/R/test_mv_rewrite_with_time_series create mode 100644 test/sql/test_materialized_view_rewrite/R/test_mv_rewrite_with_time_series_multi_mvs create mode 100644 test/sql/test_materialized_view_rewrite/T/test_mv_rewrite_with_date_trunc_rollup create mode 100644 test/sql/test_materialized_view_rewrite/T/test_mv_rewrite_with_time_series create mode 100644 test/sql/test_materialized_view_rewrite/T/test_mv_rewrite_with_time_series_multi_mvs create mode 100644 test/sql/test_meta_scan/R/test_meta_scan create mode 100644 test/sql/test_meta_scan/T/test_meta_scan create mode 100644 test/sql/test_query_cache/R/test_query_cache create mode 100644 test/sql/test_query_cache/R/test_query_cache_shard_data create mode 100644 test/sql/test_query_cache/T/test_query_cache create mode 100644 test/sql/test_query_cache/T/test_query_cache_shard_data create mode 100644 test/sql/test_rbac/R/test_view_privilege create mode 100644 test/sql/test_rbac/T/test_view_privilege create mode 100644 test/sql/test_scan/R/test_schema_scan_asan_crash create mode 100644 test/sql/test_scan/R/test_table_sample create mode 100644 test/sql/test_scan/T/test_schema_scan_asan_crash create mode 100644 test/sql/test_scan/T/test_table_sample create mode 100644 test/sql/test_sink/R/test_fault_injection_hdfs create mode 100644 test/sql/test_sink/R/test_fault_injection_oss create mode 100644 test/sql/test_sink/T/test_fault_injection_hdfs create mode 100644 test/sql/test_sink/T/test_fault_injection_oss create mode 100644 test/sql/test_transparent_mv/R/test_mv_with_multi_partition_columns_iceberg1 create mode 100644 test/sql/test_transparent_mv/R/test_mv_with_multi_partition_columns_iceberg2 create mode 100644 test/sql/test_transparent_mv/R/test_transparent_mv_olap_part1 create mode 100644 test/sql/test_transparent_mv/T/test_mv_with_multi_partition_columns_iceberg1 create mode 100644 test/sql/test_transparent_mv/T/test_mv_with_multi_partition_columns_iceberg2 create mode 100644 test/sql/test_transparent_mv/T/test_transparent_mv_olap_part1 create mode 100644 test/sql/test_udf/R/test_python_udf create mode 100644 test/sql/test_udf/T/test_python_udf create mode 100644 test/sql/test_vector_index/R/test_vector_index create mode 100644 test/sql/test_vector_index/T/test_vector_index create mode 100644 test/sql/test_window_function/R/test_window_pre_agg_with_rank create mode 100644 test/sql/test_window_function/T/test_window_pre_agg_with_rank create mode 100644 thirdparty/patches/avro-1.10.2.c.gcc14.patch create mode 100644 thirdparty/patches/breakpad-2022.07.12.patch create mode 100644 thirdparty/patches/clucene-gcc14.patch create mode 100644 thirdparty/patches/mariadb-connector-c-3.1.14-gcc14.patch create mode 100644 thirdparty/patches/poco-1.12.5-ca.patch create mode 100644 thirdparty/patches/poco-1.12.5-keep-alive.patch create mode 100644 thirdparty/patches/poco-1.12.5-zero-copy.patch create mode 100644 thirdparty/patches/rapidjson-gcc14.patch create mode 100644 thirdparty/patches/rocksdb-6.22.1-gcc14.patch create mode 100644 thirdparty/patches/rocksdb-6.22.1-metadata-header.patch create mode 100644 thirdparty/patches/sasl2-gcc14.patch create mode 100644 tools/benchmark/table_sample.sh diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5a8b569c2afce..f69e27e305b41 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,139 @@ # committer will be the owner of all codes * @StarRocks/starrocks-committer +<<<<<<< HEAD +======= +# cpp miscellaneous +/be/src/common/ @StarRocks/cpp-misc-maintainer +/be/src/gen_cpp/ @StarRocks/cpp-misc-maintainer +/be/src/gutil/ @StarRocks/cpp-misc-maintainer +/be/src/simd/ @StarRocks/cpp-misc-maintainer +/be/src/testutil/ @StarRocks/cpp-misc-maintainer +/be/src/util/ @StarRocks/cpp-misc-maintainer + +# execution engine +/be/src/column/ @StarRocks/execution-maintainer +/be/src/exec/ @StarRocks/execution-maintainer +/be/src/exprs/ @StarRocks/execution-maintainer +/be/src/runtime/ @StarRocks/execution-maintainer +/be/src/types/ @StarRocks/execution-maintainer +/be/src/udf/ @StarRocks/execution-maintainer + +# open formats +/be/src/formats/ @StarRocks/open-format-maintainer + +# storage engine +/be/src/fs/ @StarRocks/storage-maintainer +/be/src/io/ @StarRocks/storage-maintainer +/be/src/storage/ @StarRocks/storage-maintainer + +# /docs/ belong to docs-maintainer +/docs/ @StarRocks/docs-maintainer + +# /docker +/docker/ @StarRocks/docker-maintainer + +# metadata +/fe/fe-core/src/main/java/com/starrocks/authentication/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/privilege/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/common/util/concurrent/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/mysql/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/transaction/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/healthchecker/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/clone/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/consistency/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/ha/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/journal/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/leader/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/meta/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/persist/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/alter/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/backup/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/catalog/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/metric/ @StarRocks/metadata-maintainer +/fe/fe-core/src/main/java/com/starrocks/system/ @StarRocks/metadata-maintainer + +# connector +/fe/fe-core/src/main/java/com/starrocks/connector/ @StarRocks/connector-maintainer +/fe/fe-core/src/main/java/com/starrocks/credential/ @StarRocks/connector-maintainer + +# parser +/fe/fe-core/src/main/java/com/starrocks/sql/ast/ @StarRocks/parser +/fe/fe-core/src/main/java/com/starrocks/sql/parser/ @StarRocks/parser + +# analyzer +/fe/fe-core/src/main/java/com/starrocks/sql/analyzer/ @StarRocks/analyzer +/fe/fe-core/src/main/java/com/starrocks/analysis/ @StarRocks/analyzer + +# optimizer +/fe/fe-core/src/main/java/com/starrocks/sql/optimizer/ @StarRocks/optimizer +/fe/fe-core/src/main/java/com/starrocks/statistic/ @StarRocks/optimizer + +# scheduler +/fe/fe-core/src/main/java/com/starrocks/qe/scheduler/ @StarRocks/scheduler-maintainer + +# sql/parser/StarRocksLex.g4 sql/parser/StarRocks.g4 belong to syntax-committer +/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocksLex.g4 @StarRocks/syntax-committer +/fe/fe-core/src/main/java/com/starrocks/sql/parser/StarRocks.g4 @StarRocks/syntax-committer +/gensrc/script/functions.py @StarRocks/syntax-committer + +# /thirdparty/ /docker/dockerfiles/dev-env/dev-env.Dockerfile belong to thirdparty-maintainer +/be/src/thirdparty/ @StarRocks/thirdparty-maintainer +/thirdparty/ @StarRocks/thirdparty-maintainer +/docker/dockerfiles/dev-env/dev-env.Dockerfile @StarRocks/thirdparty-maintainer + +# cloud native +/be/src/storage/lake/ @StarRocks/cloud-native-maintainer +/be/src/runtime/lake_tablets_channel.h @StarRocks/cloud-native-maintainer +/be/src/runtime/lake_tablets_channel.cpp @StarRocks/cloud-native-maintainer + +# error message +/fe/fe-core/src/main/java/com/starrocks/common/ErrorCode.java @StarRocks/msg-reviewer + +# StorageEngine/ExecEnv/GlobalEnv +/be/src/runtime/exec_env.h @StarRocks/thread-committer +/be/src/runtime/exec_env.cpp @StarRocks/thread-committer +/be/src/storage/olap_server.cpp @StarRocks/thread-committer +/be/src/storage/storage_engine.h @StarRocks/thread-committer +/be/src/storage/storage_engine.cpp @StarRocks/thread-committer +/be/src/service/starrocks_main.cpp @StarRocks/thread-committer +/be/src/service/service_be/starrocks_be.cpp @StarRocks/thread-committer + +# restful +/fe/fe-core/src/main/java/com/starrocks/http @StarRocks/restful-maintainer +/be/src/http @StarRocks/restful-maintainer + + +# load and unload +/fe/fe-core/src/main/java/com/starrocks/load/* @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/plan/StreamLoad* @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/plan/*Sink.java @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/sql/InsertPlanner.java @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/sql/LoadPlanner.java @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/backup/* @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/alter/Optimize* @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/alter/Compaction* @StarRocks/load-unload-maintainer +/fe/fe-core/src/main/java/com/starrocks/catalog/*Partition* @StarRocks/load-unload-maintainer + +/be/src/storage/* @StarRocks/load-unload-maintainer +/be/src/exec/tablet_sink* @StarRocks/load-unload-maintainer +/be/src/exec/csv_scanner.cpp @StarRocks/load-unload-maintainer +/be/src/exec/json_scanner.cpp @StarRocks/load-unload-maintainer +/be/src/exec/pipeline/olap_table_sink_operator.cpp @StarRocks/load-unload-maintainer +/be/src/formats/avro/* @StarRocks/load-unload-maintainer +/be/src/formats/csv/* @StarRocks/load-unload-maintainer +/be/src/formats/json/* @StarRocks/load-unload-maintainer +/be/src/http/action/compaction_action.cpp @StarRocks/load-unload-maintainer +/be/src/http/action/*stream_load.cpp @StarRocks/load-unload-maintainer +/be/src/http/action/restore* @StarRocks/load-unload-maintainer +/be/src/runtime/routine_load/* @StarRocks/load-unload-maintainer +/be/src/runtime/stream_load/* @StarRocks/load-unload-maintainer +/be/src/runtime/load* @StarRocks/load-unload-maintainer +/be/src/runtime/tablets_channel.cpp @StarRocks/load-unload-maintainer +/be/src/runtime/export_sink.cpp @StarRocks/load-unload-maintainer + +# meta upgrade/downgrade compatibility +/fe/fe-core/src/main/java/com/starrocks/persist/gson/GsonUtils.java @StarRocks/meta-compatibility-maintainer + + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e745b2c0d9b17..201ef30255edd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -36,8 +36,16 @@ If yes, please specify the type of change: ## Bugfix cherry-pick branch check: - [ ] I have checked the version labels which the pr will be auto-backported to the target branch +<<<<<<< HEAD - [ ] 3.3 - [ ] 3.2 - [ ] 3.1 - [ ] 3.0 - [ ] 2.5 +======= + - [ ] 3.4 + - [ ] 3.3 + - [ ] 3.2 + - [ ] 3.1 + - [ ] 3.0 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/.github/workflows/ci-comment-tools.yml b/.github/workflows/ci-comment-tools.yml index 2d50623b14f31..a2cb41055c920 100644 --- a/.github/workflows/ci-comment-tools.yml +++ b/.github/workflows/ci-comment-tools.yml @@ -22,3 +22,32 @@ jobs: - name: CLOSE run: | gh pr close ${PR_NUMBER} -R ${{ github.repository }} -c "PR was manually closed." +<<<<<<< HEAD +======= + + automerge: + name: AutoMerge PR + runs-on: ubuntu-latest + if: > + contains(github.event.issue.pull_request.html_url, 'pull') && + contains(github.event.comment.body, '@Mergify automerge') + + env: + PR_NUMBER: ${{ github.event.issue.number }} + + steps: + - name: BASE REF + id: get_base_ref + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + base_ref=$(gh pr view ${PR_NUMBER} -R ${{ github.repository }} --json baseRefName | jq -r '.baseRefName') + echo "base_ref=${base_ref}" >> $GITHUB_OUTPUT + + - name: AutoMerge + if: startsWith(steps.get_base_ref.outputs.base_ref, 'mergify/bp') + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + run: | + gh pr merge ${PR_NUMBER} -R ${{ github.repository }} -s --auto +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/.github/workflows/ci-merged-sonarcloud-fe.yml b/.github/workflows/ci-merged-sonarcloud-fe.yml index b9d837e56e331..9fb6dba1bac48 100644 --- a/.github/workflows/ci-merged-sonarcloud-fe.yml +++ b/.github/workflows/ci-merged-sonarcloud-fe.yml @@ -35,14 +35,22 @@ jobs: distribution: 'adopt' - name: Cache SonarCloud packages +<<<<<<< HEAD uses: actions/cache@v3 +======= + uses: actions/cache@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages +<<<<<<< HEAD uses: actions/cache@v3 +======= + uses: actions/cache@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: path: ~/.m2 key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/ci-merged.yml b/.github/workflows/ci-merged.yml index b1a112b954b8f..f6377f9232aae 100644 --- a/.github/workflows/ci-merged.yml +++ b/.github/workflows/ci-merged.yml @@ -23,6 +23,7 @@ jobs: github.repository == 'StarRocks/starrocks' && !contains(github.event.pull_request.title, 'cherry-pick') && !contains(github.event.pull_request.title, 'backport') && ( +<<<<<<< HEAD contains(github.event.pull_request.labels.*.name, '3.3') || contains(github.event.pull_request.labels.*.name, '3.2') || contains(github.event.pull_request.labels.*.name, '3.1') || @@ -34,6 +35,32 @@ jobs: - name: backport branch-3.3 if: contains(github.event.pull_request.labels.*.name, '3.3') uses: thollander/actions-comment-pull-request@v1 +======= + contains(github.event.pull_request.labels.*.name, '3.4') || + contains(github.event.pull_request.labels.*.name, '3.3') || + contains(github.event.pull_request.labels.*.name, '3.2') || + contains(github.event.pull_request.labels.*.name, '3.1') || + contains(github.event.pull_request.labels.*.name, '3.0') ) + env: + PR_NUMBER: ${{ github.event.number }} + steps: + - name: backport branch-3.4 + if: contains(github.event.pull_request.labels.*.name, '3.4') + uses: thollander/actions-comment-pull-request@v2 + with: + message: | + @Mergifyio backport branch-3.4 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions-ecosystem/action-remove-labels@v1 + if: contains(github.event.pull_request.labels.*.name, '3.4') + with: + labels: '3.4' + + - name: backport branch-3.3 + if: contains(github.event.pull_request.labels.*.name, '3.3') + uses: thollander/actions-comment-pull-request@v2 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: message: | @Mergifyio backport branch-3.3 @@ -46,7 +73,11 @@ jobs: - name: backport branch-3.2 if: contains(github.event.pull_request.labels.*.name, '3.2') +<<<<<<< HEAD uses: thollander/actions-comment-pull-request@v1 +======= + uses: thollander/actions-comment-pull-request@v2 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: message: | @Mergifyio backport branch-3.2 @@ -59,7 +90,11 @@ jobs: - name: backport branch-3.1 if: contains(github.event.pull_request.labels.*.name, '3.1') +<<<<<<< HEAD uses: thollander/actions-comment-pull-request@v1 +======= + uses: thollander/actions-comment-pull-request@v2 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: message: | @Mergifyio backport branch-3.1 @@ -72,7 +107,11 @@ jobs: - name: backport branch-3.0 if: contains(github.event.pull_request.labels.*.name, '3.0') +<<<<<<< HEAD uses: thollander/actions-comment-pull-request@v1 +======= + uses: thollander/actions-comment-pull-request@v2 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: message: | @Mergifyio backport branch-3.0 @@ -83,6 +122,7 @@ jobs: with: labels: '3.0' +<<<<<<< HEAD - name: backport branch-2.5 if: contains(github.event.pull_request.labels.*.name, '2.5') uses: thollander/actions-comment-pull-request@v1 @@ -96,6 +136,8 @@ jobs: with: labels: '2.5' +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) thirdparty-update-image: runs-on: [self-hosted, normal] name: Thirdparty Update Image diff --git a/.github/workflows/ci-pipeline-branch.yml b/.github/workflows/ci-pipeline-branch.yml index 1aee4ec95c184..5cf4fff6781ba 100644 --- a/.github/workflows/ci-pipeline-branch.yml +++ b/.github/workflows/ci-pipeline-branch.yml @@ -382,14 +382,22 @@ jobs: distribution: 'adopt' - name: Cache SonarCloud packages +<<<<<<< HEAD uses: actions/cache@v3 +======= + uses: actions/cache@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages +<<<<<<< HEAD uses: actions/cache@v3 +======= + uses: actions/cache@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: path: ~/.m2 key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -507,4 +515,8 @@ jobs: - name: Clean run: | +<<<<<<< HEAD rm -rf ${{ github.workspace }}/* +======= + rm -rf ${{ github.workspace }}/* +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index a1614a6a0dcaf..0f724c0b5d20c 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -90,7 +90,26 @@ jobs: thirdparty: - 'thirdparty/**' - 'docker/dockerfiles/dev-env/dev-env.Dockerfile' - +<<<<<<< HEAD + +======= + + - name: Prepare info + run: | + mkdir be-path-filter && cd be-path-filter + echo ${{ steps.path-filter.outputs.be }} > src_filter.txt + echo ${{ steps.path-filter.outputs.ut }} > test_filter.txt + echo ${{ steps.path-filter.outputs.thirdparty }} > thirdparty_filter.txt + + - name: Upload the BE Filter Info + uses: actions/upload-artifact@v4 + with: + name: be-path-filter + path: ./be-path-filter/ + retention-days: 3 + overwrite: true + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) clang-format: runs-on: [self-hosted, light] needs: be-checker @@ -140,7 +159,11 @@ jobs: thirdparty-update: runs-on: [self-hosted, normal] +<<<<<<< HEAD needs: [ be-checker, clang-format ] +======= + needs: [ clang-format ] +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) name: Thirdparty Update continue-on-error: true strategy: @@ -156,10 +179,32 @@ jobs: run: | rm -rf ${{ github.workspace }} mkdir -p ${{ github.workspace }} +<<<<<<< HEAD - name: Update Image (${{ matrix.linux }}) id: update-image if: needs.be-checker.outputs.thirdparty_filter == 'true' +======= + + - name: Download BE Path Filter Artifact + uses: dawidd6/action-download-artifact@v6 + with: + name: be-path-filter + path: be-path-filter + run_id: ${{ github.run_id }} + + - name: Parsing path-filter file + id: parsing-path-filter + run: | + cd be-path-filter/; ls; + echo "src_filter=`cat src_filter.txt`" >> $GITHUB_OUTPUT + echo "test_filter.txt=`cat test_filter.txt`" >> $GITHUB_OUTPUT + echo "thirdparty_filter=`cat thirdparty_filter.txt`" >> $GITHUB_OUTPUT + + - name: Update Image (${{ matrix.linux }}) + id: update-image + if: steps.parsing-path-filter.outputs.thirdparty_filter == 'true' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) env: linux_distro: ${{ matrix.linux }} run: | @@ -176,7 +221,11 @@ jobs: if-no-files-found: ignore - name: Clean ENV +<<<<<<< HEAD if: always() && needs.be-checker.outputs.thirdparty_filter == 'true' +======= + if: always() && steps.parsing-path-filter.outputs.thirdparty_filter == 'true' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | cd ci-tool && source lib/init.sh ./bin/elastic-cluster.sh --delete @@ -193,10 +242,15 @@ jobs: steps: - name: Check Result run: | +<<<<<<< HEAD if [[ "${{ needs.thirdparty-update.result }}" == 'failure' ]]; then echo "::error:: Thirdparty Update Error!" exit 1 fi +======= + rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull >/dev/null + ./scripts/check-thirdparty-result.sh +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Download Thirdparty Artifact uses: actions/download-artifact@v4 @@ -206,7 +260,10 @@ jobs: - name: Read Info id: info +<<<<<<< HEAD if: needs.thirdparty-update.result == 'success' +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | image_cache_id=$(cat "./outputs/THIRDPARTY-RESULT-centos7/image_cache.info" || echo "") echo "centos7_image_cache_id=${image_cache_id}" >> $GITHUB_OUTPUT @@ -221,6 +278,11 @@ jobs: env: PR_NUMBER: ${{ github.event.number }} BRANCH: ${{ github.base_ref }} +<<<<<<< HEAD +======= + IMAGE_CACHE_ID: ${{ needs.thirdparty-info.outputs.ubuntu_image_cache_id }} + LINUX_DISTRO: ubuntu +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: INIT ECI & RUN UT id: run_ut @@ -228,11 +290,19 @@ jobs: timeout-minutes: 90 run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh +<<<<<<< HEAD if [[ "${{ needs.thirdparty-info.outputs.centos7_image_cache_id }}" != '' ]]; then export image_cache_id=${{ needs.thirdparty-info.outputs.centos7_image_cache_id }} export image_tag=$BRANCH-$PR_NUMBER fi ./bin/elastic-ut.sh --pr ${PR_NUMBER} --module be --repository ${{ github.repository }} --with-gcov +======= + if [[ "${IMAGE_CACHE_ID}" != '' ]]; then + export image_cache_id=${IMAGE_CACHE_ID} + export image_tag=$BRANCH-$PR_NUMBER + fi + ./bin/elastic-ut.sh --pr ${PR_NUMBER} --module be --repository ${{ github.repository }} --linuxdistro ${LINUX_DISTRO} --with-gcov +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: clean ECI if: always() @@ -266,6 +336,11 @@ jobs: env: PR_NUMBER: ${{ github.event.number }} BRANCH: ${{ github.base_ref }} +<<<<<<< HEAD +======= + IMAGE_CACHE_ID: ${{ needs.thirdparty-info.outputs.ubuntu_image_cache_id }} + LINUX_DISTRO: ubuntu +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: clean run: | @@ -281,6 +356,7 @@ jobs: - name: UPDATE ECI & RUN Clang Tidy id: run_clang_tidy shell: bash +<<<<<<< HEAD timeout-minutes: 60 run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh @@ -289,6 +365,16 @@ jobs: export image_tag=$BRANCH-$PR_NUMBER fi ./bin/elastic-build.sh --pr ${PR_NUMBER} --repository ${{ github.repository }} --be --clang-tidy +======= + timeout-minutes: 90 + run: | + rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh + if [[ "${{ needs.be-checker.outputs.thirdparty_filter }}" == 'true' ]]; then + export image_cache_id=${IMAGE_CACHE_ID} + export image_tag=$BRANCH-$PR_NUMBER + fi + ./bin/elastic-build.sh --pr ${PR_NUMBER} --repository ${{ github.repository }} --linuxdistro ${LINUX_DISTRO} --be --clang-tidy +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: clean ECI if: always() @@ -312,6 +398,11 @@ jobs: src_filter: ${{ steps.path-filter.outputs.fe }} test_filter: ${{ steps.path-filter.outputs.ut }} java_filter: ${{ steps.path-filter.outputs.java }} +<<<<<<< HEAD +======= + extension_filter: ${{ steps.path-filter.outputs.extension }} + pom_filter: ${{ steps.path-filter.outputs.pom }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - uses: dorny/paths-filter@v3 id: path-filter @@ -327,6 +418,30 @@ jobs: - 'run-fe-ut.sh' java: - '**.java' +<<<<<<< HEAD +======= + extension: + - 'java-extensions/**' + pom: + - '**/pom.xml' + + - name: Prepare info + run: | + mkdir fe-path-filter && cd fe-path-filter + echo ${{ steps.path-filter.outputs.fe }} > src_filter.txt + echo ${{ steps.path-filter.outputs.ut }} > test_filter.txt + echo ${{ steps.path-filter.outputs.java }} > java_filter.txt + echo ${{ steps.path-filter.outputs.extension }} > extension_filter.txt + echo ${{ steps.path-filter.outputs.pom }} > pom_filter.txt + + - name: Upload the FE Filter Info + uses: actions/upload-artifact@v4 + with: + name: fe-path-filter + path: ./fe-path-filter/ + retention-days: 3 + overwrite: true +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) fe-codestyle-check: runs-on: ubuntu-latest @@ -335,6 +450,11 @@ jobs: name: FE Code Style Check env: PR_NUMBER: ${{ github.event.number }} +<<<<<<< HEAD +======= + outputs: + extension_filter: ${{ needs.fe-checker.outputs.extension_filter }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: clean run: | @@ -371,7 +491,11 @@ jobs: - name: Run java checkstyle if: needs.fe-checker.outputs.java_filter == 'true' +<<<<<<< HEAD uses: dbelyaev/action-checkstyle@v1.5.6 +======= + uses: dbelyaev/action-checkstyle@v1.15.0 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: workdir: "./fe" checkstyle_config: checkstyle.xml @@ -415,20 +539,32 @@ jobs: git merge --squash --no-edit ${BRANCH} || (echo "Merge conflict, please check." && exit -1); - name: Set up JDK 17 +<<<<<<< HEAD uses: actions/setup-java@v3 +======= + uses: actions/setup-java@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: java-version: 17 distribution: 'adopt' - name: Cache SonarCloud packages +<<<<<<< HEAD uses: actions/cache@v3 +======= + uses: actions/cache@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages +<<<<<<< HEAD uses: actions/cache@v3 +======= + uses: actions/cache@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: path: ~/.m2 key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -486,9 +622,17 @@ jobs: id: run_ut shell: bash timeout-minutes: 60 +<<<<<<< HEAD run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh ./bin/elastic-ut.sh --pr ${PR_NUMBER} --module fe --branch ${{steps.branch.outputs.branch}} --build Release --repository ${{ github.repository }} +======= + env: + EXTENSION: ${{ needs.fe-codestyle-check.outputs.extension_filter }} + run: | + rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh + ./bin/elastic-ut.sh --pr ${PR_NUMBER} --module fe --branch ${{steps.branch.outputs.branch}} --build Release --repository ${{ github.repository }} --linuxdistro ubuntu +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Clean ECI if: always() @@ -534,28 +678,111 @@ jobs: build: runs-on: [self-hosted, normal] +<<<<<<< HEAD needs: [be-checker, fe-checker, test-checker, clang-tidy, fe-ut, thirdparty-info] +======= + needs: [test-checker, be-ut, fe-ut, thirdparty-info] +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) name: BUILD env: PR_NUMBER: ${{ github.event.number }} BRANCH: ${{ github.base_ref }} +<<<<<<< HEAD +======= + IMAGE_CACHE_ID: ${{ needs.thirdparty-info.outputs.ubuntu_image_cache_id }} + LINUX_DISTRO: ubuntu + GH_TOKEN: ${{ github.token }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) outputs: build_output_tar: ${{ steps.run_build.outputs.OUTPUT_TAR }} base_version: ${{ steps.run_build.outputs.BASE_VERSION }} is_self_build: ${{ steps.run_build.outputs.is_self_build }} +<<<<<<< HEAD if: > always() && (needs.clang-tidy.result == 'success' && needs.fe-ut.result == 'success') || (needs.be-checker.outputs.src_filter != 'true' && needs.fe-checker.outputs.src_filter == 'true' && needs.fe-ut.result == 'success') || (needs.fe-checker.outputs.src_filter != 'true' && needs.be-checker.outputs.src_filter == 'true' && needs.clang-tidy.result == 'success') || (needs.be-checker.outputs.src_filter != 'true' && needs.fe-checker.outputs.src_filter != 'true' && needs.test-checker.outputs.output1 == 'true') +======= + build_nece: ${{ steps.check-necessity.outputs.BUILD_NECE }} + if: > + always() && needs.be-ut.result != 'failure' && needs.fe-ut.result != 'failure' && (needs.be-ut.result == 'success' || needs.fe-ut.result == 'success' || needs.test-checker.result == 'success') +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: CLEAN run: | rm -rf ${{ github.workspace }} && mkdir -p ${{ github.workspace }} +<<<<<<< HEAD + - name: BRANCH INFO + id: branch +======= + - name: check sync + id: check-sync + run: | + labels=`gh pr view ${PR_NUMBER} -R ${GITHUB_REPOSITORY} --json labels -q '.labels[].name'` + echo "${labels}" + if [[ "${labels}" =~ sync ]]; then + echo "IS_SYNC=true" >> $GITHUB_OUTPUT + fi + + - name: Download BE Path Filter Artifact + uses: dawidd6/action-download-artifact@v6 + if: steps.check-sync.outputs.IS_SYNC != 'true' + with: + name: be-path-filter + path: be-path-filter + if_no_artifact_found: fail + run_id: ${{ github.run_id }} + + - name: Download FE Path Filter Artifact + uses: dawidd6/action-download-artifact@v6 + if: steps.check-sync.outputs.IS_SYNC != 'true' + with: + name: fe-path-filter + path: fe-path-filter + if_no_artifact_found: fail + run_id: ${{ github.run_id }} + + - name: Parsing BE path-filter file + id: parsing-be-path-filter + if: steps.check-sync.outputs.IS_SYNC != 'true' + run: | + if [[ -e be-path-filter ]]; then + cd be-path-filter/; ls; + echo "src_filter=`cat src_filter.txt`" >> $GITHUB_OUTPUT + echo "test_filter.txt=`cat test_filter.txt`" >> $GITHUB_OUTPUT + echo "thirdparty_filter=`cat thirdparty_filter.txt`" >> $GITHUB_OUTPUT + fi + + - name: Parsing FE path-filter file + id: parsing-fe-path-filter + if: steps.check-sync.outputs.IS_SYNC != 'true' + run: | + if [[ -e fe-path-filter ]]; then + cd fe-path-filter/; ls; + echo "src_filter=`cat src_filter.txt`" >> $GITHUB_OUTPUT + echo "test_filter.txt=`cat test_filter.txt`" >> $GITHUB_OUTPUT + echo "java_filter=`cat java_filter.txt`" >> $GITHUB_OUTPUT + echo "extension_filter=`cat extension_filter.txt`" >> $GITHUB_OUTPUT + echo "pom_filter=`cat pom_filter.txt`" >> $GITHUB_OUTPUT + fi + + - name: Check necessity + id: check-necessity + if: > + (needs.be-ut.result == 'success' && needs.fe-ut.result == 'success') || + (steps.parsing-be-path-filter.outputs.src_filter != 'true' && steps.parsing-fe-path-filter.outputs.src_filter == 'true' && needs.fe-ut.result == 'success') || + (steps.parsing-fe-path-filter.outputs.src_filter != 'true' && steps.parsing-be-path-filter.outputs.src_filter == 'true' && needs.be-ut.result == 'success') || + (steps.parsing-be-path-filter.outputs.src_filter != 'true' && steps.parsing-fe-path-filter.outputs.src_filter != 'true' && needs.test-checker.outputs.output1 == 'true') + run: | + echo "BUILD_NECE=true" >> $GITHUB_OUTPUT + - name: BRANCH INFO id: branch + if: steps.check-necessity.outcome == 'success' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | repo="${{ github.repository }}" bucket_prefix=`echo ${repo%/*} | tr '[:upper:]' '[:lower:]'` @@ -563,14 +790,25 @@ jobs: - name: Rebuild Checker id: rebuild-checker +<<<<<<< HEAD env: be_change: ${{ needs.be-checker.outputs.src_filter }} fe_change: ${{ needs.fe-checker.outputs.src_filter }} +======= + if: steps.check-necessity.outcome == 'success' + env: + be_change: ${{ steps.parsing-be-path-filter.outputs.src_filter }} + fe_change: ${{ steps.parsing-fe-path-filter.outputs.src_filter }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) build_type: Release run: | echo "package=${package}" >> "$GITHUB_ENV" if [[ "${be_change}" != "true" && "${fe_change}" != "true" ]]; then +<<<<<<< HEAD oss_path=oss://${bucket_prefix}-ci-release/${BRANCH}/${build_type}/inspection/pr/StarRocks- +======= + oss_path=oss://${bucket_prefix}-ci-release/${BRANCH}/${build_type}/inspection/pr/ubuntu/StarRocks- +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) package=$(ossutil64 --config-file ~/.ossutilconfig ls ${oss_path} | grep "tar.gz" | sort -n -r | head -n 1 | awk '{print $NF}') echo "package=${package}" >> $GITHUB_ENV fi @@ -579,17 +817,32 @@ jobs: id: run_build shell: bash timeout-minutes: 90 +<<<<<<< HEAD env: package: ${{ env.package }} run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh if [[ "${{ needs.be-checker.outputs.thirdparty_filter }}" == 'true' ]]; then export image_cache_id=${{ needs.thirdparty-info.outputs.centos7_image_cache_id }} +======= + if: steps.check-necessity.outcome == 'success' + env: + package: ${{ env.package }} + pom_filter: ${{ steps.parsing-fe-path-filter.outputs.pom_filter }} + run: | + rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh + if [[ "${{ steps.parsing-be-path-filter.outputs.thirdparty_filter }}" == 'true' ]]; then + export image_cache_id=${IMAGE_CACHE_ID} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) export image_tag=$BRANCH-$PR_NUMBER fi if [[ ${package} == "" ]]; then +<<<<<<< HEAD ./bin/elastic-build.sh --pr ${PR_NUMBER} --repository ${{ github.repository }} --with-gcov +======= + ./bin/elastic-build.sh --pr ${PR_NUMBER} --repository ${{ github.repository }} --linuxdistro ${LINUX_DISTRO} --with-gcov --with-trivy +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) echo "is_self_build=true" >> $GITHUB_OUTPUT else echo "Use latest tar: ${package}" @@ -600,12 +853,20 @@ jobs: fi - name: build result +<<<<<<< HEAD +======= + if: steps.check-necessity.outcome == 'success' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | echo ${{ steps.run_build.outputs.OUTPUT_TAR }} echo ${{ steps.run_build.outputs.BASE_VERSION }} > ./base_version.txt - name: Upload the Base Version uses: actions/upload-artifact@v4 +<<<<<<< HEAD +======= + if: steps.check-necessity.outcome == 'success' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: name: base_version path: ./base_version.txt @@ -627,11 +888,19 @@ jobs: deploy: runs-on: [self-hosted, normal] +<<<<<<< HEAD if: always() && needs.build.result == 'success' +======= + if: always() && needs.build.result == 'success' && needs.build.outputs.build_nece == 'true' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) needs: build name: DEPLOY SR env: PR_NUMBER: ${{ github.event.number }} +<<<<<<< HEAD +======= + LINUX_DISTRO: ubuntu +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) outputs: fe: ${{steps.deploy_sr.outputs.fe}} be: ${{steps.deploy_sr.outputs.be}} @@ -653,19 +922,26 @@ jobs: echo "cloud=true" >> "$GITHUB_OUTPUT" fi +<<<<<<< HEAD - name: BRANCH INFO id: branch run: | echo ${{github.base_ref}} echo "branch=${{github.base_ref}}" >> $GITHUB_OUTPUT +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Apply for resources id: apply_resource env: CLUSTER_NAME: ci-admit run: | cd ci-tool && source lib/init.sh +<<<<<<< HEAD ./bin/elastic-cluster.sh --template ${CLUSTER_NAME} +======= + ./bin/elastic-cluster.sh --template ${CLUSTER_NAME} --linuxdistro ${LINUX_DISTRO} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) cp conf/starrocks_deploy.conf /var/local/env/${PR_NUMBER}-starrocks_deploy.conf echo "deploy_conf_file=/var/local/env/${PR_NUMBER}-starrocks_deploy.conf" >> $GITHUB_OUTPUT @@ -679,7 +955,11 @@ jobs: if [[ "${{ needs.build.outputs.is_self_build }}" == 'true' ]]; then bucket_prefix=`echo ${repo%/*} | tr '[:upper:]' '[:lower:]'` +<<<<<<< HEAD tar_path="oss://${bucket_prefix}-ci-release/${{steps.branch.outputs.branch}}/Release/pr/${{needs.build.outputs.build_output_tar}}" +======= + tar_path="oss://${bucket_prefix}-ci-release/${{github.base_ref}}/Release/pr/${LINUX_DISTRO}/${{needs.build.outputs.build_output_tar}}" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) else tar_path="${{ needs.build.outputs.build_output_tar }}" fi @@ -752,8 +1032,14 @@ jobs: run: | branch=${{ steps.branch.outputs.branch }} bucket_prefix=${{ steps.branch.outputs.bucket_prefix }} +<<<<<<< HEAD ossutil64 --config-file ~/.ossutilconfig rm oss://${bucket_prefix}-ci-release/$branch/Release/pr/SQL-Tester-XML/${PR_NUMBER}/ -rf ossutil64 --config-file ~/.ossutilconfig cp test/ oss://${bucket_prefix}-ci-release/$branch/Release/pr/SQL-Tester-XML/${PR_NUMBER}/ --include "*.xml" --recursive --force --tagging="type=ci" +======= + xml_oss_path=oss://${bucket_prefix}-ci-release/$branch/Release/pr/SQL-Tester-XML/${PR_NUMBER}/ + ossutil64 --config-file ~/.ossutilconfig rm ${xml_oss_path} -rf + ossutil64 --config-file ~/.ossutilconfig cp test/ ${xml_oss_path} --include "*.xml" --recursive --force --tagging="type=ci" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Upload log uses: actions/upload-artifact@v4 @@ -868,8 +1154,14 @@ jobs: run: | branch=${{ steps.branch.outputs.branch }} bucket_prefix=${{ steps.branch.outputs.bucket_prefix }} +<<<<<<< HEAD ossutil64 --config-file ~/.ossutilconfig rm oss://${bucket_prefix}-ci-release/$branch/Release/pr/Admit-XML/${PR_NUMBER}/ -rf ossutil64 --config-file ~/.ossutilconfig cp StarRocksTest/result oss://${bucket_prefix}-ci-release/$branch/Release/pr/Admit-XML/${PR_NUMBER}/ --include "*.xml" --recursive --force --tagging="type=ci" +======= + xml_oss_path=oss://${bucket_prefix}-ci-release/$branch/Release/pr/Admit-XML/${PR_NUMBER}/ + ossutil64 --config-file ~/.ossutilconfig rm ${xml_oss_path} -rf + ossutil64 --config-file ~/.ossutilconfig cp StarRocksTest/result ${xml_oss_path} --include "*.xml" --recursive --force --tagging="type=ci" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Clean ENV if: always() @@ -885,6 +1177,10 @@ jobs: PR_NUMBER: ${{ github.event.number }} BRANCH: ${{ github.base_ref }} CONF_FILE: ${{ needs.deploy.outputs.deploy_conf_file }} +<<<<<<< HEAD +======= + linuxdistro: ubuntu +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: Upload info run: | @@ -920,4 +1216,8 @@ jobs: if: always() run: | rm -f $CONF_FILE - rm -rf ${{ github.workspace }}/* \ No newline at end of file +<<<<<<< HEAD + rm -rf ${{ github.workspace }}/* +======= + rm -rf ${{ github.workspace }}/* +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/.github/workflows/ci-report.yml b/.github/workflows/ci-report.yml index 50f2b53cc6070..684b18d8018df 100644 --- a/.github/workflows/ci-report.yml +++ b/.github/workflows/ci-report.yml @@ -23,6 +23,10 @@ permissions: env: HEAD_SHA: ${{ github.event.workflow_run.head_sha }} +<<<<<<< HEAD +======= + REPO: ${{ github.repository }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) jobs: INFO: @@ -34,10 +38,24 @@ jobs: PR_NUMBER: ${{ steps.pr_details.outputs.PR_NUMBER }} BASE_REF: ${{ steps.pr_details.outputs.BASE_REF }} PR_STATE: ${{ steps.pr_details.outputs.PR_STATE }} +<<<<<<< HEAD steps: - run: | sleep 10 +======= + BUCKET_PREFIX: ${{ steps.bucket_info.outputs.bucket_prefix }} + steps: + - run: | + sleep 10 + + - name: INFO + id: bucket_info + run: | + bucket_prefix=`echo ${REPO%/*} | tr '[:upper:]' '[:lower:]'` + echo "bucket_prefix=${bucket_prefix}" >> $GITHUB_OUTPUT + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Download workflow artifact - PR uses: dawidd6/action-download-artifact@v3 with: @@ -79,11 +97,16 @@ jobs: env: PR_NUMBER: ${{ needs.INFO.outputs.PR_NUMBER }} BASE_REF: ${{ needs.INFO.outputs.BASE_REF }} +<<<<<<< HEAD +======= + bucket_prefix: ${{ needs.INFO.outputs.BUCKET_PREFIX }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: CLEAN run: | rm -rf ${{ github.workspace }} && mkdir -p ${{ github.workspace }} +<<<<<<< HEAD - name: INFO id: info run: | @@ -95,6 +118,10 @@ jobs: id: download-ut-xml env: bucket_prefix: ${{ steps.info.outputs.bucket_prefix }} +======= + - name: Download FE UT XML + id: download-ut-xml +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | oss_path=oss://${bucket_prefix}-ci-release/$BASE_REF/Release/pr/UT-Report/${PR_NUMBER} size=$(ossutil64 --config-file ~/.ossutilconfig ls ${oss_path}/fe_ut_report.tar.gz | grep "Object Number is" | awk '{print $NF}') @@ -113,7 +140,11 @@ jobs: fi - name: Publish UT Report +<<<<<<< HEAD uses: mikepenz/action-junit-report@v3 +======= + uses: mikepenz/action-junit-report@v4 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) id: publish_report if: steps.download-ut-xml.outputs.size != '0' env: @@ -147,7 +178,10 @@ jobs: package_path: ${{ github.workspace }}/ci-tool/package fe_path: ${{ github.workspace }}/fe fe_core_path: ${{ github.workspace }}/fe/fe-core +<<<<<<< HEAD bucket_prefix: ${{ steps.info.outputs.bucket_prefix }} +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if: steps.merge_report.outcome == 'success' run: | rm -rf result @@ -215,25 +249,35 @@ jobs: REPO: ${{ github.repository }} PR_NUMBER: ${{ needs.INFO.outputs.PR_NUMBER }} BASE_REF: ${{ needs.INFO.outputs.BASE_REF }} +<<<<<<< HEAD +======= + bucket_prefix: ${{ needs.INFO.outputs.BUCKET_PREFIX }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: CLEAN run: | rm -rf ${{ github.workspace }} && mkdir -p ${{ github.workspace }} +<<<<<<< HEAD - name: INFO id: info run: | bucket_prefix=`echo ${REPO%/*} | tr '[:upper:]' '[:lower:]'` echo "bucket_prefix=${bucket_prefix}" >> $GITHUB_OUTPUT +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Download BE UT XML id: download-ut-xml +<<<<<<< HEAD env: bucket_prefix: ${{ steps.info.outputs.bucket_prefix }} +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | oss_path=oss://${bucket_prefix}-ci-release/$BASE_REF/Release/pr/UT-Report/${PR_NUMBER} be_ut_res_path=${oss_path}/flag/be_ut_res @@ -305,6 +349,77 @@ jobs: eci rm ${{ steps.merge.outputs.ECI_ID }} || true rm -rf ${{ steps.merge.outputs.COV_LOG }} ${{ steps.merge.outputs.COV_XML }} ${{ steps.merge.outputs.RES_FILE }} +<<<<<<< HEAD +======= + JAVA-EXTENSION-REPORT: + runs-on: [ self-hosted, quick ] + needs: INFO + if: needs.INFO.outputs.PR_NUMBER != '' && needs.INFO.outputs.PR_STATE != 'MERGED' + env: + PR_NUMBER: ${{ needs.INFO.outputs.PR_NUMBER }} + BASE_REF: ${{ needs.INFO.outputs.BASE_REF }} + bucket_prefix: ${{ needs.INFO.outputs.BUCKET_PREFIX }} + steps: + - name: CLEAN + run: | + rm -rf ${{ github.workspace }} && mkdir -p ${{ github.workspace }} + + - name: Download Java Extension UT XML + id: download-ut-xml + run: | + oss_path=oss://${bucket_prefix}-ci-release/$BASE_REF/Release/pr/UT-Report/${PR_NUMBER} + size=$(ossutil64 --config-file ~/.ossutilconfig ls ${oss_path}/java_extension_ut_report.tar.gz | grep "Object Number is" | awk '{print $NF}') + echo "size=${size}" >> $GITHUB_OUTPUT + if [[ "$size" != "0" ]]; then + mkdir java-extensions && cd java-extensions + ossutil64 --config-file ~/.ossutilconfig cp ${oss_path}/java_extension_ut_report.tar.gz . --recursive + tar zxf java_extension_ut_report.tar.gz + elif [[ "${BASE_REF}" == "main" ]]; then + rm -rf ./coverchecker && ln -s /var/local/env/coverchecker ./coverchecker && cd coverchecker && git pull + export JAVA_HOME=/var/local/env/jdk1.8.0_202; + export PATH=$JAVA_HOME/bin:$PATH; + java -jar cover-checker-console/target/cover-checker-console-1.4.0-jar-with-dependencies.jar \ + --cover /var/local/env/java_extension_empty_coverage --github-token ${{ secrets.GITHUB_TOKEN }} \ + --repo ${{ github.repository }} --threshold 80 --github-url api.github.com --pr ${PR_NUMBER} -type jacoco \ + --module "Java-Extensions" + fi + + - name: Publish UT Report + uses: mikepenz/action-junit-report@v4 + id: publish_report + if: steps.download-ut-xml.outputs.size != '0' + env: + github_token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} + with: + check_name: 'Java Extensions UT Report' + detailed_summary: true + fail_on_failure: true + commit: ${{ github.event.workflow_run.head_sha }} + report_paths: ./java-extensions/xml_dir/*.xml + + # Incremental Total Coverage + - name: Publish Incremental Coverage Report - Total + if: steps.publish_report.outcome == 'success' && env.BASE_REF == 'main' + env: + code_path: ${{ github.workspace }}/java-extensions + run: | + rm -rf ./coverchecker && ln -s /var/local/env/coverchecker ./coverchecker && cd coverchecker && git pull + export JAVA_HOME=/var/local/env/jdk1.8.0_202; + export PATH=$JAVA_HOME/bin:$PATH; + java -jar cover-checker-console/target/cover-checker-console-1.4.0-jar-with-dependencies.jar \ + --cover ${code_path}/result/ --github-token ${{ secrets.GITHUB_TOKEN }} \ + --repo ${{ github.repository }} --threshold 80 --github-url api.github.com --pr ${PR_NUMBER} -type jacoco \ + -d ${code_path}/diff.txt -dt file --module "Java-Extensions" + rm -rf coverchecker + rm -rf ci-tools + + - name: Clean ENV + if: always() + run: | + rm -rf ${{ github.workspace }}/* + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SQL-Tester-REPORT: runs-on: [ self-hosted, quick ] needs: INFO @@ -364,11 +479,16 @@ jobs: env: PR_NUMBER: ${{ needs.INFO.outputs.PR_NUMBER }} BASE_REF: ${{ needs.INFO.outputs.BASE_REF }} +<<<<<<< HEAD +======= + bucket_prefix: ${{ needs.INFO.outputs.bucket_prefix }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: CLEAN run: | rm -rf ${{ github.workspace }} && mkdir -p ${{ github.workspace }} +<<<<<<< HEAD - name: INFO id: info run: | @@ -380,6 +500,11 @@ jobs: id: download-admit-xml env: bucket_prefix: ${{ steps.info.outputs.bucket_prefix }} +======= + - name: Download Admit XML + id: download-admit-xml + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) run: | mkdir admit-result && cd admit-result oss_path=oss://${bucket_prefix}-ci-release/$BASE_REF/Release/pr/Admit-XML/${PR_NUMBER}/ @@ -410,7 +535,11 @@ jobs: NOTIFICATION: runs-on: [ self-hosted, quick ] +<<<<<<< HEAD needs: [ INFO, FE-REPORT, Admit-REPORT, BE-REPORT, SQL-Tester-REPORT ] +======= + needs: [ INFO, FE-REPORT, Admit-REPORT, BE-REPORT, SQL-Tester-REPORT, JAVA-EXTENSION-REPORT ] +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if: always() && needs.INFO.outputs.PR_NUMBER != '' && needs.INFO.outputs.PR_STATE != 'MERGED' env: WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} diff --git a/.github/workflows/ci-sync.yml b/.github/workflows/ci-sync.yml index a341ffc13f7f8..f035e08c79543 100644 --- a/.github/workflows/ci-sync.yml +++ b/.github/workflows/ci-sync.yml @@ -11,16 +11,25 @@ on: jobs: sync: +<<<<<<< HEAD runs-on: [self-hosted, quick] if: github.event.pull_request.merged == true && github.repository == 'StarRocks/starrocks' env: PR_NUMBER: ${{ github.event.number }} GH_TOKEN: ${{ secrets.PAT }} +======= + runs-on: [self-hosted, sync] + if: github.event.pull_request.merged == true && github.repository == 'StarRocks/starrocks' + env: + PR_NUMBER: ${{ github.event.number }} + GH_TOKEN: ${{ secrets.PAT2 }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) steps: - name: commit_sha id: commit_sha run: | set -x +<<<<<<< HEAD commit_sha=`curl -L \ -H "Accept: application/vnd.github+json" \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ @@ -31,6 +40,19 @@ jobs: echo "commit_sha=${commit_sha:0:7}" >> $GITHUB_OUTPUT - name: sync +======= + pr_info=$(gh pr view ${PR_NUMBER} -R ${{ github.repository }} --json mergeCommit,labels) + labels=`echo $pr_info | jq -r '.labels[].name'` + if [[ "${labels}" =~ sync ]]; then + echo "is_sync=true" >> $GITHUB_OUTPUT + else + commit_sha=`echo $pr_info | jq -r '.mergeCommit.oid'` + echo "commit_sha=${commit_sha:0:7}" >> $GITHUB_OUTPUT + fi + + - name: sync + if: steps.commit_sha.outputs.is_sync != 'true' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) env: PR_ID: ${{ github.event.number }} COMMIT_ID: ${{ steps.commit_sha.outputs.commit_sha }} diff --git a/.github/workflows/inspection-pipeline.yml b/.github/workflows/inspection-pipeline.yml index 7da3be359023d..4d4b4836df2ab 100644 --- a/.github/workflows/inspection-pipeline.yml +++ b/.github/workflows/inspection-pipeline.yml @@ -2,10 +2,18 @@ name: INSPECTION PIPELINE on: schedule: +<<<<<<< HEAD - cron: "30 0 * * 1-5" - cron: "30 4 * * 1-5" - cron: "30 9 * * 1-5" - cron: "0 11 * * 1-5" +======= + - cron: "0 0 * * 1-5" + - cron: "30 4 * * 1-5" + - cron: "30 9 * * 1-5" + - cron: "0 11 * * 1,3,5" + - cron: "0 11 * * 2,4" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) workflow_dispatch: inputs: BRANCH: @@ -16,12 +24,21 @@ on: description: 'COMMIT ID' required: true type: string +<<<<<<< HEAD TAR_PATH: description: 'TAR PATH(Release)' required: false type: string ASAN_TAR_PATH: description: 'TAR PATH(ASAN)' +======= + CENTOS_TAR_PATH: + description: 'TAR PATH(Release & Centos)' + required: false + type: string + CENTOS_ASAN_TAR_PATH: + description: 'TAR PATH(ASAN & Centos)' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) required: false type: string UBUNTU_TAR_PATH: @@ -40,6 +57,13 @@ on: description: 'RUN ADMIT?' type: string default: 'true' +<<<<<<< HEAD +======= + ALL_LINUX: + description: "ALL_LINUX? (⬜: Ubuntu && Release only)" + type: string + default: 'true' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETAIN_ENV: description: 'RETAIN THE ENVIRONMENT?' type: boolean @@ -72,10 +96,18 @@ jobs: outputs: BRANCH: ${{ steps.param.outputs.BRANCH }} PR_NUMBER: ${{ steps.param.outputs.PR_NUMBER }} +<<<<<<< HEAD TAR_PATH: ${{ steps.param.outputs.TAR_PATH }} ASAN_TAR_PATH: ${{ steps.param.outputs.ASAN_TAR_PATH }} UBUNTU_TAR_PATH: ${{ steps.param.outputs.UBUNTU_TAR_PATH }} UBUNTU_ASAN_TAR_PATH: ${{ steps.param.outputs.UBUNTU_ASAN_TAR_PATH }} +======= + CENTOS_TAR_PATH: ${{ steps.param.outputs.CENTOS_TAR_PATH }} + CENTOS_ASAN_TAR_PATH: ${{ steps.param.outputs.CENTOS_ASAN_TAR_PATH }} + UBUNTU_TAR_PATH: ${{ steps.param.outputs.UBUNTU_TAR_PATH }} + UBUNTU_ASAN_TAR_PATH: ${{ steps.param.outputs.UBUNTU_ASAN_TAR_PATH }} + BE_UT_LINUX: ${{ steps.param.outputs.BE_UT_LINUX }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETAIN_ENV: ${{ steps.param.outputs.RETAIN_ENV }} ALL_LINUX: ${{ steps.param.outputs.ALL_LINUX }} INCLUDE_ADMIT: ${{ steps.param.outputs.INCLUDE_ADMIT }} @@ -83,11 +115,25 @@ jobs: - name: CRON PARAM id: param run: | +<<<<<<< HEAD if [[ "${{ github.event_name }}" == "schedule" ]]; then if [[ "${{ github.event.schedule }}" == "0 11 * * 1-5" ]]; then branch=branch-3.2 [[ "$GITHUB_REPOSITORY" == 'StarRocks/starrocks' ]] && all_linux=true elif [[ "${{ github.event.schedule }}" == "30 0 * * 1-5" ]]; then +======= + BE_UT_LINUX=ubuntu + if [[ "${{ github.event_name }}" == "schedule" ]]; then + if [[ "${{ github.event.schedule }}" == "0 11 * * 1,3,5" ]]; then + branch=branch-3.4 + if [[ "$GITHUB_REPOSITORY" == 'StarRocks/starrocks' && `date +%u` -eq 1 ]]; then + all_linux=true + fi + elif [[ "${{ github.event.schedule }}" == "0 11 * * 2,4" ]]; then + branch=branch-3.3 + all_linux=false + elif [[ "${{ github.event.schedule }}" == "0 0 * * 1-5" ]]; then +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) branch=main if [[ `date +%u` -eq 1 || `date +%u` -eq 4 ]]; then all_linux=true @@ -95,7 +141,13 @@ jobs: else branch=main fi +<<<<<<< HEAD + base_sha=$(gh api /repos/${REPO}/branches/${branch} | jq -r .commit.sha) +======= + [[ $((`date +%e` % 2)) -eq 1 ]] && BE_UT_LINUX=centos7 base_sha=$(gh api /repos/${REPO}/branches/${branch} | jq -r .commit.sha) + echo "::notice::${branch}(${BE_UT_LINUX} ${base_sha})" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [[ "${base_sha}" == "null" ]] && (echo "::error::Get HEAD SHA error, please check." && exit -1); echo "BRANCH=${branch}" >> $GITHUB_OUTPUT echo "PR_NUMBER=${base_sha}" >> $GITHUB_OUTPUT @@ -104,6 +156,7 @@ jobs: else echo "BRANCH=${{ inputs.BRANCH }}" >> $GITHUB_OUTPUT echo "PR_NUMBER=${{ inputs.COMMIT_ID }}" >> $GITHUB_OUTPUT +<<<<<<< HEAD echo "TAR_PATH=${{ inputs.TAR_PATH }}" >> $GITHUB_OUTPUT echo "ASAN_TAR_PATH=${{ inputs.ASAN_TAR_PATH }}" >> $GITHUB_OUTPUT echo "UBUNTU_TAR_PATH=${{ inputs.UBUNTU_TAR_PATH }}" >> $GITHUB_OUTPUT @@ -112,6 +165,18 @@ jobs: echo "ALL_LINUX=true" >> $GITHUB_OUTPUT echo "INCLUDE_ADMIT=false" >> $GITHUB_OUTPUT fi +======= + echo "CENTOS_TAR_PATH=${{ inputs.CENTOS_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "CENTOS_ASAN_TAR_PATH=${{ inputs.CENTOS_ASAN_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "UBUNTU_TAR_PATH=${{ inputs.UBUNTU_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "UBUNTU_ASAN_TAR_PATH=${{ inputs.UBUNTU_ASAN_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "RETAIN_ENV=${{ inputs.RETAIN_ENV }}" >> $GITHUB_OUTPUT + echo "ALL_LINUX=${{ inputs.ALL_LINUX }}" >> $GITHUB_OUTPUT + echo "INCLUDE_ADMIT=false" >> $GITHUB_OUTPUT + fi + + echo "BE_UT_LINUX=${BE_UT_LINUX}" >> $GITHUB_OUTPUT +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) be-ut: runs-on: [self-hosted, normal] @@ -123,6 +188,10 @@ jobs: env: BRANCH: ${{ needs.info.outputs.BRANCH }} PR_NUMBER: ${{ needs.info.outputs.PR_NUMBER }} +<<<<<<< HEAD +======= + LINUX: ${{ needs.info.outputs.BE_UT_LINUX }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) strategy: fail-fast: false matrix: @@ -136,7 +205,11 @@ jobs: build_type: ${{ matrix.build_type }} run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh +<<<<<<< HEAD ./bin/elastic-ut.sh --repository ${{ github.repository }} --branch ${BRANCH} --pr ${PR_NUMBER} --module be --build ${build_type} +======= + ./bin/elastic-ut.sh --repository ${{ github.repository }} --branch ${BRANCH} --pr ${PR_NUMBER} --module be --build ${build_type} --linuxdistro ${LINUX} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: clean ECI if: always() @@ -200,7 +273,11 @@ jobs: timeout-minutes: 60 run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh +<<<<<<< HEAD ./bin/elastic-ut.sh --repository ${{ github.repository }} --branch ${BRANCH} --pr ${PR_NUMBER} --module fe --build Release +======= + ./bin/elastic-ut.sh --repository ${{ github.repository }} --branch ${BRANCH} --pr ${PR_NUMBER} --module fe --build Release --linuxdistro ubuntu +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: Clean ECI if: always() @@ -276,10 +353,18 @@ jobs: id: run_build shell: bash timeout-minutes: 90 +<<<<<<< HEAD if: (matrix.build_type == 'Release' && matrix.linux == 'centos7') || env.ALL_LINUX == 'true' run: | rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh ./bin/elastic-build.sh --repository ${{ github.repository }} --branch ${BRANCH} --pr ${PR_NUMBER} --build ${{ matrix.build_type }} --linuxdistro ${{ matrix.linux }} +======= + if: (matrix.build_type == 'Release' && matrix.linux == 'ubuntu') || env.ALL_LINUX == 'true' + run: | + rm -rf ./ci-tool && cp -rf /var/lib/ci-tool ./ci-tool && cd ci-tool && git pull && source lib/init.sh + ./bin/elastic-build.sh --repository ${{ github.repository }} --branch ${BRANCH} --pr ${PR_NUMBER} \ + --build ${{ matrix.build_type }} --linuxdistro ${{ matrix.linux }} --with-trivy +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: BUILD RESULT run: | @@ -317,8 +402,13 @@ jobs: env: ALL_LINUX: needs.info.outputs.ALL_LINUX outputs: +<<<<<<< HEAD RELEASE_TAR_PATH: ${{ steps.set_output.outputs.CENTOS_RELEASE_TAR_PATH }} ASAN_TAR_PATH: ${{ steps.set_output.outputs.CENTOS_ASAN_TAR_PATH }} +======= + CENTOS_RELEASE_TAR_PATH: ${{ steps.set_output.outputs.CENTOS_RELEASE_TAR_PATH }} + CENTOS_ASAN_TAR_PATH: ${{ steps.set_output.outputs.CENTOS_ASAN_TAR_PATH }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) UBUNTU_RELEASE_TAR_PATH: ${{ steps.set_output.outputs.UBUNTU_RELEASE_TAR_PATH }} UBUNTU_ASAN_TAR_PATH: ${{ steps.set_output.outputs.UBUNTU_ASAN_TAR_PATH }} IS_SELF_BUILD: ${{ steps.set_output.outputs.IS_SELF_BUILD }} @@ -374,8 +464,15 @@ jobs: if: always() run: | if [[ "${{steps.analyse_artifact.outcome}}" == "skipped" ]]; then +<<<<<<< HEAD echo "CENTOS_RELEASE_TAR_PATH=${{ needs.info.outputs.TAR_PATH }}" >> $GITHUB_OUTPUT echo "CENTOS_ASAN_TAR_PATH=${{ needs.info.outputs.ASAN_TAR_PATH }}" >> $GITHUB_OUTPUT +======= + echo "CENTOS_RELEASE_TAR_PATH=${{ needs.info.outputs.CENTOS_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "CENTOS_ASAN_TAR_PATH=${{ needs.info.outputs.CENTOS_ASAN_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "UBUNTU_RELEASE_TAR_PATH=${{ needs.info.outputs.UBUNTU_TAR_PATH }}" >> $GITHUB_OUTPUT + echo "UBUNTU_ASAN_TAR_PATH=${{ needs.info.outputs.UBUNTU_ASAN_TAR_PATH }}" >> $GITHUB_OUTPUT +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) echo "IS_SELF_BUILD=false" >> $GITHUB_OUTPUT else echo "CENTOS_RELEASE_TAR_PATH=${{ steps.analyse_artifact.outputs.CENTOS_RELEASE_TAR_PATH }}" >> $GITHUB_OUTPUT @@ -392,11 +489,19 @@ jobs: - info - test_filter secrets: inherit +<<<<<<< HEAD if: always() && needs.test_filter.outputs.RELEASE_TAR_PATH != '' with: BRANCH: ${{ needs.info.outputs.BRANCH }} COMMIT_ID: ${{ needs.info.outputs.PR_NUMBER }} TAR_PATH: ${{ needs.test_filter.outputs.RELEASE_TAR_PATH }} +======= + if: always() && needs.test_filter.outputs.CENTOS_RELEASE_TAR_PATH != '' && needs.info.outputs.ALL_LINUX == 'true' + with: + BRANCH: ${{ needs.info.outputs.BRANCH }} + COMMIT_ID: ${{ needs.info.outputs.PR_NUMBER }} + TAR_PATH: ${{ needs.test_filter.outputs.CENTOS_RELEASE_TAR_PATH }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) BUILD_TYPE: Release LINUX_DISTRO: centos7 IS_SELF_BUILD: ${{ needs.test_filter.outputs.IS_SELF_BUILD }} @@ -409,11 +514,19 @@ jobs: - info - test_filter secrets: inherit +<<<<<<< HEAD if: always() && needs.test_filter.outputs.ASAN_TAR_PATH != '' && needs.info.outputs.ALL_LINUX == 'true' with: BRANCH: ${{ needs.info.outputs.BRANCH }} COMMIT_ID: ${{ needs.info.outputs.PR_NUMBER }} TAR_PATH: ${{ needs.test_filter.outputs.ASAN_TAR_PATH }} +======= + if: always() && needs.test_filter.outputs.CENTOS_ASAN_TAR_PATH != '' && needs.info.outputs.ALL_LINUX == 'true' + with: + BRANCH: ${{ needs.info.outputs.BRANCH }} + COMMIT_ID: ${{ needs.info.outputs.PR_NUMBER }} + TAR_PATH: ${{ needs.test_filter.outputs.CENTOS_ASAN_TAR_PATH }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) BUILD_TYPE: ASAN LINUX_DISTRO: centos7 IS_SELF_BUILD: ${{ needs.test_filter.outputs.IS_SELF_BUILD }} @@ -426,7 +539,11 @@ jobs: - info - test_filter secrets: inherit +<<<<<<< HEAD if: always() && needs.test_filter.outputs.UBUNTU_RELEASE_TAR_PATH != '' && needs.info.outputs.ALL_LINUX == 'true' +======= + if: always() && needs.test_filter.outputs.UBUNTU_RELEASE_TAR_PATH != '' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) with: BRANCH: ${{ needs.info.outputs.BRANCH }} COMMIT_ID: ${{ needs.info.outputs.PR_NUMBER }} @@ -473,10 +590,21 @@ jobs: ASAN_CONF_FILE: ${{ needs.system-test-asan.outputs.CONF_FILE }} RELEASE_MYSQL_ECI_ID: ${{ needs.system-test-release.outputs.MYSQL_ECI_ID }} ASAN_MYSQL_ECI_ID: ${{ needs.system-test-asan.outputs.MYSQL_ECI_ID }} +<<<<<<< HEAD +======= + RELEASE_RESULT: ${{ needs.system-test-release.result }} + ASAN_RESULT: ${{ needs.system-test-asan.result }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) UBUNTU_RELEASE_CONF_FILE: ${{ needs.system-test-release-ubuntu.outputs.CONF_FILE }} UBUNTU_ASAN_CONF_FILE: ${{ needs.system-test-asan-ubuntu.outputs.CONF_FILE }} UBUNTU_RELEASE_MYSQL_ECI_ID: ${{ needs.system-test-release-ubuntu.outputs.MYSQL_ECI_ID }} UBUNTU_ASAN_MYSQL_ECI_ID: ${{ needs.system-test-asan-ubuntu.outputs.MYSQL_ECI_ID }} +<<<<<<< HEAD +======= + UBUNTU_RELEASE_RESULT: ${{ needs.system-test-release-ubuntu.result }} + UBUNTU_ASAN_RESULT: ${{ needs.system-test-asan-ubuntu.result }} + BE_UT_LINUX: ${{ needs.info.outputs.BE_UT_LINUX }} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETAIN_ENV: ${{ needs.info.outputs.RETAIN_ENV }} steps: - name: init diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index 87da3bb692a07..3d4548a279aa1 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -128,6 +128,15 @@ jobs: !contains(github.event.pull_request.title, 'cherry-pick') && !contains(github.event.pull_request.title, 'backport') steps: +<<<<<<< HEAD +======= + - name: add branch-3.4 label + if: contains(toJson(github.event.pull_request.body), '[x] 3.4') + uses: actions-ecosystem/action-add-labels@v1 + with: + labels: '3.4' + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: add branch-3.3 label if: contains(toJson(github.event.pull_request.body), '[x] 3.3') uses: actions-ecosystem/action-add-labels@v1 @@ -152,11 +161,19 @@ jobs: with: labels: '3.0' +<<<<<<< HEAD - name: add branch-2.5 label if: contains(toJson(github.event.pull_request.body), '[x] 2.5') uses: actions-ecosystem/action-add-labels@v1 with: labels: '2.5' +======= + - name: remove branch-3.4 label + if: contains(toJson(github.event.pull_request.body), '[ ] 3.4') && contains(github.event.pull_request.labels.*.name, '3.4') + uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: '3.4' +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: remove branch-3.3 label if: contains(toJson(github.event.pull_request.body), '[ ] 3.3') && contains(github.event.pull_request.labels.*.name, '3.3') @@ -182,12 +199,15 @@ jobs: with: labels: '3.0' +<<<<<<< HEAD - name: remove branch-2.5 label if: contains(toJson(github.event.pull_request.body), '[ ] 2.5') && contains(github.event.pull_request.labels.*.name, '2.5') uses: actions-ecosystem/action-remove-labels@v1 with: labels: '2.5' +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - name: check-done if: > (startsWith(github.event.pull_request.title, '[BugFix]') || diff --git a/.github/workflows/releasenotes404.yaml b/.github/workflows/releasenotes404.yaml new file mode 100644 index 0000000000000..ffa32d3f9ba0a --- /dev/null +++ b/.github/workflows/releasenotes404.yaml @@ -0,0 +1,32 @@ +name: Check releasenote links + +on: + workflow_dispatch: + schedule: + - cron: "00 42 * * SUN" + +jobs: + linkChecker: + runs-on: ubuntu-latest + permissions: + issues: write # required for peter-evans/create-issue-from-file + steps: + # Get this repo + - uses: actions/checkout@v4 + + - name: Link Checker + id: lychee + uses: lycheeverse/lychee-action@v2 + with: + args: > + --config lychee.toml + --exclude https://github.com/StarRocks/starrocks/.* + "docs/en/release_notes/*.md" "docs/zh/release_notes/*.md" + + - name: Create Issue From File + if: steps.lychee.outputs.exit_code != 0 + uses: peter-evans/create-issue-from-file@v5 + with: + title: Link Checker Report + content-filepath: ./lychee/out.md + labels: doc-feedback diff --git a/.gitignore b/.gitignore index 749a2ce168fa4..0a3a13f1f4ea1 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,10 @@ extension/spark-doris-connector/target contrib/trino-connector/target/ fe/log **/ut_ports +<<<<<<< HEAD +======= +venv/ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) custom_env.sh ut_dir log/ diff --git a/.trivyignore b/.trivyignore index 99b0370e53833..4c3f34da14d7d 100644 --- a/.trivyignore +++ b/.trivyignore @@ -6,3 +6,8 @@ CVE-2024-47554 CVE-2024-47561 # ingore nimbus-jose-jwt-9.31.jar CVE-2023-52428 +<<<<<<< HEAD +======= +# ingore io.netty:netty-common (netty-common-4.1.100.Final.jar) +CVE-2024-47535 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/README.md b/README.md index acc43b4ce2827..4bf49ddbbaf3b 100644 --- a/README.md +++ b/README.md @@ -29,15 +29,28 @@ Twitter +<<<<<<< HEAD +======= + + Gurubase + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714))

+<<<<<<< HEAD
StarRocks, a Linux Foundation project, is the next-generation data platform designed to make data-intensive real-time analytics fast and easy. It delivers query speeds 5 to 10 times faster than other popular solutions. StarRocks can perform real-time analytics well while updating historical records. It can also enhance real-time analytics with historical data from data lakes easily. With StarRocks, you can get rid of the de-normalized tables and get the best performance and flexibility.
Learn more 👉🏻 [Introduction to StarRocks](https://www.starrocks.io/blog/introduction_to_starrocks ) +======= + +StarRocks is the world's fastest open query engine for sub-second, ad-hoc analytics both on and off the data lakehouse. With average query performance 3x faster than other popular alternatives, StarRocks is a query engine that eliminates the need for denormalization and adapts to your use cases, without having to move your data or rewrite SQL. A Linux Foundation project.

+ +Learn more 👉🏻 [What Is StarRocks: Features and Use Cases](https://www.youtube.com/watch?v=RfXO5GOnbW4&ab_channel=CelerData) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714))

@@ -53,7 +66,11 @@ Learn more 👉🏻 [Introduction to StarRocks](https://www.starrocks.io/blog/in * **💡 Smart query optimization:** StarRocks can optimize complex queries through CBO (Cost Based Optimizer). With a better execution plan, the data analysis efficiency will be greatly improved. * **⚡ Real-time update:** The updated model of StarRocks can perform upsert/delete operations according to the primary key, and achieve efficient query while concurrent updates. * **🪟 Intelligent materialized view:** The materialized view of StarRocks can be automatically updated during the data import and automatically selected when the query is executed. +<<<<<<< HEAD * **✨ Querying data in data lakes directly**: StarRocks allows direct access to data from Apache Hive™, Apache Iceberg™, and Apache Hudi™ without importing. +======= +* **✨ Querying data in data lakes directly**: StarRocks allows direct access to data from Apache Hive™, Apache Iceberg™, Delta Lake™ and Apache Hudi™ without importing. +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) * **🎛️ Resource management**: This feature allows StarRocks to limit resource consumption for queries and implement isolation and efficient use of resources among tenants in the same cluster. * **💠 Easy to maintain**: Simple architecture makes StarRocks easy to deploy, maintain and scale out. StarRocks tunes its query plan agilely, balances the resources when the cluster is scaled in or out, and recovers the data replica under node failure automatically. @@ -74,7 +91,11 @@ StarRocks’s streamlined architecture is mainly composed of two modules: Fronte Starting from version 3.0, StarRocks supports a new shared-data architecture, which can provide better scalability and lower costs.

+<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714))

@@ -87,10 +108,17 @@ Starting from version 3.0, StarRocks supports a new shared-data architecture, wh | Section | Description | |-|-| +<<<<<<< HEAD | [Deploy](https://docs.starrocks.io/docs/deployment/deployment_overview/) | Learn how to run and configure StarRocks.| | [Articles](https://github.com/StarRocks/starrocks/discussions/categories/how-tos-tutorials-best-practices-and-architecture-articles)| How-tos, Tutorials, Best Practices and Architecture Articles. | | [Docs](https://docs.starrocks.io/en-us/latest/introduction/StarRocks_intro)| Full documentation. | | [Blogs](https://starrocks.io/blog) | StarRocks deep dive and user stories. | +======= +| [Quick Starts](https://docs.starrocks.io/docs/quick_start/)| How-tos and Tutorials. | +| [Deploy](https://docs.starrocks.io/docs/deployment/deployment_overview/) | Learn how to run and configure StarRocks.| +| [Docs](https://docs.starrocks.io/)| Full documentation. | +| [Blogs](https://www.starrocks.io/blog) | StarRocks deep dive and user stories. | +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ### ❓ Get support [](https://try.starrocks.com/join-starrocks-on-slack) @@ -116,6 +144,11 @@ We welcome all kinds of contributions from the community, individuals and partne **📝 License:** StarRocks is licensed under [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). **👥 Community Membership:** Learn more about different [contributor roles](community/membership.md) in StarRocks community. +<<<<<<< HEAD +======= + +**💬 Developer Group:** Please join our [Google Groups](https://groups.google.com/g/starrocks-dev) to discuss StarRocks features, project directions, issues, pull requests, or share suggestions. +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714))
@@ -124,7 +157,16 @@ We welcome all kinds of contributions from the community, individuals and partne This project is used by the following companies. Learn more about their use cases: - [Airbnb](https://www.youtube.com/watch?v=AzDxEZuMBwM&ab_channel=StarRocks_labs) +<<<<<<< HEAD - [Tencent](https://www.starrocks.io/blog/tencent-unifies-their-gaming-analytics-with-starrocks) - [Shopee](https://www.youtube.com/watch?v=FJf6tVFr-20) +======= +- [Pinterest](https://medium.com/pinterest-engineering/delivering-faster-analytics-at-pinterest-a639cdfad374) +- [Coinbase](https://www.youtube.com/watch?v=3Z9jSCaHnYg&list=PL0eWwaesODdhBhKSnvpfIEAB9sgk8rKmy) +- [Tencent(Games)](https://www.starrocks.io/blog/tencent-unifies-their-gaming-analytics-with-starrocks) +- [Tencent(LLM)](https://www.youtube.com/watch?v=WVHXFks9EQk) +- [Demandbase](https://starrocks.medium.com/demandbase-ditches-denormalization-by-switching-off-clickhouse-44195d795a83) +- [Shopee](https://celerdata.com/blog/how-shopee-3xed-their-query-performance-with-starrocks) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) - [Trip.com](https://starrocks.medium.com/trip-com-starrocks-efficiently-supports-high-concurrent-queries-dramatically-reduces-labor-and-1e1921dd6bf8) - [Didi](https://www.starrocks.io/blog/reduced-80-cost-didis-journey-from-multiple-olap-engines-to-starrocks) diff --git a/be/.gitignore b/be/.gitignore index 7debfaf7a2101..96f4061bb6edf 100644 --- a/be/.gitignore +++ b/be/.gitignore @@ -5,3 +5,7 @@ !src/ !test/ !CMakeLists.txt +<<<<<<< HEAD +======= +!extension/ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt index 5427269a119c6..e43cca057b483 100644 --- a/be/CMakeLists.txt +++ b/be/CMakeLists.txt @@ -82,8 +82,11 @@ option(WITH_GCOV "Build binary with gcov to get code coverage" OFF) option(WITH_COMPRESS "Build binary with compresss debug section" ON) +<<<<<<< HEAD option(WITH_CACHELIB "Build binary with cachelib library" OFF) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) option(WITH_STARCACHE "Build binary with starcache library" ON) option(WITH_BRCP_KEEPALIVE "Build binary with brpc_socket_keepalive (requires brpc 1.8)" OFF) @@ -93,17 +96,39 @@ option(USE_STAROS "Use StarOS to manager tablet info" OFF) option(USE_SSE4_2 "Build with SSE4.2 instruction" ON) +<<<<<<< HEAD +======= +option(USE_BMI_2 "Build with BMI2 instruction" ON) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) option(USE_AVX2 "Build with AVX2 instruction" ON) option(USE_AVX512 "Build with AVX512f/AVX512BW instruction" OFF) +<<<<<<< HEAD option(WITH_RELATIVE_SRC_PATH "Build source file with relative path" ON) +======= +option(WITH_TENANN "Build with TENANN" OFF) + +option(WITH_RELATIVE_SRC_PATH "Build source file with relative path" ON) + +# Only support tenann on x86 +if (${WITH_TENANN} STREQUAL "ON" AND NOT "${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "aarch64") + add_definitions(-DWITH_TENANN) +else() + set(WITH_TENANN "OFF") +endif() + +message(STATUS "WITH TENANN is: ${WITH_TENANN}") + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # Check gcc if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.2") message(FATAL_ERROR "Need GCC version at least 4.8.2") endif() +<<<<<<< HEAD if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "10.3.0") message(STATUS "GCC version ${CMAKE_CXX_COMPILER_VERSION} is greater than 10.3.0, disable -Werror. Be careful with compile warnings.") @@ -111,11 +136,14 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # -Werror: compile warnings should be errors when using the toolchain compiler. set(CXX_GCC_FLAGS "${CXX_GCC_FLAGS} -Werror") endif() +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") elseif (NOT APPLE) message(FATAL_ERROR "Compiler should be GNU") endif() +<<<<<<< HEAD set(PIC_LIB_PATH "${THIRDPARTY_DIR}") if(PIC_LIB_PATH) message(STATUS "defined PIC_LIB_PATH") @@ -134,6 +162,11 @@ else() set(LIBEVENT event) endif() +======= +set(CMAKE_SKIP_RPATH TRUE) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_STATIC_RUNTIME ON) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # Compile generated source if necessary message(STATUS "build gensrc if necessary") @@ -260,6 +293,13 @@ endforeach() find_package(AWSSDK REQUIRED COMPONENTS core s3 s3-crt transfer identity-management sts) include_directories(${AWSSDK_INCLUDE_DIRS}) +<<<<<<< HEAD +======= +set(Poco_ROOT_DIR ${THIRDPARTY_DIR}) +find_package(Poco REQUIRED COMPONENTS Net NetSSL) +include_directories(${Poco_INCLUDE_DIRS}) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_library(libevent STATIC IMPORTED) set_target_properties(libevent PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib/libevent.a) @@ -350,6 +390,15 @@ set_target_properties(fmt PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib64/l add_library(ryu STATIC IMPORTED) set_target_properties(ryu PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib64/libryu.a) +<<<<<<< HEAD +======= +add_library(libz STATIC IMPORTED GLOBAL) +set_target_properties(libz PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib/libz.a) + +add_library(libbz2 STATIC IMPORTED) +set_target_properties(libbz2 PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib/libbz2.a) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # Disable minidump on aarch64, hence breakpad is not needed. if ("${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86" OR "${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86_64") add_library(breakpad STATIC IMPORTED) @@ -394,12 +443,26 @@ set_target_properties(serdes PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib/ add_library(opentelemetry_exporter_jaeger_trace STATIC IMPORTED GLOBAL) set_target_properties(opentelemetry_exporter_jaeger_trace PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib64/libopentelemetry_exporter_jaeger_trace.a) +<<<<<<< HEAD +======= +set(absl_DIR "${THIRDPARTY_DIR}/lib/cmake/absl" CACHE PATH "absl search path" FORCE) +find_package(absl CONFIG REQUIRED) +set(gRPC_DIR "${THIRDPARTY_DIR}/lib/cmake/grpc" CACHE PATH "grpc search path") +find_package(gRPC CONFIG REQUIRED) +message(STATUS "Using gRPC ${gRPC_VERSION}") +get_target_property(gRPC_INCLUDE_DIR gRPC::grpc INTERFACE_INCLUDE_DIRECTORIES) +include_directories(SYSTEM ${gRPC_INCLUDE_DIR}) +add_library(protobuf::libprotobuf ALIAS protobuf) +add_library(ZLIB::ZLIB ALIAS libz) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # Disable libdefalte on aarch64 if ("${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86" OR "${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86_64") add_library(libdeflate STATIC IMPORTED GLOBAL) set_target_properties(libdeflate PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib64/libdeflate.a) endif() +<<<<<<< HEAD # cachelib set(CACHELIB_DEPENDENCIES cachelib_common @@ -437,6 +500,15 @@ if (${WITH_CACHELIB} STREQUAL "ON") set_target_properties(${dep} PROPERTIES IMPORTED_LOCATION "${location}") message(STATUS "add cachelib dependency: ${location}") endforeach() +======= +if (${WITH_TENANN} STREQUAL "ON") + add_library(tenann STATIC IMPORTED GLOBAL) + if(${USE_AVX2}) + set_target_properties(tenann PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib/libtenann-bundle-avx2.a) + else() + set_target_properties(tenann PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/lib/libtenann-bundle.a) + endif() +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) endif() if (${WITH_STARCACHE} STREQUAL "ON") @@ -462,15 +534,21 @@ if ("${USE_STAROS}" STREQUAL "ON") message(STATUS "Searching starlet related libraries from ${STARLET_INSTALL_DIR} ...") endif() +<<<<<<< HEAD # explicitly import ZLIB::ZLIB which is required by starlet thirdparty add_library(ZLIB::ZLIB STATIC IMPORTED) set_target_properties(ZLIB::ZLIB PROPERTIES IMPORTED_LOCATION ${LIBZ}) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # Tell cmake that PROTOBUF library is already found set(PROTOBUF_FOUND TRUE) # starrocks project has its imported libprotobuf.a and libre2.a # add following ALIAS so grpc can find the correct dependent libraries +<<<<<<< HEAD add_library(protobuf::libprotobuf ALIAS protobuf) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_library(re2::re2 ALIAS re2) add_library(glog::glog ALIAS glog) add_library(gflags::gflags_static ALIAS gflags) @@ -482,21 +560,27 @@ if ("${USE_STAROS}" STREQUAL "ON") add_library(starcache::starcache ALIAS starcache) add_library(Snappy::snappy ALIAS snappy) +<<<<<<< HEAD set(absl_DIR "${STARLET_INSTALL_DIR}/third_party/lib/cmake/absl" CACHE PATH "absl search path" FORCE) find_package(absl CONFIG REQUIRED) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # required by azure-* set(LIBXML2_INCLUDE_DIR "${STARLET_INSTALL_DIR}/third_party/include/libxml2" CACHE PATH "libxml2 include path") set(LIBXML2_LIBRARY "${STARLET_INSTALL_DIR}/third_party/lib/libxml2.a" CACHE FILEPATH "libxml2 static library") add_library(libxml2 STATIC IMPORTED GLOBAL) set_target_properties(libxml2 PROPERTIES IMPORTED_LOCATION ${LIBXML2_LIBRARY}) +<<<<<<< HEAD set(gRPC_DIR "${STARLET_INSTALL_DIR}/third_party/lib/cmake/grpc" CACHE PATH "grpc search path") find_package(gRPC CONFIG REQUIRED) message(STATUS "Using gRPC ${gRPC_VERSION}") get_target_property(gRPC_INCLUDE_DIR gRPC::grpc INTERFACE_INCLUDE_DIRECTORIES) include_directories(SYSTEM ${gRPC_INCLUDE_DIR}) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) set(prometheus-cpp_DIR "${STARLET_INSTALL_DIR}/third_party/lib/cmake/prometheus-cpp" CACHE PATH "prometheus cpp client search path") find_package (prometheus-cpp CONFIG REQUIRED) get_target_property(prometheus-cpp_INCLUDE_DIR prometheus-cpp::core INTERFACE_INCLUDE_DIRECTORIES) @@ -536,7 +620,10 @@ if ("${USE_STAROS}" STREQUAL "ON") endif() # LLVM +<<<<<<< HEAD # TODO(yueyang): Adjust libraries during the implementation of JIT. +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) set (LLVM_LIBRARIES LLVMRuntimeDyld LLVMBitstreamReader @@ -597,6 +684,10 @@ foreach(lib IN ITEMS ${LLVM_LIBRARIES}) set_target_properties(${lib} PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/llvm/lib/lib${lib}.a) endforeach() +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # Check Clang-Tidy include(cmake_modules/FindClangTidy.cmake) @@ -665,7 +756,19 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # ignore warning from apache-orc set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-unsafe-buffer-usage") endif () +<<<<<<< HEAD +else () +======= + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "18.0.0") + # ignore warning from apache-orc + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-switch-default") + endif () else () + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14.0.0") + # ignore error from apache-orc + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-error=dangling-reference") + endif () +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) set(CXX_GCC_FLAGS "${CXX_GCC_FLAGS} -fcoroutines") endif() @@ -675,9 +778,12 @@ set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Werror=return-type -Werror=switch") if (${USE_STAROS} STREQUAL "ON") set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -DUSE_STAROS") endif() +<<<<<<< HEAD if (${WITH_CACHELIB} STREQUAL "ON") set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -DWITH_CACHELIB") endif() +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (${WITH_STARCACHE} STREQUAL "ON") set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -DWITH_STARCACHE") endif() @@ -700,6 +806,12 @@ if ("${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86" OR "${CMAKE_BUILD_TARGET_ARCH}" # the compiler will define __AVX2__ set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -mavx2") endif() +<<<<<<< HEAD +======= + if (${USE_BMI_2}) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -mbmi2") + endif() +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (${USE_AVX512}) # the compiler will define __AVX512F__ __AVX512BW__ set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -mavx512f -mavx512bw") @@ -713,6 +825,14 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0) set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -faligned-new") endif() +<<<<<<< HEAD +======= +if (STARROCKS_JIT_ENABLE) + message(STATUS "Enable JIT") + set(CXX_GCC_FLAGS "${CXX_GCC_FLAGS} -DSTARROCKS_JIT_ENABLE") +endif() + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # For any gcc builds: # -g: Enable symbols for profiler tools # -Wno-unused-local-typedefs: Do not warn for local typedefs that are unused. @@ -738,6 +858,19 @@ if (ENABLE_FAULT_INJECTION) message(STATUS "enable fault injection") endif() +<<<<<<< HEAD +======= +option(ASSERT_STATUS_CHECKED "build with assert status checked" OFF) +if (ASSERT_STATUS_CHECKED) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -DSTARROCKS_ASSERT_STATUS_CHECKED") +endif() + +if (BUILD_FORMAT_LIB) + set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -fPIC -DBUILD_FORMAT_LIB") + message(STATUS "enable build format library") +endif() + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # For CMAKE_BUILD_TYPE=Debug # -ggdb: Enable gdb debugging # Debug information is stored as dwarf2 to be as compatible as possible @@ -858,11 +991,14 @@ set(STARROCKS_DEPENDENCIES ${STARROCKS_DEPENDENCIES} mysql ) +<<<<<<< HEAD set(STARROCKS_DEPENDENCIES ${STARROCKS_DEPENDENCIES} hdfs jvm ) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) set(JAVA_HOME ${THIRDPARTY_DIR}/open_jdk/) add_library(jvm SHARED IMPORTED) FILE(GLOB_RECURSE LIB_JVM ${JAVA_HOME}/jre/lib/*/libjvm.so) @@ -875,14 +1011,33 @@ set(STARROCKS_DEPENDENCIES ${STARROCKS_DEPENDENCIES} ) set_target_properties(aws-cpp-sdk-core PROPERTIES INTERFACE_LINK_LIBRARIES AWS::aws-crt-cpp) +<<<<<<< HEAD # Set thirdparty libraries set(STARROCKS_DEPENDENCIES ${STARROCKS_DEPENDENCIES} +======= +if (STARROCKS_JIT_ENABLE) + set(STARROCKS_DEPENDENCIES + ${STARROCKS_DEPENDENCIES} + ${WL_START_GROUP} + ${LLVM_LIBRARIES} + ${WL_END_GROUP} + ) +endif() + +# Set thirdparty libraries +set(STARROCKS_DEPENDENCIES + ${STARROCKS_DEPENDENCIES} + build_version +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ${WL_START_GROUP} clucene-core clucene-shared clucene-contribs-lib +<<<<<<< HEAD build_version +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) rocksdb libs2 snappy @@ -897,8 +1052,14 @@ set(STARROCKS_DEPENDENCIES lz4 libevent curl +<<<<<<< HEAD ${LIBZ} ${LIBBZ2} +======= + ${Poco_LIBRARIES} + libz + libbz2 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) gflags brpc protobuf @@ -913,6 +1074,13 @@ set(STARROCKS_DEPENDENCIES zstd streamvbyte arrow +<<<<<<< HEAD +======= + arrow_flight + arrow_flight_sql + gRPC::grpc + gRPC::grpc++ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) jemalloc # required by arrow parquet orc @@ -941,6 +1109,7 @@ set(STARROCKS_DEPENDENCIES avro serdes fiu +<<<<<<< HEAD ${LLVM_LIBRARIES} ${WL_END_GROUP} ) @@ -955,6 +1124,11 @@ if (${WITH_CACHELIB} STREQUAL "ON") ) endif() +======= + ${WL_END_GROUP} +) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (${WITH_STARCACHE} STREQUAL "ON") set(STARROCKS_DEPENDENCIES ${STARROCKS_DEPENDENCIES} @@ -973,6 +1147,7 @@ if ("${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86" OR "${CMAKE_BUILD_TARGET_ARCH}" ) endif() +<<<<<<< HEAD # Add all external dependencies. They should come after the starrocks libs. set(STARROCKS_LINK_LIBS ${STARROCKS_LINK_LIBS} ${STARROCKS_DEPENDENCIES}) @@ -997,11 +1172,58 @@ elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "UBSAN") set(BUILD_FOR_SANITIZE "ON") elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "TSAN") set(STARROCKS_LINK_LIBS ${STARROCKS_LINK_LIBS} -static-libtsan) +======= +if (${WITH_TENANN} STREQUAL "ON") + set(STARROCKS_DEPENDENCIES + ${STARROCKS_DEPENDENCIES} + tenann + ) +endif() + +# Add all external dependencies. They should come after the starrocks libs. + +set(STARROCKS_LINK_LIBS ${STARROCKS_LINK_LIBS} + ${STARROCKS_LINK_LIBS} + ${STARROCKS_DEPENDENCIES} + hdfs + jvm +) +set(BUILD_FOR_SANITIZE "OFF") + +# Add sanitize static link flags or jemalloc +if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG" OR "${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE") + message("use jemalloc") + set(STARROCKS_MEMORY_DEPENDENCIES_LIBS jemalloc) +elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "ASAN") + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(STARROCKS_MEMORY_DEPENDENCIES_LIBS -static-libsan) + else() + set(STARROCKS_MEMORY_DEPENDENCIES_LIBS -static-libasan) + endif() + set(BUILD_FOR_SANITIZE "ON") +elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "LSAN") + set(STARROCKS_MEMORY_DEPENDENCIES_LIBS -static-liblsan) + set(BUILD_FOR_SANITIZE "ON") +elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "UBSAN") + message("use jemalloc") + set(STARROCKS_MEMORY_DEPENDENCIES_LIBS -static-libubsan jemalloc) + set(BUILD_FOR_SANITIZE "ON") +elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "TSAN") + set(STARROCKS_MEMORY_DEPENDENCIES_LIBS -static-libtsan) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) set(BUILD_FOR_SANITIZE "ON") else() message(FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE}") endif() +<<<<<<< HEAD +======= +if (NOT BUILD_FORMAT_LIB) + # skip the STARROCKS_MEMORY_DEPENDENCIES_LIBS only when BUILD_FORMAT_LIB=ON + set(STARROCKS_LINK_LIBS ${STARROCKS_LINK_LIBS} ${STARROCKS_MEMORY_DEPENDENCIES_LIBS}) +endif() + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (NOT ("${MAKE_TEST}" STREQUAL "ON" AND "${BUILD_FOR_SANITIZE}" STREQUAL "ON")) # In other words, turn to dynamic link when MAKE_TEST and BUILD_TYPE == *SAN # otherwise do static link gcc's lib @@ -1029,8 +1251,23 @@ set (TEST_LINK_LIBS ${STARROCKS_LINK_LIBS} # Only build static libs set(BUILD_SHARED_LIBS OFF) +<<<<<<< HEAD if (NOT $ENV{STARROCKS_LINKER} STREQUAL "") add_link_options("-fuse-ld=$ENV{STARROCKS_LINKER}") +======= +set (STARROCKS_LINKER "$ENV{STARROCKS_LINKER}") +include(cmake_modules/FindGlibcVersion.cmake) + +if (GLIBC_VERSION VERSION_LESS "2.29" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14.0.0) + if (NOT DEFINED ${STARROCKS_LINKER} OR ${STARROCKS_LINKER} STREQUAL "") + set(STARROCKS_LINKER "gold") + endif() +endif() +message("using linker: ${STARROCKS_LINKER}") + +if (NOT STARROCKS_LINKER STREQUAL "") + add_link_options("-fuse-ld=${STARROCKS_LINKER}") +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) endif () if (${MAKE_TEST} STREQUAL "ON") @@ -1038,9 +1275,21 @@ if (${MAKE_TEST} STREQUAL "ON") add_definitions(-DBE_TEST) add_definitions(-DFIU_ENABLE) else() +<<<<<<< HEAD # output *.a, *.so, *.dylib to output/tmp set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR}/tmp/${CMAKE_BUILD_TYPE}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR}/tmp/${CMAKE_BUILD_TYPE}) +======= + if (BUILD_FORMAT_LIB) + # output *.a, *.so, *.dylib to output/format-lib-tmp + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR}/format-lib-tmp/${CMAKE_BUILD_TYPE}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR}/format-lib-tmp/${CMAKE_BUILD_TYPE}) + else() + # output *.a, *.so, *.dylib to output/tmp + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIR}/tmp/${CMAKE_BUILD_TYPE}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR}/tmp/${CMAKE_BUILD_TYPE}) + endif () +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) # output *.exe to output/lib set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR}/lib) endif () @@ -1074,7 +1323,11 @@ FUNCTION(ADD_BE_BENCH BENCH_NAME) find_package(benchmark REQUIRED) ADD_EXECUTABLE(${BENCH_FILE_NAME} ${BENCH_NAME}.cpp) +<<<<<<< HEAD TARGET_LINK_LIBRARIES(${BENCH_FILE_NAME} ${TEST_LINK_LIBS} benchmark benchmark_main) +======= + TARGET_LINK_LIBRARIES(${BENCH_FILE_NAME} benchmark benchmark_main ${TEST_LINK_LIBS}) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SET_TARGET_PROPERTIES(${BENCH_FILE_NAME} PROPERTIES COMPILE_FLAGS "-fno-access-control") SET_TARGET_PROPERTIES(${BENCH_FILE_NAME} PROPERTIES COMPILE_FLAGS ${CXX_FLAGS_RELEASE}) @@ -1110,8 +1363,18 @@ add_subdirectory(${SRC_DIR}/tools) add_subdirectory(${SRC_DIR}/util) add_subdirectory(${SRC_DIR}/script) +<<<<<<< HEAD if (WITH_BENCH STREQUAL "ON") message(STATUS "Build binary with bench") +======= +if (BUILD_FORMAT_LIB) + message(STATUS "Build starrocks format lib") + add_subdirectory(${SRC_DIR}/starrocks_format) +endif() + +if (WITH_BENCH STREQUAL "ON") + message(STATUS "Build binary with bench") +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_subdirectory(${SRC_DIR}/bench) endif() diff --git a/be/cmake_modules/FindClangTidy.cmake b/be/cmake_modules/FindClangTidy.cmake index 0189e46ee4d6b..dea3c7e7ea505 100644 --- a/be/cmake_modules/FindClangTidy.cmake +++ b/be/cmake_modules/FindClangTidy.cmake @@ -1,5 +1,6 @@ option(WITH_CLANG_TIDY "Use clang-tidy static analyzer" OFF) +<<<<<<< HEAD if (${WITH_CLANG_TIDY}) find_program (CLANG_TIDY_CACHE_BIN NAMES "clang-tidy-cache") find_program (CLANG_TIDY_BIN NAMES "clang-tidy-17" "clang-tidy-16" "clang-tidy-15" "clang-tidy-14" "clang-tidy-13" "clang-tidy") @@ -15,4 +16,25 @@ if (${WITH_CLANG_TIDY}) else () message (FATAL_ERROR "clang-tidy is not found") endif () +======= +if(${WITH_CLANG_TIDY}) + find_program(CLANG_TIDY_CACHE_BIN NAMES "clang-tidy-cache") + find_program( + CLANG_TIDY_BIN NAMES "clang-tidy-17" "clang-tidy-16" "clang-tidy-15" + "clang-tidy-14" "clang-tidy-13" "clang-tidy") + + if(CLANG_TIDY_CACHE_BIN) + set(CLANG_TIDY_PATH + "${CLANG_TIDY_CACHE_BIN};${CLANG_TIDY_BIN}" + CACHE STRING "Cache for clang-tidy") + else() + set(CLANG_TIDY_PATH "${CLANG_TIDY_BIN}") + endif() + + if(CLANG_TIDY_PATH) + message(STATUS "Find clang-tidy: ${CLANG_TIDY_PATH}.") + else() + message(FATAL_ERROR "clang-tidy is not found") + endif() +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) endif() diff --git a/be/cmake_modules/FindGlibcVersion.cmake b/be/cmake_modules/FindGlibcVersion.cmake new file mode 100644 index 0000000000000..82f3fc5ad3165 --- /dev/null +++ b/be/cmake_modules/FindGlibcVersion.cmake @@ -0,0 +1,25 @@ +# check glibc version, assign to GLIBC_VERSION + +set(CHECK_C_SOURCE_CODE + " +#include +#include +int main() { + const char* version = gnu_get_libc_version(); + printf(\"%s\\n\", version); + return 0; +} +") +file(WRITE ${CMAKE_BINARY_DIR}/check_c_source.c "${CHECK_C_SOURCE_CODE}") +execute_process( + COMMAND ${CMAKE_C_COMPILER} ${CMAKE_BINARY_DIR}/check_c_source.c -o + ${CMAKE_BINARY_DIR}/check_c_source RESULT_VARIABLE compile_result) +if(compile_result EQUAL 0) + execute_process( + COMMAND ${CMAKE_BINARY_DIR}/check_c_source + OUTPUT_VARIABLE GLIBC_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + message("GLIBC version: ${GLIBC_VERSION}") +else() + message(FATAL_ERROR "Failed to get the glibc version") +endif() diff --git a/be/extension/python-udf/src/flight_server.py b/be/extension/python-udf/src/flight_server.py new file mode 100644 index 0000000000000..9cc297090d3cd --- /dev/null +++ b/be/extension/python-udf/src/flight_server.py @@ -0,0 +1,155 @@ +# encoding: utf-8 + +# Copyright 2021-present StarRocks, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import pyarrow as pa +import pyarrow.flight as flight +import pyarrow +import sys +import time +import json +import base64 +import zipimport +import ast + +class CallStub(object): + def __init__(self, symbol, output_type, location, content): + self.symbol = symbol + self.output_type = output_type + self.location = location + self.content = content + self.exec_env = {} + self.eval_func = None + # extract function object + if location == "inline": + try: + exec(content, self.exec_env) + except Exception as e: + raise ValueError(f"Failed to evaluate UDF: {content} with error: {e}") + if self.symbol not in self.exec_env: + raise ValueError(f"Function {self.symbol} not found in UDF: {content}") + self.eval_func = self.exec_env[self.symbol] + else: + try: + module_with_symbol = self.symbol.split(".") + module = self.load_module(location, module_with_symbol[0]) + self.eval_func = getattr(module, module_with_symbol[1]) + except Exception as e: + raise ValueError(f"Failed to load UDF module: {location} symbol {symbol} with error: {e}") + + def cvt(self, py_list): + return pa.array(py_list, self.output_type) + + def get_imported_packages_ast(self, importer, module_name): + # acquire source + source = importer.get_source(module_name) + imported_packages = [] + if source is None: + return imported_packages + # parse source + tree = ast.parse(source) + for node in ast.walk(tree): + if isinstance(node, ast.Import): + for alias in node.names: + imported_packages.append(alias.name.split('.')[0]) + elif isinstance(node, ast.ImportFrom): + imported_packages.append(node.module.split('.')[0]) + return imported_packages + + def load_module(self, location, module_name): + importer = zipimport.zipimporter(location) + dependencies = self.get_imported_packages_ast(importer, module_name) + for dep in dependencies: + if importer.find_module(dep): + importer.load_module(dep) + module = importer.load_module(module_name) + return module + +class ScalarCallStub(CallStub): + """ + Python Scalar Call stub + """ + def __init__(self, symbol, output_type, location, content): + CallStub.__init__(self, symbol, output_type, location, content) + + def evaluate(self, batch: pa.RecordBatch) -> pa.Array: + num_rows = batch.num_rows + num_cols = len(batch.columns) + result_list = [] + for i in range(num_rows): + params = [batch.columns[j][i].as_py() for j in range(num_cols)] + res = self.eval_func(*params) + result_list.append(res) + # set result to output column + return self.cvt(result_list) + +class VectorizeArrowCallStub(CallStub): + """ + Python Vectorized Call stub + """ + def __init__(self, symbol, output_type, location, content): + CallStub.__init__(self, symbol, output_type, location, content) + + def evaluate(self, batch: pa.RecordBatch) -> pa.Array: + num_rows = batch.num_rows + num_cols = len(batch.columns) + result_list = [] + params = [batch.columns[j] for j in range(num_cols)] + res = self.eval_func(*params) + return res + +def get_call_stub(desc): + """ + Get call stub + """ + symbol = desc["symbol"] + location = desc["location"] + content = desc["content"] + input_type = desc["input_type"] + return_type_base64 = desc["return_type"] + binary_data = base64.b64decode(return_type_base64) + return_type = pa.ipc.read_schema(pa.BufferReader(binary_data)).field(0).type + if input_type == "scalar": + return ScalarCallStub(symbol, return_type, location, content) + elif input_type == "arrow": + return VectorizeArrowCallStub(symbol, return_type, location, content) + +class UDFFlightServer(flight.FlightServerBase): + def do_exchange(self, context, descriptor, reader, writer): + func_desc = json.loads(descriptor.command) + stub = get_call_stub(func_desc) + started = False + for chunk in reader: + if chunk.data: + result_column = stub.evaluate(chunk.data) + result_batch = pa.RecordBatch.from_arrays([result_column], ["result"]) + if not started: + writer.begin(result_batch.schema) + started = True + writer.write_batch(result_batch) + +def main(unix_socket_path): + location = unix_socket_path + server = UDFFlightServer(location) + print("Pywork start success") + sys.stdout.flush() + server.wait() + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Run an Arrow Flight echo server over Unix socket.") + parser.add_argument("unix_socket_path", type=str, help="The path to the Unix socket.") + args = parser.parse_args() + main(args.unix_socket_path) diff --git a/be/src/agent/agent_task.cpp b/be/src/agent/agent_task.cpp index 7b1d76730d310..2c1d178d3c860 100644 --- a/be/src/agent/agent_task.cpp +++ b/be/src/agent/agent_task.cpp @@ -41,6 +41,10 @@ #include "storage/task/engine_storage_migration_task.h" #include "storage/txn_manager.h" #include "storage/update_manager.h" +<<<<<<< HEAD +======= +#include "testutil/sync_point.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -226,10 +230,33 @@ void run_create_tablet_task(const std::shared_ptr& auto tablet_type = create_tablet_req.tablet_type; Status create_status; +<<<<<<< HEAD if (tablet_type == TTabletType::TABLET_TYPE_LAKE) { create_status = exec_env->lake_tablet_manager()->create_tablet(create_tablet_req); } else { create_status = StorageEngine::instance()->create_tablet(create_tablet_req); +======= + + if (create_tablet_req.__isset.timeout_ms && create_tablet_req.timeout_ms > 0) { + if (agent_task_req->isset.recv_time) { + int64_t current_time = time(nullptr); + TEST_SYNC_POINT_CALLBACK("AgentTask::run_create_tablet_task::time", ¤t_time); + int64_t elapsed_seconds = std::difftime(current_time, agent_task_req->recv_time); + if (elapsed_seconds * 1000 > create_tablet_req.timeout_ms) { + create_status = + Status::TimedOut(fmt::format("the task waits too long in the queue. " + "timeout: {} ms, elapsed: {} ms", + create_tablet_req.timeout_ms, elapsed_seconds * 1000)); + } + } + } + if (create_status.ok()) { + if (tablet_type == TTabletType::TABLET_TYPE_LAKE) { + create_status = exec_env->lake_tablet_manager()->create_tablet(create_tablet_req); + } else { + create_status = StorageEngine::instance()->create_tablet(create_tablet_req); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if (!create_status.ok()) { LOG(WARNING) << "create table failed. status: " << create_status.to_string() @@ -238,7 +265,11 @@ void run_create_tablet_task(const std::shared_ptr& if (tablet_type == TTabletType::TABLET_TYPE_LAKE) { error_msgs.emplace_back(create_status.to_string(false)); } else { +<<<<<<< HEAD error_msgs.emplace_back(fmt::format("create tablet {}", create_status.message())); +======= + error_msgs.emplace_back(fmt::format("create tablet failed. {}", create_status.message())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } else if (create_tablet_req.tablet_type != TTabletType::TABLET_TYPE_LAKE) { g_report_version.fetch_add(1, std::memory_order_relaxed); diff --git a/be/src/agent/finish_task.cpp b/be/src/agent/finish_task.cpp index 848300a01cdda..63c6dcd3923e3 100644 --- a/be/src/agent/finish_task.cpp +++ b/be/src/agent/finish_task.cpp @@ -18,6 +18,10 @@ #include "agent/utils.h" #include "common/logging.h" #include "runtime/exec_env.h" +<<<<<<< HEAD +======= +#include "testutil/sync_point.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/starrocks_metrics.h" namespace starrocks { @@ -26,13 +30,22 @@ const uint32_t TASK_FINISH_MAX_RETRY = 3; const uint32_t ALTER_FINISH_TASK_MAX_RETRY = 10; void finish_task(const TFinishTaskRequest& finish_task_request) { +<<<<<<< HEAD +======= + TEST_SYNC_POINT_CALLBACK("FinishAgentTask::input", + const_cast(static_cast(&finish_task_request))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Return result to FE TMasterResult result; uint32_t try_time = 0; int32_t sleep_seconds = 1; int32_t max_retry_times = TASK_FINISH_MAX_RETRY; +<<<<<<< HEAD MasterServerClient client(ExecEnv::GetInstance()->frontend_client_cache()); +======= + MasterServerClient client; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) while (try_time < max_retry_times) { StarRocksMetrics::instance()->finish_task_requests_total.increment(1); diff --git a/be/src/agent/heartbeat_server.cpp b/be/src/agent/heartbeat_server.cpp index 8f1a602d09544..f88ffdf19b581 100644 --- a/be/src/agent/heartbeat_server.cpp +++ b/be/src/agent/heartbeat_server.cpp @@ -83,8 +83,18 @@ void HeartbeatServer::heartbeat(THeartbeatResult& heartbeat_result, const TMaste << " BE/CN:" << config::enable_transparent_data_encryption; } +<<<<<<< HEAD // do heartbeat StatusOr res = compare_master_info(master_info); +======= + StatusOr res; + // reject master's heartbeat when exit + if (process_exit_in_progress()) { + res = Status::Shutdown("BE is shutting down"); + } else { + res = compare_master_info(master_info); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) res.status().to_thrift(&heartbeat_result.status); if (!res.ok()) { MasterInfoPtr ptr; @@ -128,6 +138,10 @@ void HeartbeatServer::heartbeat(THeartbeatResult& heartbeat_result, const TMaste heartbeat_result.backend_info.__set_http_port(config::be_http_port); heartbeat_result.backend_info.__set_be_rpc_port(-1); heartbeat_result.backend_info.__set_brpc_port(config::brpc_port); +<<<<<<< HEAD +======= + heartbeat_result.backend_info.__set_arrow_flight_port(config::arrow_flight_port); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #ifdef USE_STAROS heartbeat_result.backend_info.__set_starlet_port(config::starlet_port); if (StorageEngine::instance()->get_store_num() != 0) { @@ -163,11 +177,14 @@ StatusOr HeartbeatServer::compare_master_info(const static const char* LOCALHOST = "127.0.0.1"; static const char* LOCALHOST_IPV6 = "::1"; +<<<<<<< HEAD // reject master's heartbeat when exit if (process_exit_in_progress()) { return Status::InternalError("BE is shutting down"); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MasterInfoPtr curr_master_info; if (!get_master_info(&curr_master_info)) { return Status::InternalError("Fail to get local master info"); diff --git a/be/src/agent/publish_version.cpp b/be/src/agent/publish_version.cpp index 797317f33e64e..7804480e1dd16 100644 --- a/be/src/agent/publish_version.cpp +++ b/be/src/agent/publish_version.cpp @@ -109,6 +109,10 @@ void run_publish_version_task(ThreadPoolToken* token, const TPublishVersionReque task.tablet_id = itr.first.tablet_id; task.version = publish_version_req.partition_version_infos[i].version; task.rowset = std::move(itr.second); +<<<<<<< HEAD +======= + task.rowset->rowset_meta()->set_gtid(publish_version_req.gtid); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) task.is_double_write = publish_version_req.partition_version_infos[i].__isset.is_double_write && publish_version_req.partition_version_infos[i].is_double_write; } @@ -276,6 +280,7 @@ void run_publish_version_task(ThreadPoolToken* token, const TPublishVersionReque StorageEngine::instance()->replication_txn_manager()->clear_txn(transaction_id); }); } +<<<<<<< HEAD LOG(INFO) << "publish_version success. txn_id: " << transaction_id << " #partition:" << num_partition << " #tablet:" << tablet_tasks.size() << " time:" << publish_latency << "ms" << " #already_finished:" << total_tablet_cnt - num_active_tablet; @@ -284,6 +289,18 @@ void run_publish_version_task(ThreadPoolToken* token, const TPublishVersionReque LOG(WARNING) << "publish_version has error. txn_id: " << transaction_id << " #partition:" << num_partition << " #tablet:" << tablet_tasks.size() << " error_tablets(" << error_tablet_ids.size() << "):" << JoinInts(error_tablet_ids, ",") << " time:" << publish_latency << "ms" +======= + LOG(INFO) << "publish_version success. txn_id: " << transaction_id << " gtid: " << publish_version_req.gtid + << " #partition:" << num_partition << " #tablet:" << tablet_tasks.size() + << " time:" << publish_latency << "ms" + << " #already_finished:" << total_tablet_cnt - num_active_tablet; + } else { + StarRocksMetrics::instance()->publish_task_failed_total.increment(1); + LOG(WARNING) << "publish_version has error. txn_id: " << transaction_id << " gtid: " << publish_version_req.gtid + << " #partition:" << num_partition << " #tablet:" << tablet_tasks.size() << " error_tablets(" + << error_tablet_ids.size() << "):" << JoinInts(error_tablet_ids, ",") + << " time:" << publish_latency << "ms" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) << " #already_finished:" << total_tablet_cnt - num_active_tablet; } } diff --git a/be/src/agent/report_task.cpp b/be/src/agent/report_task.cpp index b608c193b1707..6925b87241b94 100644 --- a/be/src/agent/report_task.cpp +++ b/be/src/agent/report_task.cpp @@ -20,7 +20,11 @@ namespace starrocks { AgentStatus report_task(const TReportRequest& request, TMasterResult* result) { +<<<<<<< HEAD MasterServerClient client(ExecEnv::GetInstance()->frontend_client_cache()); +======= + MasterServerClient client; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return client.report(request, result); } diff --git a/be/src/agent/task_worker_pool.cpp b/be/src/agent/task_worker_pool.cpp index b8c4c2f7228d9..517daff6ea78f 100644 --- a/be/src/agent/task_worker_pool.cpp +++ b/be/src/agent/task_worker_pool.cpp @@ -846,7 +846,12 @@ void* ReportDataCacheMetricsTaskWorkerPool::_worker_thread_callback(void* arg_th LOG(WARNING) << "Fail to report resource_usage to " << master_address.hostname << ":" << master_address.port << ", err=" << status; } +<<<<<<< HEAD std::this_thread::sleep_for(std::chrono::milliseconds(config::report_datacache_metrics_interval_ms)); +======= + size_t sleep_secs = config::report_datacache_metrics_interval_ms / 1000; + nap_sleep(sleep_secs, [&]() { return worker_pool_this->_stopped.load(); }); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return nullptr; diff --git a/be/src/agent/utils.cpp b/be/src/agent/utils.cpp index 34471b605423e..4f2d46e1ca98a 100644 --- a/be/src/agent/utils.cpp +++ b/be/src/agent/utils.cpp @@ -38,11 +38,16 @@ #include "agent/master_info.h" #include "common/status.h" +<<<<<<< HEAD +======= +#include "util/thrift_rpc_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using std::map; using std::string; using std::stringstream; using std::vector; +<<<<<<< HEAD using apache::thrift::TException; using apache::thrift::transport::TTransportException; @@ -80,6 +85,23 @@ AgentStatus MasterServerClient::finish_task(const TFinishTaskRequest& request, T LOG(WARNING) << "Fail to finish_task. " << "host=" << network_address.hostname << ", port=" << network_address.port << ", error=" << e.what(); +======= + +namespace starrocks { + +AgentStatus MasterServerClient::finish_task(const TFinishTaskRequest& request, TMasterResult* result) { + Status client_status; + TNetworkAddress network_address = get_master_address(); + + client_status = ThriftRpcHelper::rpc( + network_address.hostname, network_address.port, + [&result, &request](FrontendServiceConnection& client) { client->finishTask(*result, request); }); + + if (!client_status.ok()) { + LOG(WARNING) << "Fail to finish_task. " + << "host=" << network_address.hostname << ", port=" << network_address.port + << ", error=" << client_status; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return STARROCKS_ERROR; } @@ -89,6 +111,7 @@ AgentStatus MasterServerClient::finish_task(const TFinishTaskRequest& request, T AgentStatus MasterServerClient::report(const TReportRequest& request, TMasterResult* result) { Status client_status; TNetworkAddress network_address = get_master_address(); +<<<<<<< HEAD FrontendServiceConnection client(_client_cache, network_address, config::thrift_rpc_timeout_ms, &client_status); if (!client_status.ok()) { @@ -126,6 +149,17 @@ AgentStatus MasterServerClient::report(const TReportRequest& request, TMasterRes LOG(WARNING) << "Fail to report to master. " << "host=" << network_address.hostname << ", port=" << network_address.port << ", code=" << client_status.code(); +======= + + client_status = ThriftRpcHelper::rpc( + network_address.hostname, network_address.port, + [&result, &request](FrontendServiceConnection& client) { client->report(*result, request); }); + + if (!client_status.ok()) { + LOG(WARNING) << "Fail to report to master. " + << "host=" << network_address.hostname << ", port=" << network_address.port + << ", error=" << client_status; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return STARROCKS_ERROR; } diff --git a/be/src/agent/utils.h b/be/src/agent/utils.h index 14340124b2511..51c12301412af 100644 --- a/be/src/agent/utils.h +++ b/be/src/agent/utils.h @@ -44,7 +44,11 @@ namespace starrocks { class MasterServerClient { public: +<<<<<<< HEAD explicit MasterServerClient(FrontendServiceClientCache* client_cache); +======= + explicit MasterServerClient() = default; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual ~MasterServerClient() = default; // Reprot finished task to the master server @@ -67,9 +71,12 @@ class MasterServerClient { MasterServerClient(const MasterServerClient&) = delete; const MasterServerClient& operator=(const MasterServerClient&) = delete; +<<<<<<< HEAD private: FrontendServiceClientCache* _client_cache; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/bench/CMakeLists.txt b/be/src/bench/CMakeLists.txt index ea461d683a44d..3e000eae165f5 100644 --- a/be/src/bench/CMakeLists.txt +++ b/be/src/bench/CMakeLists.txt @@ -25,3 +25,8 @@ ADD_BE_BENCH(${SRC_DIR}/bench/orc_column_reader_bench) ADD_BE_BENCH(${SRC_DIR}/bench/hash_functions_bench) ADD_BE_BENCH(${SRC_DIR}/bench/binary_column_copy_bench) ADD_BE_BENCH(${SRC_DIR}/bench/hyperscan_vec_bench) +<<<<<<< HEAD +======= +ADD_BE_BENCH(${SRC_DIR}/bench/mem_equal_bench) +ADD_BE_BENCH(${SRC_DIR}/bench/bit_unpack_bench) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/bench/bit_copy.h b/be/src/bench/bit_copy.h new file mode 100644 index 0000000000000..f8d81a37d6f13 --- /dev/null +++ b/be/src/bench/bit_copy.h @@ -0,0 +1,86 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +//// TODO, up to now, Bit Copy is only used in test and bench for preparing the +//// raw data, so we don't check the performance. +struct BitCopy { + // Returns at least 'numBits' bits of data starting at bit 'bitOffset' + // from 'source'. T must be at least 'numBits' wide. If 'numBits' bits + // from 'bitIffset' do not in T, loads the next byte to get the extra + // bits. + template + static inline T loadBits(const uint64_t* source, uint64_t bitOffset, uint8_t numBits) { + constexpr int32_t kBitSize = 8 * sizeof(T); + auto address = reinterpret_cast(source) + bitOffset / 8; + T word = *reinterpret_cast(address); + auto bit = bitOffset & 7; + if (!bit) { + return word; + } + if (numBits + bit <= kBitSize) { + return word >> bit; + } + uint8_t lastByte = reinterpret_cast(address)[sizeof(T)]; + uint64_t lastBits = static_cast(lastByte) << (kBitSize - bit); + return (word >> bit) | lastBits; + } + + // Stores the 'numBits' low bits of 'word' into bits starting at the + // 'bitOffset'th bit from target. T must be at least 'numBits' + // wide. If the bit field that is stored overflows a word of T, writes + // the trailing bits in the low bits of the next byte. Preserves all + // bits below and above the written bits. + template + static inline void storeBits(uint64_t* target, uint64_t offset, uint64_t word, uint8_t numBits) { + constexpr int32_t kBitSize = 8 * sizeof(T); + T* address = reinterpret_cast(reinterpret_cast(target) + (offset / 8)); + auto bitOffset = offset & 7; + uint64_t mask = (numBits == 64 ? ~0UL : ((1UL << numBits) - 1)) << bitOffset; + *address = (*address & ~mask) | (mask & (word << bitOffset)); + if (numBits + bitOffset > kBitSize) { + uint8_t* lastByteAddress = reinterpret_cast(address) + sizeof(T); + uint8_t lastByteBits = bitOffset + numBits - kBitSize; + uint8_t lastByteMask = (1 << lastByteBits) - 1; + *lastByteAddress = (*lastByteAddress & ~lastByteMask) | (lastByteMask & (word >> (kBitSize - bitOffset))); + } + } + + // Copies a string of bits between locations in memory given by an + // address and a bit offset for source and destination. + static inline void copyBits(const uint64_t* source, uint64_t sourceOffset, uint64_t* target, uint64_t targetOffset, + uint64_t numBits) { + uint64_t i = 0; + for (; i + 64 <= numBits; i += 64) { + uint64_t word = loadBits(source, i + sourceOffset, 64); + storeBits(target, targetOffset + i, word, 64); + } + if (i + 32 <= numBits) { + auto lastWord = loadBits(source, sourceOffset + i, 32); + storeBits(target, targetOffset + i, lastWord, 32); + i += 32; + } + if (i + 16 <= numBits) { + auto lastWord = loadBits(source, sourceOffset + i, 16); + storeBits(target, targetOffset + i, lastWord, 16); + i += 16; + } + for (; i < numBits; i += 8) { + auto copyBits = std::min(numBits - i, 8); + auto lastWord = loadBits(source, sourceOffset + i, copyBits); + storeBits(target, targetOffset + i, lastWord, copyBits); + } + } +}; diff --git a/be/src/bench/bit_unpack_bench.cpp b/be/src/bench/bit_unpack_bench.cpp new file mode 100644 index 0000000000000..1bd62951c4cce --- /dev/null +++ b/be/src/bench/bit_unpack_bench.cpp @@ -0,0 +1,350 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gutil/integral_types.h" +#include "util/bit_stream_utils.inline.h" +#ifdef __AVX2__ +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include "bench.h" +#include "bench/bit_copy.h" +#include "util/bit_packing.h" +#include "util/bit_packing_adapter.h" +#include "util/bit_packing_simd.h" + +namespace starrocks { + +class BitUnpackBench { +public: + BitUnpackBench() { SetUp(); } + ~BitUnpackBench() = default; + + static BitUnpackBench* get_instance() { + static BitUnpackBench bench; + return &bench; + } + +#define DO_BENCH_DECLARE(WIDTH) \ + void do_bench_##WIDTH##_default(int bit_width); \ + void do_bench_##WIDTH##_avx2(int bit_width); \ + void do_bench_##WIDTH##_bmi(int bit_width); + + DO_BENCH_DECLARE(32); + DO_BENCH_DECLARE(16); + DO_BENCH_DECLARE(8); + +private: + void SetUp(); + void populateBitPacked(); + + std::vector randomInts_u32; + // Array of bit packed representations of randomInts_u32. The array at index i + // is packed i bits wide and the values come from the low bits of + std::vector> bitPackedData; + + std::vector result32_; + std::vector result16_; + std::vector result8_; + + static const uint64_t kNumValues = 1024 * 1024 * 4; +}; + +void BitUnpackBench::populateBitPacked() { + bitPackedData.resize(33); + for (auto bitWidth = 1; bitWidth <= 32; ++bitWidth) { + auto numWords = (randomInts_u32.size() * bitWidth + 64 - 1) / 64; + bitPackedData[bitWidth].resize(numWords); + auto source = reinterpret_cast(randomInts_u32.data()); + auto destination = reinterpret_cast(bitPackedData[bitWidth].data()); + for (auto i = 0; i < randomInts_u32.size(); ++i) { + BitCopy::copyBits(source, i * 32, destination, i * bitWidth, bitWidth); + } + } +} + +void BitUnpackBench::SetUp() { + std::random_device rd; + std::mt19937 gen(rd()); + + std::uniform_int_distribution distr(0, std::numeric_limits::max()); + for (int32_t i = 0; i < kNumValues; i++) { + auto randomInt = distr(gen); + randomInts_u32.push_back(randomInt); + } + populateBitPacked(); + result32_.resize(kNumValues); + result16_.resize(kNumValues); + result8_.resize(kNumValues); +} + +#define DO_BENCH_DEFINE(WIDTH) \ + void BitUnpackBench::do_bench_##WIDTH##_default(int bit_width) { \ + auto source = bitPackedData[bit_width]; \ + starrocks::BitPacking::UnpackValues(bit_width, reinterpret_cast(source.data()), \ + source.size() * sizeof(uint64_t), kNumValues, result##WIDTH##_.data()); \ + } \ + \ + void BitUnpackBench::do_bench_##WIDTH##_avx2(int bit_width) { \ + auto source = bitPackedData[bit_width]; \ + starrocks::BitPackingAdapter::UnpackValues_ARROW(bit_width, reinterpret_cast(source.data()), \ + source.size() * sizeof(uint64_t), kNumValues, \ + result##WIDTH##_.data()); \ + } \ + \ + void BitUnpackBench::do_bench_##WIDTH##_bmi(int bit_width) { \ + auto source = bitPackedData[bit_width]; \ + starrocks::util::unpack(bit_width, reinterpret_cast(source.data()), \ + source.size() * sizeof(uint64_t), kNumValues, result##WIDTH##_.data()); \ + } + +DO_BENCH_DEFINE(32); +DO_BENCH_DEFINE(16); +DO_BENCH_DEFINE(8); + +#define BM_BENCH_DEFINE(WIDTH) \ + static void BM_##WIDTH##_DEFAULT(benchmark::State& state) { \ + int bit_width = state.range(0); \ + auto* instance = BitUnpackBench::get_instance(); \ + \ + for (auto _ : state) { \ + state.ResumeTiming(); \ + instance->do_bench_##WIDTH##_default(bit_width); \ + state.PauseTiming(); \ + } \ + } \ + \ + static void BM_##WIDTH##_AVX2(benchmark::State& state) { \ + int bit_width = state.range(0); \ + auto* instance = BitUnpackBench::get_instance(); \ + \ + for (auto _ : state) { \ + state.ResumeTiming(); \ + instance->do_bench_##WIDTH##_avx2(bit_width); \ + state.PauseTiming(); \ + } \ + } \ + \ + static void BM_##WIDTH##_BMI(benchmark::State& state) { \ + int bit_width = state.range(0); \ + auto* instance = BitUnpackBench::get_instance(); \ + \ + for (auto _ : state) { \ + state.ResumeTiming(); \ + instance->do_bench_##WIDTH##_bmi(bit_width); \ + state.PauseTiming(); \ + } \ + } + +BM_BENCH_DEFINE(32); +BM_BENCH_DEFINE(16); +BM_BENCH_DEFINE(8); + +BENCHMARK(BM_32_DEFAULT)->DenseRange(1, 32, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_32_AVX2)->DenseRange(1, 32, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_32_BMI)->DenseRange(1, 32, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_16_DEFAULT)->DenseRange(1, 16, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_16_AVX2)->DenseRange(1, 16, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_16_BMI)->DenseRange(1, 16, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_8_DEFAULT)->DenseRange(1, 8, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_8_AVX2)->DenseRange(1, 8, 1)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_8_BMI)->DenseRange(1, 8, 1)->Unit(benchmark::kMillisecond); + +} // namespace starrocks + +BENCHMARK_MAIN(); + +/* + * final conclusion: + * BMI is faster. + * +BM_32_DEFAULT/1 2.08 ms 2.08 ms 334 +BM_32_DEFAULT/2 2.13 ms 2.13 ms 327 +BM_32_DEFAULT/3 1.65 ms 1.65 ms 420 +BM_32_DEFAULT/4 2.24 ms 2.24 ms 305 +BM_32_DEFAULT/5 2.32 ms 2.32 ms 300 +BM_32_DEFAULT/6 2.89 ms 2.89 ms 241 +BM_32_DEFAULT/7 2.61 ms 2.61 ms 266 +BM_32_DEFAULT/8 2.68 ms 2.68 ms 258 +BM_32_DEFAULT/9 2.47 ms 2.47 ms 282 +BM_32_DEFAULT/10 2.55 ms 2.55 ms 274 +BM_32_DEFAULT/11 2.76 ms 2.76 ms 254 +BM_32_DEFAULT/12 3.17 ms 3.17 ms 225 +BM_32_DEFAULT/13 2.94 ms 2.94 ms 237 +BM_32_DEFAULT/14 3.02 ms 3.02 ms 229 +BM_32_DEFAULT/15 6.38 ms 6.38 ms 97 +BM_32_DEFAULT/16 7.58 ms 7.58 ms 84 +BM_32_DEFAULT/17 6.99 ms 6.99 ms 89 +BM_32_DEFAULT/18 7.38 ms 7.37 ms 86 +BM_32_DEFAULT/19 7.99 ms 7.99 ms 77 +BM_32_DEFAULT/20 8.38 ms 8.38 ms 76 +BM_32_DEFAULT/21 8.39 ms 8.39 ms 75 +BM_32_DEFAULT/22 8.87 ms 8.87 ms 72 +BM_32_DEFAULT/23 9.24 ms 9.23 ms 69 +BM_32_DEFAULT/24 9.94 ms 9.94 ms 64 +BM_32_DEFAULT/25 10.00 ms 10.00 ms 63 +BM_32_DEFAULT/26 10.4 ms 10.4 ms 62 +BM_32_DEFAULT/27 10.8 ms 10.8 ms 59 +BM_32_DEFAULT/28 11.3 ms 11.3 ms 57 +BM_32_DEFAULT/29 11.4 ms 11.4 ms 56 +BM_32_DEFAULT/30 11.9 ms 11.9 ms 54 +BM_32_DEFAULT/31 12.2 ms 12.2 ms 53 +BM_32_DEFAULT/32 12.2 ms 12.2 ms 53 +BM_32_AVX2/1 0.796 ms 0.796 ms 866 +BM_32_AVX2/2 0.900 ms 0.900 ms 767 +BM_32_AVX2/3 0.995 ms 0.995 ms 680 +BM_32_AVX2/4 1.05 ms 1.05 ms 658 +BM_32_AVX2/5 1.64 ms 1.64 ms 423 +BM_32_AVX2/6 1.63 ms 1.63 ms 423 +BM_32_AVX2/7 2.25 ms 2.25 ms 307 +BM_32_AVX2/8 1.47 ms 1.47 ms 467 +BM_32_AVX2/9 2.92 ms 2.92 ms 237 +BM_32_AVX2/10 3.03 ms 3.03 ms 228 +BM_32_AVX2/11 3.14 ms 3.14 ms 220 +BM_32_AVX2/12 3.28 ms 3.28 ms 211 +BM_32_AVX2/13 3.30 ms 3.30 ms 210 +BM_32_AVX2/14 3.38 ms 3.38 ms 206 +BM_32_AVX2/15 6.71 ms 6.70 ms 92 +BM_32_AVX2/16 5.95 ms 5.95 ms 106 +BM_32_AVX2/17 7.34 ms 7.34 ms 86 +BM_32_AVX2/18 7.71 ms 7.71 ms 82 +BM_32_AVX2/19 8.08 ms 8.08 ms 78 +BM_32_AVX2/20 8.34 ms 8.34 ms 76 +BM_32_AVX2/21 8.76 ms 8.76 ms 71 +BM_32_AVX2/22 9.16 ms 9.16 ms 69 +BM_32_AVX2/23 9.54 ms 9.54 ms 67 +BM_32_AVX2/24 9.67 ms 9.66 ms 66 +BM_32_AVX2/25 10.3 ms 10.3 ms 62 +BM_32_AVX2/26 10.7 ms 10.7 ms 60 +BM_32_AVX2/27 11.0 ms 11.0 ms 58 +BM_32_AVX2/28 11.3 ms 11.3 ms 57 +BM_32_AVX2/29 11.6 ms 11.6 ms 55 +BM_32_AVX2/30 12.2 ms 12.2 ms 54 +BM_32_AVX2/31 11.8 ms 11.8 ms 54 +BM_32_AVX2/32 12.1 ms 12.1 ms 52 +BM_32_BMI/1 0.761 ms 0.761 ms 900 +BM_32_BMI/2 0.864 ms 0.864 ms 799 +BM_32_BMI/3 0.960 ms 0.960 ms 719 +BM_32_BMI/4 1.05 ms 1.05 ms 652 +BM_32_BMI/5 1.14 ms 1.14 ms 600 +BM_32_BMI/6 1.25 ms 1.25 ms 544 +BM_32_BMI/7 1.34 ms 1.34 ms 503 +BM_32_BMI/8 1.46 ms 1.46 ms 477 +BM_32_BMI/9 1.64 ms 1.64 ms 427 +BM_32_BMI/10 1.76 ms 1.76 ms 397 +BM_32_BMI/11 1.86 ms 1.86 ms 372 +BM_32_BMI/12 2.00 ms 2.00 ms 343 +BM_32_BMI/13 2.11 ms 2.12 ms 328 +BM_32_BMI/14 2.23 ms 2.23 ms 310 +BM_32_BMI/15 5.62 ms 5.62 ms 109 +BM_32_BMI/16 5.95 ms 5.95 ms 106 +BM_32_BMI/17 6.53 ms 6.52 ms 97 +BM_32_BMI/18 6.88 ms 6.88 ms 92 +BM_32_BMI/19 7.24 ms 7.24 ms 87 +BM_32_BMI/20 7.61 ms 7.61 ms 84 +BM_32_BMI/21 8.01 ms 8.01 ms 79 +BM_32_BMI/22 8.41 ms 8.41 ms 75 +BM_32_BMI/23 8.81 ms 8.80 ms 72 +BM_32_BMI/24 9.19 ms 9.19 ms 69 +BM_32_BMI/25 9.62 ms 9.62 ms 67 +BM_32_BMI/26 9.98 ms 9.98 ms 63 +BM_32_BMI/27 10.5 ms 10.5 ms 61 +BM_32_BMI/28 10.9 ms 10.8 ms 59 +BM_32_BMI/29 11.1 ms 11.1 ms 58 +BM_32_BMI/30 11.5 ms 11.5 ms 55 +BM_32_BMI/31 12.0 ms 12.0 ms 54 +BM_32_BMI/32 12.7 ms 12.6 ms 50 +BM_16_DEFAULT/1 1.70 ms 1.70 ms 409 +BM_16_DEFAULT/2 1.82 ms 1.82 ms 382 +BM_16_DEFAULT/3 1.83 ms 1.83 ms 379 +BM_16_DEFAULT/4 2.05 ms 2.05 ms 336 +BM_16_DEFAULT/5 1.99 ms 1.99 ms 349 +BM_16_DEFAULT/6 2.80 ms 2.80 ms 248 +BM_16_DEFAULT/7 2.14 ms 2.14 ms 321 +BM_16_DEFAULT/8 2.54 ms 2.54 ms 275 +BM_16_DEFAULT/9 2.29 ms 2.29 ms 305 +BM_16_DEFAULT/10 2.36 ms 2.36 ms 296 +BM_16_DEFAULT/11 2.44 ms 2.44 ms 278 +BM_16_DEFAULT/12 2.53 ms 2.53 ms 275 +BM_16_DEFAULT/13 2.62 ms 2.62 ms 264 +BM_16_DEFAULT/14 2.72 ms 2.72 ms 255 +BM_16_DEFAULT/15 5.86 ms 5.85 ms 104 +BM_16_DEFAULT/16 6.68 ms 6.68 ms 94 +BM_16_AVX2/1 0.519 ms 0.519 ms 1333 +BM_16_AVX2/2 0.631 ms 0.631 ms 1087 +BM_16_AVX2/3 1.13 ms 1.13 ms 611 +BM_16_AVX2/4 0.813 ms 0.813 ms 831 +BM_16_AVX2/5 1.82 ms 1.82 ms 379 +BM_16_AVX2/6 1.80 ms 1.80 ms 382 +BM_16_AVX2/7 2.46 ms 2.46 ms 282 +BM_16_AVX2/8 1.24 ms 1.24 ms 554 +BM_16_AVX2/9 3.10 ms 3.10 ms 225 +BM_16_AVX2/10 3.22 ms 3.22 ms 216 +BM_16_AVX2/11 3.33 ms 3.33 ms 209 +BM_16_AVX2/12 3.46 ms 3.46 ms 202 +BM_16_AVX2/13 3.47 ms 3.47 ms 200 +BM_16_AVX2/14 3.56 ms 3.56 ms 194 +BM_16_AVX2/15 6.69 ms 6.69 ms 91 +BM_16_AVX2/16 5.55 ms 5.55 ms 113 +BM_16_BMI/1 0.424 ms 0.424 ms 1652 +BM_16_BMI/2 0.542 ms 0.542 ms 1268 +BM_16_BMI/3 0.630 ms 0.630 ms 1097 +BM_16_BMI/4 0.745 ms 0.745 ms 924 +BM_16_BMI/5 0.844 ms 0.844 ms 815 +BM_16_BMI/6 0.944 ms 0.944 ms 729 +BM_16_BMI/7 1.05 ms 1.05 ms 657 +BM_16_BMI/8 1.13 ms 1.14 ms 602 +BM_16_BMI/9 1.32 ms 1.32 ms 526 +BM_16_BMI/10 1.43 ms 1.43 ms 480 +BM_16_BMI/11 1.54 ms 1.54 ms 448 +BM_16_BMI/12 1.65 ms 1.65 ms 419 +BM_16_BMI/13 1.77 ms 1.77 ms 392 +BM_16_BMI/14 1.88 ms 1.88 ms 369 +BM_16_BMI/15 5.03 ms 5.03 ms 119 +BM_16_BMI/16 6.04 ms 6.04 ms 108 +BM_8_DEFAULT/1 1.66 ms 1.66 ms 421 +BM_8_DEFAULT/2 1.77 ms 1.77 ms 392 +BM_8_DEFAULT/3 2.07 ms 2.07 ms 335 +BM_8_DEFAULT/4 2.00 ms 2.00 ms 346 +BM_8_DEFAULT/5 2.23 ms 2.23 ms 314 +BM_8_DEFAULT/6 2.25 ms 2.25 ms 307 +BM_8_DEFAULT/7 2.35 ms 2.35 ms 295 +BM_8_DEFAULT/8 1.70 ms 1.70 ms 403 +BM_8_AVX2/1 0.526 ms 0.526 ms 1318 +BM_8_AVX2/2 0.614 ms 0.614 ms 1143 +BM_8_AVX2/3 1.18 ms 1.18 ms 594 +BM_8_AVX2/4 0.765 ms 0.765 ms 900 +BM_8_AVX2/5 1.90 ms 1.90 ms 368 +BM_8_AVX2/6 1.87 ms 1.87 ms 369 +BM_8_AVX2/7 2.50 ms 2.50 ms 276 +BM_8_AVX2/8 1.19 ms 1.19 ms 584 +BM_8_BMI/1 0.369 ms 0.369 ms 1891 +BM_8_BMI/2 0.453 ms 0.453 ms 1508 +BM_8_BMI/3 0.540 ms 0.540 ms 1278 +BM_8_BMI/4 0.642 ms 0.642 ms 1078 +BM_8_BMI/5 0.728 ms 0.728 ms 940 +BM_8_BMI/6 0.839 ms 0.840 ms 817 +BM_8_BMI/7 0.943 ms 0.943 ms 726 +BM_8_BMI/8 1.05 ms 1.05 ms 661 + * + */ diff --git a/be/src/bench/block_cache_bench.cpp b/be/src/bench/block_cache_bench.cpp index b69cbe269681d..0021a38b3ac20 100644 --- a/be/src/bench/block_cache_bench.cpp +++ b/be/src/bench/block_cache_bench.cpp @@ -32,9 +32,12 @@ #include "util/logging.h" #include "util/random.h" #include "util/time.h" +<<<<<<< HEAD #ifdef WITH_CACHELIB #include "block_cache/cachelib_wrapper.h" #endif +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -50,12 +53,18 @@ void delete_dir_content(const std::string& dir_path) { } } +<<<<<<< HEAD enum class CacheEngine { CACHELIB, STARCACHE }; class BlockCacheBenchSuite { public: struct BenchParams { CacheEngine cache_engine; +======= +class BlockCacheBenchSuite { +public: + struct BenchParams { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t obj_count = 0; size_t obj_key_size = 0; size_t obj_value_size = 0; @@ -115,6 +124,7 @@ class BlockCacheBenchSuite { BlockCacheBenchSuite(const CacheOptions& options, const BenchParams& params) { _params = new BlockCacheBenchSuite::BenchParams(params); +<<<<<<< HEAD if (params.cache_engine == CacheEngine::STARCACHE) { _cache = new StarCacheWrapper; #ifdef WITH_CACHELIB @@ -125,6 +135,9 @@ class BlockCacheBenchSuite { else { DCHECK(false) << "Unsupported cache engine: " << params.cache_engine; } +======= + _cache = new StarCacheWrapper; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status st = _cache->init(options); DCHECK(st.ok()) << st.message(); _ctx = new BenchContext(); @@ -284,6 +297,7 @@ static void do_bench_cache(benchmark::State& state, const CacheOptions& options, } template +<<<<<<< HEAD static void BM_bench_cachelib(benchmark::State& state, Args&&... args) { auto args_tuple = std::make_tuple(std::move(args)...); std::get<0>(args_tuple).second.cache_engine = CacheEngine::CACHELIB; @@ -294,6 +308,10 @@ template static void BM_bench_starcache(benchmark::State& state, Args&&... args) { auto args_tuple = std::make_tuple(std::move(args)...); std::get<0>(args_tuple).second.cache_engine = CacheEngine::STARCACHE; +======= +static void BM_bench_starcache(benchmark::State& state, Args&&... args) { + auto args_tuple = std::make_tuple(std::move(args)...); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) do_bench_cache(state, std::get<0>(args_tuple).first, std::get<0>(args_tuple).second); } @@ -391,6 +409,7 @@ BENCHMARK_CAPTURE(BM_bench_starcache, bench_read_write_remove_disk, read_write_r // Random offset for Read+Write+Remove Disk BENCHMARK_CAPTURE(BM_bench_starcache, bench_random_offset_read, random_offset_read_suite())->Threads(16); +<<<<<<< HEAD #ifdef WITH_CACHELIB BENCHMARK_CAPTURE(BM_bench_cachelib, bench_read_mem, read_mem_suite())->Threads(16); BENCHMARK_CAPTURE(BM_bench_cachelib, bench_read_disk, read_disk_suite())->Threads(16); @@ -398,6 +417,8 @@ BENCHMARK_CAPTURE(BM_bench_cachelib, bench_read_write_remove_disk, read_write_re BENCHMARK_CAPTURE(BM_bench_cachelib, bench_random_offset_read, random_offset_read_suite())->Threads(16); #endif +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks //BENCHMARK_MAIN(); diff --git a/be/src/bench/chunks_sorter_bench.cpp b/be/src/bench/chunks_sorter_bench.cpp index 1819e3540199e..f3a233399c48d 100644 --- a/be/src/bench/chunks_sorter_bench.cpp +++ b/be/src/bench/chunks_sorter_bench.cpp @@ -277,14 +277,22 @@ static void do_bench(benchmark::State& state, SortAlgorithm sorter_algo, Logical // TopN Sorter needs timing when updating iteration_data_size += ck->bytes_usage(); state.ResumeTiming(); +<<<<<<< HEAD sorter->update(runtime_state, ck); +======= + ASSERT_TRUE(sorter->update(runtime_state, ck).ok()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) state.PauseTiming(); mem_usage = std::max(mem_usage, sorter->mem_usage()); } data_size = std::max(data_size, iteration_data_size); state.ResumeTiming(); +<<<<<<< HEAD sorter->done(suite._runtime_state.get()); +======= + ASSERT_TRUE(sorter->done(suite._runtime_state.get()).ok()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) item_processed += total_rows; state.PauseTiming(); mem_usage = std::max(mem_usage, sorter->mem_usage()); @@ -293,13 +301,21 @@ static void do_bench(benchmark::State& state, SortAlgorithm sorter_algo, Logical size_t actual_rows = 0; while (!eos) { ChunkPtr page; +<<<<<<< HEAD sorter->get_next(&page, &eos); +======= + ASSERT_TRUE(sorter->get_next(&page, &eos).ok()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (eos) break; actual_rows += page->num_rows(); } ASSERT_TRUE(eos); ASSERT_EQ(expected_rows, actual_rows); +<<<<<<< HEAD sorter->done(suite._runtime_state.get()); +======= + ASSERT_TRUE(sorter->done(suite._runtime_state.get()).ok()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } state.counters["rows_sorted"] += item_processed; state.counters["data_size"] += data_size; @@ -438,7 +454,11 @@ static void do_merge_columnwise(benchmark::State& state, int num_runs, bool null } } SortedRuns merged; +<<<<<<< HEAD merge_sorted_chunks(sort_desc, &sort_exprs, inputs, &merged); +======= + ASSERT_TRUE(merge_sorted_chunks(sort_desc, &sort_exprs, inputs, &merged).ok()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ASSERT_EQ(input_rows, merged.num_rows()); num_rows += merged.num_rows(); diff --git a/be/src/bench/csv_reader_bench.cpp b/be/src/bench/csv_reader_bench.cpp index 0ca208b3e759c..8019fcdbd8856 100644 --- a/be/src/bench/csv_reader_bench.cpp +++ b/be/src/bench/csv_reader_bench.cpp @@ -25,6 +25,14 @@ class BenchCSVReader : public CSVReader { Status _fill_buffer() override; +<<<<<<< HEAD +======= + char* _find_line_delimiter(CSVBuffer& buffer, size_t pos) override { + // Intend no implementation just for compiling + return nullptr; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::shared_ptr _file; }; diff --git a/be/src/bench/get_dict_codes_bench.cpp b/be/src/bench/get_dict_codes_bench.cpp index 7e175000d035b..676d5793c2676 100644 --- a/be/src/bench/get_dict_codes_bench.cpp +++ b/be/src/bench/get_dict_codes_bench.cpp @@ -58,7 +58,11 @@ static void BM_GetDictCodesWithMap(benchmark::State& state) { std::uniform_int_distribution dist(0, 999); ColumnPtr column = ColumnHelper::create_column(TypeDescriptor{TYPE_VARCHAR}, true); +<<<<<<< HEAD column->append_strings_overflow(dict_values, kDictLength); +======= + (void)column->append_strings_overflow(dict_values, kDictLength); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) column->append_default(); for (int i = 0; i < kDictSize + 1; i++) { int random_number = dist(rng); diff --git a/be/src/bench/mem_equal_bench.cpp b/be/src/bench/mem_equal_bench.cpp new file mode 100644 index 0000000000000..956a0253a2ef4 --- /dev/null +++ b/be/src/bench/mem_equal_bench.cpp @@ -0,0 +1,145 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include +#include +#include +#include + +#include "column/column_hash.h" +#include "exprs/string_functions.h" +#include "util/memcmp.h" + +namespace starrocks { + +static std::string kAlphaNumber = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + +static size_t ROUND_NUM = 1000; + +static size_t PADDED_BYTES = 15; + +template +static void do_MemEqual(benchmark::State& state) { + std::random_device rd; + std::mt19937 rng(rd()); + std::uniform_int_distribution beginning_gen(0, 40); + std::uniform_int_distribution length_gen(1, 16); + + std::vector beginnings; + std::vector lengths; + + for (size_t i = 0; i < ROUND_NUM; i++) { + beginnings.emplace_back(beginning_gen(rng)); + lengths.emplace_back(length_gen(rng)); + } + + auto sum = std::accumulate(lengths.begin(), lengths.end(), 0); + std::vector buffer_0(sum + PADDED_BYTES); + std::vector buffer_1(sum + PADDED_BYTES); + + auto acc_begin = 0; + for (size_t i = 0; i < ROUND_NUM; i++) { + memcpy(buffer_0.data() + acc_begin, kAlphaNumber.data() + beginnings[i], lengths[i]); + memcpy(buffer_1.data() + acc_begin, kAlphaNumber.data() + beginnings[i], lengths[i]); + if constexpr (!equal) { + std::uniform_int_distribution index_gen(0, lengths[i] - 1); + auto index = index_gen(rng); + buffer_1[acc_begin + index] = 'z'; + } + beginnings[i] = acc_begin; + acc_begin += lengths[i]; + } + + for (auto _ : state) { + state.ResumeTiming(); + bool and_res = true; + bool or_res = false; + bool res = false; + for (size_t i = 0; i < ROUND_NUM; i++) { + if constexpr (padded) { + res = memequal_padded(buffer_0.data() + beginnings[i], lengths[i], buffer_1.data() + beginnings[i], + lengths[i]); + } else { + res = memequal(buffer_0.data() + beginnings[i], lengths[i], buffer_1.data() + beginnings[i], + lengths[i]); + } + and_res &= res; + or_res |= res; + } + state.PauseTiming(); + if constexpr (equal) { + ASSERT_TRUE(and_res); + } else { + ASSERT_FALSE(or_res); + } + } +} + +static void process_args(benchmark::internal::Benchmark* b) { + b->Iterations(100000); +} + +static void BM_memequal_padded_equal(benchmark::State& state) { + do_MemEqual(state); +} + +static void BM_memequal_padded_notequal(benchmark::State& state) { + do_MemEqual(state); +} + +static void BM_memequal_no_padded_equal(benchmark::State& state) { + do_MemEqual(state); +} + +static void BM_memequal_no_padded_notequal(benchmark::State& state) { + do_MemEqual(state); +} + +BENCHMARK(BM_memequal_padded_equal)->Apply(process_args); +BENCHMARK(BM_memequal_padded_notequal)->Apply(process_args); +BENCHMARK(BM_memequal_no_padded_equal)->Apply(process_args); +BENCHMARK(BM_memequal_no_padded_notequal)->Apply(process_args); + +/* +------------------------------------------------------------------------------------------- +Benchmark Time CPU Iterations +------------------------------------------------------------------------------------------- +BM_memequal_padded_equal/iterations:100000 1807 ns 1813 ns 100000 +BM_memequal_padded_notequal/iterations:100000 2547 ns 2552 ns 100000 +BM_memequal_no_padded_equal/iterations:100000 8560 ns 8575 ns 100000 +BM_memequal_no_padded_notequal/iterations:100000 8272 ns 8286 ns 100000 +*/ + +/* if we fix the string's length as 8, the result is as below, + * it makes sense that memequal_no_padded compare uint64 and + * memequal compare __m128i +------------------------------------------------------------------------------------------- +Benchmark Time CPU Iterations +------------------------------------------------------------------------------------------- +BM_memequal_padded_equal/iterations:100000 2456 ns 2463 ns 100000 +BM_memequal_padded_notequal/iterations:100000 2495 ns 2502 ns 100000 +BM_memequal_no_padded_equal/iterations:100000 2107 ns 2114 ns 100000 +BM_memequal_no_padded_notequal/iterations:100000 2110 ns 2117 ns 100000 + */ + +} // namespace starrocks + +BENCHMARK_MAIN(); \ No newline at end of file diff --git a/be/src/bench/orc_column_reader_bench.cpp b/be/src/bench/orc_column_reader_bench.cpp index ae51870d0732d..0e20a9fb50262 100644 --- a/be/src/bench/orc_column_reader_bench.cpp +++ b/be/src/bench/orc_column_reader_bench.cpp @@ -261,7 +261,11 @@ static void BM_primitive(benchmark::State& state) { size_t totalNumRows = 0; while (rr->next(*batch, &pos)) { ColumnPtr column = ColumnHelper::create_column(c0Type, isNullable); +<<<<<<< HEAD orcColumnReader->get_next(c0, column, 0, columnSize); +======= + CHECK(orcColumnReader->get_next(c0, column, 0, columnSize).ok()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(columnSize, column->size()); totalNumRows += columnSize; } @@ -354,4 +358,8 @@ BENCHMARK_TEMPLATE(BM_primitive, NON_NULLABLE, LogicalType::TYPE_DATETIME) } // namespace starrocks -BENCHMARK_MAIN(); \ No newline at end of file +<<<<<<< HEAD +BENCHMARK_MAIN(); +======= +BENCHMARK_MAIN(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/bench/parquet_dict_decode_bench.cpp b/be/src/bench/parquet_dict_decode_bench.cpp index e7aca5ad5063d..8f9a763651ad3 100644 --- a/be/src/bench/parquet_dict_decode_bench.cpp +++ b/be/src/bench/parquet_dict_decode_bench.cpp @@ -41,17 +41,30 @@ static void BM_DictDecoder(benchmark::State& state) { for (int i = 0; i < kDictSize; i++) { dict_values.emplace_back(Slice(kAlphaNumber.data() + i, kDictLength)); } +<<<<<<< HEAD encoder.append((const uint8_t*)dict_values.data(), kDictSize); +======= + (void)encoder.append((const uint8_t*)dict_values.data(), kDictSize); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Slice data = encoder.build(); // create decoder PlainDecoder decoder; +<<<<<<< HEAD decoder.set_data(data); dict_decoder.set_dict(kTestChunkSize, kDictSize, &decoder); if (debug) { ColumnPtr column = ColumnHelper::create_column(TypeDescriptor{TYPE_VARCHAR}, true); dict_decoder.get_dict_values(column.get()); +======= + (void)decoder.set_data(data); + (void)dict_decoder.set_dict(kTestChunkSize, kDictSize, &decoder); + + if (debug) { + ColumnPtr column = ColumnHelper::create_column(TypeDescriptor{TYPE_VARCHAR}, true); + (void)dict_decoder.get_dict_values(column.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::cout << column->debug_string() << "\n"; } } diff --git a/be/src/bench/persistent_index_bench.cpp b/be/src/bench/persistent_index_bench.cpp index 538b4fbb5bfd4..4938171f8d188 100644 --- a/be/src/bench/persistent_index_bench.cpp +++ b/be/src/bench/persistent_index_bench.cpp @@ -81,7 +81,11 @@ class PersistentIndexBenchTest { _index = std::make_unique(_index_dir); } +<<<<<<< HEAD ~PersistentIndexBenchTest() { fs::remove_all(_index_dir); } +======= + ~PersistentIndexBenchTest() { (void)fs::remove_all(_index_dir); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void do_bench(benchmark::State& state); void do_verify(); @@ -144,11 +148,19 @@ void PersistentIndexBenchTest::do_bench(benchmark::State& state) { ASSERT_CHECK(_index->commit(&_index_meta, &stat)); uint64_t tail = watch.elapsed_time(); ASSERT_CHECK(_index->on_commited()); +<<<<<<< HEAD +======= + /* `_index->get_write_amp_score` interface is removed +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (config::enable_pindex_minor_compaction) { if (_index->get_write_amp_score() > 0.0) { ASSERT_CHECK(_index->TEST_major_compaction(_index_meta)); } } +<<<<<<< HEAD +======= + */ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (stat.compaction_cost > 0) { LOG(INFO) << stat.print_str(); } @@ -193,4 +205,8 @@ BENCHMARK(bench_func)->Apply(process_args); } // namespace starrocks -BENCHMARK_MAIN(); \ No newline at end of file +<<<<<<< HEAD +BENCHMARK_MAIN(); +======= +BENCHMARK_MAIN(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/bench/runtime_filter_bench.cpp b/be/src/bench/runtime_filter_bench.cpp index 2f3e950eed754..825b4b4758dcf 100644 --- a/be/src/bench/runtime_filter_bench.cpp +++ b/be/src/bench/runtime_filter_bench.cpp @@ -77,7 +77,11 @@ static void do_benchmark_hash_partitioned(benchmark::State& state, TRuntimeFilte for (auto j = 0; j < num_rows; ++j) { auto ele = column->get(j).get_int32(); auto pp = hash_values[j] + (i * num_partitions); +<<<<<<< HEAD bfs[pp].insert(&ele); +======= + bfs[pp].insert(ele); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } for (auto p = 0; p < num_partitions; ++p) { @@ -89,10 +93,20 @@ static void do_benchmark_hash_partitioned(benchmark::State& state, TRuntimeFilte } // compute hash { +<<<<<<< HEAD int64_t t0 = MonotonicMillis(); auto& grf = gfs[0]; grf.set_join_mode(join_mode); grf.compute_hash(column_ptrs, &running_ctx); +======= + RuntimeFilterLayout layout; + layout.init(1, {}); + + int64_t t0 = MonotonicMillis(); + auto& grf = gfs[0]; + grf.set_join_mode(join_mode); + grf.compute_partition_index(layout, column_ptrs, &running_ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t t1 = MonotonicMillis(); state.counters["compute_hash_time(ms)"] = t1 - t0; // auto& ctx_hash_values = running_ctx.hash_values; diff --git a/be/src/bench/shuffle_chunk_bench.cpp b/be/src/bench/shuffle_chunk_bench.cpp index d27019b979cf1..5db06defdf039 100644 --- a/be/src/bench/shuffle_chunk_bench.cpp +++ b/be/src/bench/shuffle_chunk_bench.cpp @@ -16,6 +16,7 @@ #include #include +<<<<<<< HEAD #include "column/chunk.h" #include "column/column_helper.h" @@ -24,6 +25,16 @@ #include "runtime/chunk_cursor.h" #include "runtime/runtime_state.h" #include "runtime/types.h" +======= +#include + +#include "column/chunk.h" +#include "column/column_helper.h" +#include "column/vectorized_fwd.h" +#include "runtime/types.h" +#include "storage/chunk_helper.h" +#include "types/logical_type.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -196,6 +207,184 @@ static void bench_func(benchmark::State& state) { perf.do_bench(state); } +<<<<<<< HEAD +======= +// Benchmark SegmentedColumn::clone_selective && Chunk::append_selective function +class SegmentedChunkPerf { +public: + SegmentedChunkPerf() = default; + + void prepare_bench_segmented_chunk_clone(benchmark::State& state) { + // std::cerr << "chunk_size: " << _dest_chunk_size << std::endl; + // std::cerr << "segment_size: " << _segment_size << std::endl; + // std::cerr << "segmented_chunk_size: " << _segment_chunk_size << std::endl; + SegmentedChunkPtr seg_chunk = prepare_chunk(); + CHECK_EQ(seg_chunk->num_rows(), _segment_chunk_size); + + // random select + random_select(select, _dest_chunk_size, seg_chunk->num_rows()); + } + + void prepare_bench_chunk_clone(benchmark::State& state) { + ChunkPtr chunk = build_chunk(_segment_size); + CHECK_EQ(chunk->num_rows(), _segment_size); + random_select(select, _dest_chunk_size, chunk->num_rows()); + } + + void prepare(benchmark::State& state) { + state.PauseTiming(); + + _column_count = state.range(0); + _data_type = state.range(1); + _num_segments = state.range(2); + _types.clear(); + + prepare_bench_chunk_clone(state); + prepare_bench_segmented_chunk_clone(state); + + state.ResumeTiming(); + } + + void do_bench_segmented_chunk_clone(benchmark::State& state) { + SegmentedChunkPtr seg_chunk = prepare_chunk(); + // clone_selective + size_t items = 0; + for (auto _ : state) { + for (auto& column : seg_chunk->columns()) { + auto cloned = column->clone_selective(select.data(), 0, select.size()); + } + items += select.size(); + } + state.SetItemsProcessed(items); + } + + void do_bench_chunk_clone(benchmark::State& state) { + ChunkPtr chunk = prepare_big_chunk(); + size_t items = 0; + for (auto _ : state) { + ChunkPtr empty = chunk->clone_empty(); + empty->append_selective(*chunk, select.data(), 0, select.size()); + items += select.size(); + } + state.SetItemsProcessed(items); + } + + ChunkPtr prepare_big_chunk() { + if (_big_chunk) { + return _big_chunk; + } + _big_chunk = build_chunk(_segment_chunk_size); + return _big_chunk; + } + + SegmentedChunkPtr prepare_chunk() { + if (_seg_chunk) { + return _seg_chunk; + } + ChunkPtr chunk = build_chunk(_dest_chunk_size); + + for (int i = 0; i < (_segment_chunk_size / _dest_chunk_size); i++) { + if (!_seg_chunk) { + _seg_chunk = SegmentedChunk::create(_segment_size); + ChunkPtr chunk = build_chunk(_dest_chunk_size); + auto map = chunk->get_slot_id_to_index_map(); + for (auto entry : map) { + _seg_chunk->append_column(chunk->get_column_by_slot_id(entry.first), entry.first); + } + _seg_chunk->build_columns(); + } else { + // std::cerr << " append " << chunk->num_rows() << "rows, become " << _seg_chunk->num_rows() << std::endl; + _seg_chunk->append_chunk(chunk); + } + } + return _seg_chunk; + } + + void random_select(std::vector& select, size_t count, size_t range) { + select.resize(count); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, range - 1); + std::generate(select.begin(), select.end(), [&]() { return dis(gen); }); + } + + ChunkPtr build_chunk(size_t chunk_size) { + if (_types.empty()) { + for (int i = 0; i < _column_count; i++) { + if (_data_type == 0) { + _types.emplace_back(TypeDescriptor::create_varchar_type(128)); + } else if (_data_type == 1) { + _types.emplace_back(LogicalType::TYPE_INT); + } else { + CHECK(false) << "data type not supported: " << _data_type; + } + } + } + + auto chunk = std::make_unique(); + for (int i = 0; i < _column_count; i++) { + auto col = init_dest_column(_types[i], chunk_size); + chunk->append_column(col, i); + } + return chunk; + } + + ColumnPtr init_dest_column(const TypeDescriptor& type, size_t chunk_size) { + auto c1 = ColumnHelper::create_column(type, true); + c1->reserve(chunk_size); + for (int i = 0; i < chunk_size; i++) { + if (type.is_string_type()) { + std::string str = fmt::format("str{}", i); + c1->append_datum(Slice(str)); + } else if (type.is_integer_type()) { + c1->append_datum(i); + } else { + CHECK(false) << "data type not supported"; + } + } + return c1; + } + +private: + int _column_count = 4; + int _data_type = 0; + size_t _dest_chunk_size = 4096; + size_t _segment_size = 65536; + size_t _num_segments = 10; + size_t _segment_chunk_size = _segment_size * _num_segments; + + SegmentedChunkPtr _seg_chunk; + ChunkPtr _big_chunk; + std::vector select; + std::vector _types; +}; + +static void BenchSegmentedChunkClone(benchmark::State& state) { + google::InstallFailureSignalHandler(); + auto perf = std::make_unique(); + perf->prepare(state); + perf->do_bench_segmented_chunk_clone(state); +} + +static void BenchChunkClone(benchmark::State& state) { + google::InstallFailureSignalHandler(); + auto perf = std::make_unique(); + perf->prepare(state); + perf->do_bench_chunk_clone(state); +} + +static std::vector> chunk_clone_args() { + return { + {1, 2, 3, 4}, // num columns + {0, 1}, // data type + {1, 4, 16, 64} // num_segments + }; +} + +BENCHMARK(BenchSegmentedChunkClone)->ArgsProduct(chunk_clone_args()); +BENCHMARK(BenchChunkClone)->ArgsProduct(chunk_clone_args()); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static void process_args(benchmark::internal::Benchmark* b) { // chunk_count, column_count, node_count, src_chunk_size, null percent b->Args({400, 400, 140, 4096, 80}); diff --git a/be/src/block_cache/CMakeLists.txt b/be/src/block_cache/CMakeLists.txt index 4590f13b1f342..7ee22916a9752 100644 --- a/be/src/block_cache/CMakeLists.txt +++ b/be/src/block_cache/CMakeLists.txt @@ -27,10 +27,13 @@ set(CACHE_FILES block_cache_hit_rate_counter.hpp ) +<<<<<<< HEAD if (${WITH_CACHELIB} STREQUAL "ON") list(APPEND CACHE_FILES cachelib_wrapper.cpp) endif() +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (${WITH_STARCACHE} STREQUAL "ON") list(APPEND CACHE_FILES starcache_wrapper.cpp) endif() @@ -38,6 +41,7 @@ endif() add_library(BlockCache STATIC ${CACHE_FILES} ) +<<<<<<< HEAD if (${WITH_CACHELIB} STREQUAL "ON") set(CACHELIB_DIR ${THIRDPARTY_DIR}/cachelib) @@ -47,3 +51,5 @@ if (${WITH_CACHELIB} STREQUAL "ON") include_directories(AFTER ${CACHELIB_DIR}/deps/include) endif() +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/block_cache/block_cache.cpp b/be/src/block_cache/block_cache.cpp index 03aa089b72bb4..b09220a110f37 100644 --- a/be/src/block_cache/block_cache.cpp +++ b/be/src/block_cache/block_cache.cpp @@ -16,6 +16,7 @@ #include +<<<<<<< HEAD #include #ifdef WITH_CACHELIB @@ -26,6 +27,11 @@ #endif #include "common/config.h" #include "common/logging.h" +======= +#ifdef WITH_STARCACHE +#include "block_cache/starcache_wrapper.h" +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/statusor.h" #include "gutil/strings/substitute.h" @@ -33,8 +39,11 @@ namespace starrocks { namespace fs = std::filesystem; +<<<<<<< HEAD // The cachelib doesn't support a item (key+valueu+attribute) larger than 4 MB without chain. // So, we check and limit the block_size configured by users to avoid unexpected errors. +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // For starcache, in theory we doesn't have a hard limitation for block size, but a very large // block_size may cause heavy read amplification. So, we also limit it to 2 MB as an empirical value. const size_t BlockCache::MAX_BLOCK_SIZE = 2 * 1024 * 1024; @@ -51,12 +60,15 @@ BlockCache::~BlockCache() { Status BlockCache::init(const CacheOptions& options) { _block_size = std::min(options.block_size, MAX_BLOCK_SIZE); auto cache_options = options; +<<<<<<< HEAD #ifdef WITH_CACHELIB if (cache_options.engine == "cachelib") { _kv_cache = std::make_unique(); LOG(INFO) << "init cachelib engine, block_size: " << _block_size; } #endif +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #ifdef WITH_STARCACHE if (cache_options.engine == "starcache") { _kv_cache = std::make_unique(); @@ -208,6 +220,17 @@ Status BlockCache::shutdown() { return st; } +<<<<<<< HEAD +======= +void BlockCache::disk_spaces(std::vector* spaces) { + spaces->clear(); + auto metrics = _kv_cache->cache_metrics(0); + for (auto& dir : metrics.disk_dir_spaces) { + spaces->push_back({.path = dir.path, .size = dir.quota_bytes}); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DataCacheEngineType BlockCache::engine_type() { return _kv_cache->engine_type(); } diff --git a/be/src/block_cache/block_cache.h b/be/src/block_cache/block_cache.h index 6c715263a6f2c..0f490f23e94fd 100644 --- a/be/src/block_cache/block_cache.h +++ b/be/src/block_cache/block_cache.h @@ -92,8 +92,17 @@ class BlockCache { bool available() const { return is_initialized() && (has_mem_cache() || has_disk_cache()); } +<<<<<<< HEAD DataCacheEngineType engine_type(); +======= + void disk_spaces(std::vector* spaces); + + DataCacheEngineType engine_type(); + + std::shared_ptr starcache_instance() { return _kv_cache->starcache_instance(); } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static const size_t MAX_BLOCK_SIZE; private: @@ -103,8 +112,14 @@ class BlockCache { void _refresh_quota(); size_t _block_size = 0; +<<<<<<< HEAD std::unique_ptr _kv_cache; std::unique_ptr _disk_space_monitor; +======= + std::shared_ptr _kv_cache; + std::unique_ptr _disk_space_monitor; + std::vector _disk_paths; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::atomic _initialized = false; std::atomic _mem_quota = 0; std::atomic _disk_quota = 0; diff --git a/be/src/block_cache/cache_options.h b/be/src/block_cache/cache_options.h index 873b5dc1c1c1a..493eec94bf87c 100644 --- a/be/src/block_cache/cache_options.h +++ b/be/src/block_cache/cache_options.h @@ -52,11 +52,20 @@ struct CacheOptions { bool enable_checksum = false; bool enable_direct_io = false; bool enable_tiered_cache = true; +<<<<<<< HEAD +======= + bool enable_datacache_persistence = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string engine; size_t max_concurrent_inserts = 0; size_t max_flying_memory_mb = 0; double scheduler_threads_per_cpu = 0; double skip_read_factor = 0; +<<<<<<< HEAD +======= + uint32_t inline_item_count_limit = 0; + std::string eviction_policy; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; struct WriteCacheOptions { @@ -76,6 +85,16 @@ struct WriteCacheOptions { // It is expressed as a percentage. If evict_probability is 10, it means the probability to evict other data is 10%. int32_t evict_probability = 100; +<<<<<<< HEAD +======= + // The base frequency for target cache. + // When using multiple segment lru, a higher frequency may cause the cache is written to warm segment directly. + // For the default cache options, that `lru_segment_freq_bits` is 0: + // * The default `frequency=0` indicates the cache will be written to cold segment. + // * A frequency value greater than 0 indicates writing this cache directly to the warm segment. + int8_t frequency = 0; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct Stats { int64_t write_mem_bytes = 0; int64_t write_disk_bytes = 0; diff --git a/be/src/block_cache/datacache_utils.cpp b/be/src/block_cache/datacache_utils.cpp index 8a5c29688b32c..7af3c01c8df7c 100644 --- a/be/src/block_cache/datacache_utils.cpp +++ b/be/src/block_cache/datacache_utils.cpp @@ -20,6 +20,10 @@ #include "fs/fs.h" #include "gutil/strings/split.h" +<<<<<<< HEAD +======= +#include "util/disk_info.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/parse_util.h" namespace starrocks { @@ -156,4 +160,30 @@ void DataCacheUtils::clean_residual_datacache(const std::string& disk_path) { LOG_IF(WARNING, !st.ok()) << "fail to clean residual datacache data, reason: " << st.message(); } +<<<<<<< HEAD +======= +Status DataCacheUtils::change_disk_path(const std::string& old_disk_path, const std::string& new_disk_path) { + std::filesystem::path old_path(old_disk_path); + std::filesystem::path new_path(new_disk_path); + if (std::filesystem::exists(old_path)) { + if (DiskInfo::disk_id(old_path.c_str()) != DiskInfo::disk_id(new_path.c_str())) { + LOG(ERROR) << "fail to rename the old dataache directory [" << old_path.string() << "] to the new one [" + << new_path.string() << "] because they are located on different disks."; + return Status::InternalError("The old datacache directory is different from the new one"); + } + std::error_code ec; + std::filesystem::remove_all(new_path, ec); + if (!ec) { + std::filesystem::rename(old_path, new_path, ec); + } + if (ec) { + LOG(ERROR) << "fail to rename the old dataache directory [" << old_path.string() << "] to the new one [" + << new_path.string() << "], reason: " << ec.message(); + return Status::InternalError("fail to handle the old starlet_cache data"); + } + } + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/block_cache/datacache_utils.h b/be/src/block_cache/datacache_utils.h index 37ff3cadb4ce3..68a5b8759b04a 100644 --- a/be/src/block_cache/datacache_utils.h +++ b/be/src/block_cache/datacache_utils.h @@ -37,6 +37,14 @@ class DataCacheUtils { std::vector* disk_spaces); static void clean_residual_datacache(const std::string& disk_path); +<<<<<<< HEAD }; -} // namespace starrocks \ No newline at end of file +} // namespace starrocks +======= + + static Status change_disk_path(const std::string& old_disk_path, const std::string& new_disk_path); +}; + +} // namespace starrocks +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/block_cache/disk_space_monitor.cpp b/be/src/block_cache/disk_space_monitor.cpp index 3a6c647f8373e..c25615daa1b83 100644 --- a/be/src/block_cache/disk_space_monitor.cpp +++ b/be/src/block_cache/disk_space_monitor.cpp @@ -253,14 +253,26 @@ bool DiskSpaceMonitor::_adjust_spaces_by_disk_usage(bool immediate) { // If the current available disk space is too small, cache quota will be reset to zero to avoid overly frequent // population and eviction. _reset_spaces(); +<<<<<<< HEAD total_cache_quota = 0; if (_total_cache_quota == 0) { // If the cache quata is already zero, skip adjusting it repeatedly. +======= + if (_total_cache_quota == 0) { + // If the cache quata is already zero, skip adjusting it repeatedly. + VLOG(1) << "Skip updating the cache quota because the target quota is less than " + << "`datacache_min_disk_quota_for_adjustment`, target cache quota: " << total_cache_quota; + total_cache_quota = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return false; } else { // This warning log only be printed when the cache disk quota is adjust from a non-zero integer to zero. LOG(WARNING) << "The current available disk space is too small, so disable the disk cache directly. If you " << "still need it, you could reduce the value of `datacache_min_disk_quota_for_adjustment`"; +<<<<<<< HEAD +======= + total_cache_quota = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } LOG(INFO) << "Adjusting datacache disk quota from " << _total_cache_quota << " to " << total_cache_quota; diff --git a/be/src/block_cache/kv_cache.h b/be/src/block_cache/kv_cache.h index 4bfa306c24953..0a494f8189fc5 100644 --- a/be/src/block_cache/kv_cache.h +++ b/be/src/block_cache/kv_cache.h @@ -39,9 +39,13 @@ using DataCacheMetrics = DummyCacheMetrics; using DataCacheStatus = DummyCacheStatus; #endif +<<<<<<< HEAD enum class DataCacheEngine { STARCACHE, CACHELIB }; enum class DataCacheEngineType { STARCACHE, CACHELIB }; +======= +enum class DataCacheEngineType { STARCACHE }; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class KvCache { public: @@ -83,6 +87,11 @@ class KvCache { virtual Status shutdown() = 0; virtual DataCacheEngineType engine_type() = 0; +<<<<<<< HEAD +======= + + virtual std::shared_ptr starcache_instance() = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/block_cache/starcache_wrapper.cpp b/be/src/block_cache/starcache_wrapper.cpp index 2826c2f962838..2d887bd6db948 100644 --- a/be/src/block_cache/starcache_wrapper.cpp +++ b/be/src/block_cache/starcache_wrapper.cpp @@ -36,10 +36,31 @@ Status StarCacheWrapper::init(const CacheOptions& options) { opt.enable_os_page_cache = !options.enable_direct_io; opt.scheduler_thread_ratio_per_cpu = options.scheduler_threads_per_cpu; opt.max_flying_memory_mb = options.max_flying_memory_mb; +<<<<<<< HEAD _cache_adaptor.reset(starcache::create_default_adaptor(options.skip_read_factor)); opt.cache_adaptor = _cache_adaptor.get(); opt.instance_name = "dla_cache"; _enable_tiered_cache = options.enable_tiered_cache; +======= + opt.inline_cache_count_limit = options.inline_item_count_limit; + opt.alloc_mem_threshold = 100; + opt.evict_touch_mem_probalility = 10; + opt.evict_touch_disk_probalility = 10; + _cache_adaptor.reset(starcache::create_default_adaptor(options.skip_read_factor)); + opt.cache_adaptor = _cache_adaptor.get(); + if (options.enable_datacache_persistence) { + opt.durability_type = starcache::DurabilityType::ROCKSDB; + } + opt.instance_name = "default_cache"; + + if (options.eviction_policy == "slru") { + opt.lru_segment_ratios = {35, 65}; + } + opt.lru_segment_freq_bits = 0; + + _enable_tiered_cache = options.enable_tiered_cache; + _enable_datacache_persistence = options.enable_datacache_persistence; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _cache = std::make_unique(); return to_status(_cache->init(opt)); } @@ -56,8 +77,16 @@ Status StarCacheWrapper::write_buffer(const std::string& key, const IOBuffer& bu opts.async = options->async; opts.keep_alive = options->allow_zero_copy; opts.callback = options->callback; +<<<<<<< HEAD opts.mode = _enable_tiered_cache ? starcache::WriteOptions::WriteMode::WRITE_BACK : starcache::WriteOptions::WriteMode::WRITE_THROUGH; +======= + if (!_enable_datacache_persistence && _enable_tiered_cache) { + opts.mode = starcache::WriteOptions::WriteMode::WRITE_BACK; + } else { + opts.mode = starcache::WriteOptions::WriteMode::WRITE_THROUGH; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) opts.evict_probability = options->evict_probability; Status st; { diff --git a/be/src/block_cache/starcache_wrapper.h b/be/src/block_cache/starcache_wrapper.h index f9714a103970b..db29d4dd276af 100644 --- a/be/src/block_cache/starcache_wrapper.h +++ b/be/src/block_cache/starcache_wrapper.h @@ -56,10 +56,20 @@ class StarCacheWrapper : public KvCache { DataCacheEngineType engine_type() override { return DataCacheEngineType::STARCACHE; } +<<<<<<< HEAD private: std::unique_ptr _cache; std::unique_ptr _cache_adaptor; bool _enable_tiered_cache = false; +======= + std::shared_ptr starcache_instance() override { return _cache; } + +private: + std::shared_ptr _cache; + std::unique_ptr _cache_adaptor; + bool _enable_tiered_cache = false; + bool _enable_datacache_persistence = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; // In order to split the starcache library to a separate registry for other users such as the cloud team, diff --git a/be/src/column/adaptive_nullable_column.cpp b/be/src/column/adaptive_nullable_column.cpp index 37e229c145d28..38c81a1f6709c 100644 --- a/be/src/column/adaptive_nullable_column.cpp +++ b/be/src/column/adaptive_nullable_column.cpp @@ -140,11 +140,16 @@ bool AdaptiveNullableColumn::append_nulls(size_t count) { return true; } +<<<<<<< HEAD bool AdaptiveNullableColumn::append_strings(const Buffer& strs) { +======= +bool AdaptiveNullableColumn::append_strings(const Slice* data, size_t size) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_data_column->is_binary()) { switch (_state) { case State::kUninitialized: { _state = State::kNotConstant; +<<<<<<< HEAD std::ignore = _data_column->append_strings(strs); _size = strs.size(); break; @@ -157,21 +162,45 @@ bool AdaptiveNullableColumn::append_strings(const Buffer& strs) { case State::kMaterialized: { std::ignore = _data_column->append_strings(strs); null_column_data().resize(_null_column->size() + strs.size(), 0); +======= + std::ignore = _data_column->append_strings(data, size); + _size = size; + break; + } + case State::kNotConstant: { + std::ignore = _data_column->append_strings(data, size); + _size += size; + break; + } + case State::kMaterialized: { + std::ignore = _data_column->append_strings(data, size); + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(_null_column->size(), _data_column->size()); break; } default: { materialized_nullable(); +<<<<<<< HEAD std::ignore = _data_column->append_strings(strs); null_column_data().resize(_null_column->size() + strs.size(), 0); +======= + std::ignore = _data_column->append_strings(data, size); + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(_null_column->size(), _data_column->size()); break; } } } else { materialized_nullable(); +<<<<<<< HEAD if (_data_column->append_strings(strs)) { null_column_data().resize(_null_column->size() + strs.size(), 0); +======= + if (_data_column->append_strings(data, size)) { + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } DCHECK_EQ(_null_column->size(), _data_column->size()); @@ -180,20 +209,34 @@ bool AdaptiveNullableColumn::append_strings(const Buffer& strs) { return true; } +<<<<<<< HEAD bool AdaptiveNullableColumn::append_strings_overflow(const Buffer& strs, size_t max_length) { materialized_nullable(); if (_data_column->append_strings_overflow(strs, max_length)) { null_column_data().resize(_null_column->size() + strs.size(), 0); +======= +bool AdaptiveNullableColumn::append_strings_overflow(const Slice* data, size_t size, size_t max_length) { + materialized_nullable(); + if (_data_column->append_strings_overflow(data, size, max_length)) { + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } DCHECK_EQ(_null_column->size(), _data_column->size()); return false; } +<<<<<<< HEAD bool AdaptiveNullableColumn::append_continuous_strings(const Buffer& strs) { materialized_nullable(); if (_data_column->append_continuous_strings(strs)) { null_column_data().resize(_null_column->size() + strs.size(), 0); +======= +bool AdaptiveNullableColumn::append_continuous_strings(const Slice* data, size_t size) { + materialized_nullable(); + if (_data_column->append_continuous_strings(data, size)) { + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } DCHECK_EQ(_null_column->size(), _data_column->size()); diff --git a/be/src/column/adaptive_nullable_column.h b/be/src/column/adaptive_nullable_column.h index b247bdce6e18f..ca66489c3ad89 100644 --- a/be/src/column/adaptive_nullable_column.h +++ b/be/src/column/adaptive_nullable_column.h @@ -276,9 +276,13 @@ class AdaptiveNullableColumn final : public ColumnFactory upgrade_if_overflow() override { materialized_nullable(); +<<<<<<< HEAD if (_null_column->capacity_limit_reached()) { return Status::InternalError("Size of NullableColumn exceed the limit"); } +======= + RETURN_IF_ERROR(_null_column->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return upgrade_helper_func(&_data_column); } @@ -293,11 +297,19 @@ class AdaptiveNullableColumn final : public ColumnFactoryhas_large_column(); } +<<<<<<< HEAD bool append_strings(const Buffer& strs) override; bool append_strings_overflow(const Buffer& strs, size_t max_length) override; bool append_continuous_strings(const Buffer& strs) override; +======= + bool append_strings(const Slice* data, size_t size) override; + + bool append_strings_overflow(const Slice* data, size_t size, size_t max_length) override; + + bool append_continuous_strings(const Slice* data, size_t size) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool append_continuous_fixed_length_strings(const char* data, size_t size, int fixed_length) override; @@ -525,7 +537,11 @@ class AdaptiveNullableColumn final : public ColumnFactory& offsets) override { +======= + ColumnPtr replicate(const Buffer& offsets) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) materialized_nullable(); return NullableColumn::replicate(offsets); } @@ -556,9 +572,15 @@ class AdaptiveNullableColumn final : public ColumnFactory>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void check_or_die() const override { diff --git a/be/src/column/array_column.h b/be/src/column/array_column.h index 6ac43ec9a34ef..06d53c9feb1e2 100644 --- a/be/src/column/array_column.h +++ b/be/src/column/array_column.h @@ -97,8 +97,11 @@ class ArrayColumn final : public ColumnFactory { bool append_nulls(size_t count) override; +<<<<<<< HEAD bool append_strings(const Buffer& strs) override { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t append_numbers(const void* buff, size_t length) override { return -1; } void append_value_multiple_times(const void* value, size_t count) override; @@ -183,8 +186,14 @@ class ArrayColumn final : public ColumnFactory { std::string debug_string() const override; +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { return _elements->capacity_limit_reached(msg) || _offsets->capacity_limit_reached(msg); +======= + Status capacity_limit_reached() const override { + RETURN_IF_ERROR(_elements->capacity_limit_reached()); + return _offsets->capacity_limit_reached(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr upgrade_if_overflow() override; diff --git a/be/src/column/array_view_column.h b/be/src/column/array_view_column.h index c903e596750a5..333bc4193254e 100644 --- a/be/src/column/array_view_column.h +++ b/be/src/column/array_view_column.h @@ -104,7 +104,10 @@ class ArrayViewColumn final : public ColumnFactory { void append_value_multiple_times(const Column& src, uint32_t idx, uint32_t count) override; +<<<<<<< HEAD bool append_strings(const Buffer& strs) override { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool append_nulls(size_t count) override { return false; } size_t append_numbers(const void* buff, size_t length) override { return -1; } @@ -199,8 +202,14 @@ class ArrayViewColumn final : public ColumnFactory { std::string debug_string() const override; +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { return _elements->capacity_limit_reached(msg) || _offsets->capacity_limit_reached(msg); +======= + Status capacity_limit_reached() const override { + RETURN_IF_ERROR(_elements->capacity_limit_reached()); + return _offsets->capacity_limit_reached(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr upgrade_if_overflow() override { return nullptr; } diff --git a/be/src/column/binary_column.cpp b/be/src/column/binary_column.cpp index e209e548defa0..9064a57119d4a 100644 --- a/be/src/column/binary_column.cpp +++ b/be/src/column/binary_column.cpp @@ -24,6 +24,10 @@ #include "gutil/bits.h" #include "gutil/casts.h" #include "gutil/strings/fastmem.h" +<<<<<<< HEAD +======= +#include "gutil/strings/substitute.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/hash_util.hpp" #include "util/mysql_row_buffer.h" #include "util/raw_container.h" @@ -46,7 +50,19 @@ void BinaryColumnBase::check_or_die() const { } template +<<<<<<< HEAD void BinaryColumnBase::append(const Column& src, size_t offset, size_t count) { +======= +void BinaryColumnBase::append(const Slice& str) { + _bytes.insert(_bytes.end(), str.data, str.data + str.size); + _offsets.emplace_back(_bytes.size()); + _slices_cache = false; +} + +template +void BinaryColumnBase::append(const Column& src, size_t offset, size_t count) { + DCHECK(offset + count <= src.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const auto& b = down_cast&>(src); const unsigned char* p = &b._bytes[b._offsets[offset]]; const unsigned char* e = &b._bytes[b._offsets[offset + count]]; @@ -120,7 +136,11 @@ void BinaryColumnBase::append_value_multiple_times(const Column& src, uint32_ //TODO(fzh): optimize copy using SIMD template +<<<<<<< HEAD ColumnPtr BinaryColumnBase::replicate(const std::vector& offsets) { +======= +ColumnPtr BinaryColumnBase::replicate(const Buffer& offsets) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto dest = std::dynamic_pointer_cast>(BinaryColumnBase::create()); auto& dest_offsets = dest->get_offset(); auto& dest_bytes = dest->get_bytes(); @@ -146,8 +166,14 @@ ColumnPtr BinaryColumnBase::replicate(const std::vector& offsets) { } template +<<<<<<< HEAD bool BinaryColumnBase::append_strings(const Buffer& strs) { for (const auto& s : strs) { +======= +bool BinaryColumnBase::append_strings(const Slice* data, size_t size) { + for (size_t i = 0; i < size; i++) { + const auto& s = data[i]; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const auto* const p = reinterpret_cast(s.data); _bytes.insert(_bytes.end(), p, p + s.size); _offsets.emplace_back(_bytes.size()); @@ -159,6 +185,7 @@ bool BinaryColumnBase::append_strings(const Buffer& strs) { // NOTE: this function should not be inlined. If this function is inlined, // the append_strings_overflow will be slower by 30% template +<<<<<<< HEAD void append_fixed_length(const Buffer& strs, Bytes* bytes, typename BinaryColumnBase::Offsets* offsets) __attribute__((noinline)); @@ -166,19 +193,39 @@ template void append_fixed_length(const Buffer& strs, Bytes* bytes, typename BinaryColumnBase::Offsets* offsets) { size_t size = bytes->size(); for (const auto& s : strs) { +======= +void append_fixed_length(const Slice* data, size_t data_size, Bytes* bytes, + typename BinaryColumnBase::Offsets* offsets) __attribute__((noinline)); + +template +void append_fixed_length(const Slice* data, size_t data_size, Bytes* bytes, + typename BinaryColumnBase::Offsets* offsets) { + size_t size = bytes->size(); + for (size_t i = 0; i < data_size; i++) { + const auto& s = data[i]; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size += s.size; } size_t offset = bytes->size(); bytes->resize(size + copy_length); +<<<<<<< HEAD size_t rows = strs.size(); +======= + size_t rows = data_size; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t length = offsets->size(); raw::stl_vector_resize_uninitialized(offsets, offsets->size() + rows); for (size_t i = 0; i < rows; ++i) { +<<<<<<< HEAD memcpy(&(*bytes)[offset], strs[i].get_data(), copy_length); offset += strs[i].get_size(); +======= + memcpy(&(*bytes)[offset], data[i].get_data(), copy_length); + offset += data[i].get_size(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) (*offsets)[length++] = offset; } @@ -186,6 +233,7 @@ void append_fixed_length(const Buffer& strs, Bytes* bytes, typename Binar } template +<<<<<<< HEAD bool BinaryColumnBase::append_strings_overflow(const Buffer& strs, size_t max_length) { if (max_length <= 8) { append_fixed_length(strs, &_bytes, &_offsets); @@ -199,6 +247,22 @@ bool BinaryColumnBase::append_strings_overflow(const Buffer& strs, siz append_fixed_length(strs, &_bytes, &_offsets); } else { for (const auto& s : strs) { +======= +bool BinaryColumnBase::append_strings_overflow(const Slice* data, size_t size, size_t max_length) { + if (max_length <= 8) { + append_fixed_length(data, size, &_bytes, &_offsets); + } else if (max_length <= 16) { + append_fixed_length(data, size, &_bytes, &_offsets); + } else if (max_length <= 32) { + append_fixed_length(data, size, &_bytes, &_offsets); + } else if (max_length <= 64) { + append_fixed_length(data, size, &_bytes, &_offsets); + } else if (max_length <= 128) { + append_fixed_length(data, size, &_bytes, &_offsets); + } else { + for (size_t i = 0; i < size; i++) { + const auto& s = data[i]; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const auto* const p = reinterpret_cast(s.data); _bytes.insert(_bytes.end(), p, p + s.size); _offsets.emplace_back(_bytes.size()); @@ -209,6 +273,7 @@ bool BinaryColumnBase::append_strings_overflow(const Buffer& strs, siz } template +<<<<<<< HEAD bool BinaryColumnBase::append_continuous_strings(const Buffer& strs) { if (strs.empty()) { return true; @@ -220,6 +285,20 @@ bool BinaryColumnBase::append_continuous_strings(const Buffer& strs) { _offsets.reserve(_offsets.size() + strs.size()); for (const Slice& s : strs) { +======= +bool BinaryColumnBase::append_continuous_strings(const Slice* data, size_t size) { + if (size == 0) { + return true; + } + size_t new_size = _bytes.size(); + const auto* p = reinterpret_cast(data[0].data); + const auto* q = reinterpret_cast(data[size - 1].data + data[size - 1].size); + _bytes.insert(_bytes.end(), p, q); + + _offsets.reserve(_offsets.size() + size); + for (size_t i = 0; i < size; i++) { + const auto& s = data[i]; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) new_size += s.size; _offsets.emplace_back(new_size); } @@ -738,13 +817,18 @@ bool BinaryColumnBase::has_large_column() const { } template +<<<<<<< HEAD bool BinaryColumnBase::capacity_limit_reached(std::string* msg) const { +======= +Status BinaryColumnBase::capacity_limit_reached() const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static_assert(std::is_same_v || std::is_same_v); if constexpr (std::is_same_v) { // The size limit of a single element is 2^32 - 1. // The size limit of all elements is 2^32 - 1. // The number limit of elements is 2^32 - 1. if (_bytes.size() >= Column::MAX_CAPACITY_LIMIT) { +<<<<<<< HEAD if (msg != nullptr) { msg->append("Total byte size of binary column exceed the limit: " + std::to_string(Column::MAX_CAPACITY_LIMIT)); @@ -758,12 +842,24 @@ bool BinaryColumnBase::capacity_limit_reached(std::string* msg) const { return true; } else { return false; +======= + return Status::CapacityLimitExceed( + strings::Substitute("Total byte size of binary column exceed the limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } else if (_offsets.size() >= Column::MAX_CAPACITY_LIMIT) { + return Status::CapacityLimitExceed( + strings::Substitute("Total row count of binary column exceed the limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } else { + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } else { // The size limit of a single element is 2^32 - 1. // The size limit of all elements is 2^64 - 1. // The number limit of elements is 2^32 - 1. if (_bytes.size() >= Column::MAX_LARGE_CAPACITY_LIMIT) { +<<<<<<< HEAD if (msg != nullptr) { msg->append("Total byte size of large binary column exceed the limit: " + std::to_string(Column::MAX_LARGE_CAPACITY_LIMIT)); @@ -777,6 +873,17 @@ bool BinaryColumnBase::capacity_limit_reached(std::string* msg) const { return true; } else { return false; +======= + return Status::CapacityLimitExceed( + strings::Substitute("Total byte size of large binary column exceed the limit: $0", + std::to_string(Column::MAX_LARGE_CAPACITY_LIMIT))); + } else if (_offsets.size() >= Column::MAX_CAPACITY_LIMIT) { + return Status::CapacityLimitExceed( + strings::Substitute("Total row count of large binary column exceed the limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } else { + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } diff --git a/be/src/column/binary_column.h b/be/src/column/binary_column.h index 09bfac117a058..88b7881f39a23 100644 --- a/be/src/column/binary_column.h +++ b/be/src/column/binary_column.h @@ -32,8 +32,13 @@ class BinaryColumnBase final : public ColumnFactory> using Offset = T; using Offsets = Buffer; +<<<<<<< HEAD using Bytes = starrocks::raw::RawVectorPad16; +======= + using Byte = uint8_t; + using Bytes = starrocks::raw::RawVectorPad16>; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct BinaryDataProxyContainer { BinaryDataProxyContainer(const BinaryColumnBase& column) : _column(column) {} @@ -172,11 +177,15 @@ class BinaryColumnBase final : public ColumnFactory> // No complain about the overloaded-virtual for this function DIAGNOSTIC_PUSH DIAGNOSTIC_IGNORE("-Woverloaded-virtual") +<<<<<<< HEAD void append(const Slice& str) { _bytes.insert(_bytes.end(), str.data, str.data + str.size); _offsets.emplace_back(_bytes.size()); _slices_cache = false; } +======= + void append(const Slice& str); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DIAGNOSTIC_POP void append_datum(const Datum& datum) override { @@ -198,11 +207,19 @@ class BinaryColumnBase final : public ColumnFactory> _slices_cache = false; } +<<<<<<< HEAD bool append_strings(const Buffer& strs) override; bool append_strings_overflow(const Buffer& strs, size_t max_length) override; bool append_continuous_strings(const Buffer& strs) override; +======= + bool append_strings(const Slice* data, size_t size) override; + + bool append_strings_overflow(const Slice* data, size_t size, size_t max_length) override; + + bool append_continuous_strings(const Slice* data, size_t size) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool append_continuous_fixed_length_strings(const char* data, size_t size, int fixed_length) override; @@ -220,7 +237,11 @@ class BinaryColumnBase final : public ColumnFactory> _slices_cache = false; } +<<<<<<< HEAD ColumnPtr replicate(const std::vector& offsets) override; +======= + ColumnPtr replicate(const Buffer& offsets) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void fill_default(const Filter& filter) override; @@ -339,7 +360,11 @@ class BinaryColumnBase final : public ColumnFactory> return ss.str(); } +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override; +======= + Status capacity_limit_reached() const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: void _build_slices() const; diff --git a/be/src/column/bytes.h b/be/src/column/bytes.h index cb588a3f22dee..7bc3747df56cc 100644 --- a/be/src/column/bytes.h +++ b/be/src/column/bytes.h @@ -17,12 +17,20 @@ #include #include +<<<<<<< HEAD +======= +#include "runtime/memory/column_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/raw_container.h" namespace starrocks { // Bytes is a special vector in which the internal memory is always allocated with an additional 16 bytes, // to make life easier with 128 bit instructions. +<<<<<<< HEAD typedef starrocks::raw::RawVectorPad16 Bytes; +======= +typedef starrocks::raw::RawVectorPad16> Bytes; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/column/chunk.cpp b/be/src/column/chunk.cpp index cfc362bb9713f..925d5cbac88c8 100644 --- a/be/src/column/chunk.cpp +++ b/be/src/column/chunk.cpp @@ -132,6 +132,18 @@ void Chunk::append_column(ColumnPtr column, const FieldPtr& field) { check_or_die(); } +<<<<<<< HEAD +======= +void Chunk::append_vector_column(ColumnPtr column, const FieldPtr& field, SlotId slot_id) { + DCHECK(!_cid_to_index.contains(field->id())); + _cid_to_index[field->id()] = _columns.size(); + _slot_id_to_index[slot_id] = _columns.size(); + _columns.emplace_back(std::move(column)); + _schema->append(field); + check_or_die(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void Chunk::append_column(ColumnPtr column, SlotId slot_id) { DCHECK(!_slot_id_to_index.contains(slot_id)) << "slot_id:" + std::to_string(slot_id) << std::endl; if (UNLIKELY(_slot_id_to_index.contains(slot_id))) { diff --git a/be/src/column/chunk.h b/be/src/column/chunk.h index 43ea4a759f0f6..9d73b9ae3a7d4 100644 --- a/be/src/column/chunk.h +++ b/be/src/column/chunk.h @@ -112,6 +112,11 @@ class Chunk { // schema must exist and will be updated. void append_column(ColumnPtr column, const FieldPtr& field); +<<<<<<< HEAD +======= + void append_vector_column(ColumnPtr column, const FieldPtr& field, SlotId slot_id); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void append_column(ColumnPtr column, SlotId slot_id); void insert_column(size_t idx, ColumnPtr column, const FieldPtr& field); @@ -277,6 +282,7 @@ class Chunk { std::string rebuild_csv_row(size_t index, const std::string& delimiter) const; +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const { for (const auto& column : _columns) { if (column->capacity_limit_reached(msg)) { @@ -284,6 +290,13 @@ class Chunk { } } return false; +======= + Status capacity_limit_reached() const { + for (const auto& column : _columns) { + RETURN_IF_ERROR(column->capacity_limit_reached()); + } + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } query_cache::owner_info& owner_info() { return _owner_info; } diff --git a/be/src/column/column.cpp b/be/src/column/column.cpp index 36dbc9302feb4..089fc652736a0 100644 --- a/be/src/column/column.cpp +++ b/be/src/column/column.cpp @@ -66,7 +66,11 @@ StatusOr Column::upgrade_helper_func(ColumnPtr* col) { } } +<<<<<<< HEAD bool Column::empty_null_in_complex_column(const Filter& null_data, const std::vector& offsets) { +======= +bool Column::empty_null_in_complex_column(const Filter& null_data, const Buffer& offsets) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(null_data.size(), this->size()); if (!is_array() && !is_map()) { throw std::runtime_error("empty_null_in_complex_column() only works for array and map column."); diff --git a/be/src/column/column.h b/be/src/column/column.h index 7099080be3b06..8c6f187c8ef64 100644 --- a/be/src/column/column.h +++ b/be/src/column/column.h @@ -169,7 +169,11 @@ class Column { // for example: column(1,2)->replicate({0,2,5}) = column(1,1,2,2,2) // FixedLengthColumn, BinaryColumn and ConstColumn override this function for better performance. // TODO(fzh): optimize replicate() for ArrayColumn, ObjectColumn and others. +<<<<<<< HEAD virtual ColumnPtr replicate(const std::vector& offsets) { +======= + virtual ColumnPtr replicate(const Buffer& offsets) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto dest = this->clone_empty(); auto dest_size = offsets.size() - 1; DCHECK(this->size() >= dest_size) << "The size of the source column is less when duplicating it."; @@ -204,7 +208,13 @@ class Column { // This function will copy the [3, 2] row of src to this column. virtual void append_selective(const Column& src, const uint32_t* indexes, uint32_t from, uint32_t size) = 0; +<<<<<<< HEAD void append_selective(const Column& src, const Buffer& indexes) { +======= + template + void append_selective(const Column& src, const Container& indexes) { + static_assert(std::is_same::value, "The type of indexes must be uint32_t"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return append_selective(src, indexes.data(), 0, static_cast(indexes.size())); } @@ -216,19 +226,54 @@ class Column { // Return false if this is a non-nullable column, i.e, if `is_nullable` return false. virtual bool append_nulls(size_t count) = 0; +<<<<<<< HEAD // Append multiple strings into this column. // Return false if the column is not a binary column. [[nodiscard]] virtual bool append_strings(const Buffer& strs) = 0; +======= + template + bool append_strings(const Container& strs) { + static_assert(std::is_same::value, "Container::value_type must be Slice"); + return append_strings(strs.data(), strs.size()); + } + // Append multiple strings into this column. + // Return false if the column is not a binary column. + [[nodiscard]] virtual bool append_strings(const Slice* data, size_t size) { return false; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Like append_strings. To achieve higher performance, this function will read 16 bytes out of // bounds. So the caller must make sure that no invalid address access exception occurs for // out-of-bounds reads +<<<<<<< HEAD [[nodiscard]] virtual bool append_strings_overflow(const Buffer& strs, size_t max_length) { return false; } +======= + template + bool append_strings_overflow(const Container& strs, size_t max_length) { + static_assert(std::is_same::value, "Container::value_type must be Slice"); + return append_strings_overflow(strs.data(), strs.size(), max_length); + } + + [[nodiscard]] virtual bool append_strings_overflow(const Slice* data, size_t size, size_t max_length) { + return false; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Like `append_strings` but the corresponding storage of each slice is adjacent to the // next one's, the implementation can take advantage of this feature, e.g, copy the whole // memory at once. +<<<<<<< HEAD [[nodiscard]] virtual bool append_continuous_strings(const Buffer& strs) { return append_strings(strs); } +======= + template + [[nodiscard]] bool append_continuous_strings(const Container& strs) { + static_assert(std::is_same::value, "Container::value_type must be Slice"); + return append_continuous_strings(strs.data(), strs.size()); + } + + [[nodiscard]] virtual bool append_continuous_strings(const Slice* data, size_t size) { + return append_strings(data, size); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [[nodiscard]] virtual bool append_continuous_fixed_length_strings(const char* data, size_t size, int fixed_length) { return false; @@ -319,7 +364,11 @@ class Column { inline size_t filter(const Filter& filter, size_t count) { return filter_range(filter, 0, count); } // get rid of the case where the map/array is null but the map/array'elements are not empty. +<<<<<<< HEAD bool empty_null_in_complex_column(const Filter& null_data, const std::vector& offsets); +======= + bool empty_null_in_complex_column(const Filter& null_data, const Buffer& offsets); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // FIXME: Many derived implementation assume |to| equals to size(). virtual size_t filter_range(const Filter& filter, size_t from, size_t to) = 0; @@ -397,7 +446,11 @@ class Column { // The interface will not free memory!!! virtual void reset_column() { _delete_state = DEL_NOT_SATISFIED; } +<<<<<<< HEAD virtual bool capacity_limit_reached(std::string* msg = nullptr) const = 0; +======= + virtual Status capacity_limit_reached() const = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual Status accept(ColumnVisitor* visitor) const = 0; diff --git a/be/src/column/column_builder.h b/be/src/column/column_builder.h index 42534d9ab689b..4000367182be5 100644 --- a/be/src/column/column_builder.h +++ b/be/src/column/column_builder.h @@ -57,7 +57,11 @@ class ColumnBuilder { ColumnBuilder(DataColumnPtr column, NullColumnPtr null_column, bool has_null) : _column(std::move(column)), _null_column(std::move(null_column)), _has_null(has_null) {} //do nothing ctor, members are initialized by its offsprings. +<<<<<<< HEAD explicit ColumnBuilder(void*) {} +======= + explicit ColumnBuilder(void*) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void append(const DatumType& value) { _null_column->append(DATUM_NOT_NULL); diff --git a/be/src/column/column_hash.h b/be/src/column/column_hash.h index cfe52de4bc2a2..06cb41a52052b 100644 --- a/be/src/column/column_hash.h +++ b/be/src/column/column_hash.h @@ -16,6 +16,13 @@ #include #include +<<<<<<< HEAD +======= +#include + +#include "column/vectorized_fwd.h" +#include "storage/uint24.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #ifdef __SSE4_2__ #include @@ -126,6 +133,17 @@ struct Hash128WithSeed { return phmap_mix_with_seed()(hash_128(seed, value)); } }; +<<<<<<< HEAD +======= +template +struct HashTypeTraits { + using HashFunc = StdHashWithSeed; +}; +template <> +struct HashTypeTraits { + using HashFunc = Hash128WithSeed; +}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template struct PhmapDefaultHashFunc { diff --git a/be/src/column/column_helper.cpp b/be/src/column/column_helper.cpp index f02ef5ac50ed5..25ff4ab70877b 100644 --- a/be/src/column/column_helper.cpp +++ b/be/src/column/column_helper.cpp @@ -25,6 +25,10 @@ #include "column/vectorized_fwd.h" #include "gutil/casts.h" #include "simd/simd.h" +<<<<<<< HEAD +======= +#include "storage/chunk_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type_infra.h" #include "util/date_func.h" #include "util/percentile_value.h" @@ -32,10 +36,13 @@ namespace starrocks { +<<<<<<< HEAD NullColumnPtr ColumnHelper::one_size_not_null_column = NullColumn::create(1, 0); NullColumnPtr ColumnHelper::one_size_null_column = NullColumn::create(1, 1); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Filter& ColumnHelper::merge_nullable_filter(Column* column) { if (column->is_nullable()) { auto* nullable_column = down_cast(column); @@ -487,7 +494,11 @@ size_t ChunkSliceTemplate::skip(size_t skip_rows) { // Cutoff required rows from this chunk template +<<<<<<< HEAD Ptr ChunkSliceTemplate::cutoff(size_t required_rows) { +======= +ChunkUniquePtr ChunkSliceTemplate::cutoff(size_t required_rows) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(!empty()); size_t cut_rows = std::min(rows(), required_rows); auto res = chunk->clone_empty(cut_rows); @@ -500,7 +511,36 @@ Ptr ChunkSliceTemplate::cutoff(size_t required_rows) { return res; } +<<<<<<< HEAD template struct ChunkSliceTemplate; template struct ChunkSliceTemplate; +======= +// Specialized for SegmentedChunkPtr +template <> +ChunkUniquePtr ChunkSliceTemplate::cutoff(size_t required_rows) { + DCHECK(!empty()); + // cutoff a chunk from current segment, if it doesn't meet the requirement just let it be + ChunkPtr segment = chunk->segments()[segment_id]; + size_t segment_offset = offset % chunk->segment_size(); + size_t cut_rows = std::min(segment->num_rows() - segment_offset, required_rows); + + auto res = segment->clone_empty(cut_rows); + res->append(*segment, segment_offset, cut_rows); + offset += cut_rows; + + // move to next segment + segment_id = offset / chunk->segment_size(); + + if (empty()) { + chunk->reset(); + offset = 0; + } + return res; +} + +template struct ChunkSliceTemplate; +template struct ChunkSliceTemplate; +template struct ChunkSliceTemplate; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/column/column_helper.h b/be/src/column/column_helper.h index e0821af70ed82..5c51c849bc5d7 100644 --- a/be/src/column/column_helper.h +++ b/be/src/column/column_helper.h @@ -537,9 +537,12 @@ class ColumnHelper { static ColumnPtr convert_time_column_from_double_to_str(const ColumnPtr& column); +<<<<<<< HEAD static NullColumnPtr one_size_not_null_column; static NullColumnPtr one_size_null_column; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // unpack array column, return offsets_column, elements_column, elements_null_column static std::tuple unpack_array_column(const ColumnPtr& column); }; @@ -548,12 +551,20 @@ class ColumnHelper { template struct ChunkSliceTemplate { Ptr chunk; +<<<<<<< HEAD +======= + size_t segment_id = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t offset = 0; bool empty() const; size_t rows() const; size_t skip(size_t skip_rows); +<<<<<<< HEAD Ptr cutoff(size_t required_rows); +======= + ChunkUniquePtr cutoff(size_t required_rows); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void reset(Ptr input); }; @@ -583,5 +594,9 @@ APPLY_FOR_ALL_STRING_TYPE(GET_CONTAINER) using ChunkSlice = ChunkSliceTemplate; using ChunkSharedSlice = ChunkSliceTemplate; +<<<<<<< HEAD +======= +using SegmentedChunkSlice = ChunkSliceTemplate; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/column/column_viewer.cpp b/be/src/column/column_viewer.cpp index 9f626ee7104c8..5d7b179bfb3ba 100644 --- a/be/src/column/column_viewer.cpp +++ b/be/src/column/column_viewer.cpp @@ -15,6 +15,10 @@ #include "column/column_viewer.h" #include "column/column_helper.h" +<<<<<<< HEAD +======= +#include "runtime/global_variables.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type_infra.h" #include "util/percentile_value.h" #include "util/phmap/phmap.h" @@ -33,20 +37,32 @@ template ColumnViewer::ColumnViewer(const ColumnPtr& column) : _not_const_mask(not_const_mask(column)), _null_mask(null_mask(column)) { if (column->only_null()) { +<<<<<<< HEAD _null_column = ColumnHelper::one_size_null_column; +======= + _null_column = GlobalVariables::GetInstance()->one_size_null_column(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _column = RunTimeColumnType::create(); _column->append_default(); } else if (column->is_constant()) { auto v = ColumnHelper::as_raw_column(column); _column = ColumnHelper::cast_to(v->data_column()); +<<<<<<< HEAD _null_column = ColumnHelper::one_size_not_null_column; +======= + _null_column = GlobalVariables::GetInstance()->one_size_not_null_column(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else if (column->is_nullable()) { auto v = ColumnHelper::as_raw_column(column); _column = ColumnHelper::cast_to(v->data_column()); _null_column = ColumnHelper::as_column(v->null_column()); } else { _column = ColumnHelper::cast_to(column); +<<<<<<< HEAD _null_column = ColumnHelper::one_size_not_null_column; +======= + _null_column = GlobalVariables::GetInstance()->one_size_not_null_column(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _data = _column->get_data().data(); diff --git a/be/src/column/const_column.cpp b/be/src/column/const_column.cpp index b4ef18e7e06f3..2006fd188c4c3 100644 --- a/be/src/column/const_column.cpp +++ b/be/src/column/const_column.cpp @@ -52,7 +52,11 @@ void ConstColumn::append_value_multiple_times(const Column& src, uint32_t index, append(src, index, size); } +<<<<<<< HEAD ColumnPtr ConstColumn::replicate(const std::vector& offsets) { +======= +ColumnPtr ConstColumn::replicate(const Buffer& offsets) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ConstColumn::create(this->_data->clone_shared(), offsets.back()); } diff --git a/be/src/column/const_column.h b/be/src/column/const_column.h index fcababccb3d46..f5f8296a2dbcc 100644 --- a/be/src/column/const_column.h +++ b/be/src/column/const_column.h @@ -18,6 +18,10 @@ #include "column/datum.h" #include "column/vectorized_fwd.h" #include "common/logging.h" +<<<<<<< HEAD +======= +#include "gutil/strings/substitute.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -25,6 +29,11 @@ class ConstColumn final : public ColumnFactory { friend class ColumnFactory; public: +<<<<<<< HEAD +======= + using ValueType = void; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) explicit ConstColumn(ColumnPtr data_column); ConstColumn(ColumnPtr data_column, size_t size); @@ -110,7 +119,11 @@ class ConstColumn final : public ColumnFactory { void append_value_multiple_times(const Column& src, uint32_t index, uint32_t size) override; +<<<<<<< HEAD ColumnPtr replicate(const std::vector& offsets) override; +======= + ColumnPtr replicate(const Buffer& offsets) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool append_nulls(size_t count) override { DCHECK_GT(count, 0); @@ -126,8 +139,11 @@ class ConstColumn final : public ColumnFactory { } } +<<<<<<< HEAD bool append_strings(const Buffer& strs) override { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t append_numbers(const void* buff, size_t length) override { return -1; } void append_value_multiple_times(const void* value, size_t count) override { @@ -252,6 +268,7 @@ class ConstColumn final : public ColumnFactory { return ss.str(); } +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { RETURN_IF_UNLIKELY(_data->capacity_limit_reached(msg), true); if (_size > Column::MAX_CAPACITY_LIMIT) { @@ -261,6 +278,15 @@ class ConstColumn final : public ColumnFactory { return true; } return false; +======= + Status capacity_limit_reached() const override { + RETURN_IF_ERROR(_data->capacity_limit_reached()); + if (_size > Column::MAX_CAPACITY_LIMIT) { + return Status::CapacityLimitExceed(strings::Substitute("Row count of const column reach limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void check_or_die() const override; diff --git a/be/src/column/datum.h b/be/src/column/datum.h index cb913461411c9..39be0b1ef06e3 100644 --- a/be/src/column/datum.h +++ b/be/src/column/datum.h @@ -187,6 +187,13 @@ class Datum { return std::visit([&](const auto& arg) { return is_equal(arg); }, key); } +<<<<<<< HEAD +======= + [[nodiscard]] bool operator==(const Datum& other) const { return _value == other._value; } + + [[nodiscard]] bool operator!=(const Datum& other) const { return !(*this == other); } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: using Variant = std::variant>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class Field { public: Field(ColumnId id, std::string_view name, TypeInfoPtr type, starrocks::StorageAggregateType agg, +<<<<<<< HEAD uint8_t short_key_length, bool is_key, bool nullable) : _id(id), _agg_method(agg), +======= + AggStateDesc* agg_state_desc, uint8_t short_key_length, bool is_key, bool nullable) + : _id(id), + _agg_method(agg), + _agg_state_desc(agg_state_desc), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _name(name), _type(std::move(type)), _sub_fields(nullptr), _short_key_length(short_key_length), +<<<<<<< HEAD _flags(static_cast((is_key << kIsKeyShift) | (nullable << kNullableShift))) {} // Non-key field of any type except for ARRAY Field(ColumnId id, std::string_view name, LogicalType type, int precision, int scale, bool nullable) : Field(id, name, get_type_info(type, precision, scale), STORAGE_AGGREGATE_NONE, 0, false, nullable) {} +======= + _flags(static_cast((is_key << kIsKeyShift) | (nullable << kNullableShift))) { + if (_agg_method == STORAGE_AGGREGATE_AGG_STATE_UNION) { + DCHECK(_agg_state_desc != nullptr); + } + } + + // AggMethod is not STORAGE_AGGREGATE_AGG_STATE_UNION + Field(ColumnId id, std::string_view name, TypeInfoPtr type, starrocks::StorageAggregateType agg, + uint8_t short_key_length, bool is_key, bool nullable) + : Field(id, name, std::move(type), agg, nullptr, short_key_length, is_key, nullable) { + DCHECK(_agg_method != STORAGE_AGGREGATE_AGG_STATE_UNION); + } + + // Non-key field of any type except for ARRAY + Field(ColumnId id, std::string_view name, LogicalType type, int precision, int scale, bool nullable) + : Field(id, name, get_type_info(type, precision, scale), STORAGE_AGGREGATE_NONE, nullptr, 0, false, + nullable) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Non-key field of any type except for DECIMAL32, DECIMAL64, DECIMAL128, and ARRAY Field(ColumnId id, std::string_view name, LogicalType type, bool nullable) @@ -57,7 +88,11 @@ class Field { // Non-key field of any type Field(ColumnId id, std::string_view name, TypeInfoPtr type, bool nullable = true) +<<<<<<< HEAD : Field(id, name, std::move(type), STORAGE_AGGREGATE_NONE, 0, false, nullable) {} +======= + : Field(id, name, std::move(type), STORAGE_AGGREGATE_NONE, nullptr, 0, false, nullable) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~Field() { delete _sub_fields; } @@ -66,9 +101,16 @@ class Field { Field(const Field& rhs) : _id(rhs._id), _agg_method(rhs._agg_method), +<<<<<<< HEAD _name(rhs._name), _type(rhs._type), _sub_fields(rhs._sub_fields ? new Buffer(*rhs._sub_fields) : nullptr), +======= + _agg_state_desc(rhs._agg_state_desc), + _name(rhs._name), + _type(rhs._type), + _sub_fields(rhs._sub_fields ? new std::vector(*rhs._sub_fields) : nullptr), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _short_key_length(rhs._short_key_length), _flags(rhs._flags), _uid(rhs._uid) {} @@ -76,6 +118,10 @@ class Field { Field(Field&& rhs) noexcept : _id(rhs._id), _agg_method(rhs._agg_method), +<<<<<<< HEAD +======= + _agg_state_desc(rhs._agg_state_desc), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _name(std::move(rhs._name)), _type(std::move(rhs._type)), _sub_fields(rhs._sub_fields), @@ -92,9 +138,16 @@ class Field { _name = rhs._name; _type = rhs._type; _agg_method = rhs._agg_method; +<<<<<<< HEAD _short_key_length = rhs._short_key_length; _flags = rhs._flags; _sub_fields = rhs._sub_fields ? new Buffer(*rhs._sub_fields) : nullptr; +======= + _agg_state_desc = rhs._agg_state_desc; + _short_key_length = rhs._short_key_length; + _flags = rhs._flags; + _sub_fields = rhs._sub_fields ? new std::vector(*rhs._sub_fields) : nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _uid = rhs._uid; } return *this; @@ -106,6 +159,10 @@ class Field { _name = std::move(rhs._name); _type = std::move(rhs._type); _agg_method = rhs._agg_method; +<<<<<<< HEAD +======= + _agg_state_desc = rhs._agg_state_desc; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _short_key_length = rhs._short_key_length; _flags = rhs._flags; _uid = rhs._uid; @@ -171,6 +228,12 @@ class Field { void set_uid(ColumnUID uid) { _uid = uid; } const ColumnUID& uid() const { return _uid; } +<<<<<<< HEAD +======= + void set_agg_state_desc(AggStateDesc* agg_state_desc) { _agg_state_desc = agg_state_desc; } + AggStateDesc* get_agg_state_desc() const { return _agg_state_desc; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static FieldPtr convert_to_dict_field(const Field& field); private: @@ -179,6 +242,11 @@ class Field { ColumnId _id = 0; starrocks::StorageAggregateType _agg_method; +<<<<<<< HEAD +======= + // agg_state_desc if agg_method is STORAGE_AGGREGATE_AGG_STATE_UNION + AggStateDesc* _agg_state_desc; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CString _name; TypeInfoPtr _type = nullptr; std::vector* _sub_fields; @@ -225,16 +293,29 @@ inline const Field& Field::sub_field(int i) const { inline FieldPtr Field::with_type(const TypeInfoPtr& type) { return std::make_shared(_id, std::string_view(_name.data(), _name.size()), type, _agg_method, +<<<<<<< HEAD _short_key_length, is_key(), is_nullable()); } inline FieldPtr Field::with_name(std::string_view name) { return std::make_shared(_id, name, _type, _agg_method, _short_key_length, is_key(), is_nullable()); +======= + _agg_state_desc, _short_key_length, is_key(), is_nullable()); +} + +inline FieldPtr Field::with_name(std::string_view name) { + return std::make_shared(_id, name, _type, _agg_method, _agg_state_desc, _short_key_length, is_key(), + is_nullable()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } inline FieldPtr Field::with_nullable(bool nullable) { return std::make_shared(_id, std::string_view(_name.data(), _name.size()), _type, _agg_method, +<<<<<<< HEAD _short_key_length, is_key(), nullable); +======= + _agg_state_desc, _short_key_length, is_key(), nullable); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } inline std::ostream& operator<<(std::ostream& os, const Field& field) { diff --git a/be/src/column/fixed_length_column_base.cpp b/be/src/column/fixed_length_column_base.cpp index b29ab265f0e82..c3792b7110e5c 100644 --- a/be/src/column/fixed_length_column_base.cpp +++ b/be/src/column/fixed_length_column_base.cpp @@ -19,8 +19,13 @@ #include "column/vectorized_fwd.h" #include "exec/sorting/sort_helper.h" #include "gutil/casts.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" #include "storage/decimal12.h" +======= +#include "storage/decimal12.h" +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/hash_util.hpp" #include "util/mysql_row_buffer.h" #include "util/value_generator.h" @@ -29,11 +34,16 @@ namespace starrocks { template StatusOr FixedLengthColumnBase::upgrade_if_overflow() { +<<<<<<< HEAD if (capacity_limit_reached()) { return Status::InternalError("Size of FixedLengthColumn exceed the limit"); } else { return nullptr; } +======= + RETURN_IF_ERROR(capacity_limit_reached()); + return nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } template @@ -65,7 +75,11 @@ void FixedLengthColumnBase::append_value_multiple_times(const Column& src, ui //TODO(fzh): optimize copy using SIMD template +<<<<<<< HEAD ColumnPtr FixedLengthColumnBase::replicate(const std::vector& offsets) { +======= +ColumnPtr FixedLengthColumnBase::replicate(const Buffer& offsets) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto dest = this->clone_empty(); auto& dest_data = down_cast&>(*dest); dest_data._data.resize(offsets.back()); @@ -89,7 +103,11 @@ void FixedLengthColumnBase::fill_default(const Filter& filter) { } template +<<<<<<< HEAD Status FixedLengthColumnBase::fill_range(const Buffer& ids, const std::vector& filter) { +======= +Status FixedLengthColumnBase::fill_range(const std::vector& ids, const Filter& filter) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(filter.size(), _data.size()); size_t j = 0; for (size_t i = 0; i < _data.size(); ++i) { diff --git a/be/src/column/fixed_length_column_base.h b/be/src/column/fixed_length_column_base.h index 999abc44b691f..1050354d86a6f 100644 --- a/be/src/column/fixed_length_column_base.h +++ b/be/src/column/fixed_length_column_base.h @@ -21,6 +21,10 @@ #include "column/datum.h" #include "column/vectorized_fwd.h" #include "common/statusor.h" +<<<<<<< HEAD +======= +#include "gutil/strings/substitute.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/decimalv2_value.h" #include "types/date_value.hpp" #include "types/timestamp_value.h" @@ -123,8 +127,11 @@ class FixedLengthColumnBase : public ColumnFactory& slices __attribute__((unused))) override { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [[nodiscard]] bool contain_value(size_t start, size_t end, T value) const { DCHECK_LE(start, end); DCHECK_LE(start, _data.size()); @@ -157,11 +164,19 @@ class FixedLengthColumnBase : public ColumnFactory::next_value()); } +<<<<<<< HEAD ColumnPtr replicate(const std::vector& offsets) override; void fill_default(const Filter& filter) override; [[nodiscard]] Status fill_range(const Buffer& ids, const std::vector& filter); +======= + ColumnPtr replicate(const Buffer& offsets) override; + + void fill_default(const Filter& filter) override; + + Status fill_range(const std::vector& ids, const Filter& filter); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void update_rows(const Column& src, const uint32_t* indexes) override; @@ -236,6 +251,7 @@ class FixedLengthColumnBase : public ColumnFactory 2^32), but some interface such as update_rows() will use index of uint32_t to // access the item, so we should use 2^32 as the limit +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { if (_data.size() > Column::MAX_CAPACITY_LIMIT) { if (msg != nullptr) { @@ -245,6 +261,15 @@ class FixedLengthColumnBase : public ColumnFactory Column::MAX_CAPACITY_LIMIT) { + return Status::CapacityLimitExceed( + strings::Substitute("row count of fixed length column exceend the limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void check_or_die() const override {} diff --git a/be/src/column/hash_set.h b/be/src/column/hash_set.h index 965957f380641..c984a538674cf 100644 --- a/be/src/column/hash_set.h +++ b/be/src/column/hash_set.h @@ -17,6 +17,10 @@ #include #include "column/column_hash.h" +<<<<<<< HEAD +======= +#include "runtime/memory/counting_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/phmap/phmap.h" #include "util/phmap/phmap_dump.h" #include "util/slice.h" diff --git a/be/src/column/json_column.cpp b/be/src/column/json_column.cpp index 0c66c547486d1..4ae36bcf78e56 100644 --- a/be/src/column/json_column.cpp +++ b/be/src/column/json_column.cpp @@ -24,6 +24,10 @@ #include "common/compiler_util.h" #include "glog/logging.h" #include "gutil/casts.h" +<<<<<<< HEAD +======= +#include "gutil/strings/substitute.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "simd/simd.h" #include "types/logical_type.h" #include "util/hash_util.hpp" @@ -433,6 +437,7 @@ void JsonColumn::reset_column() { _path_to_index.clear(); } +<<<<<<< HEAD bool JsonColumn::capacity_limit_reached(std::string* msg) const { if (size() > Column::MAX_CAPACITY_LIMIT) { if (msg != nullptr) { @@ -441,6 +446,14 @@ bool JsonColumn::capacity_limit_reached(std::string* msg) const { return true; } return false; +======= +Status JsonColumn::capacity_limit_reached() const { + if (size() > Column::MAX_CAPACITY_LIMIT) { + return Status::CapacityLimitExceed(strings::Substitute("row count of object column exceed the limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void JsonColumn::check_or_die() const { diff --git a/be/src/column/json_column.h b/be/src/column/json_column.h index 46f832583b089..427d4f5b8ccc9 100644 --- a/be/src/column/json_column.h +++ b/be/src/column/json_column.h @@ -101,7 +101,11 @@ class JsonColumn final : public ColumnFactory, JsonColum void swap_column(Column& rhs) override; void reset_column() override; +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override; +======= + Status capacity_limit_reached() const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void check_or_die() const override; // support flat json on storage diff --git a/be/src/column/map_column.h b/be/src/column/map_column.h index 4617b225ff074..563c23fea91f6 100644 --- a/be/src/column/map_column.h +++ b/be/src/column/map_column.h @@ -86,8 +86,11 @@ class MapColumn final : public ColumnFactory { bool append_nulls(size_t count) override; +<<<<<<< HEAD bool append_strings(const Buffer& strs) override { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t append_numbers(const void* buff, size_t length) override { return -1; } void append_value_multiple_times(const void* value, size_t count) override; @@ -164,9 +167,16 @@ class MapColumn final : public ColumnFactory { std::string debug_string() const override; +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { return _keys->capacity_limit_reached(msg) || _values->capacity_limit_reached(msg) || _offsets->capacity_limit_reached(msg); +======= + Status capacity_limit_reached() const override { + RETURN_IF_ERROR(_keys->capacity_limit_reached()); + RETURN_IF_ERROR(_values->capacity_limit_reached()); + return _offsets->capacity_limit_reached(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr upgrade_if_overflow() override; diff --git a/be/src/column/nullable_column.cpp b/be/src/column/nullable_column.cpp index 9e88aceb47974..993b2fa8b7f3e 100644 --- a/be/src/column/nullable_column.cpp +++ b/be/src/column/nullable_column.cpp @@ -136,7 +136,11 @@ void NullableColumn::append_value_multiple_times(const Column& src, uint32_t ind DCHECK_EQ(_null_column->size(), _data_column->size()); } +<<<<<<< HEAD ColumnPtr NullableColumn::replicate(const std::vector& offsets) { +======= +ColumnPtr NullableColumn::replicate(const Buffer& offsets) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return NullableColumn::create(this->_data_column->replicate(offsets), std::dynamic_pointer_cast(this->_null_column->replicate(offsets))); } @@ -152,27 +156,45 @@ bool NullableColumn::append_nulls(size_t count) { return true; } +<<<<<<< HEAD bool NullableColumn::append_strings(const Buffer& strs) { if (_data_column->append_strings(strs)) { null_column_data().resize(_null_column->size() + strs.size(), 0); +======= +bool NullableColumn::append_strings(const Slice* data, size_t size) { + if (_data_column->append_strings(data, size)) { + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } DCHECK_EQ(_null_column->size(), _data_column->size()); return false; } +<<<<<<< HEAD bool NullableColumn::append_strings_overflow(const Buffer& strs, size_t max_length) { if (_data_column->append_strings_overflow(strs, max_length)) { null_column_data().resize(_null_column->size() + strs.size(), 0); +======= +bool NullableColumn::append_strings_overflow(const Slice* data, size_t size, size_t max_length) { + if (_data_column->append_strings_overflow(data, size, max_length)) { + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } DCHECK_EQ(_null_column->size(), _data_column->size()); return false; } +<<<<<<< HEAD bool NullableColumn::append_continuous_strings(const Buffer& strs) { if (_data_column->append_continuous_strings(strs)) { null_column_data().resize(_null_column->size() + strs.size(), 0); +======= +bool NullableColumn::append_continuous_strings(const Slice* data, size_t size) { + if (_data_column->append_continuous_strings(data, size)) { + null_column_data().resize(_null_column->size() + size, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } DCHECK_EQ(_null_column->size(), _data_column->size()); @@ -430,9 +452,13 @@ void NullableColumn::check_or_die() const { } StatusOr NullableColumn::upgrade_if_overflow() { +<<<<<<< HEAD if (_null_column->capacity_limit_reached()) { return Status::InternalError("Size of NullableColumn exceed the limit"); } +======= + RETURN_IF_ERROR(_null_column->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return upgrade_helper_func(&_data_column); } diff --git a/be/src/column/nullable_column.h b/be/src/column/nullable_column.h index 6c33d52e6b267..ce4ce001b9699 100644 --- a/be/src/column/nullable_column.h +++ b/be/src/column/nullable_column.h @@ -33,6 +33,11 @@ class NullableColumn : public ColumnFactory { friend class ColumnFactory; public: +<<<<<<< HEAD +======= + using ValueType = void; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) inline static ColumnPtr wrap_if_necessary(ColumnPtr column) { if (column->is_nullable()) { return column; @@ -150,11 +155,19 @@ class NullableColumn : public ColumnFactory { bool has_large_column() const override { return _data_column->has_large_column(); } +<<<<<<< HEAD bool append_strings(const Buffer& strs) override; bool append_strings_overflow(const Buffer& strs, size_t max_length) override; bool append_continuous_strings(const Buffer& strs) override; +======= + bool append_strings(const Slice* data, size_t size) override; + + bool append_strings_overflow(const Slice* data, size_t size, size_t max_length) override; + + bool append_continuous_strings(const Slice* data, size_t size) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool append_continuous_fixed_length_strings(const char* data, size_t size, int fixed_length) override; @@ -250,7 +263,11 @@ class NullableColumn : public ColumnFactory { _has_null = true; return true; } +<<<<<<< HEAD ColumnPtr replicate(const std::vector& offsets) override; +======= + ColumnPtr replicate(const Buffer& offsets) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t memory_usage() const override { return _data_column->memory_usage() + _null_column->memory_usage() + sizeof(bool); @@ -313,8 +330,14 @@ class NullableColumn : public ColumnFactory { return ss.str(); } +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { return _data_column->capacity_limit_reached(msg) || _null_column->capacity_limit_reached(msg); +======= + Status capacity_limit_reached() const override { + RETURN_IF_ERROR(_data_column->capacity_limit_reached()); + return _null_column->capacity_limit_reached(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void check_or_die() const override; diff --git a/be/src/column/object_column.cpp b/be/src/column/object_column.cpp index da13ca585a30e..5c6996e779b20 100644 --- a/be/src/column/object_column.cpp +++ b/be/src/column/object_column.cpp @@ -111,9 +111,16 @@ void ObjectColumn::append_value_multiple_times(const starrocks::Column& src, } template +<<<<<<< HEAD bool ObjectColumn::append_strings(const Buffer& strs) { _pool.reserve(_pool.size() + strs.size()); for (const Slice& s : strs) { +======= +bool ObjectColumn::append_strings(const Slice* data, size_t size) { + _pool.reserve(_pool.size() + size); + for (size_t i = 0; i < size; i++) { + const auto& s = data[i]; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _pool.emplace_back(s); } @@ -328,9 +335,13 @@ std::string ObjectColumn::debug_item(size_t idx) const { template StatusOr ObjectColumn::upgrade_if_overflow() { +<<<<<<< HEAD if (capacity_limit_reached()) { return Status::InternalError("Size of ObjectColumn exceed the limit"); } +======= + RETURN_IF_ERROR(capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return nullptr; } diff --git a/be/src/column/object_column.h b/be/src/column/object_column.h index 25ec0e851ecc7..a1ddc7916a4e9 100644 --- a/be/src/column/object_column.h +++ b/be/src/column/object_column.h @@ -20,6 +20,10 @@ #include "column/datum.h" #include "column/vectorized_fwd.h" #include "common/object_pool.h" +<<<<<<< HEAD +======= +#include "gutil/strings/substitute.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/bitmap_value.h" #include "types/hll.h" #include "util/json.h" @@ -100,7 +104,11 @@ class ObjectColumn : public ColumnFactory> { bool append_nulls(size_t count) override { return false; } +<<<<<<< HEAD bool append_strings(const Buffer& strs) override; +======= + bool append_strings(const Slice* data, size_t size) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t append_numbers(const void* buff, size_t length) override { return -1; } @@ -213,6 +221,7 @@ class ObjectColumn : public ColumnFactory> { return ss.str(); } +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override { if (_pool.size() > Column::MAX_CAPACITY_LIMIT) { if (msg != nullptr) { @@ -222,6 +231,14 @@ class ObjectColumn : public ColumnFactory> { return true; } return false; +======= + Status capacity_limit_reached() const override { + if (_pool.size() > Column::MAX_CAPACITY_LIMIT) { + return Status::CapacityLimitExceed(strings::Substitute("row count of object column exceed the limit: $0", + std::to_string(Column::MAX_CAPACITY_LIMIT))); + } + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr upgrade_if_overflow() override; @@ -230,7 +247,11 @@ class ObjectColumn : public ColumnFactory> { bool has_large_column() const override { return false; } +<<<<<<< HEAD void check_or_die() const {} +======= + void check_or_die() const override {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: // add this to avoid warning clang-diagnostic-overloaded-virtual diff --git a/be/src/column/schema.cpp b/be/src/column/schema.cpp index 92e554c86cc54..6949704e3276f 100644 --- a/be/src/column/schema.cpp +++ b/be/src/column/schema.cpp @@ -45,7 +45,14 @@ Schema::Schema(Schema* schema, const std::vector& cids) auto ori_sort_idxes = schema->sort_key_idxes(); std::unordered_set scids(ori_sort_idxes.begin(), ori_sort_idxes.end()); for (int i = 0; i < cids.size(); i++) { +<<<<<<< HEAD DCHECK_LT(cids[i], schema->_fields.size()); +======= + if (cids[i] >= schema->_fields.size()) { + _fields.resize(_fields.size() - 1); + continue; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _fields[i] = schema->_fields[cids[i]]; if (scids.find(cids[i]) != scids.end()) { _sort_key_idxes.emplace_back(i); diff --git a/be/src/column/struct_column.cpp b/be/src/column/struct_column.cpp index a921e0ed14736..def8780e916e8 100644 --- a/be/src/column/struct_column.cpp +++ b/be/src/column/struct_column.cpp @@ -194,10 +194,13 @@ bool StructColumn::append_nulls(size_t count) { return true; } +<<<<<<< HEAD bool StructColumn::append_strings(const Buffer& strs) { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t StructColumn::append_numbers(const void* buff, size_t length) { return -1; } @@ -447,12 +450,20 @@ void StructColumn::swap_column(Column& rhs) { // _field_names dont need swap } +<<<<<<< HEAD bool StructColumn::capacity_limit_reached(std::string* msg) const { bool res = false; for (const auto& column : _fields) { res = res || column->capacity_limit_reached(msg); } return res; +======= +Status StructColumn::capacity_limit_reached() const { + for (const auto& column : _fields) { + RETURN_IF_ERROR(column->capacity_limit_reached()); + } + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void StructColumn::check_or_die() const { diff --git a/be/src/column/struct_column.h b/be/src/column/struct_column.h index 77532683cc7a4..0e9122ff8b691 100644 --- a/be/src/column/struct_column.h +++ b/be/src/column/struct_column.h @@ -112,8 +112,11 @@ class StructColumn final : public ColumnFactory { [[nodiscard]] bool append_nulls(size_t count) override; +<<<<<<< HEAD [[nodiscard]] bool append_strings(const Buffer& strs) override; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [[nodiscard]] size_t append_numbers(const void* buff, size_t length) override; void append_value_multiple_times(const void* value, size_t count) override; @@ -171,7 +174,11 @@ class StructColumn final : public ColumnFactory { void reset_column() override; +<<<<<<< HEAD bool capacity_limit_reached(std::string* msg = nullptr) const override; +======= + Status capacity_limit_reached() const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void check_or_die() const override; diff --git a/be/src/column/vectorized_fwd.h b/be/src/column/vectorized_fwd.h index 1ef03c262dfdd..9ce9c10b57d96 100644 --- a/be/src/column/vectorized_fwd.h +++ b/be/src/column/vectorized_fwd.h @@ -17,6 +17,11 @@ #include #include +<<<<<<< HEAD +======= +#include "runtime/memory/column_allocator.h" + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { class DecimalV2Value; @@ -36,9 +41,18 @@ class Column; class Schema; struct ProtobufChunkMeta; +<<<<<<< HEAD // We may change the Buffer implementation in the future. template using Buffer = std::vector; +======= +template +class ColumnAllocator; + +// We may change the Buffer implementation in the future. +template +using Buffer = std::vector>; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class ArrayColumn; class ArrayViewColumn; @@ -108,6 +122,16 @@ using ChunkPtr = std::shared_ptr; using ChunkUniquePtr = std::unique_ptr; using Chunks = std::vector; +<<<<<<< HEAD +======= +class SegmentedColumn; +class SegmentedChunk; +using SegmentedColumnPtr = std::shared_ptr; +using SegmentedColumns = std::vector; +using SegmentedChunkPtr = std::shared_ptr; +using SegmentedChunkWeakPtr = std::weak_ptr; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using SchemaPtr = std::shared_ptr; using Fields = std::vector>; diff --git a/be/src/common/config.h b/be/src/common/config.h index f1a0cc5443bff..30fdc0031f5eb 100644 --- a/be/src/common/config.h +++ b/be/src/common/config.h @@ -82,7 +82,11 @@ CONF_String(mem_limit, "90%"); // Enable the jemalloc tracker, which is responsible for reserving memory CONF_Bool(enable_jemalloc_memory_tracker, "true"); +<<<<<<< HEAD // Consider part of jemalloc memory as fragmentation: ratio * (RSS-allocated-metadata) +======= +// Alpha number of jemalloc memory fragmentation ratio, should in range (0, 1) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_mDouble(jemalloc_fragmentation_ratio, "0.3"); // The port heartbeat service used. @@ -298,8 +302,11 @@ CONF_mBool(enable_bitmap_index_memory_page_cache, "false"); CONF_mBool(enable_zonemap_index_memory_page_cache, "false"); // whether to enable the ordinal index memory cache CONF_mBool(enable_ordinal_index_memory_page_cache, "false"); +<<<<<<< HEAD // whether to disable column pool CONF_Bool(disable_column_pool, "true"); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_mInt32(base_compaction_check_interval_seconds, "60"); CONF_mInt64(min_base_compaction_num_singleton_deltas, "5"); @@ -396,6 +403,11 @@ CONF_Int32(be_http_num_workers, "48"); // Period to update rate counters and sampling counters in ms. CONF_mInt32(periodic_counter_update_period_ms, "500"); +<<<<<<< HEAD +======= +CONF_Int32(arrow_flight_port, "-1"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Used for mini Load. mini load data file will be removed after this time. CONF_Int64(load_data_reserve_hours, "4"); // log error log will be removed after this time @@ -817,6 +829,11 @@ CONF_Int32(pipeline_analytic_removable_chunk_num, "128"); CONF_Bool(pipeline_analytic_enable_streaming_process, "true"); CONF_Bool(pipeline_analytic_enable_removable_cumulative_process, "true"); CONF_Int32(pipline_limit_max_delivery, "4096"); +<<<<<<< HEAD +======= + +CONF_mBool(use_default_dop_when_shared_scan, "true"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// For parallel scan on the single tablet. // These three configs are used to calculate the minimum number of rows picked up from a segment at one time. // It is `splitted_scan_bytes/scan_row_bytes` and restricted in the range [min_splitted_scan_rows, max_splitted_scan_rows]. @@ -877,6 +894,14 @@ CONF_Int64(object_storage_request_timeout_ms, "-1"); // if this parameter is 0, use object_storage_request_timeout_ms instead. CONF_Int64(object_storage_rename_file_request_timeout_ms, "30000"); +<<<<<<< HEAD +======= +// Retry strategy for read operation. The following two parameters are the default value of Aws +// DefaultRetryStrategy +CONF_Int64(object_storage_max_retries, "10"); +CONF_Int64(object_storage_retry_scale_factor, "25"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_Strings(fallback_to_hadoop_fs_list, ""); CONF_Strings(s3_compatible_fs_list, "s3n://, s3a://, s3://, oss://, cos://, cosn://, obs://, ks3://, tos://"); CONF_mBool(s3_use_list_objects_v1, "false"); @@ -907,6 +932,10 @@ CONF_mBool(parquet_coalesce_read_enable, "true"); CONF_Bool(parquet_late_materialization_enable, "true"); CONF_Bool(parquet_page_index_enable, "true"); CONF_mBool(parquet_statistics_process_more_filter_enable, "true"); +<<<<<<< HEAD +======= +CONF_mBool(parquet_advance_zonemap_filter, "true"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_Int32(io_coalesce_read_max_buffer_size, "8388608"); CONF_Int32(io_coalesce_read_max_distance_size, "1048576"); @@ -945,6 +974,12 @@ CONF_String(aws_sdk_logging_trace_level, "trace"); // Enabling RFC-3986 encoding will make sure these characters are properly encoded. CONF_Bool(aws_sdk_enable_compliant_rfc3986_encoding, "false"); +<<<<<<< HEAD +======= +// use poco client to replace default curl client +CONF_Bool(enable_poco_client_for_aws_sdk, "true"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // default: 16MB CONF_mInt64(experimental_s3_max_single_part_size, "16777216"); // default: 16MB @@ -967,6 +1002,12 @@ CONF_Int64(send_rpc_runtime_filter_timeout_ms, "1000"); // this is a default value, maybe changed by global_runtime_filter_rpc_http_min_size in session variable. CONF_Int64(send_runtime_filter_via_http_rpc_min_size, "67108864"); +<<<<<<< HEAD +======= +// -1: ulimited, 0: limit by memory use, >0: limit by queue_size +CONF_mInt64(runtime_filter_queue_limit, "-1"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_Int64(rpc_connect_timeout_ms, "30000"); CONF_Int32(max_batch_publish_latency_ms, "100"); @@ -1124,8 +1165,11 @@ CONF_mInt64(max_length_for_bitmap_function, "1000000"); CONF_Bool(datacache_enable, "true"); CONF_mString(datacache_mem_size, "0"); CONF_mString(datacache_disk_size, "0"); +<<<<<<< HEAD CONF_mString(datacache_disk_path, ""); CONF_String(datacache_meta_path, ""); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_Int64(datacache_block_size, "262144"); // 256K CONF_Bool(datacache_checksum_enable, "false"); CONF_Bool(datacache_direct_io_enable, "false"); @@ -1152,9 +1196,18 @@ CONF_Double(datacache_scheduler_threads_per_cpu, "0.125"); // For object data, such as parquet footer object, which can only be cached in memory are not affected // by this configuration. CONF_Bool(datacache_tiered_cache_enable, "true"); +<<<<<<< HEAD // DataCache engines, alternatives: cachelib, starcache. // Set the default value empty to indicate whether it is manully configured by users. // If not, we need to adjust the default engine based on build switches like "WITH_CACHELIB" and "WITH_STARCACHE". +======= +// Whether to persist cached data +CONF_Bool(datacache_persistence_enable, "true"); +// DataCache engines, alternatives: starcache. +// `cachelib` is not support now. +// Set the default value empty to indicate whether it is manully configured by users. +// If not, we need to adjust the default engine based on build switches like "WITH_STARCACHE". +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CONF_String(datacache_engine, ""); // The interval time (millisecond) for agent report datacache metrics to FE. CONF_mInt32(report_datacache_metrics_interval_ms, "60000"); @@ -1166,11 +1219,19 @@ CONF_mInt32(report_datacache_metrics_interval_ms, "60000"); // On the other hand, if the cache is full and the disk usage falls below the disk low level for a long time, // which is configured by `datacache_disk_idle_seconds_for_expansion`, the cache quota will be increased to keep the // disk usage around the disk safe level. +<<<<<<< HEAD CONF_mBool(datacache_auto_adjust_enable, "false"); // The high disk usage level, which trigger the cache eviction and quota decreased. CONF_mInt64(datacache_disk_high_level, "80"); // The safe disk usage level, the cache quota will be decreased to this level once it reach the high level. CONF_mInt64(datacache_disk_safe_level, "70"); +======= +CONF_mBool(datacache_auto_adjust_enable, "true"); +// The high disk usage level, which trigger the cache eviction and quota decreased. +CONF_mInt64(datacache_disk_high_level, "90"); +// The safe disk usage level, the cache quota will be decreased to this level once it reach the high level. +CONF_mInt64(datacache_disk_safe_level, "80"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The low disk usage level, which trigger the cache expansion and quota increased. CONF_mInt64(datacache_disk_low_level, "60"); // The interval seconds to check the disk usage and trigger adjustment. @@ -1182,6 +1243,20 @@ CONF_mInt64(datacache_disk_idle_seconds_for_expansion, "7200"); // cache quota will be reset to zero to avoid overly frequent population and eviction. // Default: 100G CONF_mInt64(datacache_min_disk_quota_for_adjustment, "107374182400"); +<<<<<<< HEAD +======= +// The maxmum inline cache item count in datacache. +// When a cache item has a really small data size, we will try to cache it inline with its metadata +// to optimize the io performance and reduce disk waste. +// Set the parameter to `0` will turn off this optimization. +CONF_Int32(datacache_inline_item_count_limit, "130172"); +// Whether use an unified datacache instance. +CONF_Bool(datacache_unified_instance_enable, "true"); +// The eviction policy for datacache, alternatives: [lru, slru]. +// * lru: the typical `Least Recently Used` eviction policy. +// * slru: segment lru eviction policies, which can better reduce cache pollution problem. +CONF_String(datacache_eviction_policy, "slru"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The following configurations will be deprecated, and we use the `datacache` prefix instead. // But it is temporarily necessary to keep them for a period of time to be compatible with @@ -1245,6 +1320,12 @@ CONF_Int64(query_cache_capacity, "536870912"); // ranges in [1,16], default value is 4. CONF_mInt32(query_cache_num_lanes_per_driver, "4"); +<<<<<<< HEAD +======= +// Used by vector query cache, 500MB in default +CONF_Int64(vector_query_cache_capacity, "536870912"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Used to limit buffer size of tablet send channel. CONF_mInt64(send_channel_buffer_limit, "67108864"); @@ -1270,6 +1351,11 @@ CONF_String(rocksdb_db_options_string, "create_if_missing=true;create_missing_co CONF_Int64(local_exchange_buffer_mem_limit_per_driver, "134217728"); // 128MB // only used for test. default: 128M CONF_mInt64(streaming_agg_limited_memory_size, "134217728"); +<<<<<<< HEAD +======= +// mem limit for partition hash join probe side buffer +CONF_mInt64(partition_hash_join_probe_limit_size, "134217728"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // pipeline streaming aggregate chunk buffer size CONF_mInt32(streaming_agg_chunk_buffer_size, "1024"); CONF_mInt64(wait_apply_time, "6000"); // 6s @@ -1343,7 +1429,11 @@ CONF_mBool(lake_enable_vertical_compaction_fill_data_cache, "false"); CONF_mInt32(dictionary_cache_refresh_timeout_ms, "60000"); // 1 min CONF_mInt32(dictionary_cache_refresh_threadpool_size, "8"); // json flat flag +<<<<<<< HEAD CONF_mBool(enable_json_flat, "false"); +======= +CONF_mBool(enable_json_flat, "true"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // enable compaction is base on flat json, not whole json CONF_mBool(enable_compaction_flat_json, "true"); @@ -1389,8 +1479,17 @@ CONF_mInt64(arrow_io_coalesce_read_max_buffer_size, "8388608"); CONF_mInt64(arrow_io_coalesce_read_max_distance_size, "1048576"); CONF_mInt64(arrow_read_batch_size, "4096"); +<<<<<<< HEAD // Set to true to enable socket_keepalive option in brpc CONF_mBool(brpc_socket_keepalive, "false"); +======= +// default not to build the empty index +CONF_mInt32(config_tenann_default_build_threshold, "0"); + +// Set to true to enable socket_keepalive option in brpc +CONF_mBool(brpc_socket_keepalive, "false"); +CONF_mBool(apply_del_vec_after_all_index_filter, "true"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // connector sink memory watermark CONF_mDouble(connector_sink_mem_high_watermark_ratio, "0.3"); @@ -1400,6 +1499,7 @@ CONF_mDouble(connector_sink_mem_urgent_space_ratio, "0.1"); // .crm file can be removed after 1day. CONF_mInt32(unused_crm_file_threshold_second, "86400" /** 1day **/); +<<<<<<< HEAD CONF_mBool(enable_pk_strict_memcheck, "true"); CONF_mBool(apply_del_vec_after_all_index_filter, "true"); @@ -1407,6 +1507,19 @@ CONF_mBool(apply_del_vec_after_all_index_filter, "true"); CONF_mBool(skip_lake_pk_preload, "false"); // Experimental feature, this configuration will be removed after testing is complete. CONF_mBool(lake_enable_alter_struct, "false"); +======= +// python envs config +// create time worker timeout +CONF_mInt32(create_child_worker_timeout_ms, "1000"); +// config ENV PYTHONPATH +CONF_Strings(python_envs, ""); +// report python worker STDERR to client +CONF_Bool(report_python_worker_error, "true"); +CONF_Bool(python_worker_reuse, "true"); +CONF_Int32(python_worker_expire_time_sec, "300"); +CONF_mBool(enable_pk_strict_memcheck, "true"); +CONF_mBool(skip_lake_pk_preload, "false"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Reduce core file size by not dumping jemalloc retain pages CONF_mBool(enable_core_file_size_optimization, "true"); // Current supported modules: @@ -1423,6 +1536,22 @@ CONF_mBool(enable_core_file_size_optimization, "true"); // * means release all above CONF_mString(try_release_resource_before_core_dump, "data_cache"); +<<<<<<< HEAD +======= +// Experimental feature, this configuration will be removed after testing is complete. +CONF_mBool(lake_enable_alter_struct, "true"); + +// vector index +// Enable caching index blocks for IVF-family vector indexes +CONF_mBool(enable_vector_index_block_cache, "true"); + +// concurrency of building index +CONF_mInt32(config_vector_index_build_concurrency, "8"); + +// default not to build the empty index +CONF_mInt32(config_vector_index_default_build_threshold, "0"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // When upgrade thrift to 0.20.0, the MaxMessageSize member defines the maximum size of a (received) message, in bytes. // The default value is represented by a constant named DEFAULT_MAX_MESSAGE_SIZE, whose value is 100 * 1024 * 1024 bytes. // This will cause FE to fail during deserialization when the returned result set is larger than 100M. Therefore, @@ -1448,6 +1577,7 @@ CONF_mInt32(lake_compaction_chunk_size, "4096"); CONF_mBool(skip_schema_in_rowset_meta, "true"); +<<<<<<< HEAD CONF_mInt32(max_committed_without_schema_rowset, "1000"); // ignore union type tag in avro kafka routine load @@ -1455,6 +1585,27 @@ CONF_mBool(avro_ignore_union_type_tag, "false"); CONF_mInt32(apply_version_slow_log_sec, "30"); +======= +CONF_mBool(enable_bit_unpack_simd, "true"); + +CONF_mInt32(max_committed_without_schema_rowset, "1000"); + +CONF_mInt32(apply_version_slow_log_sec, "30"); + +CONF_Int32(batch_write_thread_pool_num_min, "0"); +CONF_Int32(batch_write_thread_pool_num_max, "512"); +CONF_Int32(batch_write_thread_pool_queue_size, "4096"); +CONF_mInt32(batch_write_default_timeout_ms, "600000"); +CONF_mInt32(batch_write_rpc_request_retry_num, "10"); +CONF_mInt32(batch_write_rpc_request_retry_interval_ms, "500"); +CONF_mInt32(batch_write_rpc_reqeust_timeout_ms, "10000"); +CONF_mInt32(batch_write_poll_load_status_interval_ms, "200"); +CONF_mBool(batch_write_trace_log_enable, "false"); + +// ignore union type tag in avro kafka routine load +CONF_mBool(avro_ignore_union_type_tag, "false"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // default batch size for simdjson lib CONF_mInt32(json_parse_many_batch_size, "1000000"); CONF_mBool(enable_dynamic_batch_size_for_json_parse_many, "true"); diff --git a/be/src/common/daemon.cpp b/be/src/common/daemon.cpp index ec88d6b70c3c8..1cf0b4d166a60 100644 --- a/be/src/common/daemon.cpp +++ b/be/src/common/daemon.cpp @@ -38,7 +38,10 @@ #include "block_cache/block_cache.h" #include "column/column_helper.h" +<<<<<<< HEAD #include "column/column_pool.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/config.h" #include "common/minidump.h" #include "common/process_exit.h" @@ -73,6 +76,7 @@ namespace starrocks { DEFINE_bool(cn, false, "start as compute node"); +<<<<<<< HEAD class ReleaseColumnPool { public: explicit ReleaseColumnPool(double ratio) : _ratio(ratio) {} @@ -103,6 +107,8 @@ void gc_memory(void* arg_this) { } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /* * This thread will calculate some metrics at a fix interval(15 sec) * 1. push bytes per second @@ -177,7 +183,13 @@ void calculate_metrics(void* arg_this) { datacache_mem_bytes = datacache_metrics.mem_used_bytes + datacache_metrics.meta_used_bytes; } #ifdef USE_STAROS +<<<<<<< HEAD datacache_mem_bytes += staros::starlet::fslib::star_cache_get_memory_usage(); +======= + if (!config::datacache_unified_instance_enable) { + datacache_mem_bytes += staros::starlet::fslib::star_cache_get_memory_usage(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #endif datacache_mem_tracker->set(datacache_mem_bytes); } @@ -186,16 +198,26 @@ void calculate_metrics(void* arg_this) { LOG(INFO) << fmt::format( "Current memory statistics: process({}), query_pool({}), load({}), " +<<<<<<< HEAD "metadata({}), compaction({}), schema_change({}), column_pool({}), " +======= + "metadata({}), compaction({}), schema_change({}), " +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) "page_cache({}), update({}), chunk_allocator({}), passthrough({}), clone({}), consistency({}), " "datacache({}), jit({})", mem_metrics->process_mem_bytes.value(), mem_metrics->query_mem_bytes.value(), mem_metrics->load_mem_bytes.value(), mem_metrics->metadata_mem_bytes.value(), mem_metrics->compaction_mem_bytes.value(), mem_metrics->schema_change_mem_bytes.value(), +<<<<<<< HEAD mem_metrics->column_pool_mem_bytes.value(), mem_metrics->storage_page_cache_mem_bytes.value(), mem_metrics->update_mem_bytes.value(), mem_metrics->chunk_allocator_mem_bytes.value(), mem_metrics->passthrough_mem_bytes.value(), mem_metrics->clone_mem_bytes.value(), mem_metrics->consistency_mem_bytes.value(), datacache_mem_bytes, +======= + mem_metrics->storage_page_cache_mem_bytes.value(), mem_metrics->update_mem_bytes.value(), + mem_metrics->chunk_allocator_mem_bytes.value(), mem_metrics->passthrough_mem_bytes.value(), + mem_metrics->clone_mem_bytes.value(), mem_metrics->consistency_mem_bytes.value(), datacache_mem_bytes, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) mem_metrics->jit_cache_mem_bytes.value()); nap_sleep(15, [daemon] { return daemon->stopped(); }); @@ -241,17 +263,26 @@ static void retrieve_jemalloc_stats(JemallocStats* stats) { // Tracker the memory usage of jemalloc void jemalloc_tracker_daemon(void* arg_this) { auto* daemon = static_cast(arg_this); +<<<<<<< HEAD +======= + double smoothed_fragmentation = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) while (!daemon->stopped()) { JemallocStats stats; retrieve_jemalloc_stats(&stats); +<<<<<<< HEAD // metadata +======= + // Jemalloc metadata +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (GlobalEnv::GetInstance()->jemalloc_metadata_traker() && stats.metadata > 0) { auto tracker = GlobalEnv::GetInstance()->jemalloc_metadata_traker(); int64_t delta = stats.metadata - tracker->consumption(); tracker->consume(delta); } +<<<<<<< HEAD // fragmentation if (GlobalEnv::GetInstance()->jemalloc_fragmentation_traker()) { if (stats.resident > 0 && stats.allocated > 0 && stats.metadata > 0) { @@ -263,6 +294,28 @@ void jemalloc_tracker_daemon(void* arg_this) { if (released_a_lot) { fragmentation = 0; } +======= + // Fragmentation and dirty memory: + // Jemalloc retains some dirty memory and gradually returns it to the OS, which cannot be reused by the application. + // Failing to account for this memory in the MemoryTracker may lead to memory allocation failures or even process + // termination by the OS; however, retaining excessive memory in the tracker is also wasteful. + // To address this, we employ a smoothing formula to track fragmentation and dirty memory, which also mitigates + // the impact of sudden memory releases, such as those occurring when a large query is executed: + // S_t = \exp\left(\alpha \cdot \log(1 + x_t) + (1 - \alpha) \cdot \log(1 + S_{t-1})\right) - 1 + if (GlobalEnv::GetInstance()->jemalloc_fragmentation_traker()) { + if (stats.resident > 0 && stats.allocated > 0 && stats.metadata > 0) { + double fragmentation = stats.resident - stats.allocated - stats.metadata; + if (fragmentation < 0) fragmentation = 0; + + // log transformation + double alpha = std::clamp(config::jemalloc_fragmentation_ratio, 0.1, 0.9); + fragmentation = std::log1p(fragmentation); + // smoothing + fragmentation = alpha * fragmentation + smoothed_fragmentation * (1 - alpha); + // restore the log value + smoothed_fragmentation = fragmentation; + fragmentation = std::expm1(fragmentation); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (fragmentation >= 0) { auto tracker = GlobalEnv::GetInstance()->jemalloc_fragmentation_traker(); @@ -378,10 +431,13 @@ void Daemon::init(bool as_cn, const std::vector& paths) { TimezoneUtils::init_time_zones(); +<<<<<<< HEAD std::thread gc_thread(gc_memory, this); Thread::set_thread_name(gc_thread, "gc_daemon"); _daemon_threads.emplace_back(std::move(gc_thread)); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) init_starrocks_metrics(paths); if (config::enable_metric_calculator) { diff --git a/be/src/common/format_ip.h b/be/src/common/format_ip.h new file mode 100644 index 0000000000000..a9c8297a10ec7 --- /dev/null +++ b/be/src/common/format_ip.h @@ -0,0 +1,86 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +constexpr size_t IPV4_BINARY_LENGTH = 4; +constexpr int IPV4_MAX_OCTET_VALUE = 255; //max value of octet +constexpr size_t IPV4_OCTET_BITS = 8; +constexpr size_t DECIMAL_BASE = 10; + +namespace starrocks { + +inline bool is_numeric_ascii(char c) { + // This is faster than + // return UInt8(UInt8(c) - UInt8('0')) < UInt8(10); + // on Intel CPUs when compiled by gcc 8. + return (c >= '0' && c <= '9'); +} + +inline bool parse_ipv4(const char* pos, size_t str_len, int64_t& dst, int64_t first_octet = -1) { + if (pos == nullptr || first_octet > IPV4_MAX_OCTET_VALUE) { + return false; + } + + int64_t result = 0; + int offset = (IPV4_BINARY_LENGTH - 1) * IPV4_OCTET_BITS; + + if (first_octet >= 0) { + result |= first_octet << offset; + offset -= IPV4_OCTET_BITS; + } + + if (str_len < 7 || str_len > 15) { + return false; + } + + size_t i = 0; + for (; i < str_len; offset -= IPV4_OCTET_BITS, ++pos, ++i) { + int64_t value = 0; + size_t len = 0; + + while (i < str_len && is_numeric_ascii(*pos) && len <= 3) { + value = value * DECIMAL_BASE + (*pos - '0'); + ++len; + ++pos; + ++i; + } + + if (len == 0 || value > IPV4_MAX_OCTET_VALUE || (offset > 0 && *pos != '.')) { + return false; + } + + result |= value << offset; + + if (offset == 0) { + break; + } + } + + while (i < str_len) { + if (*pos != '\0') { + return false; + } + ++pos; + ++i; + } + + dst = result; + return true; +} + +} // namespace starrocks diff --git a/be/src/common/logconfig.cpp b/be/src/common/logconfig.cpp index b1c7bfb094b21..a4e1388e57ef4 100644 --- a/be/src/common/logconfig.cpp +++ b/be/src/common/logconfig.cpp @@ -156,9 +156,12 @@ static void failure_handler_after_output_log() { } static void failure_writer(const char* data, size_t size) { +<<<<<<< HEAD if (config::enable_core_file_size_optimization) { dontdump_unused_pages(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) dump_trace_info(); [[maybe_unused]] auto wt = write(STDERR_FILENO, data, size); } diff --git a/be/src/common/logging.h b/be/src/common/logging.h index 81e96a83a78aa..9257cd480b3e7 100644 --- a/be/src/common/logging.h +++ b/be/src/common/logging.h @@ -71,9 +71,15 @@ // Define VLOG levels. We want display per-row info less than per-file which // is less than per-query. For now per-connection is the same as per-query. +<<<<<<< HEAD #define VLOG_CONNECTION VLOG(1) #define VLOG_RPC VLOG(8) #define VLOG_QUERY VLOG(1) +======= +#define VLOG_CONNECTION VLOG(2) +#define VLOG_RPC VLOG(8) +#define VLOG_QUERY VLOG(2) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #define VLOG_FILE VLOG(2) #define VLOG_OPERATOR VLOG(3) #define VLOG_ROW VLOG(10) diff --git a/be/src/common/status.cpp b/be/src/common/status.cpp index 0b26f50833855..fb772021468fb 100644 --- a/be/src/common/status.cpp +++ b/be/src/common/status.cpp @@ -259,6 +259,11 @@ std::string Status::code_as_string() const { return "JIT compile error"; case TStatusCode::CAPACITY_LIMIT_EXCEED: return "Capaticy limit exceeded"; +<<<<<<< HEAD +======= + case TStatusCode::SHUTDOWN: + return "Shut down in progress"; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) case TStatusCode::BIG_QUERY_CPU_SECOND_LIMIT_EXCEEDED: return "Big query cpu second limit exceeded"; case TStatusCode::BIG_QUERY_SCAN_ROWS_LIMIT_EXCEEDED: diff --git a/be/src/common/status.h b/be/src/common/status.h index 759d13acbe495..4ec6484a04fb7 100644 --- a/be/src/common/status.h +++ b/be/src/common/status.h @@ -151,6 +151,11 @@ class STATUS_ATTRIBUTE Status { static Status CapacityLimitExceed(std::string_view msg) { return Status(TStatusCode::CAPACITY_LIMIT_EXCEED, msg); } +<<<<<<< HEAD +======= + static Status Shutdown(std::string_view msg) { return Status(TStatusCode::SHUTDOWN, msg); } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static Status BigQueryCpuSecondLimitExceeded(std::string_view msg) { return Status(TStatusCode::BIG_QUERY_CPU_SECOND_LIMIT_EXCEEDED, msg); } @@ -210,6 +215,11 @@ class STATUS_ATTRIBUTE Status { bool is_yield() const { return code() == TStatusCode::YIELD; } +<<<<<<< HEAD +======= + bool is_shutdown() const { return code() == TStatusCode::SHUTDOWN; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Convert into TStatus. Call this if 'status_container' contains an optional // TStatus field named 'status'. This also sets __isset.status. template diff --git a/be/src/common/vlog_cntl.h b/be/src/common/vlog_cntl.h new file mode 100644 index 0000000000000..b42e4d398e07e --- /dev/null +++ b/be/src/common/vlog_cntl.h @@ -0,0 +1,46 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include + +#include "common/config.h" +#include "gutil/macros.h" + +namespace starrocks { +class VLogCntl { +public: + static VLogCntl& getInstance() { + static VLogCntl log_module; + return log_module; + } + + DISALLOW_COPY_AND_MOVE(VLogCntl); + + void setLogLevel(const std::string& module, int level) { google::SetVLOGLevel(module.c_str(), level); } + + void enable(const std::string& module) { + int32_t vlog_level = config::sys_log_verbose_level; + google::SetVLOGLevel(module.c_str(), vlog_level); + } + + void disable(const std::string& module) { google::SetVLOGLevel(module.c_str(), 0); } + +private: + VLogCntl() = default; +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/connector/CMakeLists.txt b/be/src/connector/CMakeLists.txt index 5db1d68ab0c2e..f89cdef265555 100644 --- a/be/src/connector/CMakeLists.txt +++ b/be/src/connector/CMakeLists.txt @@ -31,4 +31,8 @@ add_library(Connector STATIC utils.cpp async_flush_stream_poller.cpp sink_memory_manager.cpp +<<<<<<< HEAD +======= + deletion_vector/deletion_vector.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ) diff --git a/be/src/connector/connector.cpp b/be/src/connector/connector.cpp index cdf1278267f11..1932a1058ed43 100644 --- a/be/src/connector/connector.cpp +++ b/be/src/connector/connector.cpp @@ -110,6 +110,7 @@ void DataSource::update_profile(const Profile& profile) { StatusOr DataSourceProvider::convert_scan_range_to_morsel_queue( const std::vector& scan_ranges, int node_id, int32_t pipeline_dop, bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, +<<<<<<< HEAD size_t num_total_scan_ranges, size_t scan_dop) { peek_scan_ranges(scan_ranges); @@ -122,6 +123,15 @@ StatusOr DataSourceProvider::convert_scan_range_to_mor morsels.emplace_back(std::make_unique(node_id, scan_range)); } } +======= + size_t num_total_scan_ranges, size_t scan_parallelism) { + peek_scan_ranges(scan_ranges); + + pipeline::Morsels morsels; + bool has_more_morsel = false; + pipeline::ScanMorsel::build_scan_morsels(node_id, scan_ranges, accept_empty_scan_ranges(), &morsels, + &has_more_morsel); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (partition_order_hint().has_value()) { bool asc = partition_order_hint().value(); @@ -143,9 +153,15 @@ StatusOr DataSourceProvider::convert_scan_range_to_mor }); } +<<<<<<< HEAD auto morsel_queue = std::make_unique(std::move(morsels)); if (scan_dop > 0) { morsel_queue->set_max_degree_of_parallelism(scan_dop); +======= + auto morsel_queue = std::make_unique(std::move(morsels), has_more_morsel); + if (scan_parallelism > 0) { + morsel_queue->set_max_degree_of_parallelism(scan_parallelism); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return morsel_queue; } diff --git a/be/src/connector/connector.h b/be/src/connector/connector.h index 4fd4a64073add..2bc4e3258d3c7 100644 --- a/be/src/connector/connector.h +++ b/be/src/connector/connector.h @@ -172,6 +172,7 @@ class DataSourceProvider { virtual StatusOr convert_scan_range_to_morsel_queue( const std::vector& scan_ranges, int node_id, int32_t pipeline_dop, bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, +<<<<<<< HEAD size_t num_total_scan_ranges, size_t scan_dop = 0); bool could_split() const { return _could_split; } @@ -179,6 +180,10 @@ class DataSourceProvider { bool could_split_physically() const { return _could_split_physically; } int64_t get_splitted_scan_rows() const { return splitted_scan_rows; } +======= + size_t num_total_scan_ranges, size_t scan_parallelism = 0); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t get_scan_dop() const { return scan_dop; } // possible physical distribution optimize of data source @@ -189,9 +194,12 @@ class DataSourceProvider { protected: std::vector _partition_exprs; +<<<<<<< HEAD bool _could_split = false; bool _could_split_physically = false; int64_t splitted_scan_rows = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t scan_dop = 0; }; using DataSourceProviderPtr = std::unique_ptr; diff --git a/be/src/connector/deletion_vector/deletion_vector.cpp b/be/src/connector/deletion_vector/deletion_vector.cpp new file mode 100644 index 0000000000000..b24835af2399e --- /dev/null +++ b/be/src/connector/deletion_vector/deletion_vector.cpp @@ -0,0 +1,170 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "deletion_vector.h" + +#include + +#include "util/base85.h" +#include "util/uuid_generator.h" + +namespace starrocks { + +Status starrocks::DeletionVector::fill_row_indexes(std::set* need_skip_rowids) { + if (_deletion_vector_descriptor->__isset.cardinality && _deletion_vector_descriptor->__isset.cardinality == 0) { + return Status::OK(); + } else if (is_inline()) { + return deserialized_inline_dv(_deletion_vector_descriptor->pathOrInlineDv, need_skip_rowids); + } else { + std::shared_ptr shared_buffered_input_stream = nullptr; + std::shared_ptr cache_input_stream = nullptr; + HdfsScanStats app_scan_stats; + HdfsScanStats fs_scan_stats; + + ASSIGN_OR_RETURN(auto path, get_absolute_path(_params.table_location)); + int64_t offset = _deletion_vector_descriptor->offset; + int64_t length = _deletion_vector_descriptor->sizeInBytes; + + ASSIGN_OR_RETURN(auto dv_file, open_random_access_file(path, fs_scan_stats, app_scan_stats, + shared_buffered_input_stream, cache_input_stream)); + // Check the dv size + uint32_t size_from_deletion_vector_file; + RETURN_IF_ERROR(dv_file->read_at_fully(offset, &size_from_deletion_vector_file, DV_SIZE_LENGTH)); + offset += DV_SIZE_LENGTH; + // the size_from_deletion_vector_file is big endian byte order + if (LittleEndian::IsLittleEndian()) { + size_from_deletion_vector_file = BigEndian::ToHost32(size_from_deletion_vector_file); + } + + if (size_from_deletion_vector_file != length) { + std::stringstream ss; + ss << "DV size mismatch, expected : " << length << " , actual : " << size_from_deletion_vector_file; + return Status::RuntimeError(ss.str()); + } + + // Check the correctness of magic number + uint32_t magic_number_from_deletion_vector_file; + RETURN_IF_ERROR(dv_file->read_at_fully(offset, &magic_number_from_deletion_vector_file, MAGIC_NUMBER_LENGTH)); + // magic_number_from_deletion_vector_file is little endian byte order + if (!LittleEndian::IsLittleEndian()) { + magic_number_from_deletion_vector_file = LittleEndian::ToHost32(magic_number_from_deletion_vector_file); + } + offset += MAGIC_NUMBER_LENGTH; + + int64_t serialized_bitmap_length = length - MAGIC_NUMBER_LENGTH; + std::unique_ptr deletion_vector(new char[serialized_bitmap_length]); + RETURN_IF_ERROR(dv_file->read_at_fully(offset, deletion_vector.get(), serialized_bitmap_length)); + + return deserialized_deletion_vector(magic_number_from_deletion_vector_file, std::move(deletion_vector), + serialized_bitmap_length, need_skip_rowids); + } +} + +StatusOr> DeletionVector::open_random_access_file( + const std::string& file_path, HdfsScanStats& fs_scan_stats, HdfsScanStats& app_scan_stats, + std::shared_ptr& shared_buffered_input_stream, + std::shared_ptr& cache_input_stream) const { + const OpenFileOptions options{.fs = _params.fs, + .path = file_path, + .fs_stats = &fs_scan_stats, + .app_stats = &app_scan_stats, + .datacache_options = _params.datacache_options}; + ASSIGN_OR_RETURN(auto file, + HdfsScanner::create_random_access_file(shared_buffered_input_stream, cache_input_stream, options)); + std::vector io_ranges{}; + int64_t offset = _deletion_vector_descriptor->offset; + int64_t length = _deletion_vector_descriptor->sizeInBytes + DV_SIZE_LENGTH; + while (offset < length) { + const int64_t remain_length = std::min(static_cast(config::io_coalesce_read_max_buffer_size), length); + io_ranges.emplace_back(offset, remain_length); + offset += remain_length; + } + + RETURN_IF_ERROR(shared_buffered_input_stream->set_io_ranges(io_ranges)); + return file; +} + +Status DeletionVector::deserialized_inline_dv(std::string& encoded_bitmap_data, + std::set* need_skip_rowids) const { + ASSIGN_OR_RETURN(auto decoded_bitmap_data, base85_decode(encoded_bitmap_data)); + uint32_t inline_magic_number; + memcpy(&inline_magic_number, decoded_bitmap_data.data(), DeletionVector::MAGIC_NUMBER_LENGTH); + + int64_t serialized_bitmap_length = decoded_bitmap_data.size() - MAGIC_NUMBER_LENGTH; + std::unique_ptr deletion_vector(new char[serialized_bitmap_length]); + memcpy(deletion_vector.get(), decoded_bitmap_data.data() + MAGIC_NUMBER_LENGTH, serialized_bitmap_length); + + return deserialized_deletion_vector(inline_magic_number, std::move(deletion_vector), serialized_bitmap_length, + need_skip_rowids); +} + +Status DeletionVector::deserialized_deletion_vector(uint32_t magic_number, std::unique_ptr serialized_dv, + int64_t serialized_bitmap_length, + std::set* need_skip_rowids) const { + if (magic_number != MAGIC_NUMBER) { + std::stringstream ss; + ss << "Unexpected magic number : " << magic_number; + return Status::RuntimeError(ss.str()); + } + + // Construct the roaring bitmap of corresponding deletion vector + roaring64_bitmap_t* bitmap = + roaring64_bitmap_portable_deserialize_safe(serialized_dv.get(), serialized_bitmap_length); + if (bitmap == nullptr) { + return Status::RuntimeError("deserialize roaring64 bitmap error"); + } + + // Construct _need_skip_rowids from bitmap + uint64_t bitmap_cardinality = roaring64_bitmap_get_cardinality(bitmap); + std::unique_ptr bitmap_array(new uint64_t[bitmap_cardinality]); + roaring64_bitmap_to_uint64_array(bitmap, bitmap_array.get()); + need_skip_rowids->insert(bitmap_array.get(), bitmap_array.get() + bitmap_cardinality); + + roaring64_bitmap_free(bitmap); + return Status::OK(); +} + +StatusOr DeletionVector::get_absolute_path(const std::string& table_location) const { + std::string& storage_type = _deletion_vector_descriptor->storageType; + std::string& path = _deletion_vector_descriptor->pathOrInlineDv; + if (storage_type == "u") { + uint32_t random_prefix_len = path.length() - ENCODED_UUID_LENGTH; + std::string random_prefix = path.substr(0, random_prefix_len); + std::string encoded_uuid = path.substr(random_prefix_len); + ASSIGN_OR_RETURN(auto decoded_uuid, base85_decode(encoded_uuid)); + if (decoded_uuid.length() < 16) { + return Status::RuntimeError("decoded uuid length less than 16"); + } + boost::uuids::uuid uuid{}; + memcpy(uuid.data, decoded_uuid.data(), 8); + memcpy(uuid.data + 8, decoded_uuid.data() + 8, 8); + return assemble_deletion_vector_path(table_location, boost::uuids::to_string(uuid), random_prefix); + } else if (storage_type == "p") { + return path; + } else { + return Status::RuntimeError(fmt::format("unsupported storage type {}", storage_type)); + } +} + +std::string DeletionVector::assemble_deletion_vector_path(const string& table_location, string&& uuid, + string& prefix) const { + std::string file_name = fmt::format("deletion_vector_{}.bin", uuid); + if (prefix.empty()) { + return fmt::format("{}/{}", table_location, file_name); + } else { + return fmt::format("{}/{}/{}", table_location, prefix, file_name); + } +} + +} // namespace starrocks diff --git a/be/src/connector/deletion_vector/deletion_vector.h b/be/src/connector/deletion_vector/deletion_vector.h new file mode 100644 index 0000000000000..7fb241b34b76c --- /dev/null +++ b/be/src/connector/deletion_vector/deletion_vector.h @@ -0,0 +1,57 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "common/status.h" +#include "exec/hdfs_scanner.h" +#include "fs/fs.h" + +namespace starrocks { + +class DeletionVector { +public: + DeletionVector(const HdfsScannerParams& scanner_params) + : _deletion_vector_descriptor(scanner_params.deletion_vector_descriptor), _params(scanner_params) {} + + Status fill_row_indexes(std::set* need_skip_rowids); + Status deserialized_inline_dv(std::string& encoded_bitmap_data, std::set* need_skip_rowids) const; + StatusOr get_absolute_path(const std::string& table_location) const; + + const bool is_inline() { + return _deletion_vector_descriptor->__isset.storageType && _deletion_vector_descriptor->storageType == "i"; + } + + static const int32_t DV_SIZE_LENGTH = 4; + static const int32_t MAGIC_NUMBER_LENGTH = 4; + static const uint32_t MAGIC_NUMBER = 1681511377; + // UUIDs always encode into 20 characters. + static const uint32_t ENCODED_UUID_LENGTH = 20; + +private: + StatusOr> open_random_access_file( + const std::string& file_path, HdfsScanStats& fs_scan_stats, HdfsScanStats& app_scan_stats, + std::shared_ptr& shared_buffered_input_stream, + std::shared_ptr& cache_input_stream) const; + + Status deserialized_deletion_vector(uint32_t magic_number, std::unique_ptr serialized_dv, + int64_t serialized_bitmap_length, std::set* need_skip_rowids) const; + + std::string assemble_deletion_vector_path(const std::string& table_location, std::string&& uuid, + std::string& prefix) const; + + const std::shared_ptr _deletion_vector_descriptor; + const HdfsScannerParams& _params; +}; +} // namespace starrocks diff --git a/be/src/connector/hive_connector.cpp b/be/src/connector/hive_connector.cpp index 8f62e8a63f10d..2652f73c8f960 100644 --- a/be/src/connector/hive_connector.cpp +++ b/be/src/connector/hive_connector.cpp @@ -177,6 +177,10 @@ Status HiveDataSource::open(RuntimeState* state) { _init_tuples_and_slots(state); _init_counter(state); RETURN_IF_ERROR(_init_partition_values()); +<<<<<<< HEAD +======= + RETURN_IF_ERROR(_init_extended_values()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_filter_by_eval_partition_conjuncts) { _no_data = true; return Status::OK(); @@ -217,6 +221,10 @@ Status HiveDataSource::_init_conjunct_ctxs(RuntimeState* state) { _update_has_any_predicate(); RETURN_IF_ERROR(_decompose_conjunct_ctxs(state)); +<<<<<<< HEAD +======= + RETURN_IF_ERROR(_setup_all_conjunct_ctxs(state)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -274,6 +282,28 @@ Status HiveDataSource::_init_partition_values() { return Status::OK(); } +<<<<<<< HEAD +======= +Status HiveDataSource::_init_extended_values() { + if (!(_hive_table != nullptr && _has_extended_columns)) return Status::OK(); + + DCHECK(_scan_range.__isset.extended_columns); + auto& id_to_column = _scan_range.extended_columns; + DCHECK(!id_to_column.empty()); + std::vector extended_column_values; + for (const auto& id : _provider->_hdfs_scan_node.extended_slot_ids) { + DCHECK(id_to_column.contains(id)); + extended_column_values.emplace_back(id_to_column[id]); + } + + RETURN_IF_ERROR(Expr::create_expr_trees(&_pool, extended_column_values, &_extended_column_values, _runtime_state)); + RETURN_IF_ERROR(Expr::prepare(_extended_column_values, _runtime_state)); + RETURN_IF_ERROR(Expr::open(_extended_column_values, _runtime_state)); + + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int32_t HiveDataSource::scan_range_indicate_const_column_index(SlotId id) const { if (!_scan_range.__isset.identity_partition_slot_ids) { return -1; @@ -287,6 +317,22 @@ int32_t HiveDataSource::scan_range_indicate_const_column_index(SlotId id) const } } +<<<<<<< HEAD +======= +int32_t HiveDataSource::extended_column_index(SlotId id) const { + if (!_provider->_hdfs_scan_node.__isset.extended_slot_ids) { + return -1; + } + auto extended_column_ids = _provider->_hdfs_scan_node.extended_slot_ids; + auto it = std::find(extended_column_ids.begin(), extended_column_ids.end(), id); + + if (it == extended_column_ids.end()) { + return -1; + } + return it - extended_column_ids.begin(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void HiveDataSource::_init_tuples_and_slots(RuntimeState* state) { const auto& hdfs_scan_node = _provider->_hdfs_scan_node; if (hdfs_scan_node.__isset.min_max_tuple_id) { @@ -307,12 +353,21 @@ void HiveDataSource::_init_tuples_and_slots(RuntimeState* state) { _partition_index_in_hdfs_partition_columns.push_back(index); _has_partition_columns = true; _has_scan_range_indicate_const_column = true; +<<<<<<< HEAD +======= + } else if (int32_t extended_col_index = extended_column_index(slots[i]->id()); extended_col_index >= 0) { + _extended_slots.push_back(slots[i]); + _extended_index_in_chunk.push_back(i); + _index_in_extended_column.push_back(extended_col_index); + _has_extended_columns = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { _materialize_slots.push_back(slots[i]); _materialize_index_in_chunk.push_back(i); } } +<<<<<<< HEAD if (_scan_range.__isset.delete_column_slot_ids && !_scan_range.delete_column_slot_ids.empty()) { std::map id_to_slots; for (const auto& slot : _materialize_slots) { @@ -331,6 +386,8 @@ void HiveDataSource::_init_tuples_and_slots(RuntimeState* state) { } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (hdfs_scan_node.__isset.hive_column_names) { _hive_column_names = hdfs_scan_node.hive_column_names; } @@ -366,7 +423,11 @@ void HiveDataSource::_init_tuples_and_slots(RuntimeState* state) { if (_materialize_slots.size() != 1) { return false; } +<<<<<<< HEAD if (!_scan_range.delete_column_slot_ids.empty()) { +======= + if (!_scan_range.delete_files.empty() || !_scan_range.extended_columns.empty()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return false; } return true; @@ -426,6 +487,26 @@ Status HiveDataSource::_decompose_conjunct_ctxs(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD +======= +Status HiveDataSource::_setup_all_conjunct_ctxs(RuntimeState* state) { + // clone conjunct from _min_max_conjunct_ctxs & _conjunct_ctxs + // then we will generate PredicateTree based on _all_conjunct_ctxs + std::vector cloned_conjunct_ctxs; + RETURN_IF_ERROR(Expr::clone_if_not_exists(state, &_pool, _min_max_conjunct_ctxs, &cloned_conjunct_ctxs)); + for (auto* ctx : cloned_conjunct_ctxs) { + _all_conjunct_ctxs.emplace_back(ctx); + } + + cloned_conjunct_ctxs.clear(); + RETURN_IF_ERROR(Expr::clone_if_not_exists(state, &_pool, _conjunct_ctxs, &cloned_conjunct_ctxs)); + for (auto* ctx : cloned_conjunct_ctxs) { + _all_conjunct_ctxs.emplace_back(ctx); + } + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void HiveDataSource::_init_counter(RuntimeState* state) { const auto& hdfs_scan_node = _provider->_hdfs_scan_node; @@ -574,6 +655,10 @@ Status HiveDataSource::_init_scanner(RuntimeState* state) { scanner_params.fs = _pool.add(fs.release()); scanner_params.path = native_file_path; scanner_params.file_size = _scan_range.file_length; +<<<<<<< HEAD +======= + scanner_params.table_location = _hive_table->get_base_path(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) scanner_params.tuple_desc = _tuple_desc; scanner_params.materialize_slots = _materialize_slots; scanner_params.materialize_index_in_chunk = _materialize_index_in_chunk; @@ -582,6 +667,15 @@ Status HiveDataSource::_init_scanner(RuntimeState* state) { scanner_params._partition_index_in_hdfs_partition_columns = _partition_index_in_hdfs_partition_columns; scanner_params.partition_values = _partition_values; scanner_params.scanner_conjunct_ctxs = _scanner_conjunct_ctxs; +<<<<<<< HEAD +======= + + scanner_params.extended_col_slots = _extended_slots; + scanner_params.extended_col_index_in_chunk = _extended_index_in_chunk; + scanner_params.index_in_extended_columns = _index_in_extended_column; + scanner_params.extended_col_values = _extended_column_values; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) scanner_params.conjunct_ctxs_by_slot = _conjunct_ctxs_by_slot; scanner_params.slots_in_conjunct = _slots_in_conjunct; scanner_params.slots_of_mutli_slot_conjunct = _slots_of_mutli_slot_conjunct; @@ -597,6 +691,7 @@ Status HiveDataSource::_init_scanner(RuntimeState* state) { scanner_params.connector_max_split_size = state->query_options().connector_max_split_size; } +<<<<<<< HEAD if (!_equality_delete_slots.empty()) { MORParams& mor_params = scanner_params.mor_params; mor_params.tuple_desc = _tuple_desc; @@ -606,15 +701,25 @@ Status HiveDataSource::_init_scanner(RuntimeState* state) { mor_params.runtime_profile = _runtime_profile; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (const auto& delete_file : scan_range.delete_files) { scanner_params.deletes.emplace_back(&delete_file); } +<<<<<<< HEAD if (dynamic_cast(_hive_table)) { auto tbl = dynamic_cast(_hive_table); scanner_params.iceberg_schema = tbl->get_iceberg_schema(); scanner_params.iceberg_equal_delete_schema = tbl->get_iceberg_equal_delete_schema(); } +======= + if (scan_range.__isset.deletion_vector_descriptor) { + scanner_params.deletion_vector_descriptor = + std::make_shared(scan_range.deletion_vector_descriptor); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (scan_range.__isset.paimon_deletion_file && !scan_range.paimon_deletion_file.path.empty()) { scanner_params.paimon_deletion_file = std::make_shared(scan_range.paimon_deletion_file); } @@ -625,6 +730,10 @@ Status HiveDataSource::_init_scanner(RuntimeState* state) { scanner_params.can_use_any_column = _can_use_any_column; scanner_params.can_use_min_max_count_opt = _can_use_min_max_count_opt; +<<<<<<< HEAD +======= + scanner_params.all_conjunct_ctxs = _all_conjunct_ctxs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) HdfsScanner* scanner = nullptr; auto format = scan_range.file_format; @@ -641,10 +750,18 @@ Status HiveDataSource::_init_scanner(RuntimeState* state) { if (scan_range.__isset.use_odps_jni_reader) { use_odps_jni_reader = scan_range.use_odps_jni_reader; } +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool use_iceberg_jni_metadata_reader = false; if (scan_range.__isset.use_iceberg_jni_metadata_reader) { use_iceberg_jni_metadata_reader = scan_range.use_iceberg_jni_metadata_reader; } +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool use_kudu_jni_reader = false; if (scan_range.__isset.use_kudu_jni_reader) { use_kudu_jni_reader = scan_range.use_kudu_jni_reader; @@ -740,6 +857,7 @@ Status HiveDataSource::_init_chunk_if_needed(ChunkPtr* chunk, size_t n) { } *chunk = ChunkHelper::new_chunk(*_tuple_desc, n); +<<<<<<< HEAD if (!_equality_delete_slots.empty()) { std::map id_to_slots; @@ -755,6 +873,8 @@ Status HiveDataSource::_init_chunk_if_needed(ChunkPtr* chunk, size_t n) { } } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } diff --git a/be/src/connector/hive_connector.h b/be/src/connector/hive_connector.h index d6b263218ba48..15fcdc468363c 100644 --- a/be/src/connector/hive_connector.h +++ b/be/src/connector/hive_connector.h @@ -71,6 +71,10 @@ class HiveDataSource final : public DataSource { return &(const_cast(_provider)->_lazy_column_coalesce_counter); } int32_t scan_range_indicate_const_column_index(SlotId id) const; +<<<<<<< HEAD +======= + int32_t extended_column_index(SlotId id) const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t raw_rows_read() const override; int64_t num_rows_read() const override; @@ -91,11 +95,19 @@ class HiveDataSource final : public DataSource { Status _init_conjunct_ctxs(RuntimeState* state); void _update_has_any_predicate(); Status _decompose_conjunct_ctxs(RuntimeState* state); +<<<<<<< HEAD +======= + Status _setup_all_conjunct_ctxs(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _init_tuples_and_slots(RuntimeState* state); void _init_counter(RuntimeState* state); void _init_rf_counters(); Status _init_partition_values(); +<<<<<<< HEAD +======= + Status _init_extended_values(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status _init_scanner(RuntimeState* state); HdfsScanner* _create_hudi_jni_scanner(const FSOptions& options); HdfsScanner* _create_paimon_jni_scanner(const FSOptions& options); @@ -117,6 +129,11 @@ class HiveDataSource final : public DataSource { // ============ conjuncts ================= std::vector _min_max_conjunct_ctxs; +<<<<<<< HEAD +======= + // contains whole conjuncts, used to generate PredicateTree + std::vector _all_conjunct_ctxs{}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // complex conjuncts, such as contains multi slot, are evaled in scanner. std::vector _scanner_conjunct_ctxs; // conjuncts that contains only one slot. @@ -133,6 +150,10 @@ class HiveDataSource final : public DataSource { // partition conjuncts of each partition slot. std::vector _partition_conjunct_ctxs; std::vector _partition_values; +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _has_partition_conjuncts = false; bool _filter_by_eval_partition_conjuncts = false; bool _no_data = false; @@ -147,11 +168,22 @@ class HiveDataSource final : public DataSource { // partition columns. std::vector _partition_slots; +<<<<<<< HEAD // iceberg equality delete column slots. std::vector _equality_delete_slots; // iceberg equality delete column tuple desc. TupleDescriptor* _delete_column_tuple_desc; +======= + std::vector _extended_column_values; + // extended columns. + std::vector _extended_slots; + // extended column index in `tuple_desc` + std::vector _extended_index_in_chunk; + // index in extended columns + std::vector _index_in_extended_column; + bool _has_extended_columns = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // partition column index in `tuple_desc` std::vector _partition_index_in_chunk; diff --git a/be/src/connector/lake_connector.cpp b/be/src/connector/lake_connector.cpp index cd119a755904b..f09081d31564c 100644 --- a/be/src/connector/lake_connector.cpp +++ b/be/src/connector/lake_connector.cpp @@ -18,6 +18,10 @@ #include "column/column_access_path.h" #include "exec/connector_scan_node.h" +<<<<<<< HEAD +======= +#include "exec/olap_scan_prepare.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/fragment_context.h" #include "runtime/global_dict/parser.h" #include "storage/column_predicate_rewriter.h" @@ -74,11 +78,16 @@ Status LakeDataSource::open(RuntimeState* state) { } // eval const conjuncts +<<<<<<< HEAD RETURN_IF_ERROR(OlapScanConjunctsManager::eval_const_conjuncts(_conjunct_ctxs, &_status)); +======= + RETURN_IF_ERROR(ScanConjunctsManager::eval_const_conjuncts(_conjunct_ctxs, &_status)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DictOptimizeParser::rewrite_descriptor(state, _conjunct_ctxs, thrift_lake_scan_node.dict_string_id_to_int_ids, &(tuple_desc->decoded_slots())); // Init _conjuncts_manager. +<<<<<<< HEAD OlapScanConjunctsManager& cm = _conjuncts_manager; cm.conjunct_ctxs_ptr = &_conjunct_ctxs; cm.tuple_desc = tuple_desc; @@ -88,6 +97,8 @@ Status LakeDataSource::open(RuntimeState* state) { cm.runtime_state = state; cm.driver_sequence = runtime_bloom_filter_eval_context.driver_sequence; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TQueryOptions& query_options = state->query_options(); int32_t max_scan_key_num; if (query_options.__isset.max_scan_key_num && query_options.max_scan_key_num > 0) { @@ -100,8 +111,29 @@ Status LakeDataSource::open(RuntimeState* state) { enable_column_expr_predicate = thrift_lake_scan_node.enable_column_expr_predicate; } +<<<<<<< HEAD // Parse conjuncts via _conjuncts_manager. RETURN_IF_ERROR(cm.parse_conjuncts(true, max_scan_key_num, enable_column_expr_predicate)); +======= + ScanConjunctsManagerOptions opts; + opts.conjunct_ctxs_ptr = &_conjunct_ctxs; + opts.tuple_desc = tuple_desc; + opts.obj_pool = &_obj_pool; + opts.key_column_names = &thrift_lake_scan_node.sort_key_column_names; + opts.runtime_filters = _runtime_filters; + opts.runtime_state = state; + opts.scan_keys_unlimited = true; + opts.max_scan_key_num = max_scan_key_num; + opts.enable_column_expr_predicate = enable_column_expr_predicate; + opts.pred_tree_params = state->fragment_ctx()->pred_tree_params(); + opts.driver_sequence = runtime_bloom_filter_eval_context.driver_sequence; + + _conjuncts_manager = std::make_unique(std::move(opts)); + ScanConjunctsManager& cm = *_conjuncts_manager; + + // Parse conjuncts via _conjuncts_manager. + RETURN_IF_ERROR(cm.parse_conjuncts()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(build_scan_range(_runtime_state)); @@ -125,8 +157,12 @@ void LakeDataSource::close(RuntimeState* state) { } Status LakeDataSource::get_next(RuntimeState* state, ChunkPtr* chunk) { +<<<<<<< HEAD chunk->reset(ChunkHelper::new_chunk_pooled(_prj_iter->output_schema(), _runtime_state->chunk_size(), _runtime_state->use_column_pool())); +======= + chunk->reset(ChunkHelper::new_chunk_pooled(_prj_iter->output_schema(), _runtime_state->chunk_size())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* chunk_ptr = chunk->get(); do { @@ -140,11 +176,19 @@ Status LakeDataSource::get_next(RuntimeState* state, ChunkPtr* chunk) { chunk_ptr->set_slot_id_to_index(slot->id(), column_index); } +<<<<<<< HEAD if (!_not_push_down_predicates.empty()) { SCOPED_TIMER(_expr_filter_timer); size_t nrows = chunk_ptr->num_rows(); _selection.resize(nrows); RETURN_IF_ERROR(_not_push_down_predicates.evaluate(chunk_ptr, _selection.data(), 0, nrows)); +======= + if (!_non_pushdown_pred_tree.empty()) { + SCOPED_TIMER(_expr_filter_timer); + size_t nrows = chunk_ptr->num_rows(); + _selection.resize(nrows); + RETURN_IF_ERROR(_non_pushdown_pred_tree.evaluate(chunk_ptr, _selection.data(), 0, nrows)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) chunk_ptr->filter(_selection); DCHECK_CHUNK(chunk_ptr); } @@ -243,7 +287,11 @@ Status LakeDataSource::init_reader_params(const std::vector& key std::vector& reader_columns) { const TLakeScanNode& thrift_lake_scan_node = _provider->_t_lake_scan_node; bool skip_aggregation = thrift_lake_scan_node.is_preaggregation; +<<<<<<< HEAD auto parser = _obj_pool.add(new PredicateParser(_tablet_schema)); +======= + auto parser = _obj_pool.add(new OlapPredicateParser(_tablet_schema)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _params.is_pipeline = true; _params.reader_type = READER_QUERY; _params.skip_aggregation = skip_aggregation; @@ -251,6 +299,7 @@ Status LakeDataSource::init_reader_params(const std::vector& key _params.runtime_state = _runtime_state; _params.use_page_cache = !config::disable_storage_page_cache && _scan_range.fill_data_cache; _params.lake_io_opts.fill_data_cache = _scan_range.fill_data_cache; +<<<<<<< HEAD _params.runtime_range_pruner = OlapRuntimeScanRangePruner(parser, _conjuncts_manager.unarrived_runtime_filters()); _params.splitted_scan_rows = _provider->get_splitted_scan_rows(); _params.scan_dop = _provider->get_scan_dop(); @@ -258,6 +307,16 @@ Status LakeDataSource::init_reader_params(const std::vector& key ASSIGN_OR_RETURN(auto pred_tree, _conjuncts_manager.get_predicate_tree(parser, _predicate_free_pool)); decide_chunk_size(!pred_tree.empty()); _has_any_predicate = !pred_tree.empty(); +======= + _params.runtime_range_pruner = OlapRuntimeScanRangePruner(parser, _conjuncts_manager->unarrived_runtime_filters()); + _params.splitted_scan_rows = _provider->get_splitted_scan_rows(); + _params.scan_dop = _provider->get_scan_dop(); + + ASSIGN_OR_RETURN(auto pred_tree, _conjuncts_manager->get_predicate_tree(parser, _predicate_free_pool)); + decide_chunk_size(!pred_tree.empty()); + _has_any_predicate = !pred_tree.empty(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) PredicateAndNode pushdown_pred_root; PredicateAndNode non_pushdown_pred_root; pred_tree.root().partition_copy([parser](const auto& node) { return parser->can_pushdown(node); }, @@ -265,6 +324,7 @@ Status LakeDataSource::init_reader_params(const std::vector& key _params.pred_tree = PredicateTree::create(std::move(pushdown_pred_root)); _non_pushdown_pred_tree = PredicateTree::create(std::move(non_pushdown_pred_root)); +<<<<<<< HEAD for (const auto& [_, col_nodes] : _non_pushdown_pred_tree.root().col_children_map()) { for (const auto& col_node : col_nodes) { _not_push_down_predicates.add(col_node.col_pred()); @@ -277,6 +337,11 @@ Status LakeDataSource::init_reader_params(const std::vector& key GlobalDictPredicatesRewriter not_pushdown_predicate_rewriter(_not_push_down_predicates, *_params.global_dictmaps); RETURN_IF_ERROR(not_pushdown_predicate_rewriter.rewrite_predicate(&_obj_pool)); +======= + { + GlobalDictPredicatesRewriter not_pushdown_predicate_rewriter(*_params.global_dictmaps); + RETURN_IF_ERROR(not_pushdown_predicate_rewriter.rewrite_predicate(&_obj_pool, _non_pushdown_pred_tree)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // Range @@ -348,8 +413,13 @@ Status LakeDataSource::init_tablet_reader(RuntimeState* runtime_state) { _params.plan_node_id = _morsel->get_plan_node_id(); _params.scan_range = _morsel->get_scan_range(); } +<<<<<<< HEAD ASSIGN_OR_RETURN(_reader, _tablet.new_reader(std::move(child_schema), need_split, _provider->could_split_physically())); +======= + ASSIGN_OR_RETURN(_reader, _tablet.new_reader(std::move(child_schema), need_split, + _provider->could_split_physically(), _morsel->rowsets())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (reader_columns.size() == scanner_columns.size()) { _prj_iter = _reader; } else { @@ -357,8 +427,23 @@ Status LakeDataSource::init_tablet_reader(RuntimeState* runtime_state) { _prj_iter = new_projection_iterator(output_schema, _reader); } +<<<<<<< HEAD if (!_not_push_down_conjuncts.empty() || !_not_push_down_predicates.empty()) { _expr_filter_timer = ADD_TIMER(_runtime_profile, "ExprFilterTime"); +======= + if (!_not_push_down_conjuncts.empty() || !_non_pushdown_pred_tree.empty()) { + _expr_filter_timer = ADD_TIMER(_runtime_profile, "ExprFilterTime"); + + _non_pushdown_predicates_counter = ADD_COUNTER_SKIP_MERGE(_runtime_profile, "NonPushdownPredicates", + TUnit::UNIT, TCounterMergeType::SKIP_ALL); + COUNTER_SET(_non_pushdown_predicates_counter, + static_cast(_not_push_down_conjuncts.size() + _non_pushdown_pred_tree.size())); + if (runtime_state->fragment_ctx()->pred_tree_params().enable_show_in_profile) { + _runtime_profile->add_info_string( + "NonPushdownPredicateTree", + _non_pushdown_pred_tree.visit([](const auto& node) { return node.debug_string(); })); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } DCHECK(_params.global_dictmaps != nullptr); @@ -465,8 +550,13 @@ Status LakeDataSource::prune_schema_by_access_paths(Schema* schema) { Status LakeDataSource::build_scan_range(RuntimeState* state) { // Get key_ranges and not_push_down_conjuncts from _conjuncts_manager. +<<<<<<< HEAD RETURN_IF_ERROR(_conjuncts_manager.get_key_ranges(&_key_ranges)); _conjuncts_manager.get_not_push_down_conjuncts(&_not_push_down_conjuncts); +======= + RETURN_IF_ERROR(_conjuncts_manager->get_key_ranges(&_key_ranges)); + _conjuncts_manager->get_not_push_down_conjuncts(&_not_push_down_conjuncts); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(state->mutable_dict_optimize_parser()->rewrite_conjuncts(&_not_push_down_conjuncts)); int scanners_per_tablet = 64; @@ -649,6 +739,14 @@ void LakeDataSource::update_counter() { COUNTER_SET(_pushdown_predicates_counter, (int64_t)_params.pred_tree.size()); +<<<<<<< HEAD +======= + if (_runtime_state->fragment_ctx()->pred_tree_params().enable_show_in_profile) { + _runtime_profile->add_info_string( + "PushdownPredicateTree", _params.pred_tree.visit([](const auto& node) { return node.debug_string(); })); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StarRocksMetrics::instance()->query_scan_bytes.increment(_bytes_read); StarRocksMetrics::instance()->query_scan_rows.increment(_raw_rows_read); @@ -794,12 +892,21 @@ DataSourceProviderPtr LakeConnector::create_data_source_provider(ConnectorScanNo StatusOr LakeDataSourceProvider::convert_scan_range_to_morsel_queue( const std::vector& scan_ranges, int node_id, int32_t pipeline_dop, bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, +<<<<<<< HEAD size_t num_total_scan_ranges, size_t scan_dop) { int64_t lake_scan_dop = 0; if (!scan_ranges.empty() && enable_tablet_internal_parallel) { ASSIGN_OR_RETURN(_could_split, _could_tablet_internal_parallel(scan_ranges, pipeline_dop, num_total_scan_ranges, tablet_internal_parallel_mode, &lake_scan_dop, &splitted_scan_rows)); +======= + size_t num_total_scan_ranges, size_t scan_parallelism) { + int64_t lake_scan_parallelism = 0; + if (!scan_ranges.empty() && enable_tablet_internal_parallel) { + ASSIGN_OR_RETURN(_could_split, _could_tablet_internal_parallel(scan_ranges, pipeline_dop, num_total_scan_ranges, + tablet_internal_parallel_mode, + &lake_scan_parallelism, &splitted_scan_rows)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_could_split) { ASSIGN_OR_RETURN(_could_split_physically, _could_split_tablet_physically(scan_ranges)); } @@ -807,12 +914,20 @@ StatusOr LakeDataSourceProvider::convert_scan_range_to return DataSourceProvider::convert_scan_range_to_morsel_queue( scan_ranges, node_id, pipeline_dop, enable_tablet_internal_parallel, tablet_internal_parallel_mode, +<<<<<<< HEAD num_total_scan_ranges, (size_t)lake_scan_dop); +======= + num_total_scan_ranges, (size_t)lake_scan_parallelism); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr LakeDataSourceProvider::_could_tablet_internal_parallel( const std::vector& scan_ranges, int32_t pipeline_dop, size_t num_total_scan_ranges, +<<<<<<< HEAD TTabletInternalParallelMode::type tablet_internal_parallel_mode, int64_t* scan_dop, +======= + TTabletInternalParallelMode::type tablet_internal_parallel_mode, int64_t* scan_parallelism, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t* splitted_scan_rows) const { //if (_t_lake_scan_node.use_pk_index) { // return false; @@ -846,15 +961,24 @@ StatusOr LakeDataSourceProvider::_could_tablet_internal_parallel( *splitted_scan_rows = std::max(config::tablet_internal_parallel_min_splitted_scan_rows, std::min(*splitted_scan_rows, config::tablet_internal_parallel_max_splitted_scan_rows)); +<<<<<<< HEAD // scan_dop is restricted in the range [1, dop]. *scan_dop = num_table_rows / *splitted_scan_rows; *scan_dop = std::max(1, std::min(*scan_dop, pipeline_dop)); +======= + *scan_parallelism = num_table_rows / *splitted_scan_rows; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (force_split) { return true; } +<<<<<<< HEAD bool could = *scan_dop >= pipeline_dop || *scan_dop >= config::tablet_internal_parallel_min_scan_dop; +======= + bool could = + *scan_parallelism >= pipeline_dop || *scan_parallelism >= config::tablet_internal_parallel_min_scan_dop; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return could; } diff --git a/be/src/connector/lake_connector.h b/be/src/connector/lake_connector.h index 7579c6b635470..460b93f7e548f 100644 --- a/be/src/connector/lake_connector.h +++ b/be/src/connector/lake_connector.h @@ -80,8 +80,12 @@ class LakeDataSource final : public DataSource { // The conjuncts couldn't push down to storage engine std::vector _not_push_down_conjuncts; PredicateTree _non_pushdown_pred_tree; +<<<<<<< HEAD ConjunctivePredicates _not_push_down_predicates; std::vector _selection; +======= + Filter _selection; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ObjectPool _obj_pool; @@ -89,7 +93,11 @@ class LakeDataSource final : public DataSource { const std::vector* _slots = nullptr; std::vector> _key_ranges; std::vector _scanner_ranges; +<<<<<<< HEAD OlapScanConjunctsManager _conjuncts_manager; +======= + std::unique_ptr _conjuncts_manager = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) lake::VersionedTablet _tablet; TabletSchemaCSPtr _tablet_schema; @@ -151,6 +159,10 @@ class LakeDataSource final : public DataSource { RuntimeProfile::Counter* _bi_filtered_counter = nullptr; RuntimeProfile::Counter* _bi_filter_timer = nullptr; RuntimeProfile::Counter* _pushdown_predicates_counter = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* _non_pushdown_predicates_counter = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* _rowsets_read_count = nullptr; RuntimeProfile::Counter* _segments_read_count = nullptr; RuntimeProfile::Counter* _total_columns_data_page_count = nullptr; @@ -204,7 +216,11 @@ class LakeDataSourceProvider final : public DataSourceProvider { StatusOr convert_scan_range_to_morsel_queue( const std::vector& scan_ranges, int node_id, int32_t pipeline_dop, bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, +<<<<<<< HEAD size_t num_total_scan_ranges, size_t scan_dop = 0) override; +======= + size_t num_total_scan_ranges, size_t scan_parallelism = 0) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // for ut void set_lake_tablet_manager(lake::TabletManager* tablet_manager) { _tablet_manager = tablet_manager; } @@ -229,6 +245,15 @@ class LakeDataSourceProvider final : public DataSourceProvider { return std::nullopt; } +<<<<<<< HEAD +======= + bool could_split() const { return _could_split; } + + bool could_split_physically() const { return _could_split_physically; } + + int64_t get_splitted_scan_rows() const { return splitted_scan_rows; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: ConnectorScanNode* _scan_node; const TLakeScanNode _t_lake_scan_node; @@ -236,6 +261,13 @@ class LakeDataSourceProvider final : public DataSourceProvider { // for ut lake::TabletManager* _tablet_manager; +<<<<<<< HEAD +======= + bool _could_split = false; + bool _could_split_physically = false; + int64_t splitted_scan_rows = 0; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: StatusOr _could_tablet_internal_parallel(const std::vector& scan_ranges, int32_t pipeline_dop, size_t num_total_scan_ranges, diff --git a/be/src/exec/CMakeLists.txt b/be/src/exec/CMakeLists.txt index aee625ffd0dcd..d6bb4a0a8ddb0 100644 --- a/be/src/exec/CMakeLists.txt +++ b/be/src/exec/CMakeLists.txt @@ -37,8 +37,13 @@ set(EXEC_FILES tablet_sink_colocate_sender.cpp tablet_sink_index_channel.cpp tablet_sink_sender.cpp +<<<<<<< HEAD multi_olap_table_sink.cpp write_combined_txn_log.cpp +======= + write_combined_txn_log.cpp + multi_olap_table_sink.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) mysql_scanner.cpp es/es_predicate.cpp es/es_scan_reader.cpp @@ -102,7 +107,10 @@ set(EXEC_FILES hdfs_scanner_text.cpp hdfs_scanner_partition.cpp cache_select_scanner.cpp +<<<<<<< HEAD mor_processor.cpp +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) json_scanner.cpp json_parser.cpp avro_scanner.cpp @@ -113,6 +121,10 @@ set(EXEC_FILES schema_scanner.cpp schema_scan_node.cpp dictionary_cache_writer.cpp +<<<<<<< HEAD +======= + arrow_flight_batch_reader.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) iceberg/iceberg_delete_builder.cpp iceberg/iceberg_delete_file_iterator.cpp paimon/paimon_delete_file_builder.cpp diff --git a/be/src/exec/aggregate/agg_hash_map.h b/be/src/exec/aggregate/agg_hash_map.h index f9f1042c9410e..d79ec6b71d86c 100644 --- a/be/src/exec/aggregate/agg_hash_map.h +++ b/be/src/exec/aggregate/agg_hash_map.h @@ -37,8 +37,11 @@ namespace starrocks { +<<<<<<< HEAD const constexpr int32_t prefetch_threhold = 8192; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using AggDataPtr = uint8_t*; // ===================== @@ -83,9 +86,12 @@ using SliceAggTwoLevelHashMap = phmap::parallel_flat_hash_map, SliceEqual, phmap::priv::Allocator>, PHMAPN>; +<<<<<<< HEAD // This is just an empirical value based on benchmark, and you can tweak it if more proper value is found. static constexpr size_t AGG_HASH_MAP_DEFAULT_PREFETCH_DIST = 16; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static_assert(sizeof(AggDataPtr) == sizeof(size_t)); #define AGG_HASH_MAP_PRECOMPUTE_HASH_VALUES(column, prefetch_dist) \ size_t const column_size = column->size(); \ @@ -121,8 +127,12 @@ struct AggHashMapWithKey { template void build_hash_map_with_selection(size_t chunk_size, const Columns& key_columns, MemPool* pool, +<<<<<<< HEAD Func&& allocate_func, Buffer* agg_states, std::vector* not_founds) { +======= + Func&& allocate_func, Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return static_cast(this)->template compute_agg_states( chunk_size, key_columns, pool, std::forward(allocate_func), agg_states, not_founds); } @@ -130,7 +140,11 @@ struct AggHashMapWithKey { template void build_hash_map_with_selection_and_allocation(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return static_cast(this)->template compute_agg_states( chunk_size, key_columns, pool, std::forward(allocate_func), agg_states, not_founds); } @@ -160,7 +174,11 @@ struct AggHashMapWithOneNumberKeyWithNullable template void compute_agg_states(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, +<<<<<<< HEAD Buffer* agg_states, std::vector* not_founds) { +======= + Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (is_nullable) { return this->template compute_agg_states_nullable( chunk_size, key_columns, pool, std::forward(allocate_func), agg_states, not_founds); @@ -174,7 +192,11 @@ struct AggHashMapWithOneNumberKeyWithNullable template ALWAYS_NOINLINE void compute_agg_states_non_nullable(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(!key_columns[0]->is_nullable()); auto column = down_cast(key_columns[0].get()); @@ -199,7 +221,11 @@ struct AggHashMapWithOneNumberKeyWithNullable template ALWAYS_NOINLINE void compute_agg_states_nullable(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Assign not_founds vector when needs compute not founds. if constexpr (compute_not_founds) { DCHECK(not_founds); @@ -237,7 +263,11 @@ struct AggHashMapWithOneNumberKeyWithNullable // prefetch branch better performance in case with larger hash tables template ALWAYS_NOINLINE void compute_agg_prefetch(ColumnType* column, Buffer* agg_states, Func&& allocate_func, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AGG_HASH_MAP_PRECOMPUTE_HASH_VALUES(column, AGG_HASH_MAP_DEFAULT_PREFETCH_DIST); for (size_t i = 0; i < column_size; i++) { AGG_HASH_MAP_PREFETCH_HASH_VALUE(); @@ -268,7 +298,11 @@ struct AggHashMapWithOneNumberKeyWithNullable // prefetch branch better performance in case with small hash tables template ALWAYS_NOINLINE void compute_agg_noprefetch(ColumnType* column, Buffer* agg_states, +<<<<<<< HEAD Func&& allocate_func, std::vector* not_founds) { +======= + Func&& allocate_func, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t num_rows = column->size(); for (size_t i = 0; i < num_rows; i++) { FieldType key = column->get_data()[i]; @@ -296,7 +330,11 @@ struct AggHashMapWithOneNumberKeyWithNullable template ALWAYS_NOINLINE void compute_agg_through_null_data(size_t chunk_size, NullableColumn* nullable_column, Buffer* agg_states, Func&& allocate_func, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* data_column = down_cast(nullable_column->data_column().get()); const auto& null_data = nullable_column->null_column_data(); for (size_t i = 0; i < chunk_size; i++) { @@ -318,7 +356,11 @@ struct AggHashMapWithOneNumberKeyWithNullable template void _handle_data_key_column(ColumnType* data_column, size_t row, Func&& allocate_func, +<<<<<<< HEAD Buffer* agg_states, std::vector* not_founds) { +======= + Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto key = data_column->get_data()[row]; auto iter = this->hash_map.lazy_emplace(key, [&](const auto& ctor) { if constexpr (compute_not_founds) { @@ -332,7 +374,11 @@ struct AggHashMapWithOneNumberKeyWithNullable } void _handle_data_key_column_without_allocate(ColumnType* data_column, size_t row, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto key = data_column->get_data()[row]; if (auto iter = this->hash_map.find(key); iter != this->hash_map.end()) { (*agg_states)[row] = iter->second; @@ -370,7 +416,11 @@ struct AggHashMapWithOneStringKeyWithNullable using Base = AggHashMapWithKey; using KeyType = typename HashMap::key_type; using Iterator = typename HashMap::iterator; +<<<<<<< HEAD using ResultVector = typename std::vector; +======= + using ResultVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template AggHashMapWithOneStringKeyWithNullable(Args&&... args) : Base(std::forward(args)...) {} @@ -379,7 +429,11 @@ struct AggHashMapWithOneStringKeyWithNullable template void compute_agg_states(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, +<<<<<<< HEAD Buffer* agg_states, std::vector* not_founds) { +======= + Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (is_nullable) { return this->template compute_agg_states_nullable( chunk_size, key_columns, pool, std::forward(allocate_func), agg_states, not_founds); @@ -393,7 +447,11 @@ struct AggHashMapWithOneStringKeyWithNullable template ALWAYS_NOINLINE void compute_agg_states_non_nullable(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(key_columns[0]->is_binary()); auto column = down_cast(key_columns[0].get()); @@ -416,7 +474,11 @@ struct AggHashMapWithOneStringKeyWithNullable template ALWAYS_NOINLINE void compute_agg_states_nullable(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Assign not_founds vector when needs compute not founds. if constexpr (compute_not_founds) { DCHECK(not_founds); @@ -453,7 +515,11 @@ struct AggHashMapWithOneStringKeyWithNullable template ALWAYS_NOINLINE void compute_agg_prefetch(BinaryColumn* column, Buffer* agg_states, MemPool* pool, +<<<<<<< HEAD Func&& allocate_func, std::vector* not_founds) { +======= + Func&& allocate_func, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AGG_HASH_MAP_PRECOMPUTE_HASH_VALUES(column, AGG_HASH_MAP_DEFAULT_PREFETCH_DIST); for (size_t i = 0; i < column_size; i++) { AGG_HASH_MAP_PREFETCH_HASH_VALUE(); @@ -464,7 +530,11 @@ struct AggHashMapWithOneStringKeyWithNullable DCHECK(not_founds); (*not_founds)[i] = 1; } +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) strings::memcpy_inlined(pos, key.data, key.size); Slice pk{pos, key.size}; AggDataPtr pv = allocate_func(pk); @@ -484,7 +554,11 @@ struct AggHashMapWithOneStringKeyWithNullable template ALWAYS_NOINLINE void compute_agg_noprefetch(BinaryColumn* column, Buffer* agg_states, MemPool* pool, +<<<<<<< HEAD Func&& allocate_func, std::vector* not_founds) { +======= + Func&& allocate_func, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t num_rows = column->size(); for (size_t i = 0; i < num_rows; i++) { auto key = column->get_slice(i); @@ -494,7 +568,11 @@ struct AggHashMapWithOneStringKeyWithNullable DCHECK(not_founds); (*not_founds)[i] = 1; } +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) strings::memcpy_inlined(pos, key.data, key.size); Slice pk{pos, key.size}; AggDataPtr pv = allocate_func(pk); @@ -515,7 +593,11 @@ struct AggHashMapWithOneStringKeyWithNullable template ALWAYS_NOINLINE void compute_agg_through_null_data(size_t chunk_size, NullableColumn* nullable_column, Buffer* agg_states, MemPool* pool, +<<<<<<< HEAD Func&& allocate_func, std::vector* not_founds) { +======= + Func&& allocate_func, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* data_column = down_cast(nullable_column->data_column().get()); const auto& null_data = nullable_column->null_column_data(); for (size_t i = 0; i < chunk_size; i++) { @@ -538,13 +620,21 @@ struct AggHashMapWithOneStringKeyWithNullable template void _handle_data_key_column(BinaryColumn* data_column, size_t row, MemPool* pool, Func&& allocate_func, +<<<<<<< HEAD Buffer* agg_states, std::vector* not_founds) { +======= + Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto key = data_column->get_slice(row); auto iter = this->hash_map.lazy_emplace(key, [&](const auto& ctor) { if constexpr (compute_not_founds) { (*not_founds)[row] = 1; } +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) strings::memcpy_inlined(pos, key.data, key.size); Slice pk{pos, key.size}; AggDataPtr pv = allocate_func(pk); @@ -554,7 +644,11 @@ struct AggHashMapWithOneStringKeyWithNullable } void _handle_data_key_column_without_allocate(BinaryColumn* data_column, size_t row, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto key = data_column->get_slice(row); if (auto iter = this->hash_map.find(key); iter != this->hash_map.end()) { (*agg_states)[row] = iter->second; @@ -569,13 +663,21 @@ struct AggHashMapWithOneStringKeyWithNullable auto* nullable_column = down_cast(key_columns[0].get()); auto* column = down_cast(nullable_column->mutable_data_column()); keys.resize(chunk_size); +<<<<<<< HEAD column->append_strings(keys); +======= + column->append_strings(keys.data(), keys.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) nullable_column->null_column_data().resize(chunk_size); } else { DCHECK(!null_key_data); auto* column = down_cast(key_columns[0].get()); keys.resize(chunk_size); +<<<<<<< HEAD column->append_strings(keys); +======= + column->append_strings(keys.data(), keys.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -595,20 +697,32 @@ struct AggHashMapWithSerializedKey : public AggHashMapWithKey>; using KeyType = typename HashMap::key_type; using Iterator = typename HashMap::iterator; +<<<<<<< HEAD using ResultVector = typename std::vector; +======= + using ResultVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template AggHashMapWithSerializedKey(int chunk_size, Args&&... args) : Base(chunk_size, std::forward(args)...), mem_pool(std::make_unique()), +<<<<<<< HEAD buffer(mem_pool->allocate(max_one_row_size * chunk_size)), +======= + buffer(mem_pool->allocate(max_one_row_size * chunk_size + SLICE_MEMEQUAL_OVERFLOW_PADDING)), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _chunk_size(chunk_size) {} AggDataPtr get_null_key_data() { return nullptr; } template void compute_agg_states(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, +<<<<<<< HEAD Buffer* agg_states, std::vector* not_founds) { +======= + Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) slice_sizes.assign(_chunk_size, 0); // Assign not_founds vector when needs compute not founds. if constexpr (compute_not_founds) { @@ -642,7 +756,11 @@ struct AggHashMapWithSerializedKey : public AggHashMapWithKey ALWAYS_NOINLINE void compute_agg_states_by_rows(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds, size_t max_serialize_each_row) { +======= + Filter* not_founds, size_t max_serialize_each_row) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; ++i) { auto serialize_cursor = buffer; for (const auto& key_column : key_columns) { @@ -658,7 +776,11 @@ struct AggHashMapWithSerializedKey : public AggHashMapWithKeyallocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) strings::memcpy_inlined(pos, key.data, key.size); Slice pk{pos, key.size}; AggDataPtr pv = allocate_func(pk); @@ -679,7 +801,11 @@ struct AggHashMapWithSerializedKey : public AggHashMapWithKey ALWAYS_NOINLINE void compute_agg_states_by_cols(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, Buffer* agg_states, +<<<<<<< HEAD std::vector* not_founds, size_t max_serialize_each_row) { +======= + Filter* not_founds, size_t max_serialize_each_row) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) uint32_t cur_max_one_row_size = get_max_serialize_size(key_columns); if (UNLIKELY(cur_max_one_row_size > max_one_row_size)) { max_one_row_size = cur_max_one_row_size; @@ -702,7 +828,11 @@ struct AggHashMapWithSerializedKey : public AggHashMapWithKeyallocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) strings::memcpy_inlined(pos, key.data, key.size); Slice pk{pos, key.size}; AggDataPtr pv = allocate_func(pk); @@ -797,7 +927,11 @@ struct AggHashMapWithSerializedKeyFixedSize template ALWAYS_NOINLINE void compute_agg_prefetch(size_t chunk_size, const Columns& key_columns, Buffer* agg_states, Func&& allocate_func, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* buffer = reinterpret_cast(caches.data()); for (const auto& key_column : key_columns) { key_column->serialize_batch(buffer, slice_sizes, chunk_size, max_fixed_size); @@ -841,7 +975,11 @@ struct AggHashMapWithSerializedKeyFixedSize template ALWAYS_NOINLINE void compute_agg_noprefetch(size_t chunk_size, const Columns& key_columns, Buffer* agg_states, Func&& allocate_func, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) constexpr int key_size = sizeof(FixedSizeSliceKey); auto* buffer = reinterpret_cast(caches.data()); for (const auto& key_column : key_columns) { @@ -876,7 +1014,11 @@ struct AggHashMapWithSerializedKeyFixedSize template void compute_agg_states(size_t chunk_size, const Columns& key_columns, MemPool* pool, Func&& allocate_func, +<<<<<<< HEAD Buffer* agg_states, std::vector* not_founds) { +======= + Buffer* agg_states, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(fixed_byte_size != -1); slice_sizes.assign(chunk_size, 0); // Assign not_founds vector when needs compute not founds. @@ -928,7 +1070,12 @@ struct AggHashMapWithSerializedKeyFixedSize Buffer slice_sizes; std::unique_ptr mem_pool; ResultVector results; +<<<<<<< HEAD std::vector tmp_slices; +======= + Buffer tmp_slices; + // std::vector tmp_slices; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int32_t _chunk_size; }; diff --git a/be/src/exec/aggregate/agg_hash_set.h b/be/src/exec/aggregate/agg_hash_set.h index 58d6589d36784..b786c7c6fe25a 100644 --- a/be/src/exec/aggregate/agg_hash_set.h +++ b/be/src/exec/aggregate/agg_hash_set.h @@ -18,6 +18,10 @@ #include "column/column_helper.h" #include "column/hash_set.h" #include "column/type_traits.h" +<<<<<<< HEAD +======= +#include "column/vectorized_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/casts.h" #include "runtime/mem_pool.h" #include "runtime/runtime_state.h" @@ -27,6 +31,29 @@ namespace starrocks { +<<<<<<< HEAD +======= +const constexpr int32_t prefetch_threhold = 8192; +// This is just an empirical value based on benchmark, and you can tweak it if more proper value is found. +static constexpr size_t AGG_HASH_MAP_DEFAULT_PREFETCH_DIST = 16; + +#define AGG_HASH_SET_PRECOMPUTE_HASH_VALS() \ + hashes.reserve(chunk_size); \ + for (size_t i = 0; i < chunk_size; i++) { \ + hashes[i] = this->hash_set.hash_function()(keys[i]); \ + } + +#define AGG_HASH_SET_PREFETCH_HASH_VAL() \ + if (i + AGG_HASH_MAP_DEFAULT_PREFETCH_DIST < chunk_size) { \ + this->hash_set.prefetch_hash(hashes[i + AGG_HASH_MAP_DEFAULT_PREFETCH_DIST]); \ + } + +#define AGG_STRING_HASH_SET_PREFETCH_HASH_VAL() \ + if (i + AGG_HASH_MAP_DEFAULT_PREFETCH_DIST < chunk_size) { \ + this->hash_set.prefetch_hash(cache[i + AGG_HASH_MAP_DEFAULT_PREFETCH_DIST].hash); \ + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // ===================== // one level agg hash set template @@ -80,11 +107,26 @@ struct AggHashSet { } void build_hash_set_with_selection(size_t chunk_size, const Columns& key_columns, MemPool* pool, +<<<<<<< HEAD std::vector* not_founds) { +======= + Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return static_cast(this)->template build_set(chunk_size, key_columns, pool, not_founds); } }; +<<<<<<< HEAD +======= +template +struct no_prefetch_set : std::false_type {}; +template +struct no_prefetch_set> : std::true_type {}; + +template +constexpr bool is_no_prefetch_set = no_prefetch_set::value; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // handle one number hash key template struct AggHashSetOfOneNumberKey : public AggHashSet> { @@ -102,16 +144,42 @@ struct AggHashSetOfOneNumberKey : public AggHashSet +<<<<<<< HEAD void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, std::vector* not_founds) { +======= + void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(!key_columns[0]->is_nullable()); if constexpr (!compute_and_allocate) { DCHECK(not_founds); not_founds->assign(chunk_size, 0); } +<<<<<<< HEAD auto* column = down_cast(key_columns[0].get()); const size_t row_num = column->size(); auto& keys = column->get_data(); for (size_t i = 0; i < row_num; ++i) { +======= + + if constexpr (is_no_prefetch_set) { + this->template build_set_noprefetch(chunk_size, key_columns, pool, not_founds); + } else { + if (this->hash_set.bucket_count() < prefetch_threhold) { + this->template build_set_noprefetch(chunk_size, key_columns, pool, not_founds); + } else { + this->template build_set_prefetch(chunk_size, key_columns, pool, not_founds); + } + } + } + + template + ALWAYS_NOINLINE void build_set_noprefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* column = down_cast(key_columns[0].get()); + auto& keys = column->get_data(); + + for (size_t i = 0; i < chunk_size; ++i) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (compute_and_allocate) { this->hash_set.emplace(keys[i]); } else { @@ -120,6 +188,26 @@ struct AggHashSetOfOneNumberKey : public AggHashSet + ALWAYS_NOINLINE void build_set_prefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* column = down_cast(key_columns[0].get()); + auto& keys = column->get_data(); + + AGG_HASH_SET_PRECOMPUTE_HASH_VALS(); + for (size_t i = 0; i < chunk_size; ++i) { + AGG_HASH_SET_PREFETCH_HASH_VAL(); + if constexpr (compute_and_allocate) { + this->hash_set.emplace_with_hash(this->hashes[i], keys[i]); + } else { + (*not_founds)[i] = this->hash_set.find(keys[i], this->hashes[i]) == this->hash_set.end(); + } + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void insert_keys_to_columns(const ResultVector& keys, const Columns& key_columns, size_t chunk_size) { auto* column = down_cast(key_columns[0].get()); column->get_data().insert(column->get_data().end(), keys.begin(), keys.begin() + chunk_size); @@ -127,6 +215,10 @@ struct AggHashSetOfOneNumberKey : public AggHashSet hashes; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template @@ -147,7 +239,13 @@ struct AggHashSetOfOneNullableNumberKey // elements that cannot be queried are not processed, // and are mainly used in the first stage of two-stage aggregation when aggr reduction is low template +<<<<<<< HEAD void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, std::vector* not_founds) { +======= + void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, Filter* not_founds) { + DCHECK(key_columns[0]->is_nullable()); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (!compute_and_allocate) { DCHECK(not_founds); not_founds->assign(chunk_size, 0); @@ -155,6 +253,7 @@ struct AggHashSetOfOneNullableNumberKey if (key_columns[0]->only_null()) { has_null_key = true; } else { +<<<<<<< HEAD DCHECK(key_columns[0]->is_nullable()); auto* nullable_column = down_cast(key_columns[0].get()); auto* data_column = down_cast(nullable_column->data_column().get()); @@ -176,6 +275,34 @@ struct AggHashSetOfOneNullableNumberKey } } else { for (size_t i = 0; i < row_num; ++i) { +======= + if constexpr (is_no_prefetch_set) { + this->template build_set_noprefetch(chunk_size, key_columns, pool, not_founds); + } else { + if (key_columns[0]->has_null() || this->hash_set.bucket_count() < prefetch_threhold) { + this->template build_set_noprefetch(chunk_size, key_columns, pool, + not_founds); + } else { + this->template build_set_prefetch(chunk_size, key_columns, pool, not_founds); + } + } + } + } + + template + ALWAYS_NOINLINE void build_set_noprefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* nullable_column = down_cast(key_columns[0].get()); + auto* data_column = down_cast(nullable_column->data_column().get()); + const auto& null_data = nullable_column->null_column_data(); + auto& keys = data_column->get_data(); + + if (nullable_column->has_null()) { + for (size_t i = 0; i < chunk_size; ++i) { + if (null_data[i]) { + has_null_key = true; + } else { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (compute_and_allocate) { this->hash_set.emplace(keys[i]); } else { @@ -183,6 +310,35 @@ struct AggHashSetOfOneNullableNumberKey } } } +<<<<<<< HEAD +======= + } else { + for (size_t i = 0; i < chunk_size; ++i) { + if constexpr (compute_and_allocate) { + this->hash_set.emplace(keys[i]); + } else { + (*not_founds)[i] = !this->hash_set.contains(keys[i]); + } + } + } + } + + template + ALWAYS_NOINLINE void build_set_prefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* nullable_column = down_cast(key_columns[0].get()); + auto* data_column = down_cast(nullable_column->data_column().get()); + auto& keys = data_column->get_data(); + + AGG_HASH_SET_PRECOMPUTE_HASH_VALS(); + for (size_t i = 0; i < chunk_size; ++i) { + AGG_HASH_SET_PREFETCH_HASH_VAL(); + if constexpr (compute_and_allocate) { + this->hash_set.emplace_with_hash(this->hashes[i], keys[i]); + } else { + (*not_founds)[i] = this->hash_set.find(keys[i], hashes[i]) == this->hash_set.end(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -196,13 +352,21 @@ struct AggHashSetOfOneNullableNumberKey static constexpr bool has_single_null_key = true; bool has_null_key = false; ResultVector results; +<<<<<<< HEAD +======= + std::vector hashes; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template struct AggHashSetOfOneStringKey : public AggHashSet> { using Iterator = typename HashSet::iterator; using KeyType = typename HashSet::key_type; +<<<<<<< HEAD using ResultVector = typename std::vector; +======= + using ResultVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AggHashSetOfOneStringKey(int32_t chunk_size) {} @@ -211,22 +375,46 @@ struct AggHashSetOfOneStringKey : public AggHashSet +<<<<<<< HEAD void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, std::vector* not_founds) { DCHECK(key_columns[0]->is_binary()); auto* column = down_cast(key_columns[0].get()); +======= + void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, Filter* not_founds) { + DCHECK(key_columns[0]->is_binary()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (!compute_and_allocate) { DCHECK(not_founds); not_founds->assign(chunk_size, 0); } +<<<<<<< HEAD size_t row_num = column->size(); for (size_t i = 0; i < row_num; ++i) { +======= + if (this->hash_set.bucket_count() < prefetch_threhold) { + this->template build_set_noprefetch(chunk_size, key_columns, pool, not_founds); + } else { + this->template build_set_prefetch(chunk_size, key_columns, pool, not_founds); + } + } + + template + ALWAYS_NOINLINE void build_set_noprefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* column = down_cast(key_columns[0].get()); + for (size_t i = 0; i < chunk_size; ++i) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto tmp = column->get_slice(i); if constexpr (compute_and_allocate) { KeyType key(tmp); this->hash_set.lazy_emplace(key, [&](const auto& ctor) { // we must persist the slice before insert +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) memcpy(pos, key.data, key.size); ctor(pos, key.size, key.hash); }); @@ -236,21 +424,62 @@ struct AggHashSetOfOneStringKey : public AggHashSet(key_columns[0].get()); keys.resize(chunk_size); column->append_strings(keys); +======= + template + ALWAYS_NOINLINE void build_set_prefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* column = down_cast(key_columns[0].get()); + cache.reserve(chunk_size); + for (size_t i = 0; i < chunk_size; ++i) { + cache[i] = KeyType(column->get_slice(i)); + } + + for (size_t i = 0; i < chunk_size; ++i) { + AGG_STRING_HASH_SET_PREFETCH_HASH_VAL(); + const auto& key = cache[i]; + if constexpr (compute_and_allocate) { + this->hash_set.lazy_emplace_with_hash(key, key.hash, [&](const auto& ctor) { + // we must persist the slice before insert + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); + memcpy(pos, key.data, key.size); + ctor(pos, key.size, key.hash); + }); + } else { + (*not_founds)[i] = this->hash_set.find(key, key.hash) == this->hash_set.end(); + } + } + } + + void insert_keys_to_columns(ResultVector& keys, const Columns& key_columns, size_t chunk_size) { + auto* column = down_cast(key_columns[0].get()); + keys.resize(chunk_size); + column->append_strings(keys.data(), keys.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } static constexpr bool has_single_null_key = false; ResultVector results; +<<<<<<< HEAD +======= + std::vector cache; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template struct AggHashSetOfOneNullableStringKey : public AggHashSet> { using Iterator = typename HashSet::iterator; using KeyType = typename HashSet::key_type; +<<<<<<< HEAD using ResultVector = typename std::vector; +======= + // using ResultVector = typename std::vector; + using ResultVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AggHashSetOfOneNullableStringKey(int32_t chunk_size) {} @@ -259,13 +488,19 @@ struct AggHashSetOfOneNullableStringKey : public AggHashSet +<<<<<<< HEAD void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, std::vector* not_founds) { +======= + void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, Filter* not_founds) { + DCHECK(key_columns[0]->is_nullable()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (!compute_and_allocate) { DCHECK(not_founds); not_founds->assign(chunk_size, 0); } if (key_columns[0]->only_null()) { has_null_key = true; +<<<<<<< HEAD } else if (key_columns[0]->is_nullable()) { auto* nullable_column = down_cast(key_columns[0].get()); auto* data_column = down_cast(nullable_column->data_column().get()); @@ -286,6 +521,29 @@ struct AggHashSetOfOneNullableStringKey : public AggHashSethas_null() || this->hash_set.bucket_count() < prefetch_threhold) { + this->template build_set_noprefetch(chunk_size, key_columns, pool, not_founds); + } else { + this->template build_set_prefetch(chunk_size, key_columns, pool, not_founds); + } + } + } + + template + ALWAYS_NOINLINE void build_set_noprefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* nullable_column = down_cast(key_columns[0].get()); + auto* data_column = down_cast(nullable_column->data_column().get()); + const auto& null_data = nullable_column->null_column_data(); + + if (nullable_column->has_null()) { + for (size_t i = 0; i < chunk_size; ++i) { + if (null_data[i]) { + has_null_key = true; + } else { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (compute_and_allocate) { _handle_data_key_column(data_column, i, pool, not_founds); } else { @@ -293,22 +551,70 @@ struct AggHashSetOfOneNullableStringKey : public AggHashSet* not_founds) { +======= + } else { + for (size_t i = 0; i < chunk_size; ++i) { + if constexpr (compute_and_allocate) { + _handle_data_key_column(data_column, i, pool, not_founds); + } else { + _handle_data_key_column(data_column, i, not_founds); + } + } + } + } + + template + ALWAYS_NOINLINE void build_set_prefetch(size_t chunk_size, const Columns& key_columns, MemPool* pool, + Filter* not_founds) { + auto* nullable_column = down_cast(key_columns[0].get()); + auto* data_column = down_cast(nullable_column->data_column().get()); + + cache.reserve(chunk_size); + for (size_t i = 0; i < chunk_size; ++i) { + cache[i] = KeyType(data_column->get_slice(i)); + } + for (size_t i = 0; i < chunk_size; ++i) { + AGG_STRING_HASH_SET_PREFETCH_HASH_VAL(); + const auto& key = cache[i]; + if constexpr (compute_and_allocate) { + this->hash_set.lazy_emplace_with_hash(key, key.hash, [&](const auto& ctor) { + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); + memcpy(pos, key.data, key.size); + ctor(pos, key.size, key.hash); + }); + } else { + (*not_founds)[i] = this->hash_set.find(key, key.hash) == this->hash_set.end(); + } + } + } + + void _handle_data_key_column(BinaryColumn* data_column, size_t row, MemPool* pool, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto tmp = data_column->get_slice(row); KeyType key(tmp); this->hash_set.lazy_emplace(key, [&](const auto& ctor) { +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) memcpy(pos, key.data, key.size); ctor(pos, key.size, key.hash); }); } +<<<<<<< HEAD void _handle_data_key_column(BinaryColumn* data_column, size_t row, std::vector* not_founds) { +======= + void _handle_data_key_column(BinaryColumn* data_column, size_t row, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto key = data_column->get_slice(row); (*not_founds)[row] = !this->hash_set.contains(key); } @@ -318,24 +624,41 @@ struct AggHashSetOfOneNullableStringKey : public AggHashSet(key_columns[0].get()); auto* column = down_cast(nullable_column->mutable_data_column()); keys.resize(chunk_size); +<<<<<<< HEAD column->append_strings(keys); +======= + column->append_strings(keys.data(), keys.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) nullable_column->null_column_data().resize(chunk_size); } static constexpr bool has_single_null_key = true; bool has_null_key = false; ResultVector results; +<<<<<<< HEAD +======= + std::vector cache; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template struct AggHashSetOfSerializedKey : public AggHashSet> { using Iterator = typename HashSet::iterator; +<<<<<<< HEAD using ResultVector = typename std::vector; +======= + // using ResultVector = typename std::vector; + using ResultVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using KeyType = typename HashSet::key_type; AggHashSetOfSerializedKey(int32_t chunk_size) : _mem_pool(std::make_unique()), +<<<<<<< HEAD _buffer(_mem_pool->allocate(max_one_row_size * chunk_size)), +======= + _buffer(_mem_pool->allocate(max_one_row_size * chunk_size + SLICE_MEMEQUAL_OVERFLOW_PADDING)), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _chunk_size(chunk_size) {} // When compute_and_allocate=false: @@ -343,7 +666,11 @@ struct AggHashSetOfSerializedKey : public AggHashSet +<<<<<<< HEAD void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, std::vector* not_founds) { +======= + void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) slice_sizes.assign(_chunk_size, 0); if constexpr (!compute_and_allocate) { DCHECK(not_founds); @@ -363,13 +690,29 @@ struct AggHashSetOfSerializedKey : public AggHashSetserialize_batch(_buffer, slice_sizes, chunk_size, max_one_row_size); } +<<<<<<< HEAD +======= + if (this->hash_set.bucket_count() < prefetch_threhold) { + this->template build_set_noprefetch(chunk_size, pool, not_founds); + } else { + this->template build_set_prefetch(chunk_size, pool, not_founds); + } + } + + template + ALWAYS_NOINLINE void build_set_noprefetch(size_t chunk_size, MemPool* pool, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; ++i) { Slice tmp = {_buffer + i * max_one_row_size, slice_sizes[i]}; if constexpr (compute_and_allocate) { KeyType key(tmp); this->hash_set.lazy_emplace(key, [&](const auto& ctor) { // we must persist the slice before insert +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) memcpy(pos, key.data, key.size); ctor(pos, key.size, key.hash); }); @@ -379,6 +722,32 @@ struct AggHashSetOfSerializedKey : public AggHashSet + ALWAYS_NOINLINE void build_set_prefetch(size_t chunk_size, MemPool* pool, Filter* not_founds) { + cache.reserve(chunk_size); + for (size_t i = 0; i < chunk_size; ++i) { + cache[i] = KeyType(Slice(_buffer + i * max_one_row_size, slice_sizes[i])); + } + + for (size_t i = 0; i < chunk_size; ++i) { + AGG_STRING_HASH_SET_PREFETCH_HASH_VAL(); + const auto& key = cache[i]; + if constexpr (compute_and_allocate) { + this->hash_set.lazy_emplace_with_hash(key, key.hash, [&](const auto& ctor) { + // we must persist the slice before insert + uint8_t* pos = pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); + memcpy(pos, key.data, key.size); + ctor(pos, key.size, key.hash); + }); + } else { + (*not_founds)[i] = this->hash_set.find(key, key.hash) == this->hash_set.end(); + } + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t get_max_serialize_size(const Columns& key_columns) { size_t max_size = 0; for (const auto& key_column : key_columns) { @@ -418,6 +787,10 @@ struct AggHashSetOfSerializedKey : public AggHashSet cache; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template @@ -433,7 +806,11 @@ struct AggHashSetOfSerializedKeyFixedSize : public AggHashSet()), +<<<<<<< HEAD buffer(_mem_pool->allocate(max_fixed_size * chunk_size)), +======= + buffer(_mem_pool->allocate(max_fixed_size * chunk_size + SLICE_MEMEQUAL_OVERFLOW_PADDING)), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _chunk_size(chunk_size) { memset(buffer, 0x0, max_fixed_size * _chunk_size); } @@ -443,7 +820,11 @@ struct AggHashSetOfSerializedKeyFixedSize : public AggHashSet +<<<<<<< HEAD void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, std::vector* not_founds) { +======= + void build_set(size_t chunk_size, const Columns& key_columns, MemPool* pool, Filter* not_founds) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(fixed_byte_size != -1); slice_sizes.assign(chunk_size, 0); if constexpr (!compute_and_allocate) { @@ -458,7 +839,10 @@ struct AggHashSetOfSerializedKeyFixedSize : public AggHashSetserialize_batch(buffer, slice_sizes, chunk_size, max_fixed_size); } +<<<<<<< HEAD +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* key = reinterpret_cast(buffer); if (has_null_column) { @@ -467,6 +851,20 @@ struct AggHashSetOfSerializedKeyFixedSize : public AggHashSethash_set.bucket_count() < prefetch_threhold) { + this->template build_set_noprefetch(chunk_size, pool, not_founds); + } else { + this->template build_set_prefetch(chunk_size, pool, not_founds); + } + } + + template + ALWAYS_NOINLINE void build_set_noprefetch(size_t chunk_size, MemPool* pool, Filter* not_founds) { + auto* key = reinterpret_cast(buffer); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; ++i) { if constexpr (compute_and_allocate) { this->hash_set.insert(key[i]); @@ -476,6 +874,24 @@ struct AggHashSetOfSerializedKeyFixedSize : public AggHashSet + ALWAYS_NOINLINE void build_set_prefetch(size_t chunk_size, MemPool* pool, Filter* not_founds) { + auto* keys = reinterpret_cast(buffer); + AGG_HASH_SET_PRECOMPUTE_HASH_VALS(); + + for (size_t i = 0; i < chunk_size; ++i) { + AGG_HASH_SET_PREFETCH_HASH_VAL(); + if constexpr (compute_and_allocate) { + this->hash_set.emplace_with_hash(hashes[i], keys[i]); + } else { + (*not_founds)[i] = this->hash_set.find(keys[i], hashes[i]) == this->hash_set.end(); + } + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void insert_keys_to_columns(ResultVector& keys, const Columns& key_columns, int32_t chunk_size) { DCHECK(fixed_byte_size != -1); tmp_slices.reserve(chunk_size); @@ -506,9 +922,17 @@ struct AggHashSetOfSerializedKeyFixedSize : public AggHashSet _mem_pool; uint8_t* buffer; ResultVector results; +<<<<<<< HEAD std::vector tmp_slices; int32_t _chunk_size; +======= + Buffer tmp_slices; + // std::vector tmp_slices; + + int32_t _chunk_size; + std::vector hashes; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exec/aggregate/aggregate_base_node.cpp b/be/src/exec/aggregate/aggregate_base_node.cpp index b712ab1071538..da3a154642748 100644 --- a/be/src/exec/aggregate/aggregate_base_node.cpp +++ b/be/src/exec/aggregate/aggregate_base_node.cpp @@ -14,7 +14,10 @@ #include "exec/aggregate/aggregate_base_node.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/strings/substitute.h" namespace starrocks { diff --git a/be/src/exec/aggregator.cpp b/be/src/exec/aggregator.cpp index 3b71df448a188..22d5b1449176f 100644 --- a/be/src/exec/aggregator.cpp +++ b/be/src/exec/aggregator.cpp @@ -29,10 +29,20 @@ #include "exec/limited_pipeline_chunk_buffer.h" #include "exec/pipeline/operator.h" #include "exec/spill/spiller.hpp" +<<<<<<< HEAD #include "exprs/anyval_util.h" #include "gen_cpp/PlanNodes_types.h" #include "runtime/current_thread.h" #include "runtime/descriptors.h" +======= +#include "exprs/agg/agg_state_merge.h" +#include "exprs/agg/agg_state_union.h" +#include "exprs/agg/aggregate_state_allocator.h" +#include "gen_cpp/PlanNodes_types.h" +#include "runtime/current_thread.h" +#include "runtime/descriptors.h" +#include "runtime/memory/roaring_hook.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type.h" #include "udf/java/utils.h" #include "util/runtime_profile.h" @@ -42,6 +52,13 @@ namespace starrocks { static const std::unordered_set ALWAYS_NULLABLE_RESULT_AGG_FUNCS = {"variance_samp", "var_samp", "stddev_samp", "covar_samp", "corr"}; +<<<<<<< HEAD +======= +static const std::string AGG_STATE_UNION_SUFFIX = "_union"; +static const std::string AGG_STATE_MERGE_SUFFIX = "_merge"; +static const std::string FUNCTION_COUNT = "count"; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template bool AggFunctionTypes::is_result_nullable() const { if constexpr (UseIntermediateAsOutput) { @@ -149,6 +166,7 @@ void AggregatorParams::init() { for (size_t i = 0; i < agg_size; ++i) { const TExpr& desc = aggregate_functions[i]; const TFunction& fn = desc.nodes[0].fn; +<<<<<<< HEAD VLOG_ROW << fn.name.function_name << " is arg nullable " << desc.nodes[0].has_nullable_child; VLOG_ROW << fn.name.function_name << " is result nullable " << desc.nodes[0].is_nullable; @@ -167,6 +185,27 @@ void AggregatorParams::init() { const bool is_input_nullable = has_outer_join_child || desc.nodes[0].has_nullable_child; agg_fn_types[i] = {return_type, serde_type, arg_typedescs, is_input_nullable, desc.nodes[0].is_nullable}; +======= + VLOG_ROW << fn.name.function_name << ", arg nullable " << desc.nodes[0].has_nullable_child + << ", result nullable " << desc.nodes[0].is_nullable; + + if (fn.name.function_name == FUNCTION_COUNT) { + // count function is always not nullable + agg_fn_types[i] = {TypeDescriptor(TYPE_BIGINT), TypeDescriptor(TYPE_BIGINT), {}, false, false}; + } else { + // whether agg function has nullable child + const bool has_nullable_child = has_outer_join_child || desc.nodes[0].has_nullable_child; + // whether agg function is nullable + bool is_nullable = desc.nodes[0].is_nullable; + // collect arg_typedescs for aggregate function. + std::vector arg_typedescs; + for (auto& type : fn.arg_types) { + arg_typedescs.push_back(TypeDescriptor::from_thrift(type)); + } + TypeDescriptor return_type = TypeDescriptor::from_thrift(fn.ret_type); + TypeDescriptor serde_type = TypeDescriptor::from_thrift(fn.aggregate_fn.intermediate_type); + agg_fn_types[i] = {return_type, serde_type, arg_typedescs, has_nullable_child, is_nullable}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) agg_fn_types[i].is_always_nullable_result = ALWAYS_NULLABLE_RESULT_AGG_FUNCS.contains(fn.name.function_name); if (fn.name.function_name == "array_agg" || fn.name.function_name == "group_concat") { @@ -201,7 +240,13 @@ void AggregatorParams::init() { #define ALIGN_TO(size, align) ((size + align - 1) / align * align) #define PAD(size, align) (align - (size % align)) % align; +<<<<<<< HEAD Aggregator::Aggregator(AggregatorParamsPtr params) : _params(std::move(params)) {} +======= +Aggregator::Aggregator(AggregatorParamsPtr params) : _params(std::move(params)) { + _allocator = std::make_unique(); +} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status Aggregator::open(RuntimeState* state) { if (_is_opened) { @@ -351,7 +396,10 @@ Status Aggregator::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile } bool has_outer_join_child = _params->has_outer_join_child; +<<<<<<< HEAD VLOG_ROW << "has_outer_join_child " << has_outer_join_child; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t group_by_size = _group_by_expr_ctxs.size(); _group_by_columns.resize(group_by_size); @@ -377,6 +425,7 @@ Status Aggregator::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile const TFunction& fn = desc.nodes[0].fn; const auto& agg_fn_type = _agg_fn_types[i]; _is_merge_funcs[i] = aggregate_functions[i].nodes[0].agg_expr.is_merge_agg; +<<<<<<< HEAD // get function if (fn.name.function_name == "count") { bool is_input_nullable = @@ -431,6 +480,13 @@ Status Aggregator::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile << return_type; _agg_functions[i] = func; } +======= + + // get function + bool is_result_nullable = _is_agg_result_nullable(desc, agg_fn_type); + RETURN_IF_ERROR(_create_aggregate_function(state, fn, is_result_nullable, &_agg_functions[i])); + VLOG_ROW << "has_outer_join_child " << has_outer_join_child << ", is_result_nullable " << is_result_nullable; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int node_idx = 0; for (int j = 0; j < desc.nodes[0].num_children; ++j) { @@ -488,14 +544,42 @@ Status Aggregator::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile // Initial for FunctionContext of every aggregate functions for (int i = 0; i < _agg_fn_ctxs.size(); ++i) { +<<<<<<< HEAD _agg_fn_ctxs[i] = FunctionContext::create_context( state, _mem_pool.get(), AnyValUtil::column_type_to_type_desc(_agg_fn_types[i].result_type), _agg_fn_types[i].arg_typedescs, _agg_fn_types[i].is_distinct, _agg_fn_types[i].is_asc_order, _agg_fn_types[i].nulls_first); +======= + auto& agg_fn_type = _agg_fn_types[i]; + auto& agg_func = _agg_functions[i]; + TypeDescriptor return_type = agg_fn_type.result_type; + std::vector arg_types = agg_fn_type.arg_typedescs; + + const AggStateDesc* agg_state_desc = nullptr; + if (dynamic_cast(agg_func)) { + auto* agg_state_union = down_cast(agg_func); + agg_state_desc = agg_state_union->get_agg_state_desc(); + } else if (dynamic_cast(agg_func)) { + auto* agg_state_merge = down_cast(agg_func); + agg_state_desc = agg_state_merge->get_agg_state_desc(); + } + if (agg_state_desc != nullptr) { + return_type = agg_state_desc->get_return_type(); + arg_types = agg_state_desc->get_arg_types(); + } + + _agg_fn_ctxs[i] = + FunctionContext::create_context(state, _mem_pool.get(), return_type, arg_types, agg_fn_type.is_distinct, + agg_fn_type.is_asc_order, agg_fn_type.nulls_first); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (state->query_options().__isset.group_concat_max_len) { _agg_fn_ctxs[i]->set_group_concat_max_len(state->query_options().group_concat_max_len); } state->obj_pool()->add(_agg_fn_ctxs[i]); +<<<<<<< HEAD +======= + _agg_fn_ctxs[i]->set_mem_usage_counter(&_agg_state_mem_usage); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // save TFunction object @@ -512,6 +596,93 @@ Status Aggregator::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile return Status::OK(); } +<<<<<<< HEAD +======= +bool Aggregator::_is_agg_result_nullable(const TExpr& desc, const AggFunctionTypes& agg_func_type) { + const TFunction& fn = desc.nodes[0].fn; + // NOTE: For count, we cannot use agg_func_type since it's only mocked valeus. + if (fn.name.function_name == FUNCTION_COUNT) { + if (fn.arg_types.empty()) { + return false; + } + return _params->has_outer_join_child || desc.nodes[0].has_nullable_child; + } else { + return agg_func_type.use_nullable_fn(_use_intermediate_as_output()); + } +} + +Status Aggregator::_create_aggregate_function(starrocks::RuntimeState* state, const TFunction& fn, + bool is_result_nullable, const AggregateFunction** ret) { + std::vector arg_types; + for (auto& type : fn.arg_types) { + arg_types.push_back(TypeDescriptor::from_thrift(type)); + } + + // check whether it's _merge/_union combinator if it contains agg state type + auto& func_name = fn.name.function_name; + if (fn.__isset.agg_state_desc) { + if (arg_types.size() != 1) { + return Status::InternalError(strings::Substitute("Invalid agg function plan: $0 with (arg type $1)", + func_name, arg_types.size())); + } + auto agg_state_desc = AggStateDesc::from_thrift(fn.agg_state_desc); + auto nested_func_name = agg_state_desc.get_func_name(); + if (nested_func_name + AGG_STATE_MERGE_SUFFIX == func_name) { + // aggregate _merge combinator + auto* nested_func = AggStateDesc::get_agg_state_func(&agg_state_desc); + if (nested_func == nullptr) { + return Status::InternalError( + strings::Substitute("Merge combinator function $0 fails to get the nested agg func: $1 ", + func_name, nested_func_name)); + } + auto merge_agg_func = std::make_shared(std::move(agg_state_desc), nested_func); + *ret = merge_agg_func.get(); + _combinator_function.emplace_back(std::move(merge_agg_func)); + } else if (nested_func_name + AGG_STATE_UNION_SUFFIX == func_name) { + // aggregate _union combinator + auto* nested_func = AggStateDesc::get_agg_state_func(&agg_state_desc); + if (nested_func == nullptr) { + return Status::InternalError( + strings::Substitute("Union combinator function $0 fails to get the nested agg func: $1 ", + func_name, nested_func_name)); + } + auto union_agg_func = std::make_shared(std::move(agg_state_desc), nested_func); + *ret = union_agg_func.get(); + _combinator_function.emplace_back(std::move(union_agg_func)); + } else { + return Status::InternalError( + strings::Substitute("Agg function combinator is not implemented: $0 ", func_name)); + } + } else { + // get function + if (func_name == FUNCTION_COUNT) { + auto* func = get_aggregate_function(FUNCTION_COUNT, TYPE_BIGINT, TYPE_BIGINT, is_result_nullable); + if (func == nullptr) { + return Status::InternalError(strings::Substitute("Invalid agg function plan: $0 ", func_name)); + } + *ret = func; + } else { + TypeDescriptor return_type = TypeDescriptor::from_thrift(fn.ret_type); + TypeDescriptor serde_type = TypeDescriptor::from_thrift(fn.aggregate_fn.intermediate_type); + DCHECK_LE(1, fn.arg_types.size()); + TypeDescriptor arg_type = arg_types[0]; + auto* func = get_aggregate_function(func_name, return_type, arg_types, is_result_nullable, fn.binary_type, + state->func_version()); + if (func == nullptr) { + return Status::InternalError(strings::Substitute( + "Invalid agg function plan: $0 with (arg type $1, serde type $2, result type $3, nullable $4)", + func_name, type_to_string(arg_type.type), type_to_string(serde_type.type), + type_to_string(return_type.type), is_result_nullable ? "true" : "false")); + } + *ret = func; + VLOG_ROW << "get agg function " << func->get_name() << " serde_type " << serde_type << " return_type " + << return_type; + } + } + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status Aggregator::reset_state(starrocks::RuntimeState* state, const std::vector& refill_chunks, pipeline::Operator* refill_op, bool reset_sink_complete) { RETURN_IF_ERROR(_reset_state(state, reset_sink_complete)); @@ -529,6 +700,10 @@ Status Aggregator::reset_state(starrocks::RuntimeState* state, const std::vector } Status Aggregator::_reset_state(RuntimeState* state, bool reset_sink_complete) { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_ht_eos = false; _num_input_rows = 0; _is_prepared = false; @@ -563,6 +738,10 @@ Status Aggregator::_reset_state(RuntimeState* state, bool reset_sink_complete) { } _mem_pool->free_all(); +<<<<<<< HEAD +======= + _agg_state_mem_usage = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_group_by_expr_ctxs.empty()) { _single_agg_state = _mem_pool->allocate_aligned(_agg_states_total_size, _max_agg_state_align_size); @@ -622,6 +801,10 @@ void Aggregator::close(RuntimeState* state) { if (_mem_pool != nullptr) { // Note: we must free agg_states object before _mem_pool free_all; if (_single_agg_state != nullptr) { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (int i = 0; i < _agg_functions.size(); i++) { _agg_functions[i]->destroy(_agg_fn_ctxs[i], _single_agg_state + _agg_states_offsets[i]); } @@ -746,6 +929,10 @@ Status Aggregator::compute_single_agg_state(Chunk* chunk, size_t chunk_size) { for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { // evaluate arguments at i-th agg function RETURN_IF_ERROR(evaluate_agg_input_column(chunk, agg_expr_ctxs[i], i)); +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // batch call update or merge for singe stage if (!_is_merge_funcs[i] && !use_intermediate) { _agg_functions[i]->update_batch_single_state(_agg_fn_ctxs[i], chunk_size, _agg_input_raw_columns[i].data(), @@ -768,6 +955,10 @@ Status Aggregator::compute_batch_agg_states(Chunk* chunk, size_t chunk_size) { for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { // evaluate arguments at i-th agg function RETURN_IF_ERROR(evaluate_agg_input_column(chunk, agg_expr_ctxs[i], i)); +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // batch call update or merge if (!_is_merge_funcs[i] && !use_intermediate) { _agg_functions[i]->update_batch(_agg_fn_ctxs[i], chunk_size, _agg_states_offsets[i], @@ -789,7 +980,11 @@ Status Aggregator::compute_batch_agg_states_with_selection(Chunk* chunk, size_t for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { RETURN_IF_ERROR(evaluate_agg_input_column(chunk, agg_expr_ctxs[i], i)); +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!_is_merge_funcs[i] && !use_intermediate) { _agg_functions[i]->update_batch_selectively(_agg_fn_ctxs[i], chunk_size, _agg_states_offsets[i], _agg_input_raw_columns[i].data(), _tmp_agg_states.data(), @@ -822,6 +1017,10 @@ Status Aggregator::convert_to_chunk_no_groupby(ChunkPtr* chunk) { // TODO(kks): we should approve memory allocate here auto use_intermediate = _use_intermediate_as_output(); Columns agg_result_column = _create_agg_result_columns(1, use_intermediate); +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!use_intermediate) { TRY_CATCH_BAD_ALLOC(_finalize_to_chunk(_single_agg_state, agg_result_column)); } else { @@ -905,8 +1104,16 @@ Status Aggregator::output_chunk_by_streaming(Chunk* input_chunk, ChunkPtr* chunk DCHECK(i < _agg_input_columns.size() && _agg_input_columns[i].size() >= 1); result_chunk->append_column(std::move(_agg_input_columns[i][0]), slot_id); } else { +<<<<<<< HEAD _agg_functions[i]->convert_to_serialize_format(_agg_fn_ctxs[i], _agg_input_columns[i], result_chunk->num_rows(), &agg_result_column[i]); +======= + { + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); + _agg_functions[i]->convert_to_serialize_format(_agg_fn_ctxs[i], _agg_input_columns[i], + result_chunk->num_rows(), &agg_result_column[i]); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) result_chunk->append_column(std::move(agg_result_column[i]), slot_id); } } @@ -1073,6 +1280,10 @@ void Aggregator::_finalize_to_chunk(ConstAggDataPtr __restrict state, const Colu } void Aggregator::_destroy_state(AggDataPtr __restrict state) { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { _agg_functions[i]->destroy(_agg_fn_ctxs[i], state + _agg_states_offsets[i]); } @@ -1401,6 +1612,10 @@ Status Aggregator::convert_hash_map_to_chunk(int32_t chunk_size, ChunkPtr* chunk { SCOPED_TIMER(_agg_stat->agg_append_timer); +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!use_intermediate) { for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { TRY_CATCH_BAD_ALLOC(_agg_functions[i]->batch_finalize(_agg_fn_ctxs[i], read_index, @@ -1429,7 +1644,11 @@ Status Aggregator::convert_hash_map_to_chunk(int32_t chunk_size, ChunkPtr* chunk DCHECK(group_by_columns.size() == 1); DCHECK(group_by_columns[0]->is_nullable()); group_by_columns[0]->append_default(); +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!use_intermediate) { TRY_CATCH_BAD_ALLOC(_finalize_to_chunk(hash_map_with_key.null_key_data, agg_result_columns)); } else { @@ -1538,6 +1757,10 @@ void Aggregator::_release_agg_memory() { // If all function states are of POD type, // then we don't have to traverse the hash table to call destroy method. // +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _hash_map_variant.visit([&](auto& hash_map_with_key) { bool skip_destroy = std::all_of(_agg_functions.begin(), _agg_functions.end(), [](auto* func) { return func->is_pod_state(); }); diff --git a/be/src/exec/aggregator.h b/be/src/exec/aggregator.h index 24157df7f8ca4..97034ace164f3 100644 --- a/be/src/exec/aggregator.h +++ b/be/src/exec/aggregator.h @@ -42,6 +42,10 @@ #include "runtime/current_thread.h" #include "runtime/descriptors.h" #include "runtime/mem_pool.h" +<<<<<<< HEAD +======= +#include "runtime/memory/counting_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/runtime_state.h" #include "runtime/types.h" #include "util/defer_op.h" @@ -266,8 +270,13 @@ class Aggregator : public pipeline::ContextWithDependency { } } +<<<<<<< HEAD [[nodiscard]] virtual Status open(RuntimeState* state); [[nodiscard]] Status prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* runtime_profile); +======= + virtual Status open(RuntimeState* state); + Status prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* runtime_profile); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state) override; const MemPool* mem_pool() const { return _mem_pool.get(); } @@ -293,12 +302,23 @@ class Aggregator : public pipeline::ContextWithDependency { bool is_hash_set() const { return _is_only_group_by_columns; } const int64_t hash_map_memory_usage() const { return _hash_map_variant.reserved_memory_usage(mem_pool()); } const int64_t hash_set_memory_usage() const { return _hash_set_variant.reserved_memory_usage(mem_pool()); } +<<<<<<< HEAD const int64_t memory_usage() const { if (is_hash_set()) { return hash_set_memory_usage(); } else if (!_group_by_expr_ctxs.empty()) { return hash_map_memory_usage(); +======= + const int64_t agg_state_memory_usage() const { return _agg_state_mem_usage; } + const int64_t allocator_memory_usage() const { return _allocator->memory_usage(); } + + const int64_t memory_usage() const { + if (is_hash_set()) { + return hash_set_memory_usage() + agg_state_memory_usage() + allocator_memory_usage(); + } else if (!_group_by_expr_ctxs.empty()) { + return hash_map_memory_usage() + agg_state_memory_usage() + allocator_memory_usage(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { return 0; } @@ -309,7 +329,11 @@ class Aggregator : public pipeline::ContextWithDependency { const AggHashMapVariant& hash_map_variant() { return _hash_map_variant; } const AggHashSetVariant& hash_set_variant() { return _hash_set_variant; } std::any& it_hash() { return _it_hash; } +<<<<<<< HEAD const std::vector& streaming_selection() { return _streaming_selection; } +======= + const Filter& streaming_selection() { return _streaming_selection; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* agg_compute_timer() { return _agg_stat->agg_compute_timer; } RuntimeProfile::Counter* agg_expr_timer() { return _agg_stat->agg_function_compute_timer; } RuntimeProfile::Counter* streaming_timer() { return _agg_stat->streaming_timer; } @@ -329,6 +353,7 @@ class Aggregator : public pipeline::ContextWithDependency { int64_t ht_rows) const; // For aggregate without group by +<<<<<<< HEAD [[nodiscard]] Status compute_single_agg_state(Chunk* chunk, size_t chunk_size); // For aggregate with group by [[nodiscard]] Status compute_batch_agg_states(Chunk* chunk, size_t chunk_size); @@ -348,13 +373,38 @@ class Aggregator : public pipeline::ContextWithDependency { // convert input chunk to spill format [[nodiscard]] Status convert_to_spill_format(Chunk* input_chunk, ChunkPtr* chunk); +======= + Status compute_single_agg_state(Chunk* chunk, size_t chunk_size); + // For aggregate with group by + Status compute_batch_agg_states(Chunk* chunk, size_t chunk_size); + Status compute_batch_agg_states_with_selection(Chunk* chunk, size_t chunk_size); + + // Convert one row agg states to chunk + Status convert_to_chunk_no_groupby(ChunkPtr* chunk); + + void process_limit(ChunkPtr* chunk); + + Status evaluate_groupby_exprs(Chunk* chunk); + Status evaluate_agg_fn_exprs(Chunk* chunk); + Status evaluate_agg_fn_exprs(Chunk* chunk, bool use_intermediate); + Status evaluate_agg_input_column(Chunk* chunk, std::vector& agg_expr_ctxs, int i); + + Status output_chunk_by_streaming(Chunk* input_chunk, ChunkPtr* chunk); + + // convert input chunk to spill format + Status convert_to_spill_format(Chunk* input_chunk, ChunkPtr* chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Elements queried in HashTable will be added to HashTable, // elements that cannot be queried are not processed, // and are mainly used in the first stage of two-stage aggregation when aggr reduction is low // selection[i] = 0: found in hash table // selection[1] = 1: not found in hash table +<<<<<<< HEAD [[nodiscard]] Status output_chunk_by_streaming_with_selection(Chunk* input_chunk, ChunkPtr* chunk); +======= + Status output_chunk_by_streaming_with_selection(Chunk* input_chunk, ChunkPtr* chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // At first, we use single hash map, if hash map is too big, // we convert the single hash map to two level hash map. @@ -362,7 +412,11 @@ class Aggregator : public pipeline::ContextWithDependency { void try_convert_to_two_level_map(); void try_convert_to_two_level_set(); +<<<<<<< HEAD [[nodiscard]] Status check_has_error(); +======= + Status check_has_error(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_aggr_mode(AggrMode aggr_mode) { _aggr_mode = aggr_mode; } // reset_state is used to clear the internal state of the Aggregator, then it can process new tablet, in @@ -372,8 +426,13 @@ class Aggregator : public pipeline::ContextWithDependency { // refill_chunk: partial-hit result of stale version. // refill_op: pre-cache agg operator, Aggregator's holder. // reset_sink_complete: reset sink_complete state. sometimes if operator sink has complete we don't have to reset sink state +<<<<<<< HEAD [[nodiscard]] Status reset_state(RuntimeState* state, const std::vector& refill_chunks, pipeline::Operator* refill_op, bool reset_sink_complete = true); +======= + Status reset_state(RuntimeState* state, const std::vector& refill_chunks, pipeline::Operator* refill_op, + bool reset_sink_complete = true); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const AggregatorParamsPtr& params() const { return _params; } @@ -407,6 +466,11 @@ class Aggregator : public pipeline::ContextWithDependency { ObjectPool* _pool; std::unique_ptr _mem_pool; +<<<<<<< HEAD +======= + // used to count heap memory usage of agg states + std::unique_ptr _allocator; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The open phase still relies on the TFunction object for some initialization operations std::vector _fns; @@ -490,7 +554,11 @@ class Aggregator : public pipeline::ContextWithDependency { AggrMode _aggr_mode = AM_DEFAULT; bool _is_passthrough = false; bool _is_pending_reset_state = false; +<<<<<<< HEAD std::vector _streaming_selection; +======= + Filter _streaming_selection; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _has_udaf = false; @@ -500,14 +568,26 @@ class Aggregator : public pipeline::ContextWithDependency { SpillProcessChannelPtr _spill_channel; bool _is_opened = false; bool _is_prepared = false; +<<<<<<< HEAD +======= + int64_t _agg_state_mem_usage = 0; + + // aggregate combinator functions since they are not persisted in agg hash map + std::vector _combinator_function; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: void build_hash_map(size_t chunk_size, bool agg_group_by_with_limit = false); void build_hash_map(size_t chunk_size, std::atomic& shared_limit_countdown, bool agg_group_by_with_limit); void build_hash_map_with_selection(size_t chunk_size); void build_hash_map_with_selection_and_allocation(size_t chunk_size, bool agg_group_by_with_limit = false); +<<<<<<< HEAD [[nodiscard]] Status convert_hash_map_to_chunk(int32_t chunk_size, ChunkPtr* chunk, bool force_use_intermediate_as_output = false); +======= + Status convert_hash_map_to_chunk(int32_t chunk_size, ChunkPtr* chunk, + bool force_use_intermediate_as_output = false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void build_hash_set(size_t chunk_size); void build_hash_set_with_selection(size_t chunk_size); @@ -534,10 +614,17 @@ class Aggregator : public pipeline::ContextWithDependency { return _aggr_mode == AM_STREAMING_PRE_CACHE || _aggr_mode == AM_BLOCKING_PRE_CACHE || !_needs_finalize; } +<<<<<<< HEAD [[nodiscard]] Status _reset_state(RuntimeState* state, bool reset_sink_complete); // initial const columns for i'th FunctionContext. [[nodiscard]] Status _evaluate_const_columns(int i); +======= + Status _reset_state(RuntimeState* state, bool reset_sink_complete); + + // initial const columns for i'th FunctionContext. + Status _evaluate_const_columns(int i); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Create new aggregate function result column by type Columns _create_agg_result_columns(size_t num_rows, bool use_intermediate); @@ -558,7 +645,11 @@ class Aggregator : public pipeline::ContextWithDependency { bool is_pending_reset_state() { return _is_pending_reset_state; } void _reset_exprs(); +<<<<<<< HEAD [[nodiscard]] Status _evaluate_group_by_exprs(Chunk* chunk); +======= + Status _evaluate_group_by_exprs(Chunk* chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Choose different agg hash map/set by different group by column's count, type, nullable template @@ -566,6 +657,14 @@ class Aggregator : public pipeline::ContextWithDependency { void _release_agg_memory(); +<<<<<<< HEAD +======= + bool _is_agg_result_nullable(const TExpr& desc, const AggFunctionTypes& agg_func_type); + + Status _create_aggregate_function(starrocks::RuntimeState* state, const TFunction& fn, bool is_result_nullable, + const AggregateFunction** ret); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template friend struct AllocateState; }; diff --git a/be/src/exec/analytor.cpp b/be/src/exec/analytor.cpp index de63a0dae3c36..7187c842ba179 100644 --- a/be/src/exec/analytor.cpp +++ b/be/src/exec/analytor.cpp @@ -22,9 +22,15 @@ #include "column/column_helper.h" #include "common/config.h" #include "common/status.h" +<<<<<<< HEAD #include "exprs/agg/count.h" #include "exprs/agg/window.h" #include "exprs/anyval_util.h" +======= +#include "exprs/agg/aggregate_state_allocator.h" +#include "exprs/agg/count.h" +#include "exprs/agg/window.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr.h" #include "exprs/expr_context.h" #include "exprs/function_context.h" @@ -123,6 +129,20 @@ Status Analytor::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* if (_tnode.analytic_node.__isset.sql_aggregate_functions) { _runtime_profile->add_info_string("AggregateFunctions", _tnode.analytic_node.sql_aggregate_functions); } +<<<<<<< HEAD +======= + + _is_merge_funcs = _tnode.analytic_node.analytic_functions[0].nodes[0].agg_expr.is_merge_agg; + if (_is_merge_funcs) { + for (size_t i = 1; i < _tnode.analytic_node.analytic_functions.size(); i++) { + DCHECK(_tnode.analytic_node.analytic_functions[i].nodes[0].agg_expr.is_merge_agg); + } + } + if (_is_merge_funcs) { + _runtime_profile->add_info_string("isMerge", "true"); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _mem_pool = std::make_unique(); const TAnalyticNode& analytic_node = _tnode.analytic_node; @@ -180,6 +200,12 @@ Status Analytor::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* return_type = TYPE_DOUBLE; } is_input_nullable = !fn.arg_types.empty() && (desc.nodes[0].has_nullable_child || has_outer_join_child); +<<<<<<< HEAD +======= + if (_is_merge_funcs && fn.name.function_name == "count") { + is_input_nullable = false; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* func = get_window_function(fn.name.function_name, TYPE_BIGINT, return_type, is_input_nullable, fn.binary_type, state->func_version()); _agg_functions[i] = func; @@ -191,6 +217,7 @@ Status Analytor::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* const TypeDescriptor return_type = TypeDescriptor::from_thrift(fn.ret_type); const TypeDescriptor arg_type = TypeDescriptor::from_thrift(fn.arg_types[0]); +<<<<<<< HEAD auto return_typedesc = AnyValUtil::column_type_to_type_desc(return_type); // Collect arg_typedescs for aggregate function. std::vector arg_typedescs; @@ -199,6 +226,15 @@ Status Analytor::prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* } _agg_fn_ctxs[i] = FunctionContext::create_context(state, _mem_pool.get(), return_typedesc, arg_typedescs); +======= + // Collect arg_typedescs for aggregate function. + std::vector arg_typedescs; + for (auto& type : fn.arg_types) { + arg_typedescs.push_back(TypeDescriptor::from_thrift(type)); + } + + _agg_fn_ctxs[i] = FunctionContext::create_context(state, _mem_pool.get(), return_type, arg_typedescs); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) state->obj_pool()->add(_agg_fn_ctxs[i]); // For nullable aggregate function(sum, max, min, avg), @@ -339,7 +375,13 @@ Status Analytor::open(RuntimeState* state) { } } AggDataPtr agg_states = _mem_pool->allocate_aligned(_agg_states_total_size, _max_agg_state_align_size); +<<<<<<< HEAD _managed_fn_states.emplace_back(std::make_unique(&_agg_fn_ctxs, agg_states, this)); +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); + _managed_fn_states.emplace_back( + std::make_unique>(&_agg_fn_ctxs, agg_states, this)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); }; @@ -366,8 +408,16 @@ void Analytor::close(RuntimeState* state) { auto agg_close = [this, state]() { // Note: we must free agg_states before _mem_pool free_all; +<<<<<<< HEAD _managed_fn_states.clear(); _managed_fn_states.shrink_to_fit(); +======= + { + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); + _managed_fn_states.clear(); + _managed_fn_states.shrink_to_fit(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_mem_pool != nullptr) { _mem_pool->free_all(); @@ -553,6 +603,10 @@ void Analytor::_remove_unused_rows(RuntimeState* state) { for (size_t i = 0; i < _order_ctxs.size(); i++) { _order_columns[i]->remove_first_n_values(remove_rows); } +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { _agg_functions[i]->reset_state_for_contraction( _agg_fn_ctxs[i], _managed_fn_states[0]->mutable_data() + _agg_states_offsets[i], remove_rows); @@ -586,6 +640,7 @@ Status Analytor::_add_chunk(const ChunkPtr& chunk) { const size_t chunk_size = chunk->num_rows(); { +<<<<<<< HEAD auto check_if_overflow = [](Column* column) { std::string msg; if (column->capacity_limit_reached(&msg)) { @@ -593,6 +648,8 @@ Status Analytor::_add_chunk(const ChunkPtr& chunk) { } return Status::OK(); }; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(_column_resize_timer); for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { for (size_t j = 0; j < _agg_expr_ctxs[i].size(); j++) { @@ -601,20 +658,32 @@ Status Analytor::_add_chunk(const ChunkPtr& chunk) { // When chunk's column is const, maybe need to unpack it. TRY_CATCH_BAD_ALLOC(_append_column(chunk_size, _agg_intput_columns[i][j].get(), column)); +<<<<<<< HEAD RETURN_IF_ERROR(check_if_overflow(_agg_intput_columns[i][j].get())); +======= + RETURN_IF_ERROR(_agg_intput_columns[i][j]->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } for (size_t i = 0; i < _partition_ctxs.size(); i++) { ASSIGN_OR_RETURN(ColumnPtr column, _partition_ctxs[i]->evaluate(chunk.get())); TRY_CATCH_BAD_ALLOC(_append_column(chunk_size, _partition_columns[i].get(), column)); +<<<<<<< HEAD RETURN_IF_ERROR(check_if_overflow(_partition_columns[i].get())); +======= + RETURN_IF_ERROR(_partition_columns[i]->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } for (size_t i = 0; i < _order_ctxs.size(); i++) { ASSIGN_OR_RETURN(ColumnPtr column, _order_ctxs[i]->evaluate(chunk.get())); TRY_CATCH_BAD_ALLOC(_append_column(chunk_size, _order_columns[i].get(), column)); +<<<<<<< HEAD RETURN_IF_ERROR(check_if_overflow(_order_columns[i].get())); +======= + RETURN_IF_ERROR(_order_columns[i]->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -933,6 +1002,10 @@ void Analytor::_materializing_process_for_sliding_frame(RuntimeState* state) { void Analytor::_update_window_batch(int64_t partition_start, int64_t partition_end, int64_t frame_start, int64_t frame_end) { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // DO NOT put timer here because this function will be used frequently, // timer will cause a sharp drop in performance. for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { @@ -951,13 +1024,30 @@ void Analytor::_update_window_batch(int64_t partition_start, int64_t partition_e // instead of _partition.end to refer to the current right boundary. frame_end = std::min(frame_end, _partition.end); } +<<<<<<< HEAD _agg_functions[i]->update_batch_single_state_with_frame( _agg_fn_ctxs[i], _managed_fn_states[0]->mutable_data() + _agg_states_offsets[i], data_columns, partition_start, partition_end, frame_start, frame_end); +======= + if (_is_merge_funcs) { + for (size_t j = frame_start; j < frame_end; j++) { + _agg_functions[i]->merge(_agg_fn_ctxs[i], data_columns[0], + _managed_fn_states[0]->mutable_data() + _agg_states_offsets[i], j); + } + } else { + _agg_functions[i]->update_batch_single_state_with_frame( + _agg_fn_ctxs[i], _managed_fn_states[0]->mutable_data() + _agg_states_offsets[i], data_columns, + partition_start, partition_end, frame_start, frame_end); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } void Analytor::_update_window_batch_removable_cumulatively() { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { const Column* agg_column = _agg_intput_columns[i][0].get(); _agg_functions[i]->update_state_removable_cumulatively( @@ -999,6 +1089,10 @@ void Analytor::_reset_state_for_next_partition() { } void Analytor::_reset_window_state() { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // DO NOT put timer here because this function will be used frequently, // timer will cause a sharp drop in performance. for (size_t i = 0; i < _agg_fn_ctxs.size(); i++) { @@ -1193,6 +1287,10 @@ void Analytor::_find_candidate_peer_group_ends() { } void Analytor::_get_window_function_result(size_t frame_start, size_t frame_end) { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(_allocator.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // DO NOT put timer here because this function will be used frequently, // timer will cause a sharp drop in performance. DCHECK_GT(frame_end, frame_start); diff --git a/be/src/exec/analytor.h b/be/src/exec/analytor.h index 39a4fe26849fc..4bcd6b31f834b 100644 --- a/be/src/exec/analytor.h +++ b/be/src/exec/analytor.h @@ -23,14 +23,21 @@ #include "exprs/expr.h" #include "gen_cpp/Types_types.h" #include "runtime/descriptors.h" +<<<<<<< HEAD +======= +#include "runtime/memory/mem_hook_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/types.h" #include "util/runtime_profile.h" namespace starrocks { +<<<<<<< HEAD class ManagedFunctionStates; using ManagedFunctionStatesPtr = std::unique_ptr; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct FunctionTypes { TypeDescriptor result_type; bool has_nullable_child; @@ -41,10 +48,23 @@ class Analytor; using AnalytorPtr = std::shared_ptr; using Analytors = std::vector; +<<<<<<< HEAD // Component used to do analytic processing // it contains common data struct and algorithm of analysis class Analytor final : public pipeline::ContextWithDependency { friend class ManagedFunctionStates; +======= +template +class ManagedFunctionStates; + +template +using ManagedFunctionStatesPtr = std::unique_ptr>; + +// Component used to do analytic processing +// it contains common data struct and algorithm of analysis +class Analytor final : public pipeline::ContextWithDependency { + friend class ManagedFunctionStates; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // [start, end) struct FrameRange { @@ -267,7 +287,11 @@ class Analytor final : public pipeline::ContextWithDependency { std::vector _is_lead_lag_functions; std::vector _agg_fn_ctxs; std::vector _agg_functions; +<<<<<<< HEAD std::vector _managed_fn_states; +======= + std::vector> _managed_fn_states; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector> _agg_expr_ctxs; std::vector> _agg_intput_columns; std::vector _agg_fn_types; @@ -335,6 +359,7 @@ class Analytor final : public pipeline::ContextWithDependency { Segment _peer_group; SegmentStatistics _peer_group_statistics; std::queue _candidate_peer_group_ends; +<<<<<<< HEAD }; // Helper class that properly invokes destructor when state goes out of scope. @@ -344,12 +369,32 @@ class ManagedFunctionStates { : _ctxs(ctxs), _agg_states(agg_states), _agg_node(agg_node) { for (int i = 0; i < _agg_node->_agg_functions.size(); i++) { _agg_node->_agg_functions[i]->create((*_ctxs)[i], _agg_states + _agg_node->_agg_states_offsets[i]); +======= + std::unique_ptr _allocator = std::make_unique(); + + bool _is_merge_funcs; +}; + +// Helper class that properly invokes destructor when state goes out of scope. +template +class ManagedFunctionStates { +public: + ManagedFunctionStates(std::vector* ctxs, AggDataPtr __restrict agg_states, T* context) + : _ctxs(ctxs), _agg_states(agg_states), _context(context) { + for (int i = 0; i < _context->_agg_functions.size(); i++) { + _context->_agg_functions[i]->create((*_ctxs)[i], _agg_states + _context->_agg_states_offsets[i]); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } ~ManagedFunctionStates() { +<<<<<<< HEAD for (int i = 0; i < _agg_node->_agg_functions.size(); i++) { _agg_node->_agg_functions[i]->destroy((*_ctxs)[i], _agg_states + _agg_node->_agg_states_offsets[i]); +======= + for (int i = 0; i < _context->_agg_functions.size(); i++) { + _context->_agg_functions[i]->destroy((*_ctxs)[i], _agg_states + _context->_agg_states_offsets[i]); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -359,7 +404,11 @@ class ManagedFunctionStates { private: std::vector* _ctxs; AggDataPtr _agg_states; +<<<<<<< HEAD Analytor* _agg_node; +======= + T* _context; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class AnalytorFactory; diff --git a/be/src/exec/arrow_flight_batch_reader.cpp b/be/src/exec/arrow_flight_batch_reader.cpp new file mode 100644 index 0000000000000..01386c2b88bee --- /dev/null +++ b/be/src/exec/arrow_flight_batch_reader.cpp @@ -0,0 +1,45 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "arrow_flight_batch_reader.h" + +#include "runtime/exec_env.h" +#include "runtime/result_buffer_mgr.h" + +namespace starrocks { + +ArrowFlightBatchReader::ArrowFlightBatchReader(const TUniqueId& query_id) : _query_id(std::move(query_id)) { + _schema = ExecEnv::GetInstance()->result_mgr()->get_arrow_schema(query_id); +} + +arrow::Status ArrowFlightBatchReader::ReadNext(std::shared_ptr* out) { + if (!_schema) { + return arrow::Status::IOError("Failed to fetch schema for query ID ", print_id(_query_id)); + } + + *out = nullptr; + auto status = ExecEnv::GetInstance()->result_mgr()->fetch_arrow_data(_query_id, out); + if (!status.ok()) { + return arrow::Status::IOError("Failed to fetch arrow data for query ID ", print_id(_query_id), ": ", + status.to_string()); + } + + return arrow::Status::OK(); +} + +std::shared_ptr ArrowFlightBatchReader::schema() const { + return _schema; +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/exec/arrow_flight_batch_reader.h b/be/src/exec/arrow_flight_batch_reader.h new file mode 100644 index 0000000000000..b651ede862ce6 --- /dev/null +++ b/be/src/exec/arrow_flight_batch_reader.h @@ -0,0 +1,34 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "arrow/record_batch.h" +#include "gen_cpp/Types_types.h" + +namespace starrocks { +class ArrowFlightBatchReader : public arrow::RecordBatchReader { +public: + ArrowFlightBatchReader(const TUniqueId& query_id); + + [[nodiscard]] std::shared_ptr schema() const override; + + arrow::Status ReadNext(std::shared_ptr* out) override; + +private: + const TUniqueId _query_id; + std::shared_ptr _schema; +}; + +} // namespace starrocks diff --git a/be/src/exec/arrow_to_starrocks_converter.cpp b/be/src/exec/arrow_to_starrocks_converter.cpp index 7aa8e8fc1fe77..b4c244afa787b 100644 --- a/be/src/exec/arrow_to_starrocks_converter.cpp +++ b/be/src/exec/arrow_to_starrocks_converter.cpp @@ -149,6 +149,7 @@ struct ArrowConverter { } }; +<<<<<<< HEAD static void simd_offsets_copy(uint32_t* dst_array, const int32_t* src_array, const size_t num_elements, const uint32_t dst_base, const uint32_t src_base) { static constexpr size_t element_size = sizeof(uint32_t); @@ -196,6 +197,18 @@ void offsets_copy(const T* arrow_offsets_data, T arrow_base_offset, size_t num_e // that would cause underflow for unsigned int; offsets_data[i] = base_offset + (arrow_offsets_data[i] - arrow_base_offset); } +======= +// {List, Binary, String}Type in arrow use int32_t as offset type, so offsets can be copied via SIMD, +// Large{List, Binary, String}Type use int64_t, so must copy offset elements one by one. +template +void offsets_copy(const T* __restrict arrow_offsets_data, T arrow_base_offset, size_t num_elements, + uint32_t* __restrict offsets_data, uint32_t base_offset) { + for (auto i = 0; i < num_elements; ++i) { + // never change following code to + // base_offsets - arrow_base_offset + arrow_offsets_data[i], + // that would cause underflow for unsigned int; + offsets_data[i] = base_offset + (arrow_offsets_data[i] - arrow_base_offset); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -416,11 +429,15 @@ struct ArrowConverter>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } diff --git a/be/src/exec/arrow_to_starrocks_converter.h b/be/src/exec/arrow_to_starrocks_converter.h index 9a75ba9256f86..27370bb91d1c1 100644 --- a/be/src/exec/arrow_to_starrocks_converter.h +++ b/be/src/exec/arrow_to_starrocks_converter.h @@ -33,8 +33,11 @@ namespace starrocks { class RuntimeState; class SlotDescriptor; struct ConvertFuncTree; +<<<<<<< HEAD } // namespace starrocks namespace starrocks { +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct ArrowConvertContext { class RuntimeState* state; @@ -77,7 +80,11 @@ LogicalType get_strict_type(ArrowTypeId at); struct ConvertFuncTree { ConvertFuncTree(ConvertFunc f) : func(f){}; +<<<<<<< HEAD ConvertFuncTree() : func(nullptr){}; +======= + ConvertFuncTree() = default; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ConvertFunc func = nullptr; std::vector field_names; // used in struct std::vector> children; diff --git a/be/src/exec/capture_version_node.cpp b/be/src/exec/capture_version_node.cpp index cf9cb32afcfea..1b0957c8e055f 100644 --- a/be/src/exec/capture_version_node.cpp +++ b/be/src/exec/capture_version_node.cpp @@ -26,9 +26,15 @@ pipeline::OpFactories CaptureVersionNode::decompose_to_pipeline(pipeline::Pipeli StatusOr CaptureVersionNode::scan_range_to_morsel_queue_factory( const std::vector& scan_ranges) { pipeline::Morsels morsels; +<<<<<<< HEAD for (const auto& scan_range : scan_ranges) { morsels.emplace_back(std::make_unique(id(), scan_range)); } +======= + [[maybe_unused]] bool has_more_morsel = false; + pipeline::ScanMorsel::build_scan_morsels(id(), scan_ranges, true, &morsels, &has_more_morsel); + DCHECK(has_more_morsel == false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto morsel_queue = std::make_unique(std::move(morsels)); return std::make_unique(std::move(morsel_queue), 1); } diff --git a/be/src/exec/chunks_sorter.cpp b/be/src/exec/chunks_sorter.cpp index ebc8a65635019..4671fe1f4bb42 100644 --- a/be/src/exec/chunks_sorter.cpp +++ b/be/src/exec/chunks_sorter.cpp @@ -41,7 +41,11 @@ static void get_compare_results_colwise(size_t rows_to_sort, Columns& order_by_c size_t order_by_column_size = order_by_columns.size(); for (size_t i = 0; i < dats_segment_size; i++) { +<<<<<<< HEAD std::vector rhs_values; +======= + Buffer rhs_values; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto& segment = data_segments[i]; for (size_t col_idx = 0; col_idx < order_by_column_size; col_idx++) { rhs_values.push_back(order_by_columns[col_idx]->get(rows_to_sort)); diff --git a/be/src/exec/chunks_sorter.h b/be/src/exec/chunks_sorter.h index 8b45f6b644312..70331d02ff162 100644 --- a/be/src/exec/chunks_sorter.h +++ b/be/src/exec/chunks_sorter.h @@ -56,9 +56,15 @@ struct DataSegment { // the second is: // compare every row in compare_results_array that <= 0 (i.e. `INCLUDE_IN_SEGMENT` part) with the first row of this DataSegment, // if < 0, then mark it with `SMALLER_THAN_MIN_OF_SEGMENT` +<<<<<<< HEAD [[nodiscard]] Status get_filter_array(std::vector& data_segments, size_t rows_to_sort, std::vector>& filter_array, const SortDescs& sort_order_flags, uint32_t& least_num, uint32_t& middle_num); +======= + Status get_filter_array(std::vector& data_segments, size_t rows_to_sort, + std::vector>& filter_array, const SortDescs& sort_order_flags, + uint32_t& least_num, uint32_t& middle_num); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void clear() { chunk.reset(std::make_unique().release()); @@ -107,9 +113,15 @@ class ChunksSorter { const bool is_topn); virtual ~ChunksSorter(); +<<<<<<< HEAD [[nodiscard]] static StatusOr materialize_chunk_before_sort( Chunk* chunk, TupleDescriptor* materialized_tuple_desc, const SortExecExprs& sort_exec_exprs, const std::vector& order_by_types); +======= + static StatusOr materialize_chunk_before_sort(Chunk* chunk, TupleDescriptor* materialized_tuple_desc, + const SortExecExprs& sort_exec_exprs, + const std::vector& order_by_types); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void setup_runtime(RuntimeState* state, RuntimeProfile* profile, MemTracker* parent_mem_tracker); @@ -118,6 +130,7 @@ class ChunksSorter { void set_spill_channel(SpillProcessChannelPtr channel) { _spill_channel = std::move(channel); } const SpillProcessChannelPtr& spill_channel() { return _spill_channel; } // Append a Chunk for sort. +<<<<<<< HEAD [[nodiscard]] virtual Status update(RuntimeState* state, const ChunkPtr& chunk) = 0; // Finish seeding Chunk, and get sorted data with top OFFSET rows have been skipped. [[nodiscard]] virtual Status do_done(RuntimeState* state) = 0; @@ -126,6 +139,16 @@ class ChunksSorter { // get_next only works after done(). [[nodiscard]] virtual Status get_next(ChunkPtr* chunk, bool* eos) = 0; +======= + virtual Status update(RuntimeState* state, const ChunkPtr& chunk) = 0; + // Finish seeding Chunk, and get sorted data with top OFFSET rows have been skipped. + virtual Status do_done(RuntimeState* state) = 0; + + Status done(RuntimeState* state); + + // get_next only works after done(). + virtual Status get_next(ChunkPtr* chunk, bool* eos) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // RuntimeFilter generate by ChunkSorter only works in TopNSorter and HeapSorter virtual std::vector* runtime_filters(ObjectPool* pool) { return nullptr; } @@ -133,6 +156,11 @@ class ChunksSorter { // Return accurate output rows of this operator virtual size_t get_output_rows() const = 0; +<<<<<<< HEAD +======= + size_t get_next_output_row() { return _next_output_row; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual int64_t mem_usage() const = 0; virtual bool is_full() { return false; } diff --git a/be/src/exec/chunks_sorter_full_sort.h b/be/src/exec/chunks_sorter_full_sort.h index faddf4c678c04..4eed9670ae48a 100644 --- a/be/src/exec/chunks_sorter_full_sort.h +++ b/be/src/exec/chunks_sorter_full_sort.h @@ -48,9 +48,15 @@ class ChunksSorterFullSort : public ChunksSorter { ~ChunksSorterFullSort() override; // Append a Chunk for sort. +<<<<<<< HEAD [[nodiscard]] Status update(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status do_done(RuntimeState* state) override; [[nodiscard]] Status get_next(ChunkPtr* chunk, bool* eos) override; +======= + Status update(RuntimeState* state, const ChunkPtr& chunk) override; + Status do_done(RuntimeState* state) override; + Status get_next(ChunkPtr* chunk, bool* eos) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t get_output_rows() const override; @@ -64,9 +70,15 @@ class ChunksSorterFullSort : public ChunksSorter { // 1. Accumulate input chunks into a big chunk(but not exceed the kMaxBufferedChunkSize), to reduce the memory copy during merge // 2. Sort the accumulated big chunk partially // 3. Merge all big-chunks into global sorted +<<<<<<< HEAD [[nodiscard]] Status _merge_unsorted(RuntimeState* state, const ChunkPtr& chunk); [[nodiscard]] Status _partial_sort(RuntimeState* state, bool done); [[nodiscard]] Status _merge_sorted(RuntimeState* state); +======= + Status _merge_unsorted(RuntimeState* state, const ChunkPtr& chunk); + Status _partial_sort(RuntimeState* state, bool done); + Status _merge_sorted(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _split_late_and_early_chunks(); void _assign_ordinals(); template diff --git a/be/src/exec/chunks_sorter_heap_sort.h b/be/src/exec/chunks_sorter_heap_sort.h index b5c2de1a4dc5f..4553feeb96617 100644 --- a/be/src/exec/chunks_sorter_heap_sort.h +++ b/be/src/exec/chunks_sorter_heap_sort.h @@ -235,9 +235,15 @@ class ChunksSorterHeapSort final : public ChunksSorter { _limit(limit) {} ~ChunksSorterHeapSort() override = default; +<<<<<<< HEAD [[nodiscard]] Status update(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status do_done(RuntimeState* state) override; [[nodiscard]] Status get_next(ChunkPtr* chunk, bool* eos) override; +======= + Status update(RuntimeState* state, const ChunkPtr& chunk) override; + Status do_done(RuntimeState* state) override; + Status get_next(ChunkPtr* chunk, bool* eos) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector* runtime_filters(ObjectPool* pool) override; int64_t mem_usage() const override { if (_sort_heap == nullptr || _sort_heap->empty()) { diff --git a/be/src/exec/chunks_sorter_topn.h b/be/src/exec/chunks_sorter_topn.h index d48782ab1dced..511da96472f1e 100644 --- a/be/src/exec/chunks_sorter_topn.h +++ b/be/src/exec/chunks_sorter_topn.h @@ -66,11 +66,19 @@ class ChunksSorterTopn : public ChunksSorter { ~ChunksSorterTopn() override; // Append a Chunk for sort. +<<<<<<< HEAD [[nodiscard]] Status update(RuntimeState* state, const ChunkPtr& chunk) override; // Finish seeding Chunk, and get sorted data with top OFFSET rows have been skipped. [[nodiscard]] Status do_done(RuntimeState* state) override; // get_next only works after done(). [[nodiscard]] Status get_next(ChunkPtr* chunk, bool* eos) override; +======= + Status update(RuntimeState* state, const ChunkPtr& chunk) override; + // Finish seeding Chunk, and get sorted data with top OFFSET rows have been skipped. + Status do_done(RuntimeState* state) override; + // get_next only works after done(). + Status get_next(ChunkPtr* chunk, bool* eos) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t get_output_rows() const override; @@ -83,6 +91,7 @@ class ChunksSorterTopn : public ChunksSorter { private: size_t _get_number_of_rows_to_sort() const { return _offset + _limit; } +<<<<<<< HEAD [[nodiscard]] Status _sort_chunks(RuntimeState* state); // build data for top-n @@ -97,12 +106,27 @@ class ChunksSorterTopn : public ChunksSorter { [[nodiscard]] Status _merge_sort_common(ChunkPtr& big_chunk, DataSegments& segments, const size_t rows_to_keep, size_t sorted_size, Permutation& new_permutation); +======= + Status _sort_chunks(RuntimeState* state); + + // build data for top-n + Status _build_sorting_data(RuntimeState* state, Permutation& permutation_second, DataSegments& segments); + + Status _hybrid_sort_first_time(RuntimeState* state, Permutation& new_permutation, DataSegments& segments); + + Status _hybrid_sort_common(RuntimeState* state, std::pair& new_permutation, + DataSegments& segments); + + Status _merge_sort_common(ChunkPtr& big_chunk, DataSegments& segments, const size_t rows_to_keep, + size_t sorted_size, Permutation& new_permutation); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static void _set_permutation_before(Permutation&, size_t size, std::vector>& filter_array); static void _set_permutation_complete(std::pair&, size_t size, std::vector>& filter_array); +<<<<<<< HEAD [[nodiscard]] Status _filter_and_sort_data(RuntimeState* state, std::pair& permutations, DataSegments& segments); @@ -112,6 +136,16 @@ class ChunksSorterTopn : public ChunksSorter { [[nodiscard]] Status _partial_sort_col_wise(RuntimeState* state, std::pair& permutations, DataSegments& segments); +======= + Status _filter_and_sort_data(RuntimeState* state, std::pair& permutations, + DataSegments& segments); + + Status _merge_sort_data_as_merged_segment(RuntimeState* state, std::pair& new_permutation, + DataSegments& segments); + + Status _partial_sort_col_wise(RuntimeState* state, std::pair& permutations, + DataSegments& segments); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // For rank type topn, it may keep more data than we need during processing, // therefor, pruning should be performed when processing is finished diff --git a/be/src/exec/connector_scan_node.cpp b/be/src/exec/connector_scan_node.cpp index 240566f6b63df..a5e6d0b7114ef 100644 --- a/be/src/exec/connector_scan_node.cpp +++ b/be/src/exec/connector_scan_node.cpp @@ -279,9 +279,12 @@ Status ConnectorScanNode::_start_scan_thread(RuntimeState* state) { } Status ConnectorScanNode::_create_and_init_scanner(RuntimeState* state, TScanRange& scan_range) { +<<<<<<< HEAD if (scan_range.__isset.broker_scan_range) { scan_range.broker_scan_range.params.__set_non_blocking_read(false); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) connector::DataSourcePtr data_source = _data_source_provider->create_data_source(scan_range); data_source->set_predicates(_conjunct_ctxs); data_source->set_runtime_filters(&_runtime_filter_collector); @@ -690,7 +693,10 @@ StatusOr ConnectorScanNode::convert_scan_range_to_mors const std::vector& scan_ranges, int node_id, int32_t pipeline_dop, bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, size_t num_total_scan_ranges) { +<<<<<<< HEAD _data_source_provider->peek_scan_ranges(scan_ranges); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return _data_source_provider->convert_scan_range_to_morsel_queue( scan_ranges, node_id, pipeline_dop, enable_tablet_internal_parallel, tablet_internal_parallel_mode, num_total_scan_ranges); diff --git a/be/src/exec/csv_scanner.cpp b/be/src/exec/csv_scanner.cpp index ade3544ae0343..9b945d6ee1ce2 100644 --- a/be/src/exec/csv_scanner.cpp +++ b/be/src/exec/csv_scanner.cpp @@ -305,6 +305,10 @@ StatusOr CSVScanner::get_next() { // if timeout happens at the beginning of reading src_chunk, we return the error state // else we will _materialize the lines read before timeout if (src_chunk->num_rows() == 0) { +<<<<<<< HEAD +======= + _reusable_empty_chunk.swap(src_chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return status; } } else { @@ -554,6 +558,14 @@ Status CSVScanner::_parse_csv(Chunk* chunk) { } ChunkPtr CSVScanner::_create_chunk(const std::vector& slots) { +<<<<<<< HEAD +======= + if (_reusable_empty_chunk) { + DCHECK(_reusable_empty_chunk->is_empty()); + return std::move(_reusable_empty_chunk); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_RAW_TIMER(&_counter->init_chunk_ns); auto chunk = std::make_shared(); diff --git a/be/src/exec/csv_scanner.h b/be/src/exec/csv_scanner.h index 6f651b54f5cc1..76a7a545bafdb 100644 --- a/be/src/exec/csv_scanner.h +++ b/be/src/exec/csv_scanner.h @@ -97,6 +97,14 @@ class CSVScanner final : public FileScanner { bool _use_v2; CSVReader::Fields fields; CSVRow row; +<<<<<<< HEAD +======= + + // An empty chunk that can be reused as the container for the result of get_next(). + // It's mainly for optimizing the performance where get_next() returns Status::Timeout + // frequently by avoiding creating a chunk in each call + ChunkPtr _reusable_empty_chunk = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exec/data_sink.cpp b/be/src/exec/data_sink.cpp index 65fee1bc9c425..9e0f533dd90ec 100644 --- a/be/src/exec/data_sink.cpp +++ b/be/src/exec/data_sink.cpp @@ -277,7 +277,12 @@ Status DataSink::decompose_data_sink_to_pipeline(pipeline::PipelineBuilderContex } else { op = std::make_shared( context->next_operator_id(), result_sink->get_sink_type(), result_sink->isBinaryFormat(), +<<<<<<< HEAD result_sink->get_format_type(), result_sink->get_output_exprs(), fragment_ctx); +======= + result_sink->get_format_type(), result_sink->get_output_exprs(), fragment_ctx, + result_sink->get_row_desc()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // Add result sink operator to last pipeline prev_operators.emplace_back(op); diff --git a/be/src/exec/data_sink.h b/be/src/exec/data_sink.h index 6c9172c944f79..bf254184dd732 100644 --- a/be/src/exec/data_sink.h +++ b/be/src/exec/data_sink.h @@ -64,6 +64,7 @@ class DataSink { DataSink() = default; virtual ~DataSink() = default; +<<<<<<< HEAD [[nodiscard]] virtual Status init(const TDataSink& thrift_sink, RuntimeState* state); // Setup. Call before send(), Open(), or Close(). @@ -74,22 +75,44 @@ class DataSink { [[nodiscard]] virtual Status open(RuntimeState* state) = 0; [[nodiscard]] virtual Status send_chunk(RuntimeState* state, Chunk* chunk); +======= + virtual Status init(const TDataSink& thrift_sink, RuntimeState* state); + + // Setup. Call before send(), Open(), or Close(). + // Subclasses must call DataSink::Prepare(). + virtual Status prepare(RuntimeState* state); + + // Setup. Call before send() or close(). + virtual Status open(RuntimeState* state) = 0; + + virtual Status send_chunk(RuntimeState* state, Chunk* chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Releases all resources that were allocated in prepare()/send(). // Further send() calls are illegal after calling close(). // It must be okay to call this multiple times. Subsequent calls should // be ignored. +<<<<<<< HEAD [[nodiscard]] virtual Status close(RuntimeState* state, Status exec_status) { +======= + virtual Status close(RuntimeState* state, Status exec_status) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _closed = true; return Status::OK(); } // Creates a new data sink from thrift_sink. A pointer to the // new sink is written to *sink, and is owned by the caller. +<<<<<<< HEAD [[nodiscard]] static Status create_data_sink(RuntimeState* state, const TDataSink& thrift_sink, const std::vector& output_exprs, const TPlanFragmentExecParams& params, int32_t sender_id, const RowDescriptor& row_desc, std::unique_ptr* sink); +======= + static Status create_data_sink(RuntimeState* state, const TDataSink& thrift_sink, + const std::vector& output_exprs, const TPlanFragmentExecParams& params, + int32_t sender_id, const RowDescriptor& row_desc, std::unique_ptr* sink); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Returns the runtime profile for the sink. virtual RuntimeProfile* profile() = 0; diff --git a/be/src/exec/dictionary_cache_writer.h b/be/src/exec/dictionary_cache_writer.h index 7942882ebb069..e8d267ac985b5 100644 --- a/be/src/exec/dictionary_cache_writer.h +++ b/be/src/exec/dictionary_cache_writer.h @@ -17,7 +17,10 @@ #include "column/chunk.h" #include "exec/pipeline/fragment_context.h" #include "gen_cpp/InternalService_types.h" +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/internal_service.pb.h" #include "runtime/runtime_state.h" #include "util/reusable_closure.h" diff --git a/be/src/exec/es/es_predicate.cpp b/be/src/exec/es/es_predicate.cpp index 0314b62614680..f0b5ba465486c 100644 --- a/be/src/exec/es/es_predicate.cpp +++ b/be/src/exec/es/es_predicate.cpp @@ -52,9 +52,15 @@ #include "exprs/expr_context.h" #include "exprs/in_const_predicate.hpp" #include "gutil/casts.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" #include "runtime/runtime_state.h" #include "runtime/string_value.h" +======= +#include "runtime/runtime_state.h" +#include "runtime/string_value.h" +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type.h" #include "util/runtime_profile.h" diff --git a/be/src/exec/es/es_scan_reader.cpp b/be/src/exec/es/es_scan_reader.cpp index b6580b249fbe2..1030a3ae1ecfd 100644 --- a/be/src/exec/es/es_scan_reader.cpp +++ b/be/src/exec/es/es_scan_reader.cpp @@ -56,10 +56,15 @@ const std::string SOURCE_SCROLL_SEARCH_FILTER_PATH = const std::string DOCVALUE_SCROLL_SEARCH_FILTER_PATH = "filter_path=_scroll_id,hits.total,hits.hits._score,hits.hits.fields"; +<<<<<<< HEAD const std::string REQUEST_SCROLL_PATH = "_scroll"; const std::string REQUEST_PREFERENCE_PREFIX = "&preference=_shards:"; const std::string REQUEST_SEARCH_SCROLL_PATH = "/_search/scroll"; const std::string REQUEST_SEPARATOR = "/"; +======= +const std::string REQUEST_PREFERENCE_PREFIX = "&preference=_shards:"; +const std::string REQUEST_SEARCH_SCROLL_PATH = "/_search/scroll"; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ESScanReader::ESScanReader(const std::string& target, const std::map& props, bool doc_value_mode) diff --git a/be/src/exec/except_hash_set.cpp b/be/src/exec/except_hash_set.cpp index bacab945d3c21..8be99689cb1cb 100644 --- a/be/src/exec/except_hash_set.cpp +++ b/be/src/exec/except_hash_set.cpp @@ -39,7 +39,12 @@ void ExceptHashSet::build_set(RuntimeState* state, const ChunkPtr& chun if (UNLIKELY(cur_max_one_row_size > buffer_state->max_one_row_size)) { buffer_state->max_one_row_size = cur_max_one_row_size; buffer_state->mem_pool.clear(); +<<<<<<< HEAD buffer_state->buffer = buffer_state->mem_pool.allocate(buffer_state->max_one_row_size * state->chunk_size()); +======= + buffer_state->buffer = buffer_state->mem_pool.allocate(buffer_state->max_one_row_size * state->chunk_size() + + SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _serialize_columns(chunk, exprs, chunk_size, buffer_state); @@ -47,7 +52,11 @@ void ExceptHashSet::build_set(RuntimeState* state, const ChunkPtr& chun for (size_t i = 0; i < chunk_size; ++i) { ExceptSliceFlag key(buffer_state->buffer + i * buffer_state->max_one_row_size, buffer_state->slice_sizes[i]); _hash_set->lazy_emplace(key, [&](const auto& ctor) { +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.slice.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.slice.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) memcpy(pos, key.slice.data, key.slice.size); ctor(pos, key.slice.size); }); diff --git a/be/src/exec/except_hash_set.h b/be/src/exec/except_hash_set.h index 1470bb52ae319..ae03accf65849 100644 --- a/be/src/exec/except_hash_set.h +++ b/be/src/exec/except_hash_set.h @@ -54,7 +54,11 @@ template class ExceptHashSet { public: using Iterator = typename HashSet::iterator; +<<<<<<< HEAD using KeyVector = std::vector; +======= + using KeyVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Used to allocate memory for serializing columns to the key. struct BufferState { diff --git a/be/src/exec/exec_node.h b/be/src/exec/exec_node.h index 6ec88a728b39f..eba5616221d16 100644 --- a/be/src/exec/exec_node.h +++ b/be/src/exec/exec_node.h @@ -96,7 +96,11 @@ class ExecNode { /// Initializes this object from the thrift tnode desc. The subclass should /// do any initialization that can fail in Init() rather than the ctor. /// If overridden in subclass, must first call superclass's Init(). +<<<<<<< HEAD [[nodiscard]] virtual Status init(const TPlanNode& tnode, RuntimeState* state); +======= + virtual Status init(const TPlanNode& tnode, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Sets up internal structures, etc., without doing any actual work. // Must be called prior to open(). Will only be called once in this @@ -105,11 +109,16 @@ class ExecNode { // in prepare(). Retrieving the jit compiled function pointer must happen in // open(). // If overridden in subclass, must first call superclass's prepare(). +<<<<<<< HEAD [[nodiscard]] virtual Status prepare(RuntimeState* state); +======= + virtual Status prepare(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Performs any preparatory work prior to calling get_next(). // Can be called repeatedly (after calls to close()). // Caller must not be holding any io buffers. This will cause deadlock. +<<<<<<< HEAD [[nodiscard]] virtual Status open(RuntimeState* state); [[nodiscard]] virtual Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos); @@ -119,6 +128,16 @@ class ExecNode { [[nodiscard]] static Status get_next_big_chunk( RuntimeState*, ChunkPtr*, bool*, ChunkPtr& pre_output_chunk, const std::function& specific_get_next); +======= + virtual Status open(RuntimeState* state); + + virtual Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos); + + // Used by sub nodes to get big chunk. + // specific_get_next is the subclass's implementation to get datas. + static Status get_next_big_chunk(RuntimeState*, ChunkPtr*, bool*, ChunkPtr& pre_output_chunk, + const std::function& specific_get_next); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Resets the stream of row batches to be retrieved by subsequent GetNext() calls. // Clears all internal state, returning this node to the state it was in after calling @@ -133,12 +152,20 @@ class ExecNode { // implementation calls Reset() on children. // Note that this function may be called many times (proportional to the input data), // so should be fast. +<<<<<<< HEAD [[nodiscard]] virtual Status reset(RuntimeState* state); +======= + virtual Status reset(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // This should be called before close() and after get_next(), it is responsible for // collecting statistics sent with row batch, it can't be called when prepare() returns // error. +<<<<<<< HEAD [[nodiscard]] virtual Status collect_query_statistics(QueryStatistics* statistics); +======= + virtual Status collect_query_statistics(QueryStatistics* statistics); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // close() will get called for every exec node, regardless of what else is called and // the status of these calls (i.e. prepare() may never have been called, or @@ -155,8 +182,13 @@ class ExecNode { // Creates exec node tree from list of nodes contained in plan via depth-first // traversal. All nodes are placed in pool. // Returns error if 'plan' is corrupted, otherwise success. +<<<<<<< HEAD [[nodiscard]] static Status create_tree(RuntimeState* state, ObjectPool* pool, const TPlan& plan, const DescriptorTbl& descs, ExecNode** root); +======= + static Status create_tree(RuntimeState* state, ObjectPool* pool, const TPlan& plan, const DescriptorTbl& descs, + ExecNode** root); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Collect all nodes of given 'node_type' that are part of this subtree, and return in // 'nodes'. @@ -168,6 +200,7 @@ class ExecNode { // evaluate exprs over chunk to get a filter // if filter_ptr is not null, save filter to filter_ptr. // then running filter on chunk. +<<<<<<< HEAD [[nodiscard]] static Status eval_conjuncts(const std::vector& ctxs, Chunk* chunk, FilterPtr* filter_ptr = nullptr, bool apply_filter = true); [[nodiscard]] static StatusOr eval_conjuncts_into_filter(const std::vector& ctxs, @@ -176,6 +209,16 @@ class ExecNode { static void eval_filter_null_values(Chunk* chunk, const std::vector& filter_null_value_columns); [[nodiscard]] Status init_join_runtime_filters(const TPlanNode& tnode, RuntimeState* state); +======= + static Status eval_conjuncts(const std::vector& ctxs, Chunk* chunk, FilterPtr* filter_ptr = nullptr, + bool apply_filter = true); + static StatusOr eval_conjuncts_into_filter(const std::vector& ctxs, Chunk* chunk, + Filter* filter); + + static void eval_filter_null_values(Chunk* chunk, const std::vector& filter_null_value_columns); + + Status init_join_runtime_filters(const TPlanNode& tnode, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void register_runtime_filter_descriptor(RuntimeState* state, RuntimeFilterProbeDescriptor* rf_desc); void eval_join_runtime_filters(Chunk* chunk); void eval_join_runtime_filters(ChunkPtr* chunk); @@ -249,8 +292,13 @@ class ExecNode { const std::vector& children() const { return _children; } +<<<<<<< HEAD [[nodiscard]] static Status create_vectorized_node(RuntimeState* state, ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs, ExecNode** node); +======= + static Status create_vectorized_node(RuntimeState* state, ObjectPool* pool, const TPlanNode& tnode, + const DescriptorTbl& descs, ExecNode** node); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: friend class DataSink; @@ -302,9 +350,14 @@ class ExecNode { /// Valid to call in or after Prepare(). bool is_in_subplan() const { return false; } +<<<<<<< HEAD [[nodiscard]] static Status create_tree_helper(RuntimeState* state, ObjectPool* pool, const std::vector& tnodes, const DescriptorTbl& descs, ExecNode* parent, int* node_idx, ExecNode** root); +======= + static Status create_tree_helper(RuntimeState* state, ObjectPool* pool, const std::vector& tnodes, + const DescriptorTbl& descs, ExecNode* parent, int* node_idx, ExecNode** root); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual bool is_scan_node() const { return false; } @@ -315,7 +368,11 @@ class ExecNode { // Executes _debug_action if phase matches _debug_phase. // 'phase' must not be INVALID. +<<<<<<< HEAD [[nodiscard]] Status exec_debug_action(TExecNodePhase::type phase); +======= + Status exec_debug_action(TExecNodePhase::type phase); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: // TODO: delete this function if removed tupleId diff --git a/be/src/exec/file_scanner.cpp b/be/src/exec/file_scanner.cpp index bc5e7e8c368a5..5891e253b6efa 100644 --- a/be/src/exec/file_scanner.cpp +++ b/be/src/exec/file_scanner.cpp @@ -284,11 +284,15 @@ Status FileScanner::create_sequential_file(const TBrokerRangeDesc& range_desc, c range_desc.load_id.printTo(ss); return Status::InternalError(std::string(ss.str())); } +<<<<<<< HEAD bool non_blocking_read = false; if (params.__isset.non_blocking_read) { non_blocking_read = params.non_blocking_read; } auto stream = std::make_shared(std::move(pipe), non_blocking_read); +======= + auto stream = std::make_shared(std::move(pipe)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) src_file = std::make_shared(std::move(stream), "stream-load-pipe"); break; } diff --git a/be/src/exec/hash_join_components.cpp b/be/src/exec/hash_join_components.cpp index e671280cc011d..e9077b15a3075 100644 --- a/be/src/exec/hash_join_components.cpp +++ b/be/src/exec/hash_join_components.cpp @@ -14,12 +14,61 @@ #include "exec/hash_join_components.h" +<<<<<<< HEAD #include "column/vectorized_fwd.h" #include "exec/hash_joiner.h" namespace starrocks { Status HashJoinProber::push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) { +======= +#include +#include +#include + +#include "column/vectorized_fwd.h" +#include "common/config.h" +#include "common/logging.h" +#include "common/object_pool.h" +#include "exec/hash_joiner.h" +#include "exec/join_hash_map.h" +#include "exprs/agg/distinct.h" +#include "exprs/expr_context.h" +#include "gutil/casts.h" +#include "runtime/descriptors.h" +#include "runtime/mem_tracker.h" +#include "util/cpu_info.h" +#include "util/runtime_profile.h" + +namespace starrocks { + +class SingleHashJoinProberImpl final : public HashJoinProberImpl { +public: + SingleHashJoinProberImpl(HashJoiner& hash_joiner) : HashJoinProberImpl(hash_joiner) {} + ~SingleHashJoinProberImpl() override = default; + bool probe_chunk_empty() const override { return _probe_chunk == nullptr; } + Status on_input_finished(RuntimeState* state) override { return Status::OK(); } + Status push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) override; + StatusOr probe_chunk(RuntimeState* state) override; + StatusOr probe_remain(RuntimeState* state, bool* has_remain) override; + void reset(RuntimeState* runtime_state) override { + _probe_chunk.reset(); + _current_probe_has_remain = false; + if (_hash_table != nullptr) { + _hash_table->reset_probe_state(runtime_state); + } + } + void set_ht(JoinHashTable* hash_table) { _hash_table = hash_table; } + +private: + JoinHashTable* _hash_table = nullptr; + ChunkPtr _probe_chunk; + Columns _key_columns; + bool _current_probe_has_remain = false; +}; + +Status SingleHashJoinProberImpl::push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(!_probe_chunk); _probe_chunk = std::move(chunk); _current_probe_has_remain = true; @@ -27,6 +76,7 @@ Status HashJoinProber::push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) { return Status::OK(); } +<<<<<<< HEAD StatusOr HashJoinProber::probe_chunk(RuntimeState* state, JoinHashTable* hash_table) { auto chunk = std::make_shared(); TRY_CATCH_ALLOC_SCOPE_START() @@ -34,6 +84,15 @@ StatusOr HashJoinProber::probe_chunk(RuntimeState* state, JoinHashTabl RETURN_IF_ERROR(hash_table->probe(state, _key_columns, &_probe_chunk, &chunk, &_current_probe_has_remain)); RETURN_IF_ERROR(_hash_joiner.filter_probe_output_chunk(chunk, *hash_table)); RETURN_IF_ERROR(_hash_joiner.lazy_output_chunk(state, &_probe_chunk, &chunk, *hash_table)); +======= +StatusOr SingleHashJoinProberImpl::probe_chunk(RuntimeState* state) { + auto chunk = std::make_shared(); + TRY_CATCH_ALLOC_SCOPE_START() + DCHECK(_current_probe_has_remain && _probe_chunk); + RETURN_IF_ERROR(_hash_table->probe(state, _key_columns, &_probe_chunk, &chunk, &_current_probe_has_remain)); + RETURN_IF_ERROR(_hash_joiner.filter_probe_output_chunk(chunk, *_hash_table)); + RETURN_IF_ERROR(_hash_joiner.lazy_output_chunk(state, &_probe_chunk, &chunk, *_hash_table)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!_current_probe_has_remain) { _probe_chunk = nullptr; } @@ -41,6 +100,7 @@ StatusOr HashJoinProber::probe_chunk(RuntimeState* state, JoinHashTabl return chunk; } +<<<<<<< HEAD StatusOr HashJoinProber::probe_remain(RuntimeState* state, JoinHashTable* hash_table, bool* has_remain) { auto chunk = std::make_shared(); TRY_CATCH_ALLOC_SCOPE_START() @@ -48,10 +108,20 @@ StatusOr HashJoinProber::probe_remain(RuntimeState* state, JoinHashTab *has_remain = _current_probe_has_remain; RETURN_IF_ERROR(_hash_joiner.filter_post_probe_output_chunk(chunk)); RETURN_IF_ERROR(_hash_joiner.lazy_output_chunk(state, nullptr, &chunk, *hash_table)); +======= +StatusOr SingleHashJoinProberImpl::probe_remain(RuntimeState* state, bool* has_remain) { + auto chunk = std::make_shared(); + TRY_CATCH_ALLOC_SCOPE_START() + RETURN_IF_ERROR(_hash_table->probe_remain(state, &chunk, &_current_probe_has_remain)); + *has_remain = _current_probe_has_remain; + RETURN_IF_ERROR(_hash_joiner.filter_post_probe_output_chunk(chunk)); + RETURN_IF_ERROR(_hash_joiner.lazy_output_chunk(state, nullptr, &chunk, *_hash_table)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TRY_CATCH_ALLOC_SCOPE_END() return chunk; } +<<<<<<< HEAD void HashJoinProber::reset() { _probe_chunk.reset(); _current_probe_has_remain = false; @@ -62,21 +132,292 @@ void HashJoinBuilder::create(const HashTableParam& param) { } void HashJoinBuilder::close() { +======= +void HashJoinProber::attach(HashJoinBuilder* builder, const HashJoinProbeMetrics& probe_metrics) { + builder->visitHt([&](JoinHashTable* ht) { + ht->set_probe_profile(probe_metrics.search_ht_timer, probe_metrics.output_probe_column_timer, + probe_metrics.output_build_column_timer, probe_metrics.probe_counter); + }); + _impl = builder->create_prober(); +} + +class PartitionChunkChannel { +public: + PartitionChunkChannel(MemTracker* tracker) : _tracker(tracker) {} + bool processing() const { return _processing; } + void set_processing(bool processing) { _processing = processing; } + + ChunkPtr pull() { + auto chunk = std::move(_chunks.front()); + _tracker->release(chunk->memory_usage()); + _chunks.pop_front(); + return chunk; + } + + void push(ChunkPtr&& chunk) { + _tracker->consume(chunk->memory_usage()); + _chunks.emplace_back(std::move(chunk)); + } + + const ChunkPtr& back() { return _chunks.back(); } + + bool is_full() const { + return _chunks.size() >= 4 || _tracker->consumption() > config::partition_hash_join_probe_limit_size; + } + + size_t size() const { return _chunks.size(); } + + bool is_empty() const { return _chunks.empty() || _chunks.front()->is_empty(); } + + bool not_empty() const { return !is_empty(); } + +private: + MemTracker* _tracker; + std::deque _chunks; + bool _processing = false; +}; + +class PartitionedHashJoinProberImpl final : public HashJoinProberImpl { +public: + PartitionedHashJoinProberImpl(HashJoiner& hash_joiner) : HashJoinProberImpl(hash_joiner) {} + ~PartitionedHashJoinProberImpl() override = default; + bool probe_chunk_empty() const override; + Status on_input_finished(RuntimeState* state) override; + Status push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) override; + StatusOr probe_chunk(RuntimeState* state) override; + StatusOr probe_remain(RuntimeState* state, bool* has_remain) override; + void reset(RuntimeState* runtime_state) override; + void set_probers(std::vector>&& probers) { + _probers = std::move(probers); + _partition_input_channels.resize(_probers.size(), PartitionChunkChannel(&_mem_tracker)); + } + +private: + MemTracker _mem_tracker; + bool _all_input_finished = false; + int32_t _remain_partition_idx = 0; + std::vector> _probers; + std::vector _partition_input_channels; +}; + +bool PartitionedHashJoinProberImpl::probe_chunk_empty() const { + auto& probers = _probers; + size_t num_partitions = probers.size(); + + if (!_all_input_finished) { + for (size_t i = 0; i < num_partitions; ++i) { + if (!probers[i]->probe_chunk_empty() || _partition_input_channels[i].processing()) { + return false; + } + } + } else { + for (size_t i = 0; i < num_partitions; ++i) { + if (!probers[i]->probe_chunk_empty() || _partition_input_channels[i].not_empty()) { + return false; + } + } + } + + return true; +} + +Status PartitionedHashJoinProberImpl::on_input_finished(RuntimeState* runtime_state) { + SCOPED_TIMER(_hash_joiner.probe_metrics().partition_probe_overhead); + _all_input_finished = true; + auto& probers = _probers; + size_t num_partitions = probers.size(); + + for (size_t i = 0; i < num_partitions; ++i) { + if (_partition_input_channels[i].is_empty()) { + continue; + } + if (!probers[i]->probe_chunk_empty()) { + continue; + } + RETURN_IF_ERROR(probers[i]->push_probe_chunk(runtime_state, _partition_input_channels[i].pull())); + } + return Status::OK(); +} + +Status PartitionedHashJoinProberImpl::push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) { + SCOPED_TIMER(_hash_joiner.probe_metrics().partition_probe_overhead); + auto& probers = _probers; + auto& partition_keys = _hash_joiner.probe_expr_ctxs(); + + size_t num_rows = chunk->num_rows(); + size_t num_partitions = probers.size(); + size_t num_partition_cols = partition_keys.size(); + + std::vector partition_columns(num_partition_cols); + for (size_t i = 0; i < num_partition_cols; ++i) { + ASSIGN_OR_RETURN(partition_columns[i], partition_keys[i]->evaluate(chunk.get())); + } + std::vector hash_values; + { + hash_values.assign(num_rows, HashUtil::FNV_SEED); + + for (const ColumnPtr& column : partition_columns) { + column->fnv_hash(hash_values.data(), 0, num_rows); + } + // find partition id + for (size_t i = 0; i < hash_values.size(); ++i) { + hash_values[i] = HashUtil::fmix32(hash_values[i]) & (num_partitions - 1); + } + } + + const auto& partitions = hash_values; + + std::vector selection; + selection.resize(chunk->num_rows()); + + std::vector channel_row_idx_start_points; + channel_row_idx_start_points.assign(num_partitions + 1, 0); + + for (uint32_t i : partitions) { + channel_row_idx_start_points[i]++; + } + + for (int32_t i = 1; i <= channel_row_idx_start_points.size() - 1; ++i) { + channel_row_idx_start_points[i] += channel_row_idx_start_points[i - 1]; + } + + for (int32_t i = chunk->num_rows() - 1; i >= 0; --i) { + selection[channel_row_idx_start_points[partitions[i]] - 1] = i; + channel_row_idx_start_points[partitions[i]]--; + } + _partition_input_channels.resize(num_partitions, PartitionChunkChannel(&_mem_tracker)); + + for (size_t i = 0; i < num_partitions; ++i) { + auto from = channel_row_idx_start_points[i]; + auto size = channel_row_idx_start_points[i + 1] - from; + if (size == 0) { + continue; + } + + if (_partition_input_channels[i].is_empty()) { + _partition_input_channels[i].push(chunk->clone_empty()); + } + + if (_partition_input_channels[i].back()->num_rows() + size <= 4096) { + _partition_input_channels[i].back()->append_selective(*chunk, selection.data(), from, size); + } else { + _partition_input_channels[i].push(chunk->clone_empty()); + _partition_input_channels[i].back()->append_selective(*chunk, selection.data(), from, size); + } + + if (_partition_input_channels[i].is_full()) { + _partition_input_channels[i].set_processing(true); + RETURN_IF_ERROR(probers[i]->push_probe_chunk(state, _partition_input_channels[i].pull())); + } + } + + return Status::OK(); +} + +StatusOr PartitionedHashJoinProberImpl::probe_chunk(RuntimeState* state) { + auto& probers = _probers; + size_t num_partitions = probers.size(); + if (_all_input_finished) { + for (size_t i = 0; i < num_partitions; ++i) { + if (probers[i]->probe_chunk_empty() && _partition_input_channels[i].is_empty()) { + continue; + } + if (probers[i]->probe_chunk_empty()) { + RETURN_IF_ERROR(probers[i]->push_probe_chunk(state, _partition_input_channels[i].pull())); + } + auto chunk = std::make_shared(); + ASSIGN_OR_RETURN(chunk, probers[i]->probe_chunk(state)) + return chunk; + } + } else { + for (size_t i = 0; i < num_partitions; ++i) { + if (probers[i]->probe_chunk_empty() && !_partition_input_channels[i].processing()) { + continue; + } + if (probers[i]->probe_chunk_empty()) { + RETURN_IF_ERROR(probers[i]->push_probe_chunk(state, _partition_input_channels[i].pull())); + } + _partition_input_channels[i].set_processing(_partition_input_channels[i].size() > 1); + auto chunk = std::make_shared(); + ASSIGN_OR_RETURN(chunk, probers[i]->probe_chunk(state)) + return chunk; + } + } + CHECK(false); + + return nullptr; +} + +StatusOr PartitionedHashJoinProberImpl::probe_remain(RuntimeState* state, bool* has_remain) { + auto& probers = _probers; + size_t num_partitions = probers.size(); + while (_remain_partition_idx < num_partitions) { + auto chunk = std::make_shared(); + bool sub_map_has_remain = false; + ASSIGN_OR_RETURN(chunk, probers[_remain_partition_idx]->probe_remain(state, &sub_map_has_remain)); + if (!sub_map_has_remain) { + _remain_partition_idx++; + } + if (chunk->is_empty()) { + continue; + } + *has_remain = true; + return chunk; + } + + *has_remain = false; + return nullptr; +} + +void PartitionedHashJoinProberImpl::reset(RuntimeState* runtime_state) { + _probers.clear(); + _partition_input_channels.clear(); + _all_input_finished = false; + _remain_partition_idx = 0; +} + +void SingleHashJoinBuilder::create(const HashTableParam& param) { + _ht.create(param); +} + +void SingleHashJoinBuilder::close() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _key_columns.clear(); _ht.close(); } +<<<<<<< HEAD void HashJoinBuilder::reset(const HashTableParam& param) { +======= +void SingleHashJoinBuilder::reset(const HashTableParam& param) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) close(); create(param); } +<<<<<<< HEAD void HashJoinBuilder::reset_probe(RuntimeState* state) { _key_columns.clear(); _ht.reset_probe_state(state); } Status HashJoinBuilder::append_chunk(const ChunkPtr& chunk) { +======= +bool SingleHashJoinBuilder::anti_join_key_column_has_null() const { + if (_ht.get_key_columns().size() != 1) { + return false; + } + auto& column = _ht.get_key_columns()[0]; + if (column->is_nullable()) { + const auto& null_column = ColumnHelper::as_raw_column(column)->null_column(); + DCHECK_GT(null_column->size(), 0); + return null_column->contain_value(1, null_column->size(), 1); + } + return false; +} + +Status SingleHashJoinBuilder::do_append_chunk(const ChunkPtr& chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (UNLIKELY(_ht.get_row_count() + chunk->num_rows() >= max_hash_table_element_size)) { return Status::NotSupported(strings::Substitute("row count of right table in hash join > $0", UINT32_MAX)); } @@ -88,11 +429,421 @@ Status HashJoinBuilder::append_chunk(const ChunkPtr& chunk) { return Status::OK(); } +<<<<<<< HEAD Status HashJoinBuilder::build(RuntimeState* state) { +======= +Status SingleHashJoinBuilder::build(RuntimeState* state) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(_hash_joiner.build_metrics().build_ht_timer); TRY_CATCH_BAD_ALLOC(RETURN_IF_ERROR(_ht.build(state))); _ready = true; return Status::OK(); } +<<<<<<< HEAD +======= +void SingleHashJoinBuilder::visitHt(const std::function& visitor) { + visitor(&_ht); +} + +std::unique_ptr SingleHashJoinBuilder::create_prober() { + auto res = std::make_unique(_hash_joiner); + res->set_ht(&_ht); + return res; +} + +void SingleHashJoinBuilder::clone_readable(HashJoinBuilder* builder) { + auto* other = down_cast(builder); + other->_ht = _ht.clone_readable_table(); +} + +ChunkPtr SingleHashJoinBuilder::convert_to_spill_schema(const ChunkPtr& chunk) const { + return _ht.convert_to_spill_schema(chunk); +} + +enum class CacheLevel { L2, L3, MEMORY }; + +class AdaptivePartitionHashJoinBuilder final : public HashJoinBuilder { +public: + AdaptivePartitionHashJoinBuilder(HashJoiner& hash_joiner); + ~AdaptivePartitionHashJoinBuilder() override = default; + + void create(const HashTableParam& param) override; + + void close() override; + + void reset(const HashTableParam& param) override; + + Status do_append_chunk(const ChunkPtr& chunk) override; + + Status build(RuntimeState* state) override; + + bool anti_join_key_column_has_null() const override; + + int64_t ht_mem_usage() const override; + + void get_build_info(size_t* bucket_size, float* avg_keys_per_bucket) override; + + size_t get_output_probe_column_count() const override; + size_t get_output_build_column_count() const override; + + void visitHt(const std::function& visitor) override; + + std::unique_ptr create_prober() override; + + void clone_readable(HashJoinBuilder* builder) override; + + ChunkPtr convert_to_spill_schema(const ChunkPtr& chunk) const override; + +private: + size_t _estimated_row_size(const HashTableParam& param) const; + size_t _estimated_probe_cost(const HashTableParam& param) const; + template + size_t _estimated_build_cost(size_t build_row_size) const; + void _adjust_partition_rows(size_t build_row_size); + + void _init_partition_nums(const HashTableParam& param); + Status _convert_to_single_partition(); + Status _append_chunk_to_partitions(const ChunkPtr& chunk); + +private: + std::vector> _builders; + + size_t _partition_num = 0; + size_t _partition_join_min_rows = 0; + size_t _partition_join_max_rows = 0; + + size_t _probe_estimated_costs = 0; + + size_t _fit_L2_cache_max_rows = 0; + size_t _fit_L3_cache_max_rows = 0; + + size_t _L2_cache_size = 0; + size_t _L3_cache_size = 0; + + size_t _pushed_chunks = 0; +}; + +AdaptivePartitionHashJoinBuilder::AdaptivePartitionHashJoinBuilder(HashJoiner& hash_joiner) + : HashJoinBuilder(hash_joiner) { + static constexpr size_t DEFAULT_L2_CACHE_SIZE = 1 * 1024 * 1024; + static constexpr size_t DEFAULT_L3_CACHE_SIZE = 32 * 1024 * 1024; + const auto& cache_sizes = CpuInfo::get_cache_sizes(); + _L2_cache_size = cache_sizes[CpuInfo::L2_CACHE]; + _L3_cache_size = cache_sizes[CpuInfo::L3_CACHE]; + _L2_cache_size = _L2_cache_size ? _L2_cache_size : DEFAULT_L2_CACHE_SIZE; + _L3_cache_size = _L3_cache_size ? _L3_cache_size : DEFAULT_L3_CACHE_SIZE; +} + +size_t AdaptivePartitionHashJoinBuilder::_estimated_row_size(const HashTableParam& param) const { + size_t estimated_each_row = 0; + + for (auto* tuple : param.build_row_desc->tuple_descriptors()) { + for (auto slot : tuple->slots()) { + if (param.build_output_slots.contains(slot->id())) { + estimated_each_row += get_size_of_fixed_length_type(slot->type().type); + estimated_each_row += type_estimated_overhead_bytes(slot->type().type); + } + } + } + + // for hash table bucket + estimated_each_row += 4; + + return estimated_each_row; +} + +// We could use a better estimation model. +size_t AdaptivePartitionHashJoinBuilder::_estimated_probe_cost(const HashTableParam& param) const { + size_t size = 0; + + for (auto* tuple : param.probe_row_desc->tuple_descriptors()) { + for (auto slot : tuple->slots()) { + if (param.probe_output_slots.contains(slot->id())) { + size += get_size_of_fixed_length_type(slot->type().type); + size += type_estimated_overhead_bytes(slot->type().type); + } + } + } + // we define probe cost is bytes size * 6 + return size * 6; +} + +template <> +size_t AdaptivePartitionHashJoinBuilder::_estimated_build_cost(size_t build_row_size) const { + return build_row_size / 2; +} + +template <> +size_t AdaptivePartitionHashJoinBuilder::_estimated_build_cost(size_t build_row_size) const { + return build_row_size; +} + +template <> +size_t AdaptivePartitionHashJoinBuilder::_estimated_build_cost(size_t build_row_size) const { + return build_row_size * 2; +} + +void AdaptivePartitionHashJoinBuilder::_adjust_partition_rows(size_t build_row_size) { + build_row_size = std::max(build_row_size, 4UL); + _fit_L2_cache_max_rows = _L2_cache_size / build_row_size; + _fit_L3_cache_max_rows = _L3_cache_size / build_row_size; + + // If the hash table is smaller than the L2 cache. we don't think partition hash join is needed. + _partition_join_min_rows = _fit_L2_cache_max_rows; + // If the hash table after partition can't be loaded to L3. we don't think partition hash join is needed. + _partition_join_max_rows = _fit_L3_cache_max_rows * _partition_num; + + if (_probe_estimated_costs + _estimated_build_cost(build_row_size) < + _estimated_build_cost(build_row_size)) { + // overhead after hash table partitioning + probe extra cost < cost before partitioning + // nothing to do + } else if (_probe_estimated_costs + _estimated_build_cost(build_row_size) < + _estimated_build_cost(build_row_size)) { + // It is only after this that performance gains can be realized beyond the L3 cache. + _partition_join_min_rows = _fit_L3_cache_max_rows; + } else { + // Partitioned joins don't have performance gains. Not using partition hash join. + _partition_num = 1; + } + + VLOG_OPERATOR << "TRACE:" + << "partition_num=" << _partition_num << " partition_join_min_rows=" << _partition_join_min_rows + << " partition_join_max_rows=" << _partition_join_max_rows << " probe cost=" << _probe_estimated_costs + << " build cost L2=" << _estimated_build_cost(build_row_size) + << " build cost L3=" << _estimated_build_cost(build_row_size) + << " build cost Mem=" << _estimated_build_cost(build_row_size); +} + +void AdaptivePartitionHashJoinBuilder::_init_partition_nums(const HashTableParam& param) { + _partition_num = 16; + + size_t estimated_bytes_each_row = _estimated_row_size(param); + + _probe_estimated_costs = _estimated_probe_cost(param); + + _adjust_partition_rows(estimated_bytes_each_row); + + COUNTER_SET(_hash_joiner.build_metrics().partition_nums, (int64_t)_partition_num); +} + +void AdaptivePartitionHashJoinBuilder::create(const HashTableParam& param) { + _init_partition_nums(param); + for (size_t i = 0; i < _partition_num; ++i) { + _builders.emplace_back(std::make_unique(_hash_joiner)); + _builders.back()->create(param); + } +} + +void AdaptivePartitionHashJoinBuilder::close() { + for (const auto& builder : _builders) { + builder->close(); + } + _builders.clear(); + _partition_num = 0; + _partition_join_min_rows = 0; + _partition_join_max_rows = 0; + _probe_estimated_costs = 0; + _fit_L2_cache_max_rows = 0; + _fit_L3_cache_max_rows = 0; + _pushed_chunks = 0; +} + +void AdaptivePartitionHashJoinBuilder::reset(const HashTableParam& param) { + close(); + create(param); +} + +bool AdaptivePartitionHashJoinBuilder::anti_join_key_column_has_null() const { + return std::any_of(_builders.begin(), _builders.end(), + [](const auto& builder) { return builder->anti_join_key_column_has_null(); }); +} + +void AdaptivePartitionHashJoinBuilder::get_build_info(size_t* bucket_size, float* avg_keys_per_bucket) { + size_t total_bucket_size = 0; + float total_keys_per_bucket = 0; + for (const auto& builder : _builders) { + size_t bucket_size = 0; + float keys_per_bucket = 0; + builder->get_build_info(&bucket_size, &keys_per_bucket); + total_bucket_size += bucket_size; + total_keys_per_bucket += keys_per_bucket; + } + *bucket_size = total_bucket_size; + *avg_keys_per_bucket = total_keys_per_bucket / _builders.size(); +} + +size_t AdaptivePartitionHashJoinBuilder::get_output_probe_column_count() const { + return _builders[0]->get_output_probe_column_count(); +} + +size_t AdaptivePartitionHashJoinBuilder::get_output_build_column_count() const { + return _builders[0]->get_output_build_column_count(); +} + +int64_t AdaptivePartitionHashJoinBuilder::ht_mem_usage() const { + return std::accumulate(_builders.begin(), _builders.end(), 0L, + [](int64_t sum, const auto& builder) { return sum + builder->ht_mem_usage(); }); +} + +Status AdaptivePartitionHashJoinBuilder::_convert_to_single_partition() { + // merge all partition data to the first partition + for (size_t i = 1; i < _builders.size(); ++i) { + _builders[0]->hash_table().merge_ht(_builders[i]->hash_table()); + } + _builders.resize(1); + _partition_num = 1; + return Status::OK(); +} + +Status AdaptivePartitionHashJoinBuilder::_append_chunk_to_partitions(const ChunkPtr& chunk) { + const std::vector& build_partition_keys = _hash_joiner.build_expr_ctxs(); + + size_t num_rows = chunk->num_rows(); + size_t num_partitions = _builders.size(); + size_t num_partition_cols = build_partition_keys.size(); + + std::vector partition_columns(num_partition_cols); + for (size_t i = 0; i < num_partition_cols; ++i) { + ASSIGN_OR_RETURN(partition_columns[i], build_partition_keys[i]->evaluate(chunk.get())); + } + std::vector hash_values; + { + hash_values.assign(num_rows, HashUtil::FNV_SEED); + + for (const ColumnPtr& column : partition_columns) { + column->fnv_hash(hash_values.data(), 0, num_rows); + } + // find partition id + for (size_t i = 0; i < hash_values.size(); ++i) { + hash_values[i] = HashUtil::fmix32(hash_values[i]) & (num_partitions - 1); + } + } + + const auto& partitions = hash_values; + + std::vector selection; + selection.resize(chunk->num_rows()); + + std::vector channel_row_idx_start_points; + channel_row_idx_start_points.assign(num_partitions + 1, 0); + + for (uint32_t i : partitions) { + channel_row_idx_start_points[i]++; + } + + for (int32_t i = 1; i <= channel_row_idx_start_points.size() - 1; ++i) { + channel_row_idx_start_points[i] += channel_row_idx_start_points[i - 1]; + } + + for (int32_t i = chunk->num_rows() - 1; i >= 0; --i) { + selection[channel_row_idx_start_points[partitions[i]] - 1] = i; + channel_row_idx_start_points[partitions[i]]--; + } + + for (size_t i = 0; i < num_partitions; ++i) { + auto from = channel_row_idx_start_points[i]; + auto size = channel_row_idx_start_points[i + 1] - from; + if (size == 0) { + continue; + } + // TODO: make builder implements append with selective + auto partition_chunk = chunk->clone_empty(); + partition_chunk->append_selective(*chunk, selection.data(), from, size); + RETURN_IF_ERROR(_builders[i]->append_chunk(std::move(partition_chunk))); + } + return Status::OK(); +} + +Status AdaptivePartitionHashJoinBuilder::do_append_chunk(const ChunkPtr& chunk) { + if (_partition_num > 1 && hash_table_row_count() > _partition_join_max_rows) { + RETURN_IF_ERROR(_convert_to_single_partition()); + } + + if (_partition_num > 1 && ++_pushed_chunks % 8 == 0) { + size_t build_row_size = ht_mem_usage() / hash_table_row_count(); + _adjust_partition_rows(build_row_size); + if (_partition_num == 1) { + RETURN_IF_ERROR(_convert_to_single_partition()); + } + } + + if (_partition_num > 1) { + RETURN_IF_ERROR(_append_chunk_to_partitions(chunk)); + } else { + RETURN_IF_ERROR(_builders[0]->do_append_chunk(chunk)); + } + + return Status::OK(); +} + +ChunkPtr AdaptivePartitionHashJoinBuilder::convert_to_spill_schema(const ChunkPtr& chunk) const { + return _builders[0]->convert_to_spill_schema(chunk); +} + +Status AdaptivePartitionHashJoinBuilder::build(RuntimeState* state) { + DCHECK_EQ(_partition_num, _builders.size()); + + if (_partition_num > 1 && hash_table_row_count() < _partition_join_min_rows) { + RETURN_IF_ERROR(_convert_to_single_partition()); + } + + for (auto& builder : _builders) { + RETURN_IF_ERROR(builder->build(state)); + } + _ready = true; + return Status::OK(); +} + +void AdaptivePartitionHashJoinBuilder::visitHt(const std::function& visitor) { + for (auto& builder : _builders) { + builder->visitHt(visitor); + } +} + +std::unique_ptr AdaptivePartitionHashJoinBuilder::create_prober() { + DCHECK_EQ(_partition_num, _builders.size()); + + if (_partition_num == 1) { + return _builders[0]->create_prober(); + } else { + std::vector> sub_probers; + auto prober = std::make_unique(_hash_joiner); + sub_probers.resize(_partition_num); + for (size_t i = 0; i < _builders.size(); ++i) { + sub_probers[i].reset(down_cast(_builders[i]->create_prober().release())); + } + prober->set_probers(std::move(sub_probers)); + return prober; + } +} + +void AdaptivePartitionHashJoinBuilder::clone_readable(HashJoinBuilder* builder) { + for (auto& builder : _builders) { + DCHECK(builder->ready()); + } + DCHECK(_ready); + DCHECK_EQ(_partition_num, _builders.size()); + auto other = down_cast(builder); + other->_builders.clear(); + other->_partition_num = _partition_num; + other->_partition_join_max_rows = _partition_join_max_rows; + other->_partition_join_min_rows = _partition_join_min_rows; + other->_ready = _ready; + for (size_t i = 0; i < _partition_num; ++i) { + other->_builders.emplace_back(std::make_unique(_hash_joiner)); + _builders[i]->clone_readable(other->_builders[i].get()); + } +} + +HashJoinBuilder* HashJoinBuilderFactory::create(ObjectPool* pool, const HashJoinBuildOptions& options, + HashJoiner& hash_joiner) { + if (options.enable_partitioned_hash_join) { + return pool->add(new AdaptivePartitionHashJoinBuilder(hash_joiner)); + } else { + return pool->add(new SingleHashJoinBuilder(hash_joiner)); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/hash_join_components.h b/be/src/exec/hash_join_components.h index f4ed16d79d453..710273dedbe8e 100644 --- a/be/src/exec/hash_join_components.h +++ b/be/src/exec/hash_join_components.h @@ -14,6 +14,12 @@ #pragma once +<<<<<<< HEAD +======= +#include +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/vectorized_fwd.h" #include "common/object_pool.h" #include "exec/join_hash_map.h" @@ -21,10 +27,32 @@ namespace starrocks { class HashJoiner; +<<<<<<< HEAD +======= +struct HashJoinProbeMetrics; +class HashJoinBuilder; + +class HashJoinProberImpl { +public: + virtual ~HashJoinProberImpl() = default; + virtual bool probe_chunk_empty() const = 0; + virtual Status on_input_finished(RuntimeState* state) = 0; + virtual Status push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) = 0; + virtual StatusOr probe_chunk(RuntimeState* state) = 0; + virtual StatusOr probe_remain(RuntimeState* state, bool* has_remain) = 0; + virtual void reset(RuntimeState* runtime_state) = 0; + +protected: + HashJoinProberImpl(HashJoiner& hash_joiner) : _hash_joiner(hash_joiner) {} + HashJoiner& _hash_joiner; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class HashJoinProber { public: HashJoinProber(HashJoiner& hash_joiner) : _hash_joiner(hash_joiner) {} +<<<<<<< HEAD bool probe_chunk_empty() const { return _probe_chunk == nullptr; } [[nodiscard]] Status push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk); @@ -45,11 +73,50 @@ class HashJoinProber { bool _current_probe_has_remain = false; }; +======= + bool probe_chunk_empty() const { return _impl == nullptr || _impl->probe_chunk_empty(); } + + Status push_probe_chunk(RuntimeState* state, ChunkPtr&& chunk) { + return _impl->push_probe_chunk(state, std::move(chunk)); + } + + Status on_input_finished(RuntimeState* state) { + if (_impl == nullptr) { + return Status::OK(); + } + return _impl->on_input_finished(state); + } + + // probe hash table + StatusOr probe_chunk(RuntimeState* state) { return _impl->probe_chunk(state); } + + StatusOr probe_remain(RuntimeState* state, bool* has_remain) { + return _impl->probe_remain(state, has_remain); + } + + void reset(RuntimeState* runtime_state) { return _impl->reset(runtime_state); } + + HashJoinProber* clone_empty(ObjectPool* pool) { return pool->add(new HashJoinProber(_hash_joiner)); } + + void attach(HashJoinBuilder* builder, const HashJoinProbeMetrics& probe_metrics); + + bool has_attached() const { return _impl != nullptr; } + + bool need_input() const { return has_attached() && probe_chunk_empty(); } + +private: + HashJoiner& _hash_joiner; + std::unique_ptr _impl; +}; + +// build hash table +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class HashJoinBuilder { public: static constexpr size_t max_hash_table_element_size = UINT32_MAX; HashJoinBuilder(HashJoiner& hash_joiner) : _hash_joiner(hash_joiner) {} +<<<<<<< HEAD void create(const HashTableParam& param); @@ -80,4 +147,105 @@ class HashJoinBuilder { bool _ready = false; }; +======= + virtual ~HashJoinBuilder() = default; + + virtual void create(const HashTableParam& param) = 0; + + // append chunk to hash table + Status append_chunk(const ChunkPtr& chunk) { + _inc_row_count(chunk->num_rows()); + return do_append_chunk(chunk); + } + virtual Status do_append_chunk(const ChunkPtr& chunk) = 0; + + virtual Status build(RuntimeState* state) = 0; + + virtual void close() = 0; + + virtual void reset(const HashTableParam& param) = 0; + + virtual int64_t ht_mem_usage() const = 0; + + // used for check NULL_AWARE_LEFT_ANTI_JOIN build side has null + virtual bool anti_join_key_column_has_null() const = 0; + + bool ready() const { return _ready; } + + size_t hash_table_row_count() const { return _hash_table_row_count; } + + virtual size_t get_output_probe_column_count() const = 0; + virtual size_t get_output_build_column_count() const = 0; + + virtual void get_build_info(size_t* bucket_size, float* avg_keys_per_bucket) = 0; + + virtual void visitHt(const std::function& visitor) = 0; + + virtual std::unique_ptr create_prober() = 0; + + // clone readable to to builder + virtual void clone_readable(HashJoinBuilder* builder) = 0; + + virtual ChunkPtr convert_to_spill_schema(const ChunkPtr& chunk) const = 0; + +protected: + HashJoiner& _hash_joiner; + bool _ready = false; + +private: + size_t _hash_table_row_count = 0; + void _inc_row_count(size_t num_rows) { _hash_table_row_count += num_rows; } +}; + +// HashJoinBuilder with single partition +class SingleHashJoinBuilder final : public HashJoinBuilder { +public: + SingleHashJoinBuilder(HashJoiner& hash_joiner) : HashJoinBuilder(hash_joiner) {} + + void create(const HashTableParam& param) override; + + JoinHashTable& hash_table() { return _ht; } + + void close() override; + + void reset(const HashTableParam& param) override; + + Status do_append_chunk(const ChunkPtr& chunk) override; + + Status build(RuntimeState* state) override; + + bool anti_join_key_column_has_null() const override; + + int64_t ht_mem_usage() const override { return _ht.mem_usage(); } + + void get_build_info(size_t* bucket_size, float* avg_keys_per_bucket) override { + *bucket_size = _ht.get_bucket_size(); + *avg_keys_per_bucket = _ht.get_keys_per_bucket(); + } + + size_t get_output_probe_column_count() const override { return _ht.get_output_probe_column_count(); } + size_t get_output_build_column_count() const override { return _ht.get_output_build_column_count(); } + + void visitHt(const std::function& visitor) override; + + std::unique_ptr create_prober() override; + + void clone_readable(HashJoinBuilder* builder) override; + + ChunkPtr convert_to_spill_schema(const ChunkPtr& chunk) const override; + +private: + JoinHashTable _ht; + Columns _key_columns; +}; + +struct HashJoinBuildOptions { + bool enable_partitioned_hash_join = false; +}; + +class HashJoinBuilderFactory { +public: + static HashJoinBuilder* create(ObjectPool* pool, const HashJoinBuildOptions& options, HashJoiner& hash_joiner); +}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks \ No newline at end of file diff --git a/be/src/exec/hash_join_node.cpp b/be/src/exec/hash_join_node.cpp index c95989ff98bab..7d111dcec0698 100644 --- a/be/src/exec/hash_join_node.cpp +++ b/be/src/exec/hash_join_node.cpp @@ -145,6 +145,12 @@ Status HashJoinNode::init(const TPlanNode& tnode, RuntimeState* state) { if (tnode.hash_join_node.__isset.late_materialization) { _enable_late_materialization = tnode.hash_join_node.late_materialization; } +<<<<<<< HEAD +======= + if (tnode.hash_join_node.__isset.enable_partition_hash_join) { + _enable_partition_hash_join = tnode.hash_join_node.enable_partition_hash_join; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -168,6 +174,10 @@ Status HashJoinNode::prepare(RuntimeState* state) { ADD_CHILD_TIMER(_runtime_profile, "6-OtherJoinConjunctEvaluateTime", "ProbeTime"); _where_conjunct_evaluate_timer = ADD_CHILD_TIMER(_runtime_profile, "7-WhereConjunctEvaluateTime", "ProbeTime"); +<<<<<<< HEAD +======= + _probe_counter = ADD_COUNTER(_runtime_profile, "probeCount", TUnit::UNIT); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _probe_rows_counter = ADD_COUNTER(_runtime_profile, "ProbeRows", TUnit::UNIT); _build_rows_counter = ADD_COUNTER(_runtime_profile, "BuildRows", TUnit::UNIT); _build_buckets_counter = ADD_COUNTER(_runtime_profile, "BuildBuckets", TUnit::UNIT); @@ -196,11 +206,19 @@ void HashJoinNode::_init_hash_table_param(HashTableParam* param) { param->build_row_desc = &child(1)->row_desc(); param->probe_row_desc = &child(0)->row_desc(); param->search_ht_timer = _search_ht_timer; +<<<<<<< HEAD +======= + param->probe_counter = _probe_counter; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) param->output_build_column_timer = _output_build_column_timer; param->output_probe_column_timer = _output_probe_column_timer; param->build_output_slots = _output_slots; param->probe_output_slots = _output_slots; param->enable_late_materialization = _enable_late_materialization; +<<<<<<< HEAD +======= + param->enable_partition_hash_join = _enable_partition_hash_join; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::set predicate_slots; for (ExprContext* expr_context : _conjunct_ctxs) { @@ -470,7 +488,12 @@ pipeline::OpFactories HashJoinNode::_decompose_to_pipeline(pipeline::PipelineBui HashJoinerParam param(pool, _hash_join_node, _is_null_safes, _build_expr_ctxs, _probe_expr_ctxs, _other_join_conjunct_ctxs, _conjunct_ctxs, child(1)->row_desc(), child(0)->row_desc(), child(1)->type(), child(0)->type(), child(1)->conjunct_ctxs().empty(), _build_runtime_filters, +<<<<<<< HEAD _output_slots, _output_slots, _distribution_mode, false, _enable_late_materialization); +======= + _output_slots, _output_slots, _distribution_mode, false, _enable_late_materialization, + _enable_partition_hash_join); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto hash_joiner_factory = std::make_shared(param); // Create a shared RefCountedRuntimeFilterCollector diff --git a/be/src/exec/hash_join_node.h b/be/src/exec/hash_join_node.h index b165d0becc47d..9cb2d26aa8394 100644 --- a/be/src/exec/hash_join_node.h +++ b/be/src/exec/hash_join_node.h @@ -32,7 +32,10 @@ class ExprContext; class ColumnRef; class RuntimeFilterBuildDescriptor; +<<<<<<< HEAD static constexpr size_t kHashJoinKeyColumnOffset = 1; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class HashJoinNode final : public ExecNode { public: HashJoinNode(ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs); @@ -116,6 +119,10 @@ class HashJoinNode final : public ExecNode { bool _is_push_down = false; bool _enable_late_materialization = false; +<<<<<<< HEAD +======= + bool _enable_partition_hash_join = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) JoinHashTable _ht; @@ -144,6 +151,10 @@ class HashJoinNode final : public ExecNode { RuntimeProfile::Counter* _merge_input_chunk_timer = nullptr; RuntimeProfile::Counter* _probe_timer = nullptr; RuntimeProfile::Counter* _search_ht_timer = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* _probe_counter = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* _output_build_column_timer = nullptr; RuntimeProfile::Counter* _output_probe_column_timer = nullptr; RuntimeProfile::Counter* _build_rows_counter = nullptr; diff --git a/be/src/exec/hash_joiner.cpp b/be/src/exec/hash_joiner.cpp index 6b5fb7e954049..9ed05141c91a5 100644 --- a/be/src/exec/hash_joiner.cpp +++ b/be/src/exec/hash_joiner.cpp @@ -20,11 +20,23 @@ #include "column/column_helper.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "common/statusor.h" #include "exec/hash_join_components.h" #include "exec/spill/spiller.hpp" #include "exprs/column_ref.h" #include "exprs/expr.h" +======= +#include "common/config.h" +#include "common/status.h" +#include "common/statusor.h" +#include "exec/hash_join_components.h" +#include "exec/join_hash_map.h" +#include "exec/spill/spiller.hpp" +#include "exprs/column_ref.h" +#include "exprs/expr.h" +#include "gen_cpp/Metrics_types.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/strings/substitute.h" #include "runtime/current_thread.h" #include "simd/simd.h" @@ -39,6 +51,11 @@ void HashJoinProbeMetrics::prepare(RuntimeProfile* runtime_profile) { probe_conjunct_evaluate_timer = ADD_TIMER(runtime_profile, "ProbeConjunctEvaluateTime"); other_join_conjunct_evaluate_timer = ADD_TIMER(runtime_profile, "OtherJoinConjunctEvaluateTime"); where_conjunct_evaluate_timer = ADD_TIMER(runtime_profile, "WhereConjunctEvaluateTime"); +<<<<<<< HEAD +======= + probe_counter = ADD_COUNTER(runtime_profile, "probeCount", TUnit::UNIT); + partition_probe_overhead = ADD_TIMER(runtime_profile, "PartitionProbeOverhead"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void HashJoinBuildMetrics::prepare(RuntimeProfile* runtime_profile) { @@ -50,8 +67,13 @@ void HashJoinBuildMetrics::prepare(RuntimeProfile* runtime_profile) { runtime_filter_num = ADD_COUNTER(runtime_profile, "RuntimeFilterNum", TUnit::UNIT); build_keys_per_bucket = ADD_COUNTER(runtime_profile, "BuildKeysPerBucket%", TUnit::UNIT); hash_table_memory_usage = ADD_COUNTER(runtime_profile, "HashTableMemoryUsage", TUnit::BYTES); +<<<<<<< HEAD partial_runtime_bloom_filter_bytes = ADD_COUNTER(runtime_profile, "PartialRuntimeBloomFilterBytes", TUnit::BYTES); +======= + partial_runtime_bloom_filter_bytes = ADD_COUNTER(runtime_profile, "PartialRuntimeBloomFilterBytes", TUnit::BYTES); + partition_nums = ADD_COUNTER(runtime_profile, "PartitionNums", TUnit::UNIT); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } HashJoiner::HashJoiner(const HashJoinerParam& param) @@ -82,7 +104,15 @@ HashJoiner::HashJoiner(const HashJoinerParam& param) if (param._hash_join_node.__isset.build_runtime_filters_from_planner) { _build_runtime_filters_from_planner = param._hash_join_node.build_runtime_filters_from_planner; } +<<<<<<< HEAD _hash_join_builder = _pool->add(new HashJoinBuilder(*this)); +======= + + HashJoinBuildOptions build_options; + build_options.enable_partitioned_hash_join = param._enable_partition_hash_join; + + _hash_join_builder = HashJoinBuilderFactory::create(_pool, build_options, *this); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _hash_join_prober = _pool->add(new HashJoinProber(*this)); _build_metrics = _pool->add(new HashJoinBuildMetrics()); _probe_metrics = _pool->add(new HashJoinProbeMetrics()); @@ -107,10 +137,16 @@ Status HashJoiner::prepare_builder(RuntimeState* state, RuntimeProfile* runtime_ _init_hash_table_param(&_hash_table_param); _hash_join_builder->create(hash_table_param()); +<<<<<<< HEAD auto& ht = _hash_join_builder->hash_table(); _output_probe_column_count = ht.get_output_probe_column_count(); _output_build_column_count = ht.get_output_build_column_count(); +======= + + _output_probe_column_count = _hash_join_builder->get_output_probe_column_count(); + _output_build_column_count = _hash_join_builder->get_output_build_column_count(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -125,6 +161,7 @@ Status HashJoiner::prepare_prober(RuntimeState* state, RuntimeProfile* runtime_p runtime_profile->add_info_string("JoinType", to_string(_join_type)); _probe_metrics->prepare(runtime_profile); +<<<<<<< HEAD auto& hash_table = _hash_join_builder->hash_table(); hash_table.set_probe_profile(probe_metrics().search_ht_timer, probe_metrics().output_probe_column_timer, probe_metrics().output_build_column_timer); @@ -132,6 +169,12 @@ Status HashJoiner::prepare_prober(RuntimeState* state, RuntimeProfile* runtime_p _hash_table_param.search_ht_timer = probe_metrics().search_ht_timer; _hash_table_param.output_build_column_timer = probe_metrics().output_build_column_timer; _hash_table_param.output_probe_column_timer = probe_metrics().output_probe_column_timer; +======= + _hash_table_param.search_ht_timer = probe_metrics().search_ht_timer; + _hash_table_param.output_build_column_timer = probe_metrics().output_build_column_timer; + _hash_table_param.output_probe_column_timer = probe_metrics().output_probe_column_timer; + _hash_table_param.probe_counter = probe_metrics().probe_counter; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -206,9 +249,18 @@ Status HashJoiner::append_spill_task(RuntimeState* state, std::functionbuild(state)); +<<<<<<< HEAD size_t bucket_size = _hash_join_builder->hash_table().get_bucket_size(); COUNTER_SET(build_metrics().build_buckets_counter, static_cast(bucket_size)); COUNTER_SET(build_metrics().build_keys_per_bucket, static_cast(100 * avg_keys_per_bucket())); +======= + + size_t bucket_size = 0; + float avg_keys_per_bucket = 0; + _hash_join_builder->get_build_info(&bucket_size, &avg_keys_per_bucket); + COUNTER_SET(build_metrics().build_buckets_counter, static_cast(bucket_size)); + COUNTER_SET(build_metrics().build_keys_per_bucket, static_cast(100 * avg_keys_per_bucket)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); @@ -217,7 +269,11 @@ Status HashJoiner::build_ht(RuntimeState* state) { bool HashJoiner::need_input() const { // when _buffered_chunk accumulates several chunks to form into a large enough chunk, it is moved into // _probe_chunk for probe operations. +<<<<<<< HEAD return _phase == HashJoinPhase::PROBE && _hash_join_prober->probe_chunk_empty(); +======= + return _phase == HashJoinPhase::PROBE && _hash_join_prober->need_input(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } bool HashJoiner::has_output() const { @@ -243,6 +299,13 @@ Status HashJoiner::push_chunk(RuntimeState* state, ChunkPtr&& chunk) { return _hash_join_prober->push_probe_chunk(state, std::move(chunk)); } +<<<<<<< HEAD +======= +Status HashJoiner::probe_input_finished(RuntimeState* state) { + return _hash_join_prober->on_input_finished(state); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr HashJoiner::pull_chunk(RuntimeState* state) { DCHECK(_phase != HashJoinPhase::BUILD); return _pull_probe_output_chunk(state); @@ -252,10 +315,16 @@ StatusOr HashJoiner::_pull_probe_output_chunk(RuntimeState* state) { DCHECK(_phase != HashJoinPhase::BUILD); auto chunk = std::make_shared(); +<<<<<<< HEAD auto& ht = _hash_join_builder->hash_table(); if (_phase == HashJoinPhase::PROBE || !_hash_join_prober->probe_chunk_empty()) { ASSIGN_OR_RETURN(chunk, _hash_join_prober->probe_chunk(state, &ht)) +======= + + if (_phase == HashJoinPhase::PROBE || !_hash_join_prober->probe_chunk_empty()) { + ASSIGN_OR_RETURN(chunk, _hash_join_prober->probe_chunk(state)) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return chunk; } @@ -266,7 +335,11 @@ StatusOr HashJoiner::_pull_probe_output_chunk(RuntimeState* state) { } bool has_remain = false; +<<<<<<< HEAD ASSIGN_OR_RETURN(chunk, _hash_join_prober->probe_remain(state, &ht, &has_remain)) +======= + ASSIGN_OR_RETURN(chunk, _hash_join_prober->probe_remain(state, &has_remain)) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!has_remain) { enter_eos_phase(); @@ -288,13 +361,21 @@ Status HashJoiner::create_runtime_filters(RuntimeState* state) { } uint64_t runtime_join_filter_pushdown_limit = runtime_bloom_filter_row_limit(); +<<<<<<< HEAD auto& ht = _hash_join_builder->hash_table(); +======= + size_t ht_row_count = _hash_join_builder->hash_table_row_count(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_is_push_down) { if (_probe_node_type == TPlanNodeType::EXCHANGE_NODE && _build_node_type == TPlanNodeType::EXCHANGE_NODE) { _is_push_down = false; +<<<<<<< HEAD } else if (ht.get_row_count() > runtime_join_filter_pushdown_limit) { +======= + } else if (ht_row_count > runtime_join_filter_pushdown_limit) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_push_down = false; } @@ -311,6 +392,7 @@ Status HashJoiner::create_runtime_filters(RuntimeState* state) { return _create_runtime_bloom_filters(state, runtime_join_filter_pushdown_limit); } +<<<<<<< HEAD void HashJoiner::reference_hash_table(HashJoiner* src_join_builder) { auto& hash_table = _hash_join_builder->hash_table(); @@ -329,6 +411,26 @@ void HashJoiner::reference_hash_table(HashJoiner* src_join_builder) { // _phase may be EOS. auto old_phase = HashJoinPhase::BUILD; _phase.compare_exchange_strong(old_phase, src_join_builder->_phase.load()); +======= +void HashJoiner::reference_hash_table(HashJoiner* src_join_builder_cntl) { + if (this == src_join_builder_cntl) { + _hash_join_prober->attach(src_join_builder_cntl->hash_join_builder(), probe_metrics()); + } else { + src_join_builder_cntl->hash_join_builder()->clone_readable(this->hash_join_builder()); + _hash_join_prober->attach(this->hash_join_builder(), probe_metrics()); + _hash_table_param = src_join_builder_cntl->hash_table_param(); + + // _hash_table_build_rows is root truth, it used to by _short_circuit_break(). + _hash_table_build_rows = src_join_builder_cntl->_hash_table_build_rows; + _output_probe_column_count = src_join_builder_cntl->_output_probe_column_count; + _output_build_column_count = src_join_builder_cntl->_output_build_column_count; + + // _phase may be EOS. + auto old_phase = HashJoinPhase::BUILD; + _phase.compare_exchange_strong(old_phase, src_join_builder_cntl->_phase.load()); + } + _has_referenced_hash_table = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void HashJoiner::set_prober_finished() { @@ -345,8 +447,15 @@ void HashJoiner::decr_prober(RuntimeState* state) { } float HashJoiner::avg_keys_per_bucket() const { +<<<<<<< HEAD const auto& hash_table = _hash_join_builder->hash_table(); return hash_table.get_keys_per_bucket(); +======= + size_t bucket_size = 0; + float avg_keys_per_bucket = 0; + _hash_join_builder->get_build_info(&bucket_size, &avg_keys_per_bucket); + return avg_keys_per_bucket; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status HashJoiner::reset_probe(starrocks::RuntimeState* state) { @@ -357,13 +466,18 @@ Status HashJoiner::reset_probe(starrocks::RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD _hash_join_prober->reset(); _hash_join_builder->reset_probe(state); +======= + _hash_join_prober->reset(state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } +<<<<<<< HEAD bool HashJoiner::_has_null(const ColumnPtr& column) { if (column->is_nullable()) { const auto& null_column = ColumnHelper::as_raw_column(column)->null_column(); @@ -373,6 +487,8 @@ bool HashJoiner::_has_null(const ColumnPtr& column) { return false; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status HashJoiner::_calc_filter_for_other_conjunct(ChunkPtr* chunk, Filter& filter, bool& filter_all, bool& hit_all) { filter_all = false; hit_all = false; @@ -512,12 +628,16 @@ Status HashJoiner::_process_where_conjunct(ChunkPtr* chunk) { Status HashJoiner::_create_runtime_in_filters(RuntimeState* state) { SCOPED_TIMER(build_metrics().build_runtime_filter_timer); size_t ht_row_count = get_ht_row_count(); +<<<<<<< HEAD auto& ht = _hash_join_builder->hash_table(); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (ht_row_count > config::max_pushdown_conditions_per_column) { return Status::OK(); } +<<<<<<< HEAD if (ht_row_count > 0) { // there is a bug (DSDB-3860) in old planner if probe_expr is not slot-ref, and this fix is workaround. size_t size = _build_expr_ctxs.size(); @@ -531,6 +651,16 @@ Status HashJoiner::_create_runtime_in_filters(RuntimeState* state) { if (!to_build[i]) continue; ColumnPtr column = ht.get_key_columns()[i]; Expr* probe_expr = _probe_expr_ctxs[i]->root(); +======= + std::vector hash_tables; + _hash_join_builder->visitHt([&hash_tables](JoinHashTable* ht) { hash_tables.push_back(ht); }); + + if (ht_row_count > 0) { + size_t size = _build_expr_ctxs.size(); + for (size_t i = 0; i < size; i++) { + Expr* probe_expr = _probe_expr_ctxs[i]->root(); + DCHECK(probe_expr->is_slotref()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // create and fill runtime in filter. VectorizedInConstPredicateBuilder builder(state, _pool, probe_expr); builder.set_eq_null(_is_null_safes[i]); @@ -540,10 +670,22 @@ Status HashJoiner::_create_runtime_in_filters(RuntimeState* state) { _runtime_in_filters.push_back(nullptr); continue; } +<<<<<<< HEAD if (probe_expr->type().is_string_type()) { _string_key_columns.emplace_back(column); } builder.add_values(column, kHashJoinKeyColumnOffset); +======= + + for (auto* ht : hash_tables) { + ColumnPtr column = ht->get_key_columns()[i]; + if (probe_expr->type().is_string_type()) { + _string_key_columns.emplace_back(column); + } + builder.add_values(column, kHashJoinKeyColumnOffset); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _runtime_in_filters.push_back(builder.get_in_const_predicate()); } } @@ -554,7 +696,14 @@ Status HashJoiner::_create_runtime_in_filters(RuntimeState* state) { Status HashJoiner::_create_runtime_bloom_filters(RuntimeState* state, int64_t limit) { SCOPED_TIMER(build_metrics().build_runtime_filter_timer); +<<<<<<< HEAD auto& ht = _hash_join_builder->hash_table(); +======= + size_t ht_row_count = get_ht_row_count(); + std::vector hash_tables; + _hash_join_builder->visitHt([&hash_tables](JoinHashTable* ht) { hash_tables.emplace_back(ht); }); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto* rf_desc : _build_runtime_filters) { rf_desc->set_is_pipeline(true); // skip if it does not have consumer. @@ -562,14 +711,31 @@ Status HashJoiner::_create_runtime_bloom_filters(RuntimeState* state, int64_t li _runtime_bloom_filter_build_params.emplace_back(); continue; } +<<<<<<< HEAD if (!rf_desc->has_remote_targets() && ht.get_row_count() > limit) { +======= + if (!rf_desc->has_remote_targets() && ht_row_count > limit) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _runtime_bloom_filter_build_params.emplace_back(); continue; } int expr_order = rf_desc->build_expr_order(); +<<<<<<< HEAD ColumnPtr column = ht.get_key_columns()[expr_order]; bool eq_null = _is_null_safes[expr_order]; +======= + bool eq_null = _is_null_safes[expr_order]; + bool is_empty = false; + std::vector columns; + + for (auto* ht : hash_tables) { + ColumnPtr column = ht->get_key_columns()[expr_order]; + is_empty |= column == nullptr || column->empty(); + columns.push_back(column); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MutableJoinRuntimeFilterPtr filter = nullptr; auto multi_partitioned = rf_desc->layout().pipeline_level_multi_partitioned(); multi_partitioned |= rf_desc->num_colocate_partition() > 0; @@ -577,6 +743,7 @@ Status HashJoiner::_create_runtime_bloom_filters(RuntimeState* state, int64_t li LogicalType build_type = rf_desc->build_expr_type(); filter = std::shared_ptr( RuntimeFilterHelper::create_runtime_bloom_filter(nullptr, build_type)); +<<<<<<< HEAD if (filter == nullptr) continue; filter->set_join_mode(rf_desc->join_mode()); filter->init(ht.get_row_count()); @@ -585,6 +752,20 @@ Status HashJoiner::_create_runtime_bloom_filters(RuntimeState* state, int64_t li } _runtime_bloom_filter_build_params.emplace_back(pipeline::RuntimeBloomFilterBuildParam( multi_partitioned, eq_null, std::move(column), std::move(filter))); +======= + if (filter == nullptr) { + _runtime_bloom_filter_build_params.emplace_back(); + continue; + } + filter->set_join_mode(rf_desc->join_mode()); + filter->init(ht_row_count); + RETURN_IF_ERROR(RuntimeFilterHelper::fill_runtime_bloom_filter(columns, build_type, filter.get(), + kHashJoinKeyColumnOffset, eq_null)); + } + + _runtime_bloom_filter_build_params.emplace_back(pipeline::RuntimeBloomFilterBuildParam( + multi_partitioned, eq_null, is_empty, std::move(columns), std::move(filter))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } diff --git a/be/src/exec/hash_joiner.h b/be/src/exec/hash_joiner.h index 6a08c86ddb27e..8f271bb82edff 100644 --- a/be/src/exec/hash_joiner.h +++ b/be/src/exec/hash_joiner.h @@ -72,7 +72,11 @@ struct HashJoinerParam { bool build_conjunct_ctxs_is_empty, std::list build_runtime_filters, std::set build_output_slots, std::set probe_output_slots, const TJoinDistributionMode::type distribution_mode, bool mor_reader_mode, +<<<<<<< HEAD bool enable_late_materialization) +======= + bool enable_late_materialization, bool enable_partition_hash_join) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : _pool(pool), _hash_join_node(hash_join_node), _is_null_safes(std::move(is_null_safes)), @@ -90,7 +94,12 @@ struct HashJoinerParam { _probe_output_slots(std::move(probe_output_slots)), _distribution_mode(distribution_mode), _mor_reader_mode(mor_reader_mode), +<<<<<<< HEAD _enable_late_materialization(enable_late_materialization) {} +======= + _enable_late_materialization(enable_late_materialization), + _enable_partition_hash_join(enable_partition_hash_join) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) HashJoinerParam(HashJoinerParam&&) = default; HashJoinerParam(HashJoinerParam&) = default; @@ -115,6 +124,10 @@ struct HashJoinerParam { const TJoinDistributionMode::type _distribution_mode; const bool _mor_reader_mode; const bool _enable_late_materialization; +<<<<<<< HEAD +======= + const bool _enable_partition_hash_join; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; inline bool could_short_circuit(TJoinOp::type join_type) { @@ -142,6 +155,11 @@ struct HashJoinProbeMetrics { RuntimeProfile::Counter* other_join_conjunct_evaluate_timer = nullptr; RuntimeProfile::Counter* where_conjunct_evaluate_timer = nullptr; RuntimeProfile::Counter* output_build_column_timer = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* probe_counter = nullptr; + RuntimeProfile::Counter* partition_probe_overhead = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void prepare(RuntimeProfile* runtime_profile); }; @@ -155,12 +173,21 @@ struct HashJoinBuildMetrics { RuntimeProfile::Counter* runtime_filter_num = nullptr; RuntimeProfile::Counter* build_keys_per_bucket = nullptr; RuntimeProfile::Counter* hash_table_memory_usage = nullptr; +<<<<<<< HEAD RuntimeProfile::Counter* partial_runtime_bloom_filter_bytes = nullptr; +======= + RuntimeProfile::Counter* partial_runtime_bloom_filter_bytes = nullptr; + RuntimeProfile::Counter* partition_nums = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void prepare(RuntimeProfile* runtime_profile); }; +<<<<<<< HEAD +======= +// TODO: rename HashJoiner to HashJoinController +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class HashJoiner final : public pipeline::ContextWithDependency { public: explicit HashJoiner(const HashJoinerParam& param); @@ -171,8 +198,13 @@ class HashJoiner final : public pipeline::ContextWithDependency { } } +<<<<<<< HEAD [[nodiscard]] Status prepare_builder(RuntimeState* state, RuntimeProfile* runtime_profile); [[nodiscard]] Status prepare_prober(RuntimeState* state, RuntimeProfile* runtime_profile); +======= + Status prepare_builder(RuntimeState* state, RuntimeProfile* runtime_profile); + Status prepare_prober(RuntimeState* state, RuntimeProfile* runtime_profile); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state) override; bool need_input() const; @@ -199,6 +231,7 @@ class HashJoiner final : public pipeline::ContextWithDependency { void enter_eos_phase() { _phase = HashJoinPhase::EOS; } // build phase +<<<<<<< HEAD [[nodiscard]] Status append_chunk_to_ht(const ChunkPtr& chunk); [[nodiscard]] Status append_chunk_to_spill_buffer(RuntimeState* state, const ChunkPtr& chunk); @@ -209,6 +242,19 @@ class HashJoiner final : public pipeline::ContextWithDependency { // probe phase [[nodiscard]] Status push_chunk(RuntimeState* state, ChunkPtr&& chunk); [[nodiscard]] StatusOr pull_chunk(RuntimeState* state); +======= + Status append_chunk_to_ht(const ChunkPtr& chunk); + + Status append_chunk_to_spill_buffer(RuntimeState* state, const ChunkPtr& chunk); + + Status append_spill_task(RuntimeState* state, std::function()>& spill_task); + + Status build_ht(RuntimeState* state); + // probe phase + Status push_chunk(RuntimeState* state, ChunkPtr&& chunk); + Status probe_input_finished(RuntimeState* state); + StatusOr pull_chunk(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pipeline::RuntimeInFilters& get_runtime_in_filters() { return _runtime_in_filters; } pipeline::RuntimeBloomFilters& get_runtime_bloom_filters() { return _build_runtime_filters; } @@ -220,7 +266,11 @@ class HashJoiner final : public pipeline::ContextWithDependency { HashJoinBuilder* hash_join_builder() { return _hash_join_builder; } +<<<<<<< HEAD [[nodiscard]] Status create_runtime_filters(RuntimeState* state); +======= + Status create_runtime_filters(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void reference_hash_table(HashJoiner* src_join_builder); @@ -231,7 +281,11 @@ class HashJoiner final : public pipeline::ContextWithDependency { bool has_referenced_hash_table() const { return _has_referenced_hash_table; } Columns string_key_columns() { return _string_key_columns; } +<<<<<<< HEAD [[nodiscard]] Status reset_probe(RuntimeState* state); +======= + Status reset_probe(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) float avg_keys_per_bucket() const; @@ -259,22 +313,43 @@ class HashJoiner final : public pipeline::ContextWithDependency { void set_spill_strategy(spill::SpillStrategy strategy) { _spill_strategy = strategy; } spill::SpillStrategy spill_strategy() { return _spill_strategy; } +<<<<<<< HEAD [[nodiscard]] Status prepare_probe_key_columns(Columns* key_columns, const ChunkPtr& chunk) { +======= + Status prepare_probe_key_columns(Columns* key_columns, const ChunkPtr& chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(probe_metrics().probe_conjunct_evaluate_timer); RETURN_IF_ERROR(_prepare_key_columns(*key_columns, chunk, _probe_expr_ctxs)); return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status prepare_build_key_columns(Columns* key_columns, const ChunkPtr& chunk) { +======= + Status prepare_build_key_columns(Columns* key_columns, const ChunkPtr& chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(build_metrics().build_conjunct_evaluate_timer); RETURN_IF_ERROR(_prepare_key_columns(*key_columns, chunk, _build_expr_ctxs)); return Status::OK(); } +<<<<<<< HEAD const std::vector probe_expr_ctxs() { return _probe_expr_ctxs; } HashJoinProber* new_prober(ObjectPool* pool) { return _hash_join_prober->clone_empty(pool); } HashJoinBuilder* new_builder(ObjectPool* pool) { return _hash_join_builder->clone_empty(pool); } +======= + const std::vector& probe_expr_ctxs() { return _probe_expr_ctxs; } + const std::vector& build_expr_ctxs() { return _build_expr_ctxs; } + + HashJoinProber* new_prober(ObjectPool* pool) { return _hash_join_prober->clone_empty(pool); } + HashJoinBuilder* new_builder(ObjectPool* pool) { + // We don't support spill partition hash join now. + HashJoinBuildOptions options; + options.enable_partitioned_hash_join = false; + return HashJoinBuilderFactory::create(pool, options, *this); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status filter_probe_output_chunk(ChunkPtr& chunk, JoinHashTable& hash_table) { // Probe in JoinHashMap is divided into probe with other_conjuncts and without other_conjuncts. @@ -302,7 +377,11 @@ class HashJoiner final : public pipeline::ContextWithDependency { } } +<<<<<<< HEAD [[nodiscard]] Status filter_post_probe_output_chunk(ChunkPtr& chunk) { +======= + Status filter_post_probe_output_chunk(ChunkPtr& chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Post probe needn't process _other_join_conjunct_ctxs, because they // are `ON` predicates, which need to be processed only on probe phase. if (chunk && !chunk->is_empty() && !_conjunct_ctxs.empty()) { @@ -319,8 +398,12 @@ class HashJoiner final : public pipeline::ContextWithDependency { void _init_hash_table_param(HashTableParam* param); +<<<<<<< HEAD [[nodiscard]] Status _prepare_key_columns(Columns& key_columns, const ChunkPtr& chunk, const vector& expr_ctxs) { +======= + Status _prepare_key_columns(Columns& key_columns, const ChunkPtr& chunk, const vector& expr_ctxs) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) key_columns.resize(0); for (auto& expr_ctx : expr_ctxs) { ASSIGN_OR_RETURN(auto column_ptr, expr_ctx->evaluate(chunk.get())); @@ -356,11 +439,17 @@ class HashJoiner final : public pipeline::ContextWithDependency { return; } +<<<<<<< HEAD auto& ht = _hash_join_builder->hash_table(); if (row_count > 0) { if (_join_type == TJoinOp::NULL_AWARE_LEFT_ANTI_JOIN && ht.get_key_columns().size() == 1 && _has_null(ht.get_key_columns()[0]) && _other_join_conjunct_ctxs.empty()) { +======= + if (row_count > 0) { + if (_join_type == TJoinOp::NULL_AWARE_LEFT_ANTI_JOIN && + _hash_join_builder->anti_join_key_column_has_null() && _other_join_conjunct_ctxs.empty()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The current implementation of HashTable will reserve a row for judging the end of the linked list. // When performing expression calculations (such as cast string to int), // it is possible that this reserved row will generate Null, @@ -372,6 +461,7 @@ class HashJoiner final : public pipeline::ContextWithDependency { } } +<<<<<<< HEAD [[nodiscard]] StatusOr _pull_probe_output_chunk(RuntimeState* state); [[nodiscard]] Status _calc_filter_for_other_conjunct(ChunkPtr* chunk, Filter& filter, bool& filter_all, @@ -389,6 +479,24 @@ class HashJoiner final : public pipeline::ContextWithDependency { [[nodiscard]] Status _create_runtime_in_filters(RuntimeState* state); [[nodiscard]] Status _create_runtime_bloom_filters(RuntimeState* state, int64_t limit); +======= + StatusOr _pull_probe_output_chunk(RuntimeState* state); + + Status _calc_filter_for_other_conjunct(ChunkPtr* chunk, Filter& filter, bool& filter_all, bool& hit_all); + static void _process_row_for_other_conjunct(ChunkPtr* chunk, size_t start_column, size_t column_count, + bool filter_all, bool hit_all, const Filter& filter); + + Status _process_outer_join_with_other_conjunct(ChunkPtr* chunk, size_t start_column, size_t column_count, + JoinHashTable& hash_table); + Status _process_semi_join_with_other_conjunct(ChunkPtr* chunk, JoinHashTable& hash_table); + Status _process_right_anti_join_with_other_conjunct(ChunkPtr* chunk, JoinHashTable& hash_table); + Status _process_other_conjunct(ChunkPtr* chunk, JoinHashTable& hash_table); + Status _process_where_conjunct(ChunkPtr* chunk); + + Status _create_runtime_in_filters(RuntimeState* state); + + Status _create_runtime_bloom_filters(RuntimeState* state, int64_t limit); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: const THashJoinNode& _hash_join_node; diff --git a/be/src/exec/hdfs_scanner.cpp b/be/src/exec/hdfs_scanner.cpp index 29eb1020016d8..584761333e27a 100644 --- a/be/src/exec/hdfs_scanner.cpp +++ b/be/src/exec/hdfs_scanner.cpp @@ -21,6 +21,11 @@ #include "io/cache_select_input_stream.hpp" #include "io/compressed_input_stream.h" #include "io/shared_buffered_input_stream.h" +<<<<<<< HEAD +======= +#include "pipeline/fragment_context.h" +#include "storage/predicate_parser.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/compression/compression_utils.h" #include "util/compression/stream_compression.h" @@ -86,7 +91,10 @@ Status HdfsScanner::init(RuntimeState* runtime_state, const HdfsScannerParams& s _runtime_state = runtime_state; _scanner_params = scanner_params; +<<<<<<< HEAD RETURN_IF_ERROR(_init_mor_processor(runtime_state, scanner_params.mor_params)); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(do_init(runtime_state, scanner_params)); return Status::OK(); @@ -105,6 +113,19 @@ Status HdfsScanner::_build_scanner_context() { partition_values.emplace_back(std::move(partition_value_column)); } +<<<<<<< HEAD +======= + // evaluate extended column values + std::vector& extended_values = ctx.extended_values; + for (size_t i = 0; i < _scanner_params.extended_col_slots.size(); i++) { + int extended_col_idx = _scanner_params.index_in_extended_columns[i]; + ASSIGN_OR_RETURN(auto extended_value_column, + _scanner_params.extended_col_values[extended_col_idx]->evaluate(nullptr)); + DCHECK(extended_value_column->is_constant()); + extended_values.emplace_back(std::move(extended_value_column)); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ctx.conjunct_ctxs_by_slot = _scanner_params.conjunct_ctxs_by_slot; // build columns of materialized and partition. @@ -133,7 +154,19 @@ Status HdfsScanner::_build_scanner_context() { ctx.partition_columns.emplace_back(std::move(column)); } +<<<<<<< HEAD ctx.tuple_desc = _scanner_params.tuple_desc; +======= + for (size_t i = 0; i < _scanner_params.extended_col_slots.size(); i++) { + auto* slot = _scanner_params.extended_col_slots[i]; + HdfsScannerContext::ColumnInfo column; + column.slot_desc = slot; + column.idx_in_chunk = _scanner_params.extended_col_index_in_chunk[i]; + ctx.extended_columns.emplace_back(std::move(column)); + } + + ctx.slot_descs = _scanner_params.tuple_desc->slots(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ctx.scan_range = _scanner_params.scan_range; ctx.runtime_filter_collector = _scanner_params.runtime_filter_collector; ctx.min_max_conjunct_ctxs = _scanner_params.min_max_conjunct_ctxs; @@ -151,6 +184,7 @@ Status HdfsScanner::_build_scanner_context() { ctx.split_context = _scanner_params.split_context; ctx.enable_split_tasks = _scanner_params.enable_split_tasks; ctx.connector_max_split_size = _scanner_params.connector_max_split_size; +<<<<<<< HEAD return Status::OK(); } @@ -162,6 +196,25 @@ Status HdfsScanner::_init_mor_processor(RuntimeState* runtime_state, const MORPa _mor_processor = std::make_shared(params.runtime_profile); RETURN_IF_ERROR(_mor_processor->init(runtime_state, params)); +======= + + if (config::parquet_advance_zonemap_filter) { + ScanConjunctsManagerOptions opts; + opts.conjunct_ctxs_ptr = &_scanner_params.all_conjunct_ctxs; + opts.tuple_desc = _scanner_params.tuple_desc; + opts.obj_pool = _runtime_state->obj_pool(); + opts.runtime_filters = _scanner_params.runtime_filter_collector; + opts.runtime_state = _runtime_state; + opts.enable_column_expr_predicate = true; + opts.is_olap_scan = false; + opts.pred_tree_params = _runtime_state->fragment_ctx()->pred_tree_params(); + ctx.conjuncts_manager = std::make_unique(std::move(opts)); + RETURN_IF_ERROR(ctx.conjuncts_manager->parse_conjuncts()); + ConnectorPredicateParser predicate_parser{&ctx.slot_descs}; + ASSIGN_OR_RETURN(ctx.predicate_tree, + ctx.conjuncts_manager->get_predicate_tree(&predicate_parser, ctx.predicate_free_pool)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -175,7 +228,10 @@ Status HdfsScanner::get_next(RuntimeState* runtime_state, ChunkPtr* chunk) { SCOPED_RAW_TIMER(&_app_stats.expr_filter_ns); RETURN_IF_ERROR(ExecNode::eval_conjuncts(_scanner_params.scanner_conjunct_ctxs, (*chunk).get())); } +<<<<<<< HEAD RETURN_IF_ERROR(_mor_processor->get_next(runtime_state, chunk)); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else if (status.is_end_of_file()) { // do nothing. } else { @@ -192,7 +248,10 @@ Status HdfsScanner::open(RuntimeState* runtime_state) { } RETURN_IF_ERROR(_build_scanner_context()); RETURN_IF_ERROR(do_open(runtime_state)); +<<<<<<< HEAD RETURN_IF_ERROR(_mor_processor->build_hash_table(runtime_state)); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _opened = true; VLOG_FILE << "open file success: " << _scanner_params.path << ", scan range = [" << _scanner_params.scan_range->offset << "," @@ -214,14 +273,24 @@ void HdfsScanner::close() noexcept { update_counter(); do_close(_runtime_state); _file.reset(nullptr); +<<<<<<< HEAD _mor_processor->close(_runtime_state); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr> HdfsScanner::create_random_access_file( std::shared_ptr& shared_buffered_input_stream, std::shared_ptr& cache_input_stream, const OpenFileOptions& options) { ASSIGN_OR_RETURN(std::unique_ptr raw_file, options.fs->new_random_access_file(options.path)) +<<<<<<< HEAD const int64_t file_size = options.file_size; +======= + int64_t file_size = options.file_size; + if (file_size < 0) { + ASSIGN_OR_RETURN(file_size, raw_file->stream()->get_size()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) raw_file->set_size(file_size); const std::string& filename = raw_file->filename(); @@ -558,6 +627,7 @@ StatusOr HdfsScannerContext::should_skip_by_evaluating_not_existed_slots() } void HdfsScannerContext::append_or_update_partition_column_to_chunk(ChunkPtr* chunk, size_t row_count) { +<<<<<<< HEAD if (partition_columns.size() == 0) return; ChunkPtr& ck = (*chunk); for (size_t i = 0; i < partition_columns.size(); i++) { @@ -576,6 +646,37 @@ void HdfsScannerContext::append_or_update_partition_column_to_chunk(ChunkPtr* ch chunk_part_column->assign(row_count, 0); } ck->append_or_update_column(std::move(chunk_part_column), slot_desc->id()); +======= + append_or_update_column_to_chunk(chunk, row_count, partition_columns, partition_values); +} + +void HdfsScannerContext::append_or_update_extended_column_to_chunk(ChunkPtr* chunk, size_t row_count) { + append_or_update_column_to_chunk(chunk, row_count, extended_columns, extended_values); +} + +void HdfsScannerContext::append_or_update_column_to_chunk(ChunkPtr* chunk, size_t row_count, + const std::vector& columns, + const std::vector& values) { + if (columns.size() == 0) return; + + ChunkPtr& ck = (*chunk); + for (size_t i = 0; i < columns.size(); i++) { + SlotDescriptor* slot_desc = columns[i].slot_desc; + DCHECK(values[i]->is_constant()); + auto* const_column = ColumnHelper::as_raw_column(values[i]); + ColumnPtr data_column = const_column->data_column(); + auto chunk_column = ColumnHelper::create_column(slot_desc->type(), slot_desc->is_nullable()); + + if (row_count > 0) { + if (data_column->is_nullable()) { + chunk_column->append_nulls(1); + } else { + chunk_column->append(*data_column, 0, 1); + } + chunk_column->assign(row_count, 0); + } + ck->append_or_update_column(std::move(chunk_column), slot_desc->id()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } ck->set_num_rows(row_count); } diff --git a/be/src/exec/hdfs_scanner.h b/be/src/exec/hdfs_scanner.h index 040b8e382badd..2a32a817e5f5c 100644 --- a/be/src/exec/hdfs_scanner.h +++ b/be/src/exec/hdfs_scanner.h @@ -17,7 +17,12 @@ #include #include +<<<<<<< HEAD #include "exec/mor_processor.h" +======= +#include "exec/olap_scan_prepare.h" +#include "exec/pipeline/scan/morsel.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr.h" #include "exprs/expr_context.h" #include "exprs/runtime_filter_bank.h" @@ -82,6 +87,11 @@ struct HdfsScanStats { // page index int64_t rows_before_page_index = 0; int64_t page_index_ns = 0; +<<<<<<< HEAD +======= + int64_t parquet_total_row_groups = 0; + int64_t parquet_filtered_row_groups = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // late materialize round-by-round int64_t group_min_round_cost = 0; @@ -159,6 +169,10 @@ struct HdfsScannerParams { // runtime bloom filter. const RuntimeFilterProbeCollector* runtime_filter_collector = nullptr; +<<<<<<< HEAD +======= + std::vector all_conjunct_ctxs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // all conjuncts except `conjunct_ctxs_by_slot`, like compound predicates std::vector scanner_conjunct_ctxs; std::unordered_set slots_in_conjunct; @@ -174,6 +188,11 @@ struct HdfsScannerParams { std::string path; // The file size. -1 means unknown. int64_t file_size = -1; +<<<<<<< HEAD +======= + // the table location + std::string table_location; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TupleDescriptor* tuple_desc = nullptr; @@ -190,6 +209,14 @@ struct HdfsScannerParams { // partition conjunct, used to generate partition columns std::vector partition_values; +<<<<<<< HEAD +======= + std::vector extended_col_slots; + std::vector extended_col_index_in_chunk; + std::vector index_in_extended_columns; + std::vector extended_col_values; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // min max conjunct for filter row group or page // should clone in scanner std::vector min_max_conjunct_ctxs; @@ -204,9 +231,15 @@ struct HdfsScannerParams { std::vector deletes; +<<<<<<< HEAD const TIcebergSchema* iceberg_schema = nullptr; const TIcebergSchema* iceberg_equal_delete_schema = nullptr; +======= + std::shared_ptr deletion_vector_descriptor = nullptr; + + const TIcebergSchema* iceberg_schema = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_lazy_materialization_slot(SlotId slot_id) const; @@ -219,7 +252,10 @@ struct HdfsScannerParams { bool can_use_any_column = false; bool can_use_min_max_count_opt = false; bool orc_use_column_names = false; +<<<<<<< HEAD MORParams mor_params; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t connector_max_split_size = 0; }; @@ -244,7 +280,11 @@ struct HdfsScannerContext { return case_sensitive ? name : boost::algorithm::to_lower_copy(name); } +<<<<<<< HEAD const TupleDescriptor* tuple_desc = nullptr; +======= + std::vector slot_descs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::unordered_map> conjunct_ctxs_by_slot; // materialized column read from parquet file @@ -256,6 +296,14 @@ struct HdfsScannerContext { // partition column value which read from hdfs file path std::vector partition_values; +<<<<<<< HEAD +======= + // extended column + std::vector extended_columns; + + std::vector extended_values; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // scan range const THdfsScanRange* scan_range = nullptr; bool enable_split_tasks = false; @@ -317,6 +365,13 @@ struct HdfsScannerContext { void append_or_update_partition_column_to_chunk(ChunkPtr* chunk, size_t row_count); void append_or_update_count_column_to_chunk(ChunkPtr* chunk, size_t row_count); +<<<<<<< HEAD +======= + void append_or_update_extended_column_to_chunk(ChunkPtr* chunk, size_t row_count); + void append_or_update_column_to_chunk(ChunkPtr* chunk, size_t row_count, const std::vector& columns, + const std::vector& values); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // if we can skip this file by evaluating conjuncts of non-existed columns with default value. StatusOr should_skip_by_evaluating_not_existed_slots(); std::vector not_existed_slots; @@ -327,6 +382,14 @@ struct HdfsScannerContext { Status evaluate_on_conjunct_ctxs_by_slot(ChunkPtr* chunk, Filter* filter); void merge_split_tasks(); +<<<<<<< HEAD +======= + + // used for parquet zone map filter only + std::unique_ptr conjuncts_manager = nullptr; + std::vector> predicate_free_pool; + PredicateTree predicate_tree; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; struct OpenFileOptions { @@ -372,10 +435,18 @@ class HdfsScanner { void move_split_tasks(std::vector* split_tasks); bool has_split_tasks() const { return _scanner_ctx.has_split_tasks; } +<<<<<<< HEAD protected: static StatusOr> create_random_access_file( std::shared_ptr& shared_buffered_input_stream, std::shared_ptr& cache_input_stream, const OpenFileOptions& options); +======= + static StatusOr> create_random_access_file( + std::shared_ptr& shared_buffered_input_stream, + std::shared_ptr& cache_input_stream, const OpenFileOptions& options); + +protected: +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status open_random_access_file(); static CompressionTypePB get_compression_type_from_path(const std::string& filename); @@ -386,7 +457,10 @@ class HdfsScanner { std::atomic _closed = false; Status _build_scanner_context(); void update_hdfs_counter(HdfsScanProfile* profile); +<<<<<<< HEAD Status _init_mor_processor(RuntimeState* runtime_state, const MORParams& params); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: HdfsScannerContext _scanner_ctx; @@ -400,8 +474,11 @@ class HdfsScanner { std::shared_ptr _cache_input_stream = nullptr; std::shared_ptr _shared_buffered_input_stream = nullptr; int64_t _total_running_time = 0; +<<<<<<< HEAD std::shared_ptr _mor_processor; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exec/hdfs_scanner_orc.cpp b/be/src/exec/hdfs_scanner_orc.cpp index c52a1031cee56..24697b39d8b66 100644 --- a/be/src/exec/hdfs_scanner_orc.cpp +++ b/be/src/exec/hdfs_scanner_orc.cpp @@ -322,6 +322,7 @@ bool OrcRowReaderFilter::filterOnPickStringDictionary( Status HdfsOrcScanner::build_iceberg_delete_builder() { if (_scanner_params.deletes.empty()) return Status::OK(); SCOPED_RAW_TIMER(&_app_stats.iceberg_delete_file_build_ns); +<<<<<<< HEAD const IcebergDeleteBuilder iceberg_delete_builder(_scanner_params.fs, _scanner_params.path, &_need_skip_rowids, _scanner_params.datacache_options); @@ -330,6 +331,22 @@ Status HdfsOrcScanner::build_iceberg_delete_builder() { _scanner_params.mor_params.equality_slots, _runtime_state, _mor_processor)); } +======= + const auto iceberg_delete_builder = + std::make_unique(&_need_skip_rowids, _runtime_state, _scanner_params); + + for (const auto& delete_file : _scanner_params.deletes) { + if (delete_file->file_content == TIcebergFileContent::POSITION_DELETES) { + RETURN_IF_ERROR(iceberg_delete_builder->build_orc(*delete_file)); + } else { + const auto s = strings::Substitute("Unsupported iceberg file content: $0 in the scanner thread", + delete_file->file_content); + LOG(WARNING) << s; + return Status::InternalError(s); + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _app_stats.iceberg_delete_files_per_scan += _scanner_params.deletes.size(); return Status::OK(); } @@ -568,6 +585,10 @@ Status HdfsOrcScanner::do_get_next(RuntimeState* runtime_state, ChunkPtr* chunk) } _scanner_ctx.append_or_update_partition_column_to_chunk(chunk, rows_read); +<<<<<<< HEAD +======= + _scanner_ctx.append_or_update_extended_column_to_chunk(chunk, rows_read); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // check after partition/extended column added DCHECK_EQ(rows_read, chunk->get()->num_rows()); diff --git a/be/src/exec/hdfs_scanner_parquet.cpp b/be/src/exec/hdfs_scanner_parquet.cpp index f937f79ceb39e..53fcbe71a17b5 100644 --- a/be/src/exec/hdfs_scanner_parquet.cpp +++ b/be/src/exec/hdfs_scanner_parquet.cpp @@ -14,10 +14,18 @@ #include "exec/hdfs_scanner_parquet.h" +<<<<<<< HEAD +======= +#include "connector/deletion_vector/deletion_vector.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/hdfs_scanner.h" #include "exec/iceberg/iceberg_delete_builder.h" #include "exec/paimon/paimon_delete_file_builder.h" #include "formats/parquet/file_reader.h" +<<<<<<< HEAD +======= +#include "pipeline/fragment_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/runtime_profile.h" namespace starrocks { @@ -27,6 +35,7 @@ static const std::string kParquetProfileSectionPrefix = "Parquet"; Status HdfsParquetScanner::do_init(RuntimeState* runtime_state, const HdfsScannerParams& scanner_params) { if (!scanner_params.deletes.empty()) { SCOPED_RAW_TIMER(&_app_stats.iceberg_delete_file_build_ns); +<<<<<<< HEAD std::unique_ptr iceberg_delete_builder(new IcebergDeleteBuilder( scanner_params.fs, scanner_params.path, &_need_skip_rowids, scanner_params.datacache_options)); for (const auto& tdelete_file : scanner_params.deletes) { @@ -34,12 +43,31 @@ Status HdfsParquetScanner::do_init(RuntimeState* runtime_state, const HdfsScanne runtime_state->timezone(), *tdelete_file, scanner_params.mor_params.equality_slots, scanner_params.mor_params.delete_column_tuple_desc, scanner_params.iceberg_equal_delete_schema, runtime_state, _mor_processor)); +======= + auto iceberg_delete_builder = + std::make_unique(&_need_skip_rowids, runtime_state, scanner_params); + for (const auto& delete_file : scanner_params.deletes) { + if (delete_file->file_content == TIcebergFileContent::POSITION_DELETES) { + RETURN_IF_ERROR(iceberg_delete_builder->build_parquet(*delete_file)); + } else { + const auto s = strings::Substitute("Unsupported iceberg file content: $0 in the scanner thread", + delete_file->file_content); + LOG(WARNING) << s; + return Status::InternalError(s); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _app_stats.iceberg_delete_files_per_scan += scanner_params.deletes.size(); } else if (scanner_params.paimon_deletion_file != nullptr) { std::unique_ptr paimon_delete_file_builder( new PaimonDeleteFileBuilder(scanner_params.fs, &_need_skip_rowids)); RETURN_IF_ERROR(paimon_delete_file_builder->build(scanner_params.paimon_deletion_file.get())); +<<<<<<< HEAD +======= + } else if (scanner_params.deletion_vector_descriptor != nullptr) { + std::unique_ptr dv = std::make_unique(scanner_params); + RETURN_IF_ERROR(dv->fill_row_indexes(&_need_skip_rowids)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } @@ -84,6 +112,12 @@ void HdfsParquetScanner::do_update_counter(HdfsScanProfile* profile) { // page index RuntimeProfile::Counter* rows_before_page_index = nullptr; RuntimeProfile::Counter* page_index_timer = nullptr; +<<<<<<< HEAD +======= + // filter stats + RuntimeProfile::Counter* total_row_groups = nullptr; + RuntimeProfile::Counter* filtered_row_groups = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile* root = profile->runtime_profile; ADD_COUNTER(root, kParquetProfileSectionPrefix, TUnit::NONE); @@ -124,6 +158,11 @@ void HdfsParquetScanner::do_update_counter(HdfsScanProfile* profile) { kParquetProfileSectionPrefix); rows_before_page_index = ADD_CHILD_COUNTER(root, "RowsBeforePageIndex", TUnit::UNIT, kParquetProfileSectionPrefix); page_index_timer = ADD_CHILD_TIMER(root, "PageIndexTime", kParquetProfileSectionPrefix); +<<<<<<< HEAD +======= + total_row_groups = ADD_CHILD_COUNTER(root, "TotalRowGroups", TUnit::UNIT, kParquetProfileSectionPrefix); + filtered_row_groups = ADD_CHILD_COUNTER(root, "FilteredRowGroups", TUnit::UNIT, kParquetProfileSectionPrefix); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) COUNTER_UPDATE(request_bytes_read, _app_stats.request_bytes_read); COUNTER_UPDATE(request_bytes_read_uncompressed, _app_stats.request_bytes_read_uncompressed); @@ -149,6 +188,15 @@ void HdfsParquetScanner::do_update_counter(HdfsScanProfile* profile) { do_update_iceberg_v2_counter(root, kParquetProfileSectionPrefix); COUNTER_UPDATE(rows_before_page_index, _app_stats.rows_before_page_index); COUNTER_UPDATE(page_index_timer, _app_stats.page_index_ns); +<<<<<<< HEAD +======= + COUNTER_UPDATE(total_row_groups, _app_stats.parquet_total_row_groups); + COUNTER_UPDATE(filtered_row_groups, _app_stats.parquet_filtered_row_groups); + if (_scanner_ctx.conjuncts_manager != nullptr && + _runtime_state->fragment_ctx()->pred_tree_params().enable_show_in_profile) { + root->add_info_string("ParquetPredicateTreeFilter", _scanner_ctx.predicate_tree.root().debug_string()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status HdfsParquetScanner::do_open(RuntimeState* runtime_state) { diff --git a/be/src/exec/hdfs_scanner_text.cpp b/be/src/exec/hdfs_scanner_text.cpp index 989daff172ede..edb0f5124dc75 100644 --- a/be/src/exec/hdfs_scanner_text.cpp +++ b/be/src/exec/hdfs_scanner_text.cpp @@ -330,6 +330,10 @@ Status HdfsTextScanner::_parse_csv(int chunk_size, ChunkPtr* chunk) { _column_raw_ptrs.resize(num_columns); for (int i = 0; i < num_columns; i++) { _column_raw_ptrs[i] = chunk->get()->get_column_by_index(i).get(); +<<<<<<< HEAD +======= + _column_raw_ptrs[i]->reserve(chunk_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } csv::Converter::Options options; diff --git a/be/src/exec/iceberg/iceberg_delete_builder.cpp b/be/src/exec/iceberg/iceberg_delete_builder.cpp index 4c3e4c2569570..749c31a1e4cec 100644 --- a/be/src/exec/iceberg/iceberg_delete_builder.cpp +++ b/be/src/exec/iceberg/iceberg_delete_builder.cpp @@ -14,15 +14,24 @@ #include "exec/iceberg/iceberg_delete_builder.h" +<<<<<<< HEAD #include "column/vectorized_fwd.h" #include "exec/hdfs_scanner.h" +======= +#include + +#include "column/vectorized_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/iceberg/iceberg_delete_file_iterator.h" #include "formats/orc/orc_chunk_reader.h" #include "formats/orc/orc_input_stream.h" #include "formats/parquet/file_reader.h" #include "gen_cpp/Types_types.h" #include "runtime/descriptors.h" +<<<<<<< HEAD #include "storage/chunk_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -38,6 +47,7 @@ static const IcebergColumnMeta k_delete_file_path{ static const IcebergColumnMeta k_delete_file_pos{ .id = INT32_MAX - 102, .col_name = "pos", .type = TPrimitiveType::BIGINT}; +<<<<<<< HEAD Status ParquetPositionDeleteBuilder::build(const std::string& timezone, const std::string& delete_file_path, int64_t file_length, std::set* need_skip_rowids) { std::vector slot_descriptors{&(IcebergDeleteFileMeta::get_delete_file_path_slot()), @@ -67,10 +77,45 @@ Status ParquetPositionDeleteBuilder::build(const std::string& timezone, const st if (!status.is_end_of_file()) { LOG(WARNING) << status; return status; +======= +StatusOr> IcebergDeleteBuilder::open_random_access_file( + const TIcebergDeleteFile& delete_file, HdfsScanStats& fs_scan_stats, HdfsScanStats& app_scan_stats, + std::shared_ptr& shared_buffered_input_stream, + std::shared_ptr& cache_input_stream) const { + const OpenFileOptions options{.fs = _params.fs, + .path = delete_file.full_path, + .file_size = delete_file.length, + .fs_stats = &fs_scan_stats, + .app_stats = &app_scan_stats, + .datacache_options = _params.datacache_options}; + ASSIGN_OR_RETURN(auto file, + HdfsScanner::create_random_access_file(shared_buffered_input_stream, cache_input_stream, options)); + std::vector io_ranges{}; + int64_t offset = 0; + while (offset < delete_file.length) { + const int64_t remain_length = + std::min(static_cast(config::io_coalesce_read_max_buffer_size), delete_file.length - offset); + io_ranges.emplace_back(offset, remain_length); + offset += remain_length; + } + + RETURN_IF_ERROR(shared_buffered_input_stream->set_io_ranges(io_ranges)); + return file; +} + +Status IcebergDeleteBuilder::fill_skip_rowids(const ChunkPtr& chunk) const { + const ColumnPtr& file_path = chunk->get_column_by_slot_id(k_delete_file_path.id); + const ColumnPtr& pos = chunk->get_column_by_slot_id(k_delete_file_pos.id); + for (int i = 0; i < chunk->num_rows(); i++) { + if (file_path->get(i).get_slice() == _params.path) { + _need_skip_rowids->emplace(pos->get(i).get_int64()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } +<<<<<<< HEAD Status ORCPositionDeleteBuilder::build(const std::string& timezone, const std::string& delete_file_path, int64_t file_length, std::set* need_skip_rowids) { std::vector slot_descriptors{&(IcebergDeleteFileMeta::get_delete_file_path_slot()), @@ -84,6 +129,103 @@ Status ORCPositionDeleteBuilder::build(const std::string& timezone, const std::s try { orc::ReaderOptions options; reader = orc::createReader(std::move(input_stream), options); +======= +Status IcebergDeleteBuilder::build_parquet(const TIcebergDeleteFile& delete_file) const { + HdfsScanStats app_scan_stats; + HdfsScanStats fs_scan_stats; + std::shared_ptr shared_buffered_input_stream = nullptr; + std::shared_ptr cache_input_stream = nullptr; + + ASSIGN_OR_RETURN(auto file, open_random_access_file(delete_file, fs_scan_stats, app_scan_stats, + shared_buffered_input_stream, cache_input_stream)); + + std::unique_ptr reader; + try { + reader = std::make_unique(_runtime_state->chunk_size(), file.get(), + file->get_size().value()); + } catch (std::exception& e) { + const auto s = strings::Substitute( + "IcebergDeleteBuilder::build_parquet create parquet::FileReader failed. reason = $0", e.what()); + LOG(WARNING) << s; + return Status::InternalError(s); + } + + auto scanner_ctx = std::make_unique(); + std::vector columns; + THdfsScanRange scan_range; + scan_range.offset = 0; + scan_range.length = delete_file.length; + std::vector slot_descriptors{&(IcebergDeleteFileMeta::get_delete_file_path_slot()), + &(IcebergDeleteFileMeta::get_delete_file_pos_slot())}; + for (size_t i = 0; i < slot_descriptors.size(); i++) { + auto* slot = slot_descriptors[i]; + HdfsScannerContext::ColumnInfo column; + column.slot_desc = slot; + column.idx_in_chunk = i; + column.decode_needed = true; + columns.emplace_back(column); + } + + std::vector schema_fields; + + // build file path field + TIcebergSchemaField file_path_field; + file_path_field.__set_field_id(k_delete_file_path.id); + file_path_field.__set_name(k_delete_file_path.col_name); + schema_fields.push_back(file_path_field); + + // build position field + TIcebergSchemaField pos_field; + pos_field.__set_field_id(k_delete_file_pos.id); + pos_field.__set_name(k_delete_file_pos.col_name); + schema_fields.push_back(pos_field); + + TIcebergSchema iceberg_schema = TIcebergSchema(); + iceberg_schema.__set_fields(schema_fields); + + std::atomic lazy_column_coalesce_counter = 0; + scanner_ctx->timezone = timezone; + scanner_ctx->slot_descs = slot_descriptors; + scanner_ctx->iceberg_schema = &iceberg_schema; + scanner_ctx->materialized_columns = std::move(columns); + scanner_ctx->scan_range = &scan_range; + scanner_ctx->lazy_column_coalesce_counter = &lazy_column_coalesce_counter; + scanner_ctx->stats = &app_scan_stats; + RETURN_IF_ERROR(reader->init(scanner_ctx.get())); + + while (true) { + ChunkPtr chunk = ChunkHelper::new_chunk(slot_descriptors, _runtime_state->chunk_size()); + Status status = reader->get_next(&chunk); + if (status.is_end_of_file()) { + break; + } + + RETURN_IF_ERROR(status); + RETURN_IF_ERROR(fill_skip_rowids(chunk)); + } + update_delete_file_io_counter(_params.profile->runtime_profile, app_scan_stats, fs_scan_stats, cache_input_stream, + shared_buffered_input_stream); + return Status::OK(); +} + +Status IcebergDeleteBuilder::build_orc(const TIcebergDeleteFile& delete_file) const { + std::vector slot_descriptors{&(IcebergDeleteFileMeta::get_delete_file_path_slot()), + &(IcebergDeleteFileMeta::get_delete_file_pos_slot())}; + + HdfsScanStats app_scan_stats; + HdfsScanStats fs_scan_stats; + std::shared_ptr shared_buffered_input_stream; + std::shared_ptr cache_input_stream; + + ASSIGN_OR_RETURN(auto file, open_random_access_file(delete_file, fs_scan_stats, app_scan_stats, + shared_buffered_input_stream, cache_input_stream)); + + auto input_stream = std::make_unique(file.get(), delete_file.length, nullptr); + std::unique_ptr reader; + try { + orc::ReaderOptions options; + reader = createReader(std::move(input_stream), options); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } catch (std::exception& e) { auto s = strings::Substitute("ORCPositionDeleteBuilder::build create orc::Reader failed. reason = $0", e.what()); @@ -91,10 +233,17 @@ Status ORCPositionDeleteBuilder::build(const std::string& timezone, const std::s return Status::InternalError(s); } +<<<<<<< HEAD auto orc_reader = std::make_unique(4096, slot_descriptors); orc_reader->disable_broker_load_mode(); orc_reader->set_current_file_name(delete_file_path); RETURN_IF_ERROR(orc_reader->set_timezone(timezone)); +======= + auto orc_reader = std::make_unique(_runtime_state->chunk_size(), slot_descriptors); + orc_reader->disable_broker_load_mode(); + orc_reader->set_current_file_name(delete_file.full_path); + RETURN_IF_ERROR(orc_reader->set_timezone(_runtime_state->timezone())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(orc_reader->init(std::move(reader))); orc::RowReader::ReadPosition position; @@ -103,7 +252,11 @@ Status ORCPositionDeleteBuilder::build(const std::string& timezone, const std::s while (true) { s = orc_reader->read_next(&position); if (s.is_end_of_file()) { +<<<<<<< HEAD return Status::OK(); +======= + break; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } RETURN_IF_ERROR(s); @@ -112,6 +265,7 @@ Status ORCPositionDeleteBuilder::build(const std::string& timezone, const std::s if (!ret.ok()) { return ret.status(); } +<<<<<<< HEAD ChunkPtr chunk = ret.value(); size_t chunk_size = chunk->num_rows(); @@ -234,6 +388,12 @@ Status ParquetEqualityDeleteBuilder::build(const std::string& timezone, const st ChunkPtr& result = chunk; RETURN_IF_ERROR(mor_processor->append_chunk_to_hashtable(result)); } +======= + RETURN_IF_ERROR(fill_skip_rowids(ret.value())); + } + update_delete_file_io_counter(_params.profile->runtime_profile, app_scan_stats, fs_scan_stats, cache_input_stream, + shared_buffered_input_stream); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -257,14 +417,130 @@ SlotDescriptor IcebergDeleteFileMeta::gen_slot_helper(const IcebergColumnMeta& m return {desc}; } +<<<<<<< HEAD SlotDescriptor& IcebergDeleteFileMeta::get_delete_file_path_slot() { static SlotDescriptor k_delete_file_path_slot = IcebergDeleteFileMeta::gen_slot_helper(k_delete_file_path); +======= +void IcebergDeleteBuilder::update_delete_file_io_counter( + RuntimeProfile* parent_profile, const HdfsScanStats& app_stats, const HdfsScanStats& fs_stats, + const std::shared_ptr& cache_input_stream, + const std::shared_ptr& shared_buffered_input_stream) { + const std::string ICEBERG_TIMER = "ICEBERG_V2_MOR"; + ADD_COUNTER(parent_profile, ICEBERG_TIMER, TUnit::NONE); + { + static const char* prefix = "MOR_InputStream"; + ADD_CHILD_COUNTER(parent_profile, prefix, TUnit::NONE, ICEBERG_TIMER); + + RuntimeProfile::Counter* app_io_bytes_read_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_AppIOBytesRead", TUnit::BYTES, prefix); + RuntimeProfile::Counter* app_io_timer = ADD_CHILD_TIMER(parent_profile, "MOR_AppIOTime", prefix); + RuntimeProfile::Counter* app_io_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_AppIOCounter", TUnit::UNIT, prefix); + + RuntimeProfile::Counter* fs_bytes_read_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_FSIOBytesRead", TUnit::BYTES, prefix); + RuntimeProfile::Counter* fs_io_timer = ADD_CHILD_TIMER(parent_profile, "MOR_FSIOTime", prefix); + RuntimeProfile::Counter* fs_io_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_FSIOCounter", TUnit::UNIT, prefix); + + COUNTER_UPDATE(app_io_timer, app_stats.io_ns); + COUNTER_UPDATE(app_io_counter, app_stats.io_count); + COUNTER_UPDATE(app_io_bytes_read_counter, app_stats.bytes_read); + COUNTER_UPDATE(fs_bytes_read_counter, fs_stats.bytes_read); + COUNTER_UPDATE(fs_io_timer, fs_stats.io_ns); + COUNTER_UPDATE(fs_io_counter, fs_stats.io_count); + } + + { + static const char* prefix = "MOR_SharedBuffered"; + ADD_CHILD_COUNTER(parent_profile, prefix, TUnit::NONE, ICEBERG_TIMER); + RuntimeProfile::Counter* shared_buffered_shared_io_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_SharedIOBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* shared_buffered_shared_align_io_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_SharedAlignIOBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* shared_buffered_shared_io_count = + ADD_CHILD_COUNTER(parent_profile, "MOR_SharedIOCount", TUnit::UNIT, prefix); + RuntimeProfile::Counter* shared_buffered_shared_io_timer = + ADD_CHILD_TIMER(parent_profile, "SharedIOTime", prefix); + RuntimeProfile::Counter* shared_buffered_direct_io_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DirectIOBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* shared_buffered_direct_io_count = + ADD_CHILD_COUNTER(parent_profile, "MOR_DirectIOCount", TUnit::UNIT, prefix); + RuntimeProfile::Counter* shared_buffered_direct_io_timer = + ADD_CHILD_TIMER(parent_profile, "MOR_DirectIOTime", prefix); + + COUNTER_UPDATE(shared_buffered_shared_io_count, shared_buffered_input_stream->shared_io_count()); + COUNTER_UPDATE(shared_buffered_shared_io_bytes, shared_buffered_input_stream->shared_io_bytes()); + COUNTER_UPDATE(shared_buffered_shared_align_io_bytes, shared_buffered_input_stream->shared_align_io_bytes()); + COUNTER_UPDATE(shared_buffered_shared_io_timer, shared_buffered_input_stream->shared_io_timer()); + COUNTER_UPDATE(shared_buffered_direct_io_count, shared_buffered_input_stream->direct_io_count()); + COUNTER_UPDATE(shared_buffered_direct_io_bytes, shared_buffered_input_stream->direct_io_bytes()); + COUNTER_UPDATE(shared_buffered_direct_io_timer, shared_buffered_input_stream->direct_io_timer()); + } + + if (cache_input_stream) { + static const char* prefix = "MOR_DataCache"; + ADD_CHILD_COUNTER(parent_profile, prefix, TUnit::NONE, ICEBERG_TIMER); + RuntimeProfile::Counter* datacache_read_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheReadCounter", TUnit::UNIT, prefix); + RuntimeProfile::Counter* datacache_read_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheReadBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* datacache_read_mem_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheReadMemBytes", TUnit::BYTES, "MOR_DataCacheReadBytes"); + RuntimeProfile::Counter* datacache_read_disk_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheReadDiskBytes", TUnit::BYTES, "MOR_DataCacheReadBytes"); + RuntimeProfile::Counter* datacache_skip_read_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheSkipReadCounter", TUnit::UNIT, prefix); + RuntimeProfile::Counter* datacache_skip_read_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheSkipReadBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* datacache_read_timer = + ADD_CHILD_TIMER(parent_profile, "MOR_DataCacheReadTimer", prefix); + RuntimeProfile::Counter* datacache_write_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheWriteCounter", TUnit::UNIT, prefix); + RuntimeProfile::Counter* datacache_write_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheWriteBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* datacache_write_timer = + ADD_CHILD_TIMER(parent_profile, "MOR_DataCacheWriteTimer", prefix); + RuntimeProfile::Counter* datacache_write_fail_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheWriteFailCounter", TUnit::UNIT, prefix); + RuntimeProfile::Counter* datacache_write_fail_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheWriteFailBytes", TUnit::BYTES, prefix); + RuntimeProfile::Counter* datacache_read_block_buffer_counter = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheReadBlockBufferCounter", TUnit::UNIT, prefix); + RuntimeProfile::Counter* datacache_read_block_buffer_bytes = + ADD_CHILD_COUNTER(parent_profile, "MOR_DataCacheReadBlockBufferBytes", TUnit::BYTES, prefix); + + const io::CacheInputStream::Stats& stats = cache_input_stream->stats(); + COUNTER_UPDATE(datacache_read_counter, stats.read_cache_count); + COUNTER_UPDATE(datacache_read_bytes, stats.read_cache_bytes); + COUNTER_UPDATE(datacache_read_mem_bytes, stats.read_mem_cache_bytes); + COUNTER_UPDATE(datacache_read_disk_bytes, stats.read_disk_cache_bytes); + COUNTER_UPDATE(datacache_read_timer, stats.read_cache_ns); + COUNTER_UPDATE(datacache_skip_read_counter, stats.skip_read_cache_count); + COUNTER_UPDATE(datacache_skip_read_bytes, stats.skip_read_cache_bytes); + COUNTER_UPDATE(datacache_write_counter, stats.write_cache_count); + COUNTER_UPDATE(datacache_write_bytes, stats.write_cache_bytes); + COUNTER_UPDATE(datacache_write_timer, stats.write_cache_ns); + COUNTER_UPDATE(datacache_write_fail_counter, stats.write_cache_fail_count); + COUNTER_UPDATE(datacache_write_fail_bytes, stats.write_cache_fail_bytes); + COUNTER_UPDATE(datacache_read_block_buffer_counter, stats.read_block_buffer_count); + COUNTER_UPDATE(datacache_read_block_buffer_bytes, stats.read_block_buffer_bytes); + } +} + +SlotDescriptor& IcebergDeleteFileMeta::get_delete_file_path_slot() { + static SlotDescriptor k_delete_file_path_slot = gen_slot_helper(k_delete_file_path); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return k_delete_file_path_slot; } SlotDescriptor& IcebergDeleteFileMeta::get_delete_file_pos_slot() { +<<<<<<< HEAD static SlotDescriptor k_delete_file_pos_slot = IcebergDeleteFileMeta::gen_slot_helper(k_delete_file_pos); +======= + static SlotDescriptor k_delete_file_pos_slot = gen_slot_helper(k_delete_file_pos); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return k_delete_file_pos_slot; } diff --git a/be/src/exec/iceberg/iceberg_delete_builder.h b/be/src/exec/iceberg/iceberg_delete_builder.h index 1f6c5e6e9513f..8f0f3072762fb 100644 --- a/be/src/exec/iceberg/iceberg_delete_builder.h +++ b/be/src/exec/iceberg/iceberg_delete_builder.h @@ -14,6 +14,7 @@ #pragma once +<<<<<<< HEAD #include #include "block_cache/cache_options.h" @@ -22,11 +23,16 @@ #include "exec/parquet_scanner.h" #include "fs/fs.h" #include "gutil/strings/substitute.h" +======= +#include "common/status.h" +#include "exec/hdfs_scanner.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/descriptors.h" namespace starrocks { struct IcebergColumnMeta; +<<<<<<< HEAD class DeleteBuilder { public: DeleteBuilder(FileSystem* fs, const DataCacheOptions& datacache_options) @@ -167,6 +173,35 @@ class IcebergDeleteBuilder { std::string _datafile_path; std::set* _need_skip_rowids; const DataCacheOptions _datacache_options; +======= +class IcebergDeleteBuilder { +public: + IcebergDeleteBuilder(std::set* need_skip_rowids, RuntimeState* state, + const HdfsScannerParams& scanner_params) + : _need_skip_rowids(need_skip_rowids), _params(scanner_params), _runtime_state(state) {} + + ~IcebergDeleteBuilder() = default; + + Status build_orc(const TIcebergDeleteFile& delete_file) const; + + Status build_parquet(const TIcebergDeleteFile& delete_file) const; + +private: + StatusOr> open_random_access_file( + const TIcebergDeleteFile& delete_file, HdfsScanStats& fs_scan_stats, HdfsScanStats& app_scan_stats, + std::shared_ptr& shared_buffered_input_stream, + std::shared_ptr& cache_input_stream) const; + + static void update_delete_file_io_counter( + RuntimeProfile* parent_profile, const HdfsScanStats& app_stats, const HdfsScanStats& fs_stats, + const std::shared_ptr& cache_input_stream, + const std::shared_ptr& shared_buffered_input_stream); + Status fill_skip_rowids(const ChunkPtr& chunk) const; + + std::set* _need_skip_rowids; + const HdfsScannerParams& _params; + RuntimeState* _runtime_state; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class IcebergDeleteFileMeta { diff --git a/be/src/exec/intersect_hash_set.cpp b/be/src/exec/intersect_hash_set.cpp index e1e3136667124..2e5a984cc8e06 100644 --- a/be/src/exec/intersect_hash_set.cpp +++ b/be/src/exec/intersect_hash_set.cpp @@ -23,7 +23,11 @@ template Status IntersectHashSet::init(RuntimeState* state) { _hash_set = std::make_unique(); _mem_pool = std::make_unique(); +<<<<<<< HEAD _buffer = _mem_pool->allocate(_max_one_row_size * state->chunk_size()); +======= + _buffer = _mem_pool->allocate(_max_one_row_size * state->chunk_size() + SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_UNLIKELY_NULL(_buffer, Status::MemoryAllocFailed("alloc mem for intersect hash set failed")); return Status::OK(); } @@ -38,7 +42,11 @@ void IntersectHashSet::build_set(RuntimeState* state, const ChunkPtr& c if (UNLIKELY(cur_max_one_row_size > _max_one_row_size)) { _max_one_row_size = cur_max_one_row_size; _mem_pool->clear(); +<<<<<<< HEAD _buffer = _mem_pool->allocate(_max_one_row_size * state->chunk_size()); +======= + _buffer = _mem_pool->allocate(_max_one_row_size * state->chunk_size() + SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _serialize_columns(chunkPtr, exprs, chunk_size); @@ -47,7 +55,11 @@ void IntersectHashSet::build_set(RuntimeState* state, const ChunkPtr& c IntersectSliceFlag key(_buffer + i * _max_one_row_size, _slice_sizes[i]); _hash_set->lazy_emplace(key, [&](const auto& ctor) { // we must persist the slice before insert +<<<<<<< HEAD uint8_t* pos = pool->allocate(key.slice.size); +======= + uint8_t* pos = pool->allocate_with_reserve(key.slice.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) memcpy(pos, key.slice.data, key.slice.size); ctor(pos, key.slice.size); }); @@ -63,7 +75,11 @@ Status IntersectHashSet::refine_intersect_row(RuntimeState* state, cons if (UNLIKELY(cur_max_one_row_size > _max_one_row_size)) { _max_one_row_size = cur_max_one_row_size; _mem_pool->clear(); +<<<<<<< HEAD _buffer = _mem_pool->allocate(_max_one_row_size * state->chunk_size()); +======= + _buffer = _mem_pool->allocate(_max_one_row_size * state->chunk_size() + SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (UNLIKELY(_buffer == nullptr)) { return Status::InternalError("Mem usage has exceed the limit of BE"); } diff --git a/be/src/exec/intersect_hash_set.h b/be/src/exec/intersect_hash_set.h index 76ae84d54f185..2abd689927776 100644 --- a/be/src/exec/intersect_hash_set.h +++ b/be/src/exec/intersect_hash_set.h @@ -52,7 +52,11 @@ template class IntersectHashSet { public: using Iterator = typename HashSet::iterator; +<<<<<<< HEAD using KeyVector = typename std::vector; +======= + using KeyVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) IntersectHashSet() = default; diff --git a/be/src/exec/jdbc_scanner.cpp b/be/src/exec/jdbc_scanner.cpp index 7c03023773fc4..248e59aaf604b 100644 --- a/be/src/exec/jdbc_scanner.cpp +++ b/be/src/exec/jdbc_scanner.cpp @@ -27,6 +27,10 @@ #include "exprs/expr_context.h" #include "runtime/types.h" #include "types/logical_type.h" +<<<<<<< HEAD +======= +#include "types/type_checker_manager.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "udf/java/java_udf.h" #include "util/defer_op.h" @@ -139,7 +143,10 @@ Status JDBCScanner::_init_jdbc_scan_context(RuntimeState* state) { // use query timeout or default value of HikariConfig int connection_timeout_ms = state->query_options().__isset.query_timeout ? state->query_options().query_timeout * 1000 : 30 * 1000; +<<<<<<< HEAD +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto scan_ctx = env->NewObject(scan_context_cls, constructor, driver_class_name, jdbc_url, user, passwd, sql, statement_fetch_size, connection_pool_size, minimum_idle_connections, idle_timeout_ms, connection_timeout_ms); @@ -199,6 +206,7 @@ void JDBCScanner::_init_profile() { } StatusOr JDBCScanner::_precheck_data_type(const std::string& java_class, SlotDescriptor* slot_desc) { +<<<<<<< HEAD auto type = slot_desc->type().type; if (java_class == "java.lang.Byte") { if (type != TYPE_BOOLEAN && type != TYPE_TINYINT && type != TYPE_SMALLINT && type != TYPE_INT && @@ -380,6 +388,9 @@ StatusOr JDBCScanner::_precheck_data_type(const std::string& java_c return TYPE_VARCHAR; } __builtin_unreachable(); +======= + return TypeCheckerManager::getInstance().checkType(java_class, slot_desc); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status JDBCScanner::_init_column_class_name(RuntimeState* state) { diff --git a/be/src/exec/jdbc_scanner.h b/be/src/exec/jdbc_scanner.h index cc6693d69b9c0..a5b02bdceb2d3 100644 --- a/be/src/exec/jdbc_scanner.h +++ b/be/src/exec/jdbc_scanner.h @@ -56,17 +56,26 @@ class JDBCScanner { ~JDBCScanner() = default; +<<<<<<< HEAD [[nodiscard]] Status open(RuntimeState* state); [[nodiscard]] Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos); [[nodiscard]] Status close(RuntimeState* state); +======= + Status open(RuntimeState* state); + + Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos); + + Status close(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: void _init_profile(); StatusOr _precheck_data_type(const std::string& java_class, SlotDescriptor* slot_desc); +<<<<<<< HEAD [[nodiscard]] Status _init_jdbc_bridge(); [[nodiscard]] Status _init_jdbc_scan_context(RuntimeState* state); @@ -84,6 +93,25 @@ class JDBCScanner { [[nodiscard]] Status _fill_chunk(jobject jchunk, size_t num_rows, ChunkPtr* chunk); [[nodiscard]] Status _close_jdbc_scanner(); +======= + Status _init_jdbc_bridge(); + + Status _init_jdbc_scan_context(RuntimeState* state); + + Status _init_jdbc_scanner(); + + Status _init_column_class_name(RuntimeState* state); + + Status _init_jdbc_util(); + + Status _has_next(bool* result); + + Status _get_next_chunk(jobject* chunk, size_t* num_rows); + + Status _fill_chunk(jobject jchunk, size_t num_rows, ChunkPtr* chunk); + + Status _close_jdbc_scanner(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) JDBCScanContext _scan_ctx; // result column slot desc diff --git a/be/src/exec/jni_scanner.cpp b/be/src/exec/jni_scanner.cpp index ceb5265eccd76..bc068be791539 100644 --- a/be/src/exec/jni_scanner.cpp +++ b/be/src/exec/jni_scanner.cpp @@ -94,8 +94,15 @@ Status JniScanner::_init_jni_table_scanner(JNIEnv* env, RuntimeState* runtime_st jclass scanner_factory_class = env->FindClass(_jni_scanner_factory_class.c_str()); jmethodID scanner_factory_constructor = env->GetMethodID(scanner_factory_class, "", "()V"); jobject scanner_factory_obj = env->NewObject(scanner_factory_class, scanner_factory_constructor); +<<<<<<< HEAD jmethodID get_scanner_method = env->GetMethodID(scanner_factory_class, "getScannerClass", "()Ljava/lang/Class;"); _jni_scanner_cls = (jclass)env->CallObjectMethod(scanner_factory_obj, get_scanner_method); +======= + jmethodID get_scanner_method = + env->GetMethodID(scanner_factory_class, "getScannerClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + jstring scanner_type = env->NewStringUTF(_scanner_type().c_str()); + _jni_scanner_cls = (jclass)env->CallObjectMethod(scanner_factory_obj, get_scanner_method, scanner_type); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_check_jni_exception(env, "Failed to init the scanner class.")); env->DeleteLocalRef(scanner_factory_class); env->DeleteLocalRef(scanner_factory_obj); @@ -629,6 +636,7 @@ std::unique_ptr create_odps_jni_scanner(const JniScanner::CreateOpti // ---------------iceberg metadata jni scanner------------------ std::unique_ptr create_iceberg_metadata_jni_scanner(const JniScanner::CreateOptions& options) { const auto& scan_range = *(options.scan_range); +<<<<<<< HEAD const auto* hdfs_table = dynamic_cast(options.hive_table); std::map jni_scanner_params; @@ -639,6 +647,21 @@ std::unique_ptr create_iceberg_metadata_jni_scanner(const JniScanner jni_scanner_params["serialized_table"] = options.scan_node->serialized_table; jni_scanner_params["split_info"] = scan_range.serialized_split; jni_scanner_params["load_column_stats"] = options.scan_node->load_column_stats ? "true" : "false"; +======= + + const auto* hdfs_table = dynamic_cast(options.hive_table); + std::map jni_scanner_params; + + jni_scanner_params["metadata_column_names"] = hdfs_table->get_hive_column_names(); + jni_scanner_params["metadata_column_types"] = hdfs_table->get_hive_column_types(); + jni_scanner_params["time_zone"] = hdfs_table->get_time_zone(); + + jni_scanner_params["split_info"] = scan_range.serialized_split; + jni_scanner_params["serialized_predicate"] = options.scan_node->serialized_predicate; + jni_scanner_params["serialized_table"] = options.scan_node->serialized_table; + jni_scanner_params["load_column_stats"] = options.scan_node->load_column_stats ? "true" : "false"; + jni_scanner_params["scanner_type"] = options.scan_node->metadata_table_type; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::string scanner_factory_class = "com/starrocks/connector/iceberg/IcebergMetadataScannerFactory"; return std::make_unique(scanner_factory_class, jni_scanner_params); diff --git a/be/src/exec/jni_scanner.h b/be/src/exec/jni_scanner.h index 5c25b2fbea938..1958e273b1cf0 100644 --- a/be/src/exec/jni_scanner.h +++ b/be/src/exec/jni_scanner.h @@ -86,6 +86,13 @@ class JniScanner : public HdfsScanner { Status _release_off_heap_table(JNIEnv* env); +<<<<<<< HEAD +======= + std::string _scanner_type() { + return _jni_scanner_params.contains("scanner_type") ? _jni_scanner_params["scanner_type"] : "default"; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) jclass _jni_scanner_cls = nullptr; jobject _jni_scanner_obj = nullptr; jmethodID _jni_scanner_open = nullptr; diff --git a/be/src/exec/join_hash_map.cpp b/be/src/exec/join_hash_map.cpp index 5643fea99fd08..bca39be44ad50 100644 --- a/be/src/exec/join_hash_map.cpp +++ b/be/src/exec/join_hash_map.cpp @@ -24,6 +24,10 @@ #include "exec/hash_join_node.h" #include "serde/column_array_serde.h" #include "simd/simd.h" +<<<<<<< HEAD +======= +#include "util/runtime_profile.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -305,11 +309,20 @@ JoinHashTable JoinHashTable::clone_readable_table() { void JoinHashTable::set_probe_profile(RuntimeProfile::Counter* search_ht_timer, RuntimeProfile::Counter* output_probe_column_timer, +<<<<<<< HEAD RuntimeProfile::Counter* output_build_column_timer) { +======= + RuntimeProfile::Counter* output_build_column_timer, + RuntimeProfile::Counter* probe_count) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_probe_state == nullptr) return; _probe_state->search_ht_timer = search_ht_timer; _probe_state->output_probe_column_timer = output_probe_column_timer; _probe_state->output_build_column_timer = output_build_column_timer; +<<<<<<< HEAD +======= + _probe_state->probe_counter = probe_count; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } float JoinHashTable::get_keys_per_bucket() const { @@ -331,6 +344,10 @@ void JoinHashTable::create(const HashTableParam& param) { _probe_state->search_ht_timer = param.search_ht_timer; _probe_state->output_probe_column_timer = param.output_probe_column_timer; _probe_state->output_build_column_timer = param.output_build_column_timer; +<<<<<<< HEAD +======= + _probe_state->probe_counter = param.probe_counter; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _table_items->build_chunk = std::make_shared(); @@ -654,7 +671,27 @@ void JoinHashTable::append_chunk(const ChunkPtr& chunk, const Columns& key_colum _table_items->row_count += chunk->num_rows(); } +<<<<<<< HEAD StatusOr JoinHashTable::convert_to_spill_schema(const ChunkPtr& chunk) const { +======= +void JoinHashTable::merge_ht(const JoinHashTable& ht) { + _table_items->row_count += ht._table_items->row_count; + + Columns& columns = _table_items->build_chunk->columns(); + Columns& other_columns = ht._table_items->build_chunk->columns(); + + for (size_t i = 0; i < _table_items->build_column_count; i++) { + if (!columns[i]->is_nullable() && other_columns[i]->is_nullable()) { + // upgrade to nullable column + columns[i] = NullableColumn::create(columns[i], NullColumn::create(columns[i]->size(), 0)); + } + columns[i]->append(*other_columns[i], 1, other_columns[i]->size() - 1); + } +} + +ChunkPtr JoinHashTable::convert_to_spill_schema(const ChunkPtr& chunk) const { + DCHECK(chunk != nullptr && chunk->num_rows() > 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkPtr output = std::make_shared(); // for (size_t i = 0; i < _table_items->build_column_count; i++) { diff --git a/be/src/exec/join_hash_map.h b/be/src/exec/join_hash_map.h index 3efb212174450..c8f3efff00e95 100644 --- a/be/src/exec/join_hash_map.h +++ b/be/src/exec/join_hash_map.h @@ -14,6 +14,10 @@ #pragma once +<<<<<<< HEAD +======= +#include "util/runtime_profile.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #define JOIN_HASH_MAP_H #include @@ -101,8 +105,13 @@ struct JoinHashTableItems { //TODO: memory continues problem? ChunkPtr build_chunk = nullptr; Columns key_columns; +<<<<<<< HEAD Buffer build_slots; Buffer probe_slots; +======= + std::vector build_slots; + std::vector probe_slots; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // A hash value is the bucket index of the hash map. "JoinHashTableItems.first" is the // buckets of the hash map, and it holds the index of the first key value saved in each bucket, // while other keys can be found by following the indices saved in @@ -197,6 +206,10 @@ struct HashTableProbeState { RuntimeProfile::Counter* search_ht_timer = nullptr; RuntimeProfile::Counter* output_probe_column_timer = nullptr; RuntimeProfile::Counter* output_build_column_timer = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* probe_counter = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) HashTableProbeState() : build_index_column(UInt32Column::create()), @@ -256,7 +269,12 @@ struct HashTableProbeState { cur_row_match_count(rhs.cur_row_match_count), probe_pool(rhs.probe_pool == nullptr ? nullptr : std::make_unique()), search_ht_timer(rhs.search_ht_timer), +<<<<<<< HEAD output_probe_column_timer(rhs.output_probe_column_timer) {} +======= + output_probe_column_timer(rhs.output_probe_column_timer), + probe_counter(rhs.probe_counter) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Disable copy assignment. HashTableProbeState& operator=(const HashTableProbeState& rhs) = delete; @@ -277,6 +295,10 @@ struct HashTableProbeState { struct HashTableParam { bool with_other_conjunct = false; bool enable_late_materialization = false; +<<<<<<< HEAD +======= + bool enable_partition_hash_join = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TJoinOp::type join_type = TJoinOp::INNER_JOIN; const RowDescriptor* build_row_desc = nullptr; const RowDescriptor* probe_row_desc = nullptr; @@ -288,6 +310,10 @@ struct HashTableParam { RuntimeProfile::Counter* search_ht_timer = nullptr; RuntimeProfile::Counter* output_build_column_timer = nullptr; RuntimeProfile::Counter* output_probe_column_timer = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* probe_counter = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool mor_reader_mode = false; }; @@ -331,7 +357,11 @@ class JoinHashMapHelper { const static uint32_t MAX_BUCKET_SIZE = 1 << 31; static uint32_t calc_bucket_size(uint32_t size) { +<<<<<<< HEAD size_t expect_bucket_size = static_cast(size) + (size - 1) / 7; +======= + size_t expect_bucket_size = static_cast(size) + (size - 1) / 4; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Limit the maximum hash table bucket size. if (expect_bucket_size >= MAX_BUCKET_SIZE) { return MAX_BUCKET_SIZE; @@ -816,7 +846,11 @@ class JoinHashTable { // and the different probe state from this. JoinHashTable clone_readable_table(); void set_probe_profile(RuntimeProfile::Counter* search_ht_timer, RuntimeProfile::Counter* output_probe_column_timer, +<<<<<<< HEAD RuntimeProfile::Counter* output_build_column_timer); +======= + RuntimeProfile::Counter* output_build_column_timer, RuntimeProfile::Counter* probe_counter); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void create(const HashTableParam& param); void close(); @@ -829,11 +863,21 @@ class JoinHashTable { Status lazy_output(RuntimeState* state, ChunkPtr* probe_chunk, ChunkPtr* result_chunk); void append_chunk(const ChunkPtr& chunk, const Columns& key_columns); +<<<<<<< HEAD // convert input column to spill schema order StatusOr convert_to_spill_schema(const ChunkPtr& chunk) const; const ChunkPtr& get_build_chunk() const { return _table_items->build_chunk; } Columns& get_key_columns() { return _table_items->key_columns; } +======= + void merge_ht(const JoinHashTable& ht); + // convert input column to spill schema order + ChunkPtr convert_to_spill_schema(const ChunkPtr& chunk) const; + + const ChunkPtr& get_build_chunk() const { return _table_items->build_chunk; } + Columns& get_key_columns() { return _table_items->key_columns; } + const Columns& get_key_columns() const { return _table_items->key_columns; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) uint32_t get_row_count() const { return _table_items->row_count; } size_t get_probe_column_count() const { return _table_items->probe_column_count; } size_t get_output_probe_column_count() const { return _table_items->output_probe_column_count; } @@ -855,7 +899,11 @@ class JoinHashTable { JoinHashMapType _choose_join_hash_map(); static size_t _get_size_of_fixed_and_contiguous_type(LogicalType data_type); +<<<<<<< HEAD [[nodiscard]] Status _upgrade_key_columns_if_overflow(); +======= + Status _upgrade_key_columns_if_overflow(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _remove_duplicate_index_for_left_outer_join(Filter* filter); void _remove_duplicate_index_for_left_semi_join(Filter* filter); diff --git a/be/src/exec/join_hash_map.tpp b/be/src/exec/join_hash_map.tpp index 0f1039b3d555e..879075e7c27f5 100644 --- a/be/src/exec/join_hash_map.tpp +++ b/be/src/exec/join_hash_map.tpp @@ -13,6 +13,10 @@ // limitations under the License. #include "simd/simd.h" +<<<<<<< HEAD +======= +#include "util/runtime_profile.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #define JOIN_HASH_MAP_TPP @@ -899,7 +903,11 @@ void JoinHashMap::_search_ht_impl(RuntimeState* state, } #define RETURN_IF_CHUNK_FULL() \ +<<<<<<< HEAD if (match_count > state->chunk_size()) { \ +======= + if (UNLIKELY(match_count > state->chunk_size())) { \ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _probe_state->next[i] = _table_items->next[build_index]; \ _probe_state->cur_probe_index = i; \ _probe_state->cur_build_index = build_index; \ @@ -1028,6 +1036,11 @@ void JoinHashMap::_probe_from_ht(RuntimeState* state, } } +<<<<<<< HEAD +======= + [[maybe_unused]] size_t probe_cont = 0; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t probe_row_count = _probe_state->probe_row_count; for (; i < probe_row_count; i++) { if constexpr (first_probe) { @@ -1035,7 +1048,11 @@ void JoinHashMap::_probe_from_ht(RuntimeState* state, } size_t build_index = _probe_state->next[i]; if (build_index != 0) { +<<<<<<< HEAD do { +======= + if (_table_items->used_buckets == _table_items->row_count) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (ProbeFunc().equal(build_data[build_index], probe_data[i])) { _probe_state->probe_index[match_count] = i; _probe_state->build_index[match_count] = build_index; @@ -1047,8 +1064,30 @@ void JoinHashMap::_probe_from_ht(RuntimeState* state, } RETURN_IF_CHUNK_FULL() } +<<<<<<< HEAD build_index = _table_items->next[build_index]; } while (build_index != 0); +======= + probe_cont++; + } else { + do { + if (ProbeFunc().equal(build_data[build_index], probe_data[i])) { + _probe_state->probe_index[match_count] = i; + _probe_state->build_index[match_count] = build_index; + match_count++; + + if constexpr (first_probe) { + _probe_state->cur_row_match_count++; + _probe_state->probe_match_filter[i] = 1; + } + RETURN_IF_CHUNK_FULL() + } + probe_cont++; + auto next_index = _table_items->next[build_index]; + build_index = next_index; + } while (build_index != 0); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (first_probe) { if (_probe_state->cur_row_match_count > 1) { @@ -1062,6 +1101,11 @@ void JoinHashMap::_probe_from_ht(RuntimeState* state, } } +<<<<<<< HEAD +======= + // COUNTER_UPDATE(_probe_state->probe_counter, probe_cont); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (first_probe) { CHECK_MATCH() } diff --git a/be/src/exec/json_scanner.cpp b/be/src/exec/json_scanner.cpp index a5bf4ee2edcbe..69bf509fcf2b0 100644 --- a/be/src/exec/json_scanner.cpp +++ b/be/src/exec/json_scanner.cpp @@ -25,6 +25,10 @@ #include "column/adaptive_nullable_column.h" #include "column/chunk.h" #include "column/column_helper.h" +<<<<<<< HEAD +======= +#include "column/vectorized_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/json_parser.h" #include "exprs/cast_expr.h" #include "exprs/column_ref.h" @@ -109,6 +113,12 @@ StatusOr JsonScanner::get_next() { // return Status::EndOfFile("EOF of reading json file, nothing read"); return src_chunk; } else if (status.is_time_out()) { +<<<<<<< HEAD +======= + if (src_chunk->is_empty()) { + _reusable_empty_chunk.swap(src_chunk); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // if timeout happens at the beginning of reading src_chunk, we return the error state // else we will _materialize the lines read before timeout and return ok() return status; @@ -240,6 +250,15 @@ Status JsonScanner::parse_json_paths(const std::string& jsonpath, std::vectoris_empty()); + _reusable_empty_chunk.swap(*chunk); + return Status::OK(); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_RAW_TIMER(&_counter->init_chunk_ns); *chunk = std::make_shared(); size_t slot_size = _src_slot_descriptors.size(); @@ -282,7 +301,17 @@ Status JsonScanner::_open_next_reader() { } _cur_file_reader = std::make_unique(_state, _counter, this, file, _strict_mode, _src_slot_descriptors, _json_types, range_desc); +<<<<<<< HEAD RETURN_IF_ERROR(_cur_file_reader->open()); +======= + st = _cur_file_reader->open(); + // Timeout can happen when reading data from a TimeBoundedStreamLoadPipe. + // In this case, open file should be successful, and just need to try to + // read data next time + if (!st.ok() && !st.is_time_out()) { + return st; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _next_range++; return Status::OK(); } @@ -587,7 +616,11 @@ Status JsonReader::_construct_row_without_jsonpath(simdjson::ondemand::object* r if (UNLIKELY(i == _op_col_index)) { // special treatment for __op column, fill default value '0' rather than null if (column->is_binary()) { +<<<<<<< HEAD std::ignore = column->append_strings(std::vector{Slice{"0"}}); +======= + std::ignore = column->append_strings(std::vector{Slice{"0"}}); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { column->append_datum(Datum((uint8_t)0)); } @@ -614,7 +647,12 @@ Status JsonReader::_construct_row_with_jsonpath(simdjson::ondemand::object* row, if (strcmp(column_name, "__op") == 0) { // special treatment for __op column, fill default value '0' rather than null if (column->is_binary()) { +<<<<<<< HEAD column->append_strings(std::vector{Slice{"0"}}); +======= + Slice s{"0"}; + column->append_strings(&s, 1); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { column->append_datum(Datum((uint8_t)0)); } @@ -646,7 +684,12 @@ Status JsonReader::_construct_row_with_jsonpath(simdjson::ondemand::object* row, if (strcmp(column_name, "__op") == 0) { // special treatment for __op column, fill default value '0' rather than null if (column->is_binary()) { +<<<<<<< HEAD column->append_strings(std::vector{Slice{"0"}}); +======= + Slice s{"0"}; + column->append_strings(&s, 1); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { column->append_datum(Datum((uint8_t)0)); } diff --git a/be/src/exec/json_scanner.h b/be/src/exec/json_scanner.h index 04e73ffa83fc0..31018449593ad 100644 --- a/be/src/exec/json_scanner.h +++ b/be/src/exec/json_scanner.h @@ -74,6 +74,14 @@ class JsonScanner : public FileScanner { std::vector> _json_paths; std::vector _root_paths; bool _strip_outer_array = false; +<<<<<<< HEAD +======= + + // An empty chunk that can be reused as the container for the result of get_next(). + // It's mainly for optimizing the performance where get_next() returns Status::Timeout + // frequently by avoiding creating a chunk in each call + ChunkPtr _reusable_empty_chunk = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; // Reader to parse the json. diff --git a/be/src/exec/local_file_writer.cpp b/be/src/exec/local_file_writer.cpp index 196b7687928c6..2f9a1904642cb 100644 --- a/be/src/exec/local_file_writer.cpp +++ b/be/src/exec/local_file_writer.cpp @@ -17,10 +17,16 @@ #include "exec/local_file_writer.h" +<<<<<<< HEAD #include #include "util/error_util.h" +======= +#include +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { LocalFileWriter::LocalFileWriter(std::string path, int64_t start_offset) @@ -34,7 +40,11 @@ Status LocalFileWriter::open() { _fp = fopen(_path.c_str(), "w+"); if (_fp == nullptr) { std::stringstream ss; +<<<<<<< HEAD ss << "Open file failed. path=" << _path << ", errno= " << errno << ", description=" << get_str_err_msg(); +======= + ss << "Open file failed. path=" << _path << ", errno= " << errno << ", description=" << std::strerror(errno); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::InternalError(ss.str()); } @@ -43,7 +53,11 @@ Status LocalFileWriter::open() { if (success != 0) { std::stringstream ss; ss << "Seek to start_offset failed. offset=" << _start_offset << ", errno= " << errno +<<<<<<< HEAD << ", description=" << get_str_err_msg(); +======= + << ", description=" << std::strerror(errno); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::InternalError(ss.str()); } } @@ -57,7 +71,11 @@ Status LocalFileWriter::write(const uint8_t* buf, size_t buf_len, size_t* writte std::stringstream error_msg; error_msg << "fail to write to file. " << " len=" << buf_len << ", path=" << _path << ", failed with errno=" << errno +<<<<<<< HEAD << ", description=" << get_str_err_msg(); +======= + << ", description=" << std::strerror(errno); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::InternalError(error_msg.str()); } diff --git a/be/src/exec/olap_common.cpp b/be/src/exec/olap_common.cpp index 978b5c4af2b8f..5382035388751 100644 --- a/be/src/exec/olap_common.cpp +++ b/be/src/exec/olap_common.cpp @@ -44,8 +44,13 @@ #include "exec/scan_node.h" #include "gutil/stl_util.h" #include "gutil/strings/substitute.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" #include "storage/tuple.h" +======= +#include "storage/tuple.h" +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -193,11 +198,32 @@ Status OlapScanKeys::get_key_range(std::vector>* } template +<<<<<<< HEAD +======= +TCondition ColumnValueRange::to_olap_not_null_filter() const { + TCondition condition; + condition.__set_is_index_filter_only(_is_index_filter_only); + condition.__set_column_name(_column_name); + condition.__set_condition_op("IS"); + condition.condition_values.emplace_back("NOT NULL"); + + return condition; +} + +template +template +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void ColumnValueRange::to_olap_filter(std::vector& filters) { // If we have fixed range value, we generate in/not-in predicates. if (is_fixed_value_range()) { DCHECK(_fixed_op == FILTER_IN || _fixed_op == FILTER_NOT_IN); bool filter_in = (_fixed_op == FILTER_IN) ? true : false; +<<<<<<< HEAD +======= + if constexpr (Negative) { + filter_in = !filter_in; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::string op = (filter_in) ? "*=" : "!="; TCondition condition; @@ -226,7 +252,15 @@ void ColumnValueRange::to_olap_filter(std::vector& filters) { low.__set_is_index_filter_only(_is_index_filter_only); if (_type_min != _low_value || FILTER_LARGER_OR_EQUAL != _low_op) { low.__set_column_name(_column_name); +<<<<<<< HEAD low.__set_condition_op((_low_op == FILTER_LARGER_OR_EQUAL ? ">=" : ">>")); +======= + if constexpr (Negative) { + low.__set_condition_op((_low_op == FILTER_LARGER_OR_EQUAL ? "<<" : "<=")); + } else { + low.__set_condition_op((_low_op == FILTER_LARGER_OR_EQUAL ? ">=" : ">>")); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) low.condition_values.push_back(cast_to_string(_low_value, type(), precision(), scale())); } @@ -238,7 +272,15 @@ void ColumnValueRange::to_olap_filter(std::vector& filters) { high.__set_is_index_filter_only(_is_index_filter_only); if (_type_max != _high_value || FILTER_LESS_OR_EQUAL != _high_op) { high.__set_column_name(_column_name); +<<<<<<< HEAD high.__set_condition_op((_high_op == FILTER_LESS_OR_EQUAL ? "<=" : "<<")); +======= + if constexpr (Negative) { + high.__set_condition_op((_high_op == FILTER_LESS_OR_EQUAL ? ">>" : ">=")); + } else { + high.__set_condition_op((_high_op == FILTER_LESS_OR_EQUAL ? "<=" : "<<")); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) high.condition_values.push_back(cast_to_string(_high_value, type(), precision(), scale())); } @@ -439,8 +481,13 @@ Status ColumnValueRange::add_range(SQLFilterOp op, T value) { if (value > _low_value) { _low_value = value; _low_op = op; +<<<<<<< HEAD } else if (value <= _type_min) { return Status::NotSupported("reject value smaller than or equals to type min"); +======= + } else if (value < _type_min) { + return Status::NotSupported("reject value smaller than type min"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { // accept this value, but keep range unchanged. } @@ -461,8 +508,13 @@ Status ColumnValueRange::add_range(SQLFilterOp op, T value) { if (value < _high_value) { _high_value = value; _high_op = op; +<<<<<<< HEAD } else if (value >= _type_max) { return Status::NotSupported("reject value larger than or equals to type max"); +======= + } else if (value > _type_max) { + return Status::NotSupported("reject value larger than type max"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { // accept this value, but keep range unchanged. } @@ -638,6 +690,21 @@ ColumnValueRange::ColumnValueRange(std::string col_name, LogicalType type, T _fixed_op(FILTER_IN) {} template +<<<<<<< HEAD +======= +ColumnValueRange::ColumnValueRange(std::string col_name, LogicalType type, T type_min, T type_max, T min, T max) + : _column_name(std::move(col_name)), + _column_type(type), + _type_min(type_min), + _type_max(type_max), + _low_value(min), + _high_value(max), + _low_op(FILTER_LARGER_OR_EQUAL), + _high_op(FILTER_LESS_OR_EQUAL), + _fixed_op(FILTER_IN) {} + +template +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool ColumnValueRange::is_fixed_value_range() const { return _fixed_values.size() != 0 || _empty_range; } @@ -710,6 +777,7 @@ int ColumnValueRange::scale() const { return this->_scale; } +<<<<<<< HEAD template class ColumnValueRange; template class ColumnValueRange; template class ColumnValueRange; @@ -741,6 +809,31 @@ template Status OlapScanKeys::extend_scan_key(ColumnValueRange& rang template Status OlapScanKeys::extend_scan_key(ColumnValueRange& range, int32_t max_scan_key_num); template Status OlapScanKeys::extend_scan_key(ColumnValueRange& range, int32_t max_scan_key_num); +======= +#define InsitializeColumnValueRange(T) \ + template class ColumnValueRange; \ + \ + template void ColumnValueRange::to_olap_filter(std::vector&); \ + template void ColumnValueRange::to_olap_filter(std::vector&); \ + \ + template Status OlapScanKeys::extend_scan_key(ColumnValueRange & range, int32_t max_scan_key_num); + +InsitializeColumnValueRange(int8_t); +InsitializeColumnValueRange(uint8_t); +InsitializeColumnValueRange(int16_t); +InsitializeColumnValueRange(int32_t); +InsitializeColumnValueRange(int64_t); +InsitializeColumnValueRange(__int128); +InsitializeColumnValueRange(StringValue); +InsitializeColumnValueRange(Slice); +InsitializeColumnValueRange(DateTimeValue); +InsitializeColumnValueRange(DecimalV2Value); +InsitializeColumnValueRange(bool); +InsitializeColumnValueRange(DateValue); +InsitializeColumnValueRange(TimestampValue); + +#undef InsitializeColumnValueRange +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/olap_common.h b/be/src/exec/olap_common.h index 22d2be2e8eafd..3676df376c4ad 100644 --- a/be/src/exec/olap_common.h +++ b/be/src/exec/olap_common.h @@ -72,10 +72,18 @@ class ColumnValueRange { typedef typename std::set::iterator iterator_type; ColumnValueRange(); ColumnValueRange(std::string col_name, LogicalType type, T min, T max); +<<<<<<< HEAD [[nodiscard]] Status add_fixed_values(SQLFilterOp op, const std::set& values); [[nodiscard]] Status add_range(SQLFilterOp op, T value); +======= + ColumnValueRange(std::string col_name, LogicalType type, T type_min, T type_max, T min, T max); + + Status add_fixed_values(SQLFilterOp op, const std::set& values); + + Status add_range(SQLFilterOp op, T value); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_precision(int precision); @@ -123,8 +131,16 @@ class ColumnValueRange { void set_index_filter_only(bool is_index_only) { _is_index_filter_only = is_index_only; } +<<<<<<< HEAD + void to_olap_filter(std::vector& filters); + +======= + template void to_olap_filter(std::vector& filters); + TCondition to_olap_not_null_filter() const; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void clear(); private: @@ -153,9 +169,15 @@ class OlapScanKeys { OlapScanKeys() = default; template +<<<<<<< HEAD [[nodiscard]] Status extend_scan_key(ColumnValueRange& range, int32_t max_scan_key_num); [[nodiscard]] Status get_key_range(std::vector>* key_range); +======= + Status extend_scan_key(ColumnValueRange& range, int32_t max_scan_key_num); + + Status get_key_range(std::vector>* key_range); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool has_range_value() const { return _has_range_value; } diff --git a/be/src/exec/olap_scan_node.cpp b/be/src/exec/olap_scan_node.cpp index f3981d55d7c27..b91017ce068cd 100644 --- a/be/src/exec/olap_scan_node.cpp +++ b/be/src/exec/olap_scan_node.cpp @@ -20,7 +20,10 @@ #include #include "column/column_access_path.h" +<<<<<<< HEAD #include "column/column_pool.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/type_traits.h" #include "common/compiler_util.h" #include "common/status.h" @@ -144,7 +147,11 @@ Status OlapScanNode::open(RuntimeState* state) { RETURN_IF_ERROR(ExecNode::open(state)); Status status; +<<<<<<< HEAD RETURN_IF_ERROR(OlapScanConjunctsManager::eval_const_conjuncts(_conjunct_ctxs, &status)); +======= + RETURN_IF_ERROR(ScanConjunctsManager::eval_const_conjuncts(_conjunct_ctxs, &status)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _update_status(status); DictOptimizeParser::rewrite_descriptor(state, _conjunct_ctxs, _olap_scan_node.dict_string_id_to_int_ids, @@ -159,7 +166,10 @@ Status OlapScanNode::get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos) { RETURN_IF_ERROR(exec_debug_action(TExecNodePhase::GETNEXT)); SCOPED_TIMER(_runtime_profile->total_time_counter()); +<<<<<<< HEAD bool first_call = !_start; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!_start && _status.ok()) { Status status = _start_scan(state); _update_status(status); @@ -210,7 +220,11 @@ Status OlapScanNode::get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos) { // is the first time of calling `get_next`, pass the second argument of `_fill_chunk_pool` as // true to ensure that the newly allocated column objects will be returned back into the column // pool. +<<<<<<< HEAD TRY_CATCH_BAD_ALLOC(_fill_chunk_pool(1, first_call && state->use_column_pool())); +======= + TRY_CATCH_BAD_ALLOC(_fill_chunk_pool(1)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) eval_join_runtime_filters(chunk); _num_rows_returned += (*chunk)->num_rows(); COUNTER_SET(_rows_returned_counter, _num_rows_returned); @@ -256,11 +270,14 @@ void OlapScanNode::close(RuntimeState* state) { chunk.reset(); } +<<<<<<< HEAD if (runtime_state() != nullptr) { // Reduce the memory usage if the the average string size is greater than 512. release_large_columns(runtime_state()->chunk_size() * 512); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (const auto& rowsets_per_tablet : _tablet_rowsets) { Rowset::release_readers(rowsets_per_tablet); } @@ -275,10 +292,17 @@ OlapScanNode::~OlapScanNode() { DCHECK(is_closed()); } +<<<<<<< HEAD void OlapScanNode::_fill_chunk_pool(int count, bool force_column_pool) { const size_t capacity = runtime_state()->chunk_size(); for (int i = 0; i < count; i++) { ChunkPtr chunk(ChunkHelper::new_chunk_pooled(*_chunk_schema, capacity, force_column_pool)); +======= +void OlapScanNode::_fill_chunk_pool(int count) { + const size_t capacity = runtime_state()->chunk_size(); + for (int i = 0; i < count; i++) { + ChunkPtr chunk(ChunkHelper::new_chunk_pooled(*_chunk_schema, capacity)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) { std::lock_guard l(_mtx); _chunk_pool.push(std::move(chunk)); @@ -410,9 +434,16 @@ StatusOr OlapScanNode::convert_scan_range_to_morsel_qu bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, size_t num_total_scan_ranges) { pipeline::Morsels morsels; +<<<<<<< HEAD for (const auto& scan_range : scan_ranges) { morsels.emplace_back(std::make_unique(node_id, scan_range)); } +======= + [[maybe_unused]] bool has_more_morsel = false; + pipeline::ScanMorsel::build_scan_morsels(node_id, scan_ranges, accept_empty_scan_ranges(), &morsels, + &has_more_morsel); + DCHECK(has_more_morsel == false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (partition_order_hint().has_value()) { bool asc = partition_order_hint().value(); @@ -521,6 +552,7 @@ Status OlapScanNode::collect_query_statistics(QueryStatistics* statistics) { Status OlapScanNode::_start_scan(RuntimeState* state) { RETURN_IF_CANCELLED(state); +<<<<<<< HEAD OlapScanConjunctsManager& cm = _conjuncts_manager; cm.conjunct_ctxs_ptr = &_conjunct_ctxs; cm.tuple_desc = _tuple_desc; @@ -529,6 +561,8 @@ Status OlapScanNode::_start_scan(RuntimeState* state) { cm.runtime_filters = &_runtime_filter_collector; cm.runtime_state = state; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TQueryOptions& query_options = state->query_options(); int32_t max_scan_key_num; if (query_options.__isset.max_scan_key_num && query_options.max_scan_key_num > 0) { @@ -541,7 +575,26 @@ Status OlapScanNode::_start_scan(RuntimeState* state) { if (_olap_scan_node.__isset.enable_column_expr_predicate) { enable_column_expr_predicate = _olap_scan_node.enable_column_expr_predicate; } +<<<<<<< HEAD RETURN_IF_ERROR(cm.parse_conjuncts(scan_keys_unlimited, max_scan_key_num, enable_column_expr_predicate)); +======= + + ScanConjunctsManagerOptions opts; + opts.conjunct_ctxs_ptr = &_conjunct_ctxs; + opts.tuple_desc = _tuple_desc; + opts.obj_pool = _pool; + opts.key_column_names = &_olap_scan_node.sort_key_column_names; + opts.runtime_filters = &_runtime_filter_collector; + opts.runtime_state = state; + opts.scan_keys_unlimited = scan_keys_unlimited; + opts.max_scan_key_num = max_scan_key_num; + opts.enable_column_expr_predicate = enable_column_expr_predicate; + + _conjuncts_manager = std::make_unique(std::move(opts)); + ScanConjunctsManager& cm = *_conjuncts_manager; + + RETURN_IF_ERROR(cm.parse_conjuncts()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_start_scan_thread(state)); return Status::OK(); @@ -576,6 +629,15 @@ void OlapScanNode::_init_counter(RuntimeState* state) { _bf_filtered_counter = ADD_CHILD_COUNTER(_scan_profile, "BloomFilterFilterRows", TUnit::UNIT, "SegmentInit"); _gin_filtered_counter = ADD_CHILD_COUNTER(_runtime_profile, "GinFilterRows", TUnit::UNIT, "SegmentInit"); _gin_filtered_timer = ADD_CHILD_TIMER(_runtime_profile, "GinFilter", "SegmentInit"); +<<<<<<< HEAD +======= + _get_row_ranges_by_vector_index_timer = ADD_CHILD_TIMER(_scan_profile, "GetVectorRowRangesTime", "SegmentInit"); + _vector_search_timer = ADD_CHILD_TIMER(_scan_profile, "VectorSearchTime", "SegmentInit"); + _vector_index_filtered_counter = + ADD_CHILD_COUNTER(_scan_profile, "VectorIndexFilterRows", TUnit::UNIT, "SegmentInit"); + _process_vector_distance_and_id_timer = + ADD_CHILD_TIMER(_scan_profile, "ProcessVectorDistanceAndIdTime", "SegmentInit"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _seg_zm_filtered_counter = ADD_CHILD_COUNTER(_scan_profile, "SegmentZoneMapFilterRows", TUnit::UNIT, "SegmentInit"); _seg_rt_filtered_counter = ADD_CHILD_COUNTER(_scan_profile, "SegmentRuntimeZoneMapFilterRows", TUnit::UNIT, "SegmentInit"); @@ -661,9 +723,15 @@ Status OlapScanNode::_start_scan_thread(RuntimeState* state) { } std::vector> key_ranges; +<<<<<<< HEAD RETURN_IF_ERROR(_conjuncts_manager.get_key_ranges(&key_ranges)); std::vector conjunct_ctxs; _conjuncts_manager.get_not_push_down_conjuncts(&conjunct_ctxs); +======= + RETURN_IF_ERROR(_conjuncts_manager->get_key_ranges(&key_ranges)); + std::vector conjunct_ctxs; + _conjuncts_manager->get_not_push_down_conjuncts(&conjunct_ctxs); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(state->mutable_dict_optimize_parser()->rewrite_conjuncts(&conjunct_ctxs)); @@ -722,7 +790,11 @@ Status OlapScanNode::_start_scan_thread(RuntimeState* state) { COUNTER_SET(_task_concurrency, (int64_t)concurrency); int chunks = _chunks_per_scanner * concurrency; _chunk_pool.reserve(chunks); +<<<<<<< HEAD TRY_CATCH_BAD_ALLOC(_fill_chunk_pool(chunks, state->use_column_pool())); +======= + TRY_CATCH_BAD_ALLOC(_fill_chunk_pool(chunks)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(_mtx); for (int i = 0; i < concurrency; i++) { CHECK(_submit_scanner(_pending_scanners.pop(), true)); @@ -749,11 +821,25 @@ StatusOr OlapScanNode::get_tablet(const TInternalScanRange* sca StatusOr> OlapScanNode::capture_tablet_rowsets(const TabletSharedPtr& tablet, const TInternalScanRange* scan_range) { std::vector rowsets; +<<<<<<< HEAD int64_t version = strtoul(scan_range->version.c_str(), nullptr, 10); // Capture row sets of this version tablet. std::shared_lock l(tablet->get_header_lock()); RETURN_IF_ERROR(tablet->capture_consistent_rowsets(Version(0, version), &rowsets)); Rowset::acquire_readers(rowsets); +======= + if (scan_range->__isset.gtid) { + std::shared_lock l(tablet->get_header_lock()); + RETURN_IF_ERROR(tablet->capture_consistent_rowsets(scan_range->gtid, &rowsets)); + Rowset::acquire_readers(rowsets); + } else { + int64_t version = strtoul(scan_range->version.c_str(), nullptr, 10); + // Capture row sets of this version tablet. + std::shared_lock l(tablet->get_header_lock()); + RETURN_IF_ERROR(tablet->capture_consistent_rowsets(Version(0, version), &rowsets)); + Rowset::acquire_readers(rowsets); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return rowsets; } diff --git a/be/src/exec/olap_scan_node.h b/be/src/exec/olap_scan_node.h index c1260aa123a40..4b0e3246a58d9 100644 --- a/be/src/exec/olap_scan_node.h +++ b/be/src/exec/olap_scan_node.h @@ -150,7 +150,11 @@ class OlapScanNode final : public starrocks::ScanNode { void _update_status(const Status& status); Status _get_status(); +<<<<<<< HEAD void _fill_chunk_pool(int count, bool force_column_pool); +======= + void _fill_chunk_pool(int count); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _submit_scanner(TabletScanner* scanner, bool blockable); void _close_pending_scanners(); @@ -172,7 +176,11 @@ class OlapScanNode final : public starrocks::ScanNode { TOlapScanNode _olap_scan_node; std::vector> _scan_ranges; TupleDescriptor* _tuple_desc = nullptr; +<<<<<<< HEAD OlapScanConjunctsManager _conjuncts_manager; +======= + std::unique_ptr _conjuncts_manager = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const Schema* _chunk_schema = nullptr; int32_t _num_scanners = 0; @@ -248,6 +256,13 @@ class OlapScanNode final : public starrocks::ScanNode { RuntimeProfile::Counter* _bi_filter_timer = nullptr; RuntimeProfile::Counter* _gin_filtered_counter = nullptr; RuntimeProfile::Counter* _gin_filtered_timer = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* _get_row_ranges_by_vector_index_timer = nullptr; + RuntimeProfile::Counter* _vector_search_timer = nullptr; + RuntimeProfile::Counter* _vector_index_filtered_counter = nullptr; + RuntimeProfile::Counter* _process_vector_distance_and_id_timer = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* _pushdown_predicates_counter = nullptr; RuntimeProfile::Counter* _rowsets_read_count = nullptr; RuntimeProfile::Counter* _segments_read_count = nullptr; diff --git a/be/src/exec/olap_scan_prepare.cpp b/be/src/exec/olap_scan_prepare.cpp index 3aa2df0f1b0c2..5781a5eaa00c6 100644 --- a/be/src/exec/olap_scan_prepare.cpp +++ b/be/src/exec/olap_scan_prepare.cpp @@ -17,9 +17,18 @@ #include #include "column/type_traits.h" +<<<<<<< HEAD #include "exprs/dictmapping_expr.h" #include "exprs/expr_context.h" #include "exprs/in_const_predicate.hpp" +======= +#include "exprs/binary_predicate.h" +#include "exprs/compound_predicate.h" +#include "exprs/dictmapping_expr.h" +#include "exprs/expr_context.h" +#include "exprs/in_const_predicate.hpp" +#include "exprs/is_null_predicate.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/map_util.h" #include "runtime/descriptors.h" #include "storage/column_predicate.h" @@ -33,6 +42,13 @@ namespace starrocks { +<<<<<<< HEAD +======= +// ------------------------------------------------------------------------------------ +// Util methods. +// ------------------------------------------------------------------------------------ + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static bool ignore_cast(const SlotDescriptor& slot, const Expr& expr) { if (slot.type().is_date_type() && expr.type().is_date_type()) { return true; @@ -40,11 +56,23 @@ static bool ignore_cast(const SlotDescriptor& slot, const Expr& expr) { return slot.type().is_string_type() && expr.type().is_string_type(); } +<<<<<<< HEAD static Expr* get_root_expr(ExprContext* ctx) { if (dynamic_cast(ctx->root())) { return ctx->root()->get_child(1); } return ctx->root(); +======= +static Expr* get_root_expr(Expr* root) { + if (dynamic_cast(root)) { + return root->get_child(1); + } + return root; +} + +static Expr* get_root_expr(ExprContext* ctx) { + return get_root_expr(ctx->root()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } template @@ -56,7 +84,11 @@ static bool check_decimal_overflow(int precision, const ValueType& value) { } } +<<<<<<< HEAD template +======= +template +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static bool get_predicate_value(ObjectPool* obj_pool, const SlotDescriptor& slot, const Expr* expr, ExprContext* ctx, ValueType* value, SQLFilterOp* op, Status* status) { if (expr->get_num_children() != 2) { @@ -118,9 +150,15 @@ static bool get_predicate_value(ObjectPool* obj_pool, const SlotDescriptor& slot } if (expr->op() == TExprOpcode::EQ || expr->op() == TExprOpcode::NE) { +<<<<<<< HEAD *op = to_olap_filter_type(expr->op(), false); } else { *op = to_olap_filter_type(expr->op(), reverse_op); +======= + *op = to_olap_filter_type(expr->op(), false); + } else { + *op = to_olap_filter_type(expr->op(), reverse_op); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if constexpr (std::is_same_v) { @@ -171,6 +209,7 @@ static bool get_predicate_value(ObjectPool* obj_pool, const SlotDescriptor& slot return true; } +<<<<<<< HEAD template void OlapScanConjunctsManager::normalize_in_or_equal_predicate(const SlotDescriptor& slot, ColumnValueRange* range) { @@ -188,6 +227,201 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicate(const SlotDescrip const Expr* l = root_expr->get_child(0); if ((!l->is_slotref()) || (l->type().type != slot.type().type && !ignore_cast(slot, *l))) { +======= +static std::vector build_expr_context_containers(const std::vector& expr_contexts) { + std::vector containers; + for (auto* expr_ctx : expr_contexts) { + containers.emplace_back(expr_ctx); + } + return containers; +} + +static std::vector build_raw_expr_containers(const std::vector& exprs) { + std::vector containers; + for (auto* expr : exprs) { + containers.emplace_back(expr); + } + return containers; +} + +template +static TExprOpcode::type maybe_invert_in_and_equal_op(const TExprOpcode::type op) { + if constexpr (!Negative) { + return op; + } else { + switch (op) { + case TExprOpcode::FILTER_IN: + return TExprOpcode::FILTER_NOT_IN; + case TExprOpcode::FILTER_NOT_IN: + return TExprOpcode::FILTER_IN; + case TExprOpcode::EQ: + return TExprOpcode::NE; + case TExprOpcode::NE: + return TExprOpcode::EQ; + + default: + return op; + } + } +} + +// ------------------------------------------------------------------------------------ +// ChunkPredicateBuilder +// ------------------------------------------------------------------------------------ + +BoxedExpr::BoxedExpr(Expr* root_expr) : root_expr(root_expr) {} +Expr* BoxedExpr::root() const { + return get_root_expr(root_expr); +} +StatusOr BoxedExpr::expr_context(ObjectPool* obj_pool, RuntimeState* state) const { + if (new_expr_ctx == nullptr) { + // Copy expr to prevent two ExprContexts from owning the same Expr, which will cause the same Expr to be + // closed twice. + // - The ExprContext in the `original _opts.conjunct_ctxs_ptr` will own an Expr and all its children. + // - The newly created ExprContext here will also own this Expr. + auto* new_expr = Expr::copy(obj_pool, root_expr); + new_expr_ctx = obj_pool->add(new ExprContext(new_expr)); + RETURN_IF_ERROR(new_expr_ctx->prepare(state)); + RETURN_IF_ERROR(new_expr_ctx->open(state)); + } + return new_expr_ctx; +} + +BoxedExprContext::BoxedExprContext(ExprContext* expr_ctx) : expr_ctx(expr_ctx) {} +Expr* BoxedExprContext::root() const { + return get_root_expr(expr_ctx); +} +StatusOr BoxedExprContext::expr_context(ObjectPool* obj_pool, RuntimeState* state) const { + return expr_ctx; +} + +template +ChunkPredicateBuilder::ChunkPredicateBuilder(const ScanConjunctsManagerOptions& opts, std::vector exprs, + bool is_root_builder) + : _opts(opts), _exprs(std::move(exprs)), _is_root_builder(is_root_builder), _normalized_exprs(_exprs.size()) {} + +template +StatusOr ChunkPredicateBuilder::parse_conjuncts() { + RETURN_IF_ERROR(normalize_expressions()); + RETURN_IF_ERROR(build_olap_filters()); + + // Only the root builder builds scan keys. + if (_is_root_builder && _opts.is_olap_scan) { + RETURN_IF_ERROR(build_scan_keys(_opts.scan_keys_unlimited, _opts.max_scan_key_num)); + } + + if (_opts.enable_column_expr_predicate) { + VLOG_FILE << "OlapScanConjunctsManager: enable_column_expr_predicate = true. push down column expr predicates"; + RETURN_IF_ERROR(build_column_expr_predicates()); + } + + ASSIGN_OR_RETURN(auto normalized, _normalize_compound_predicates()); + if (_is_root_builder) { + return normalized; + } + // Non-root builder return true only when all the child predicates are normalized. + return normalized && !SIMD::contain_zero(_normalized_exprs); +} + +template +StatusOr ChunkPredicateBuilder::_normalize_compound_predicates() { + const size_t num_preds = _exprs.size(); + for (size_t i = 0; i < num_preds; i++) { + if (_normalized_exprs[i]) { + continue; + } + + ASSIGN_OR_RETURN(const bool normalized, _normalize_compound_predicate(_exprs[i].root())); + if (!normalized && !_is_root_builder) { + return false; + } + _normalized_exprs[i] = normalized; + } + + return true; +} + +template +StatusOr ChunkPredicateBuilder::_normalize_compound_predicate(const Expr* root_expr) { + auto process = [&]() -> StatusOr { + ChunkPredicateBuilder child_builder( + _opts, build_raw_expr_containers(root_expr->children()), false); + ASSIGN_OR_RETURN(const bool normalized, child_builder.parse_conjuncts()); + if (normalized) { + _child_builders.emplace_back(std::move(child_builder)); + } + return normalized; + }; + + if (TExprOpcode::COMPOUND_OR == root_expr->op()) { + if (!_opts.pred_tree_params.enable_or) { + return false; + } + return process.template operator()(); + } + + if (TExprOpcode::COMPOUND_AND == root_expr->op()) { + return process.template operator()(); + } + + return false; +} + +template +StatusOr> ChunkPredicateBuilder::get_predicate_tree_root( + PredicateParser* parser, ColumnPredicatePtrs& col_preds_owner) { + auto compound_node = PredicateCompoundNode{}; + + const size_t start_i = col_preds_owner.size(); + RETURN_IF_ERROR(_get_column_predicates(parser, col_preds_owner)); + for (size_t i = start_i; i < col_preds_owner.size(); i++) { + compound_node.add_child(PredicateColumnNode{col_preds_owner[i].get()}); + } + + for (auto& child_builder : _child_builders) { + RETURN_IF_ERROR(std::visit( + [&](auto& c) { + ASSIGN_OR_RETURN(auto child_node, c.get_predicate_tree_root(parser, col_preds_owner)); + compound_node.add_child(std::move(child_node)); + return Status::OK(); + }, + child_builder)); + } + + return compound_node; +} + +template +static bool is_not_in(const auto* pred) { + if constexpr (Negative) { + return !pred->is_not_in(); + } else { + return pred->is_not_in(); + } +}; + +// clang-format off +template +template +requires(!lt_is_date) Status ChunkPredicateBuilder::normalize_in_or_equal_predicate( + const SlotDescriptor& slot, ColumnValueRange* range) { + // clang-format on + + Status status; + + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) { + continue; + } + + const Expr* root_expr = _exprs[i].root(); + + // 1. Normalize in conjuncts like 'where col in (v1, v2, v3)' + if (TExprOpcode::FILTER_IN == maybe_invert_in_and_equal_op(root_expr->op())) { + const Expr* l = root_expr->get_child(0); + + if (!l->is_slotref() || (l->type().type != slot.type().type && !ignore_cast(slot, *l))) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) continue; } std::vector slot_ids; @@ -198,7 +432,11 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicate(const SlotDescrip continue; } +<<<<<<< HEAD if (pred->is_not_in() || pred->null_in_set() || +======= + if (is_not_in(pred) || pred->null_in_set() || +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pred->hash_set().size() > config::max_pushdown_conditions_per_column) { continue; } @@ -208,13 +446,18 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicate(const SlotDescrip values.insert(value); } if (range->add_fixed_values(FILTER_IN, values).ok()) { +<<<<<<< HEAD normalized_conjuncts[i] = true; +======= + _normalized_exprs[i] = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } // 2. Normalize eq conjuncts like 'where col = value' if (TExprNodeType::BINARY_PRED == root_expr->node_type() && +<<<<<<< HEAD FILTER_IN == to_olap_filter_type(root_expr->op(), false)) { using ValueType = typename RunTimeTypeTraits::CppType; SQLFilterOp op; @@ -244,6 +487,42 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicateop()) { +======= + FILTER_IN == to_olap_filter_type(root_expr->op(), false)) { + using ValueType = typename RunTimeTypeTraits::CppType; + SQLFilterOp op; + ValueType value; + ASSIGN_OR_RETURN(auto* expr_context, _exprs[i].expr_context(_opts.obj_pool, _opts.runtime_state)); + bool ok = + get_predicate_value(_opts.obj_pool, slot, root_expr, expr_context, &value, &op, &status); + if (ok && range->add_fixed_values(FILTER_IN, std::set{value}).ok()) { + _normalized_exprs[i] = true; + } + } + } + + return Status::OK(); +} + +// clang-format off +// explicit specialization for DATE. +template +template +requires lt_is_date Status ChunkPredicateBuilder::normalize_in_or_equal_predicate( + const SlotDescriptor& slot, ColumnValueRange* range) { + // clang-format on + Status status; + + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) { + continue; + } + + const Expr* root_expr = _exprs[i].root(); + + // 1. Normalize in conjuncts like 'where col in (v1, v2, v3)' + if (TExprOpcode::FILTER_IN == maybe_invert_in_and_equal_op(root_expr->op())) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const Expr* l = root_expr->get_child(0); // TODO(zhuming): DATE column may be casted to double. if (l->type().type != starrocks::TYPE_DATE && l->type().type != starrocks::TYPE_DATETIME) { @@ -270,7 +549,11 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicateis_not_in() || pred->null_in_set() || +======= + if (is_not_in(pred) || pred->null_in_set() || +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pred->hash_set().size() > config::max_pushdown_conditions_per_column) { continue; } @@ -283,7 +566,12 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicate*>(root_expr); +<<<<<<< HEAD if (pred->is_not_in() || pred->null_in_set() || +======= + + if (is_not_in(pred) || pred->null_in_set() || +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pred->hash_set().size() > config::max_pushdown_conditions_per_column) { continue; } @@ -296,13 +584,18 @@ void OlapScanConjunctsManager::normalize_in_or_equal_predicateadd_fixed_values(FILTER_IN, values).ok()) { +<<<<<<< HEAD normalized_conjuncts[i] = true; +======= + _normalized_exprs[i] = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } // 2. Normalize eq conjuncts like 'where col = value' if (TExprNodeType::BINARY_PRED == root_expr->node_type() && +<<<<<<< HEAD FILTER_IN == to_olap_filter_type(root_expr->op(), false)) { SQLFilterOp op; DateValue value{0}; @@ -327,6 +620,37 @@ void OlapScanConjunctsManager::normalize_binary_predicate(const SlotDescriptor& } Expr* root_expr = get_root_expr(conjunct_ctxs[i]); +======= + FILTER_IN == to_olap_filter_type(root_expr->op(), false)) { + SQLFilterOp op; + DateValue value{0}; + ASSIGN_OR_RETURN(auto* expr_context, _exprs[i].expr_context(_opts.obj_pool, _opts.runtime_state)); + bool ok = + get_predicate_value(_opts.obj_pool, slot, root_expr, expr_context, &value, &op, &status); + if (ok && range->add_fixed_values(FILTER_IN, std::set{value}).ok()) { + _normalized_exprs[i] = true; + } + } + } + + return Status::OK(); +} + +template +template +Status ChunkPredicateBuilder::normalize_binary_predicate(const SlotDescriptor& slot, + ColumnValueRange* range) { + Status status; + DCHECK((SlotType == slot.type().type) || (SlotType == TYPE_VARCHAR && slot.type().type == TYPE_CHAR)); + + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) { + continue; + } + + const Expr* root_expr = _exprs[i].root(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (TExprNodeType::BINARY_PRED != root_expr->node_type()) { continue; } @@ -335,6 +659,7 @@ void OlapScanConjunctsManager::normalize_binary_predicate(const SlotDescriptor& SQLFilterOp op; ValueType value; +<<<<<<< HEAD bool ok = get_predicate_value(obj_pool, slot, root_expr, conjunct_ctxs[i], &value, &op, &status); if (ok && range->add_range(op, static_cast(value)).ok()) { normalized_conjuncts[i] = true; @@ -355,6 +680,71 @@ void OlapScanConjunctsManager::normalize_join_runtime_filter(const SlotDescripto } const Expr* root_expr = get_root_expr(conjunct_ctxs[i]); +======= + ASSIGN_OR_RETURN(auto* expr_context, _exprs[i].expr_context(_opts.obj_pool, _opts.runtime_state)); + bool ok = get_predicate_value(_opts.obj_pool, slot, root_expr, expr_context, &value, &op, &status); + if (ok && range->add_range(op, static_cast(value)).ok()) { + _normalized_exprs[i] = true; + } + } + + return Status::OK(); +} + +template +template class Decoder, class... Args> +void ChunkPredicateBuilder::normalized_rf_with_null(const JoinRuntimeFilter* rf, Expr* col_ref, + Args&&... args) { + DCHECK(Type == CompoundNodeType::AND); + + ObjectPool* pool = _opts.obj_pool; + + const auto* filter = down_cast*>(rf); + using DecoderType = Decoder::CppType>; + DecoderType decoder(std::forward(args)...); + detail::RuntimeColumnPredicateBuilder::MinMaxParser, DecoderType> parser(filter, + &decoder); + const TypeDescriptor& col_type = col_ref->type(); + + ColumnPtr const_min_col = parser.template min_const_column(col_type); + ColumnPtr const_max_col = parser.template max_const_column(col_type); + VectorizedLiteral* min_literal = pool->add(new VectorizedLiteral(std::move(const_min_col), col_type)); + VectorizedLiteral* max_literal = pool->add(new VectorizedLiteral(std::move(const_max_col), col_type)); + + Expr* left_expr = _gen_min_binary_pred(col_ref, min_literal, filter->left_close_interval()); + Expr* right_expr = _gen_max_binary_pred(col_ref, max_literal, filter->right_close_interval()); + Expr* is_null_expr = _gen_is_null_pred(col_ref); + Expr* and_expr = _gen_and_pred(left_expr, right_expr); + + std::vector containers; + containers.emplace_back(and_expr); + containers.emplace_back(is_null_expr); + ChunkPredicateBuilder child_builder(_opts, containers, false); + + auto normalized = child_builder.parse_conjuncts(); + if (!normalized.ok()) { + } else if (normalized.value()) { + _child_builders.emplace_back(child_builder); + } +} + +template +template +Status ChunkPredicateBuilder::normalize_join_runtime_filter(const SlotDescriptor& slot, + ColumnValueRange* range) { + if (!_is_root_builder) { + return Status::OK(); + } + DCHECK(!Negative); + + // in runtime filter + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) { + continue; + } + + const Expr* root_expr = _exprs[i].root(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (TExprOpcode::FILTER_IN == root_expr->op()) { const Expr* l = root_expr->get_child(0); if (!l->is_slotref() || (l->type().type != slot.type().type && !ignore_cast(slot, *l))) { @@ -369,7 +759,11 @@ void OlapScanConjunctsManager::normalize_join_runtime_filter(const SlotDescripto } // Ensure we don't compute this conjuncts again in olap scanner +<<<<<<< HEAD normalized_conjuncts[i] = true; +======= + _normalized_exprs[i] = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (pred->is_not_in() || pred->null_in_set() || pred->hash_set().size() > config::max_pushdown_conditions_per_column) { @@ -386,9 +780,15 @@ void OlapScanConjunctsManager::normalize_join_runtime_filter(const SlotDescripto } // bloom runtime filter +<<<<<<< HEAD for (const auto& it : runtime_filters->descriptors()) { const RuntimeFilterProbeDescriptor* desc = it.second; const JoinRuntimeFilter* rf = desc->runtime_filter(driver_sequence); +======= + for (const auto& it : _opts.runtime_filters->descriptors()) { + RuntimeFilterProbeDescriptor* desc = it.second; + const JoinRuntimeFilter* rf = desc->runtime_filter(_opts.driver_sequence); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using RangeType = ColumnValueRange; using ValueType = typename RunTimeTypeTraits::CppType; SlotId slot_id; @@ -398,12 +798,19 @@ void OlapScanConjunctsManager::normalize_join_runtime_filter(const SlotDescripto // runtime filter existed and does not have null. if (rf == nullptr) { +<<<<<<< HEAD rt_ranger_params.add_unarrived_rf(desc, &slot, driver_sequence); continue; } if (rf->has_null()) continue; +======= + rt_ranger_params.add_unarrived_rf(desc, &slot, _opts.driver_sequence); + continue; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // If this column doesn't have other filter, we use join runtime filter // to fast comput row range in storage engine if (range->is_init_state()) { @@ -414,6 +821,7 @@ void OlapScanConjunctsManager::normalize_join_runtime_filter(const SlotDescripto // If a scanner has finished building a runtime filter, // the rest of the runtime filters will be normalized here +<<<<<<< HEAD auto& global_dicts = runtime_state->get_query_global_dict_map(); if constexpr (SlotType == TYPE_VARCHAR) { if (auto iter = global_dicts.find(slot_id); iter != global_dicts.end()) { @@ -454,11 +862,81 @@ void OlapScanConjunctsManager::normalize_not_in_or_not_equal_predicate(const Slo bool ok = get_predicate_value(obj_pool, slot, root_expr, conjunct_ctxs[i], &value, &op, &status); if (ok && range->add_fixed_values(FILTER_NOT_IN, std::set{value}).ok()) { normalized_conjuncts[i] = true; +======= + auto& global_dicts = _opts.runtime_state->get_query_global_dict_map(); + if constexpr (SlotType == TYPE_VARCHAR) { + if (auto iter = global_dicts.find(slot_id); iter != global_dicts.end()) { + if (rf->has_null()) { + normalized_rf_with_null( + rf, desc->probe_expr_ctx()->root(), &iter->second.first); + } else { + detail::RuntimeColumnPredicateBuilder::build_minmax_range< + RangeType, SlotType, LowCardDictType, + detail::RuntimeColumnPredicateBuilder::GlobalDictCodeDecoder>(*range, rf, + &iter->second.first); + } + } else { + if (rf->has_null()) { + normalized_rf_with_null( + rf, desc->probe_expr_ctx()->root(), nullptr); + } else { + detail::RuntimeColumnPredicateBuilder::build_minmax_range< + RangeType, SlotType, SlotType, detail::RuntimeColumnPredicateBuilder::DummyDecoder>( + *range, rf, nullptr); + } + } + } else { + if (rf->has_null()) { + normalized_rf_with_null( + rf, desc->probe_expr_ctx()->root(), nullptr); + } else { + detail::RuntimeColumnPredicateBuilder::build_minmax_range< + RangeType, SlotType, SlotType, detail::RuntimeColumnPredicateBuilder::DummyDecoder>(*range, rf, + nullptr); + } + } + } + + return Status::OK(); +} + +template +template +Status ChunkPredicateBuilder::normalize_not_in_or_not_equal_predicate( + const SlotDescriptor& slot, ColumnValueRange* range) { + Status status; + DCHECK((SlotType == slot.type().type) || (SlotType == TYPE_VARCHAR && slot.type().type == TYPE_CHAR)); + + using ValueType = typename RunTimeTypeTraits::CppType; + // handle not equal. + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) { + continue; + } + const Expr* root_expr = _exprs[i].root(); + + // handle not equal + if (root_expr->node_type() == TExprNodeType::BINARY_PRED && + maybe_invert_in_and_equal_op(root_expr->op()) == TExprOpcode::NE) { + SQLFilterOp op; + ValueType value; + ASSIGN_OR_RETURN(auto* expr_context, _exprs[i].expr_context(_opts.obj_pool, _opts.runtime_state)); + bool ok = + get_predicate_value(_opts.obj_pool, slot, root_expr, expr_context, &value, &op, &status); + if (ok && range->add_fixed_values(FILTER_NOT_IN, std::set{value}).ok()) { + _normalized_exprs[i] = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } // handle not in +<<<<<<< HEAD if (root_expr->node_type() == TExprNodeType::IN_PRED && root_expr->op() == TExprOpcode::FILTER_NOT_IN) { +======= + if (root_expr->node_type() == TExprNodeType::IN_PRED && + maybe_invert_in_and_equal_op(root_expr->op()) == TExprOpcode::FILTER_NOT_IN) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const Expr* l = root_expr->get_child(0); if (!l->is_slotref() || (l->type().type != slot.type().type && !ignore_cast(slot, *l))) { continue; @@ -467,10 +945,19 @@ void OlapScanConjunctsManager::normalize_not_in_or_not_equal_predicate(const Slo if (1 == l->get_slot_ids(&slot_ids) && slot_ids[0] == slot.id()) { const auto* pred = down_cast*>(root_expr); +<<<<<<< HEAD // RTF won't generate not in predicate DCHECK(!pred->is_join_runtime_filter()); if (!pred->is_not_in() || pred->null_in_set() || +======= + + if (pred->is_join_runtime_filter()) { + continue; + } + + if (!is_not_in(pred) || pred->null_in_set() || +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pred->hash_set().size() > config::max_pushdown_conditions_per_column) { continue; } @@ -480,11 +967,16 @@ void OlapScanConjunctsManager::normalize_not_in_or_not_equal_predicate(const Slo values.insert(value); } if (range->add_fixed_values(FILTER_NOT_IN, values).ok()) { +<<<<<<< HEAD normalized_conjuncts[i] = true; +======= + _normalized_exprs[i] = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } } +<<<<<<< HEAD } void OlapScanConjunctsManager::normalize_is_null_predicate(const SlotDescriptor& slot) { @@ -495,6 +987,19 @@ void OlapScanConjunctsManager::normalize_is_null_predicate(const SlotDescriptor& continue; } Expr* root_expr = get_root_expr(conjunct_ctxs[i]); +======= + + return Status::OK(); +} + +template +Status ChunkPredicateBuilder::normalize_is_null_predicate(const SlotDescriptor& slot) { + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) { + continue; + } + const Expr* root_expr = _exprs[i].root(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (TExprNodeType::FUNCTION_CALL == root_expr->node_type()) { std::string is_null_str; if (root_expr->is_null_scalar_function(is_null_str)) { @@ -511,6 +1016,7 @@ void OlapScanConjunctsManager::normalize_is_null_predicate(const SlotDescriptor& is_null.condition_op = "is"; is_null.condition_values.push_back(is_null_str); is_null_vector.push_back(is_null); +<<<<<<< HEAD normalized_conjuncts[i] = true; } } @@ -535,6 +1041,40 @@ struct ColumnRangeBuilder { if constexpr (ltype == TYPE_TIME || ltype == TYPE_NULL || ltype == TYPE_JSON || lt_is_float || lt_is_binary) { return nullptr; +======= + _normalized_exprs[i] = true; + } + } + } + + return Status::OK(); +} + +template +template +Status ChunkPredicateBuilder::normalize_predicate(const SlotDescriptor& slot, + ColumnValueRange* range) { + constexpr bool Negative = Type == CompoundNodeType::OR; + RETURN_IF_ERROR((normalize_in_or_equal_predicate(slot, range))); + RETURN_IF_ERROR((normalize_binary_predicate(slot, range))); + // Execute normalize_not_in_or_not_equal_predicate after normalize_binary_predicate, + // because the range generated by not in predicates cannot be merged with the range generated by binary predicates. + RETURN_IF_ERROR((normalize_not_in_or_not_equal_predicate(slot, range))); + RETURN_IF_ERROR(normalize_is_null_predicate(slot)); + // Must handle join runtime filter last + RETURN_IF_ERROR((normalize_join_runtime_filter(slot, range))); + + return Status::OK(); +} + +struct ColumnRangeBuilder { + template + Status operator()(ChunkPredicateBuilder* parent, const SlotDescriptor* slot, + std::map* column_value_ranges) { + if constexpr (ltype == TYPE_TIME || ltype == TYPE_NULL || ltype == TYPE_JSON || lt_is_float || + lt_is_binary) { + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { // Treat tinyint and boolean as int constexpr LogicalType limit_type = ltype == TYPE_TINYINT || ltype == TYPE_BOOLEAN ? TYPE_INT : ltype; @@ -556,12 +1096,18 @@ struct ColumnRangeBuilder { range.set_precision(slot->type().precision); range.set_scale(slot->type().scale); } +<<<<<<< HEAD cm->normalize_predicate(*slot, &range); return nullptr; +======= + + return parent->template normalize_predicate(*slot, &range); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } }; +<<<<<<< HEAD Status OlapScanConjunctsManager::normalize_conjuncts() { // Note: _normalized_conjuncts size must be equal to _conjunct_ctxs size, // but HashJoinNode will push down predicate to OlapScanNode's _conjunct_ctxs, @@ -575,21 +1121,55 @@ Status OlapScanConjunctsManager::normalize_conjuncts() { for (auto& slot : tuple_desc->decoded_slots()) { type_dispatch_predicate(slot->type().type, false, ColumnRangeBuilder(), this, slot, &column_value_ranges); +======= +template +Status ChunkPredicateBuilder::normalize_expressions() { + // Note: _normalized_exprs size must be equal to _conjunct_ctxs size, + // but HashJoinNode will push down predicate to OlapScanNode's _conjunct_ctxs, + // So _conjunct_ctxs will change after OlapScanNode prepare, + // So we couldn't resize _normalized_exprs when OlapScanNode init or prepare + + // TODO(zhuming): if any of the normalized column range is empty, we can know that + // no row will be selected anymore and can return EOF directly. + for (auto& slot : _opts.tuple_desc->decoded_slots()) { + RETURN_IF_ERROR(type_dispatch_predicate(slot->type().type, false, ColumnRangeBuilder(), this, slot, + &column_value_ranges)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } +<<<<<<< HEAD Status OlapScanConjunctsManager::build_olap_filters() { +======= +template +Status ChunkPredicateBuilder::build_olap_filters() { + constexpr bool Negative = Type == CompoundNodeType::OR; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) olap_filters.clear(); // False alert from clang-tidy-14 // NOLINTNEXTLINE(performance-for-range-copy) for (auto iter : column_value_ranges) { std::vector filters; +<<<<<<< HEAD std::visit([&](auto&& range) { range.to_olap_filter(filters); }, iter.second); bool empty_range = std::visit([](auto&& range) { return range.is_empty_value_range(); }, iter.second); if (empty_range) { return Status::EndOfFile("EOF, Filter by always false condition"); +======= + std::visit([&](auto&& range) { range.template to_olap_filter(filters); }, iter.second); + const bool empty_range = std::visit([](auto&& range) { return range.is_empty_value_range(); }, iter.second); + if (empty_range) { + if constexpr (!Negative) { + return Status::EndOfFile("EOF, Filter by always false condition"); + } else { + auto not_null_filter = + std::visit([&](auto&& range) { return range.to_olap_not_null_filter(); }, iter.second); + filters.clear(); + filters.emplace_back(std::move(not_null_filter)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } for (auto& filter : filters) { @@ -630,10 +1210,18 @@ class ExtendScanKeyVisitor : public boost::static_visitor { int32_t _max_scan_key_num; }; +<<<<<<< HEAD Status OlapScanConjunctsManager::build_scan_keys(bool unlimited, int32_t max_scan_key_num) { int conditional_key_columns = 0; scan_keys.set_is_convertible(unlimited); const std::vector& ref_key_column_names = *key_column_names; +======= +template +Status ChunkPredicateBuilder::build_scan_keys(bool unlimited, int32_t max_scan_key_num) { + int conditional_key_columns = 0; + scan_keys.set_is_convertible(unlimited); + const std::vector& ref_key_column_names = *_opts.key_column_names; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (const auto& key_column_name : ref_key_column_names) { if (column_value_ranges.count(key_column_name) == 0) { @@ -652,6 +1240,7 @@ Status OlapScanConjunctsManager::build_scan_keys(bool unlimited, int32_t max_sca return Status::OK(); } +<<<<<<< HEAD StatusOr OlapScanConjunctsManager::get_predicate_tree(PredicateParser* parser, ColumnPredicatePtrs& col_preds_owner) { RETURN_IF_ERROR(get_column_predicates(parser, col_preds_owner)); @@ -663,6 +1252,11 @@ StatusOr OlapScanConjunctsManager::get_predicate_tree(PredicatePa } Status OlapScanConjunctsManager::get_column_predicates(PredicateParser* parser, ColumnPredicatePtrs& col_preds_owner) { +======= +template +Status ChunkPredicateBuilder::_get_column_predicates(PredicateParser* parser, + ColumnPredicatePtrs& col_preds_owner) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto& f : olap_filters) { std::unique_ptr p(parser->parse_thrift_cond(f)); RETURN_IF(!p, Status::RuntimeError("invalid filter")); @@ -675,6 +1269,7 @@ Status OlapScanConjunctsManager::get_column_predicates(PredicateParser* parser, col_preds_owner.emplace_back(std::move(p)); } +<<<<<<< HEAD const auto& slots = tuple_desc->decoded_slots(); for (auto& iter : slot_index_to_expr_ctxs) { int slot_index = iter.first; @@ -682,6 +1277,13 @@ Status OlapScanConjunctsManager::get_column_predicates(PredicateParser* parser, const SlotDescriptor* slot_desc = slots[slot_index]; for (ExprContext* ctx : expr_ctxs) { ASSIGN_OR_RETURN(auto tmp, parser->parse_expr_ctx(*slot_desc, runtime_state, ctx)); +======= + const auto& slots = _opts.tuple_desc->decoded_slots(); + for (auto& [slot_index, expr_ctxs] : slot_index_to_expr_ctxs) { + const SlotDescriptor* slot_desc = slots[slot_index]; + for (ExprContext* ctx : expr_ctxs) { + ASSIGN_OR_RETURN(auto tmp, parser->parse_expr_ctx(*slot_desc, _opts.runtime_state, ctx)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::unique_ptr p(std::move(tmp)); if (p == nullptr) { std::stringstream ss; @@ -696,6 +1298,7 @@ Status OlapScanConjunctsManager::get_column_predicates(PredicateParser* parser, } } } +<<<<<<< HEAD return Status::OK(); } @@ -719,6 +1322,14 @@ Status OlapScanConjunctsManager::eval_const_conjuncts(const std::vector>* key_ranges) { +======= + + return Status::OK(); +} + +template +Status ChunkPredicateBuilder::get_key_ranges(std::vector>* key_ranges) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(scan_keys.get_key_range(key_ranges)); if (key_ranges->empty()) { key_ranges->emplace_back(std::make_unique()); @@ -726,6 +1337,7 @@ Status OlapScanConjunctsManager::get_key_ranges(std::vector* predicates) { DCHECK_EQ(conjunct_ctxs_ptr->size(), normalized_conjuncts.size()); for (size_t i = 0; i < normalized_conjuncts.size(); i++) { @@ -738,12 +1350,24 @@ void OlapScanConjunctsManager::get_not_push_down_conjuncts(std::vector slot_id_to_index; const auto& slots = tuple_desc->decoded_slots(); +======= +template +bool ChunkPredicateBuilder::is_pred_normalized(size_t index) const { + return index < _normalized_exprs.size() && _normalized_exprs[index]; +} + +template +Status ChunkPredicateBuilder::build_column_expr_predicates() { + std::map slot_id_to_index; + const auto& slots = _opts.tuple_desc->decoded_slots(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (int i = 0; i < slots.size(); i++) { const SlotDescriptor* slot_desc = slots[i]; SlotId slot_id = slot_desc->id(); slot_id_to_index.insert(std::make_pair(slot_id, i)); } +<<<<<<< HEAD const auto& conjunct_ctxs = (*conjunct_ctxs_ptr); for (size_t i = 0; i < conjunct_ctxs.size(); i++) { if (normalized_conjuncts[i]) continue; @@ -751,6 +1375,14 @@ void OlapScanConjunctsManager::build_column_expr_predicates() { ExprContext* ctx = conjunct_ctxs[i]; std::vector slot_ids; ctx->root()->get_slot_ids(&slot_ids); +======= + for (size_t i = 0; i < _exprs.size(); i++) { + if (_normalized_exprs[i]) continue; + + const Expr* root_expr = _exprs[i].root(); + std::vector slot_ids; + root_expr->get_slot_ids(&slot_ids); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (slot_ids.size() != 1) continue; int index = -1; { @@ -771,6 +1403,7 @@ void OlapScanConjunctsManager::build_column_expr_predicates() { slot_index_to_expr_ctxs.insert(make_pair(index, std::vector{})); iter = slot_index_to_expr_ctxs.find(index); } +<<<<<<< HEAD iter->second.emplace_back(ctx); normalized_conjuncts[i] = true; } @@ -784,8 +1417,145 @@ Status OlapScanConjunctsManager::parse_conjuncts(bool scan_keys_unlimited, int32 if (enable_column_expr_predicate) { VLOG_FILE << "OlapScanConjunctsManager: enable_column_expr_predicate = true. push down column expr predicates"; build_column_expr_predicates(); +======= + ASSIGN_OR_RETURN(auto* expr_ctx, _exprs[i].expr_context(_opts.obj_pool, _opts.runtime_state)); + iter->second.emplace_back(expr_ctx); + _normalized_exprs[i] = true; + } + + return Status::OK(); +} + +template +Expr* ChunkPredicateBuilder::_gen_min_binary_pred(Expr* col_ref, VectorizedLiteral* min_literal, + bool is_close_interval) { + TExprNode node; + node.node_type = TExprNodeType::BINARY_PRED; + node.type = TypeDescriptor(TYPE_BOOLEAN).to_thrift(); + node.child_type = to_thrift(col_ref->type().type); + if (is_close_interval) { + node.__set_opcode(TExprOpcode::GE); + } else { + node.__set_opcode(TExprOpcode::GT); + } + + Expr* expr = _opts.obj_pool->add(VectorizedBinaryPredicateFactory::from_thrift(node)); + expr->add_child(col_ref); + expr->add_child(min_literal); + return expr; +} + +template +Expr* ChunkPredicateBuilder::_gen_max_binary_pred(Expr* col_ref, VectorizedLiteral* max_literal, + bool is_close_interval) { + TExprNode node; + node.node_type = TExprNodeType::BINARY_PRED; + node.type = TypeDescriptor(TYPE_BOOLEAN).to_thrift(); + node.child_type = to_thrift(col_ref->type().type); + if (is_close_interval) { + node.__set_opcode(TExprOpcode::LE); + } else { + node.__set_opcode(TExprOpcode::LT); + } + + Expr* expr = _opts.obj_pool->add(VectorizedBinaryPredicateFactory::from_thrift(node)); + expr->add_child(col_ref); + expr->add_child(max_literal); + return expr; +} + +template +Expr* ChunkPredicateBuilder::_gen_is_null_pred(Expr* col_ref) { + TExprNode null_pred_node; + null_pred_node.node_type = TExprNodeType::FUNCTION_CALL; + TFunction fn; + fn.name.function_name = "is_null_pred"; + null_pred_node.__set_fn(fn); + TTypeNode type_node; + type_node.type = TTypeNodeType::SCALAR; + TScalarType scalar_type; + scalar_type.__set_type(TPrimitiveType::BOOLEAN); + type_node.__set_scalar_type(scalar_type); + null_pred_node.type.types.emplace_back(type_node); + + Expr* expr = _opts.obj_pool->add(VectorizedIsNullPredicateFactory::from_thrift(null_pred_node)); + expr->add_child(col_ref); + return expr; +} + +template +Expr* ChunkPredicateBuilder::_gen_and_pred(Expr* left, Expr* right) { + TExprNode and_pred_node; + and_pred_node.node_type = TExprNodeType::COMPOUND_PRED; + and_pred_node.num_children = 2; + and_pred_node.is_nullable = true; + and_pred_node.__set_opcode(TExprOpcode::COMPOUND_AND); + and_pred_node.__set_child_type(TPrimitiveType::BOOLEAN); + and_pred_node.__set_type(TypeDescriptor(TYPE_BOOLEAN).to_thrift()); + + Expr* expr = _opts.obj_pool->add(VectorizedCompoundPredicateFactory::from_thrift(and_pred_node)); + expr->add_child(left); + expr->add_child(right); + return expr; +} + +// ------------------------------------------------------------------------------------ +// OlapScanConjunctsManager +// ------------------------------------------------------------------------------------ + +ScanConjunctsManager::ScanConjunctsManager(ScanConjunctsManagerOptions&& opts) + : _opts(opts), _root_builder(_opts, build_expr_context_containers(*_opts.conjunct_ctxs_ptr), true) {} + +Status ScanConjunctsManager::parse_conjuncts() { + return _root_builder.parse_conjuncts().status(); +} + +Status ScanConjunctsManager::eval_const_conjuncts(const std::vector& conjunct_ctxs, Status* status) { + *status = Status::OK(); + for (const auto& ctx : conjunct_ctxs) { + // if conjunct is constant, compute direct and set eos = true + if (ctx->root()->is_constant()) { + ASSIGN_OR_RETURN(ColumnPtr value, ctx->root()->evaluate_const(ctx)); + + if (value == nullptr || value->only_null() || value->is_null(0)) { + *status = Status::EndOfFile("conjuncts evaluated to null"); + break; + } else if (value->is_constant() && !ColumnHelper::get_const_value(value)) { + *status = Status::EndOfFile("conjuncts evaluated to false"); + break; + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } +<<<<<<< HEAD +======= +StatusOr ScanConjunctsManager::get_predicate_tree(PredicateParser* parser, + ColumnPredicatePtrs& col_preds_owner) { + ASSIGN_OR_RETURN(auto pred_root, _root_builder.get_predicate_tree_root(parser, col_preds_owner)); + return PredicateTree::create(std::move(pred_root)); +} + +Status ScanConjunctsManager::get_key_ranges(std::vector>* key_ranges) { + return _root_builder.get_key_ranges(key_ranges); +} + +void ScanConjunctsManager::get_not_push_down_conjuncts(std::vector* predicates) { + // DCHECK_EQ(_opts.conjunct_ctxs_ptr->size(), _normalized_exprs.size()); + const size_t num_preds = _opts.conjunct_ctxs_ptr->size(); + for (size_t i = 0; i < num_preds; i++) { + if (!_root_builder.is_pred_normalized(i)) { + predicates->push_back(_opts.conjunct_ctxs_ptr->at(i)); + } + } +} + +const UnarrivedRuntimeFilterList& ScanConjunctsManager::unarrived_runtime_filters() { + return _root_builder.unarrived_runtime_filters(); +} + +template class ChunkPredicateBuilder; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/olap_scan_prepare.h b/be/src/exec/olap_scan_prepare.h index 0eca5cc3e6e44..a9e7a7e3dd5b3 100644 --- a/be/src/exec/olap_scan_prepare.h +++ b/be/src/exec/olap_scan_prepare.h @@ -20,13 +20,21 @@ #include "exprs/expr_context.h" #include "storage/olap_runtime_range_pruner.h" #include "storage/predicate_tree/predicate_tree_fwd.h" +<<<<<<< HEAD namespace starrocks { +======= +#include "storage/predicate_tree_params.h" + +namespace starrocks { + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class RuntimeState; class RuntimeFilterProbeCollector; class PredicateParser; class ColumnPredicate; +<<<<<<< HEAD using ColumnPredicatePtr = std::unique_ptr; using ColumnPredicatePtrs = std::vector; @@ -49,12 +57,155 @@ class OlapScanConjunctsManager { OlapScanKeys scan_keys; // from _column_value_ranges std::vector olap_filters; // from _column_value_ranges std::vector is_null_vector; // from conjunct_ctxs +======= +class VectorizedLiteral; +using ColumnPredicatePtr = std::unique_ptr; +using ColumnPredicatePtrs = std::vector; + +struct ScanConjunctsManagerOptions { + // fields from olap scan node + const std::vector* conjunct_ctxs_ptr = nullptr; + const TupleDescriptor* tuple_desc = nullptr; + ObjectPool* obj_pool = nullptr; + const std::vector* key_column_names = nullptr; + const RuntimeFilterProbeCollector* runtime_filters = nullptr; + RuntimeState* runtime_state = nullptr; + + int32_t driver_sequence = -1; + + bool scan_keys_unlimited = true; + int32_t max_scan_key_num = 1024; + bool enable_column_expr_predicate = false; + bool is_olap_scan = true; + + PredicateTreeParams pred_tree_params; +}; + +struct BoxedExpr { + explicit BoxedExpr(Expr* root_expr); + + Expr* root() const; + StatusOr expr_context(ObjectPool* obj_pool, RuntimeState* state) const; + + Expr* root_expr; + mutable ExprContext* new_expr_ctx = nullptr; +}; + +struct BoxedExprContext { + explicit BoxedExprContext(ExprContext* expr_ctx); + + Expr* root() const; + StatusOr expr_context(ObjectPool* obj_pool, RuntimeState* state) const; + + ExprContext* expr_ctx; +}; + +template +concept BoxedExprType = std::is_same_v || std::is_same_v; + +template +class ChunkPredicateBuilder { +public: + ChunkPredicateBuilder(const ScanConjunctsManagerOptions& opts, std::vector exprs, bool is_root_builder); + + StatusOr parse_conjuncts(); + + StatusOr> get_predicate_tree_root(PredicateParser* parser, + ColumnPredicatePtrs& col_preds_owner); + + Status get_key_ranges(std::vector>* key_ranges); + + bool is_pred_normalized(size_t index) const; + + const UnarrivedRuntimeFilterList& unarrived_runtime_filters() { return rt_ranger_params; } + + template class Decoder, class... Args> + void normalized_rf_with_null(const JoinRuntimeFilter* rf, Expr* col_ref, Args&&... args); + +private: + const ScanConjunctsManagerOptions& _opts; + const std::vector _exprs; + const bool _is_root_builder; + + using ChunkPredicateBuilderVar = std::variant, + ChunkPredicateBuilder>; + std::vector _child_builders; + + // fields generated by parsing conjunct ctxs. + // same size with |_conjunct_ctxs|, indicate which element has been normalized. + std::vector _normalized_exprs; + std::map column_value_ranges; // from conjunct_ctxs + OlapScanKeys scan_keys; // from _column_value_ranges + std::vector olap_filters; // from _column_value_ranges + std::vector is_null_vector; // from conjunct_ctxs + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::map> slot_index_to_expr_ctxs; // from conjunct_ctxs // unreached runtime filter and they can push down to storage engine UnarrivedRuntimeFilterList rt_ranger_params; +<<<<<<< HEAD +public: +======= +private: + StatusOr _normalize_compound_predicates(); + StatusOr _normalize_compound_predicate(const Expr* root_expr); + + Status _get_column_predicates(PredicateParser* parser, ColumnPredicatePtrs& col_preds_owner); + + friend struct ColumnRangeBuilder; + friend class ConjunctiveTestFixture; + + Status normalize_expressions(); + Status build_olap_filters(); + Status build_scan_keys(bool unlimited, int32_t max_scan_key_num); + + // If Type is OR, to convert OR to AND to utilize existing parsing logic, perform the `Negative` operation + // in normalize_xxx_predicate and build_olap_filters. For example, `pred_c1_1 or pred_c1_2 or pred_c2_1 or pred_c2_2` + // will be converted to `!(!pred_c1_1 and !pred_c1_2) or !(!pred_c2_1 and !pred_c2_2)` + // The specific steps are as follows: + // 1. When normalizing predicates to value ranges, pass true to of each normalize_xxx_predicate. + // 2. When building olap filters by the normalized value ranges, pass true to of ColumnValueRange::to_olap_filter. + template + Status normalize_predicate(const SlotDescriptor& slot, ColumnValueRange* range); + + template + requires(!lt_is_date) Status + normalize_in_or_equal_predicate(const SlotDescriptor& slot, ColumnValueRange* range); + template + requires lt_is_date Status normalize_in_or_equal_predicate(const SlotDescriptor& slot, + ColumnValueRange* range); + + template + Status normalize_binary_predicate(const SlotDescriptor& slot, ColumnValueRange* range); + + template + Status normalize_join_runtime_filter(const SlotDescriptor& slot, ColumnValueRange* range); + + template + Status normalize_not_in_or_not_equal_predicate(const SlotDescriptor& slot, ColumnValueRange* range); + + Status normalize_is_null_predicate(const SlotDescriptor& slot); + + // To build `ColumnExprPredicate`s from conjuncts passed from olap scan node. + // `ColumnExprPredicate` would be used in late materialization, zone map filtering, + // dict encoded column filtering and bitmap value column filtering etc. + Status build_column_expr_predicates(); + + Expr* _gen_min_binary_pred(Expr* col_ref, VectorizedLiteral* min_literal, bool is_close_interval); + Expr* _gen_max_binary_pred(Expr* col_ref, VectorizedLiteral* max_literal, bool is_close_interval); + Expr* _gen_is_null_pred(Expr* col_ref); + Expr* _gen_and_pred(Expr* left, Expr* right); +}; + +class ScanConjunctsManager { public: + explicit ScanConjunctsManager(ScanConjunctsManagerOptions&& opts); + + Status parse_conjuncts(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static Status eval_const_conjuncts(const std::vector& conjunct_ctxs, Status* status); StatusOr get_predicate_tree(PredicateParser* parser, ColumnPredicatePtrs& col_preds_owner); @@ -63,6 +214,7 @@ class OlapScanConjunctsManager { void get_not_push_down_conjuncts(std::vector* predicates); +<<<<<<< HEAD Status parse_conjuncts(bool scan_keys_unlimited, int32_t max_scan_key_num, bool enable_column_expr_predicate = false); @@ -99,6 +251,13 @@ class OlapScanConjunctsManager { // `ColumnExprPredicate` would be used in late materialization, zone map filtering, // dict encoded column filtering and bitmap value column filtering etc. void build_column_expr_predicates(); +======= + const UnarrivedRuntimeFilterList& unarrived_runtime_filters(); + +private: + ScanConjunctsManagerOptions _opts; + ChunkPredicateBuilder _root_builder; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exec/olap_utils.h b/be/src/exec/olap_utils.h index ec34a37b2683f..7dc0055a02989 100644 --- a/be/src/exec/olap_utils.h +++ b/be/src/exec/olap_utils.h @@ -106,4 +106,38 @@ inline SQLFilterOp to_olap_filter_type(TExprOpcode::type type, bool opposite) { return FILTER_IN; } +<<<<<<< HEAD +======= +inline SQLFilterOp invert_olap_filter_type(const SQLFilterOp op) { + switch (op) { + case FILTER_LARGER: + return FILTER_LESS_OR_EQUAL; + case FILTER_LARGER_OR_EQUAL: + return FILTER_LESS; + case FILTER_LESS: + return FILTER_LARGER_OR_EQUAL; + case FILTER_LESS_OR_EQUAL: + return FILTER_LARGER; + case FILTER_IN: + return FILTER_NOT_IN; + case FILTER_NOT_IN: + return FILTER_IN; + default: + VLOG(2) << "Unkown SQLFilterOp when inverting it: " << op; + DCHECK(false); + } + return FILTER_IN; +} + +template +SQLFilterOp to_olap_filter_type(TExprOpcode::type type, bool opposite) { + const auto op = to_olap_filter_type(type, opposite); + if constexpr (Negative) { + return invert_olap_filter_type(op); + } else { + return op; + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/orc_scanner.cpp b/be/src/exec/orc_scanner.cpp index 080a1ce860459..8e1036760e3d5 100644 --- a/be/src/exec/orc_scanner.cpp +++ b/be/src/exec/orc_scanner.cpp @@ -86,6 +86,12 @@ Status ORCScanner::open() { RETURN_IF_ERROR(_orc_reader->set_timezone(_state->timezone())); _orc_reader->set_runtime_state(_state); _orc_reader->set_case_sensitive(_case_sensitive); +<<<<<<< HEAD +======= + if (_scan_range.params.__isset.flexible_column_mapping && _scan_range.params.flexible_column_mapping) { + _orc_reader->set_invalid_as_null(true); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_open_next_orc_reader()); return Status::OK(); diff --git a/be/src/exec/parquet_reader.cpp b/be/src/exec/parquet_reader.cpp index ec12c8842cc7d..c7f8539deff4c 100644 --- a/be/src/exec/parquet_reader.cpp +++ b/be/src/exec/parquet_reader.cpp @@ -248,7 +248,11 @@ Status ParquetReaderWrap::column_indices(const std::vector& tup for (auto index : iter->second) { _parquet_column_ids.emplace_back(index); } +<<<<<<< HEAD } else { +======= + } else if (!_invalid_as_null) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::stringstream str_error; str_error << "Column: " << slot_desc->col_name() << " is not found in file: " << _filename; LOG(WARNING) << str_error.str(); diff --git a/be/src/exec/parquet_reader.h b/be/src/exec/parquet_reader.h index df23659510cc8..f633b701bfa7f 100644 --- a/be/src/exec/parquet_reader.h +++ b/be/src/exec/parquet_reader.h @@ -74,6 +74,10 @@ class ParquetReaderWrap { int64_t num_rows() { return _num_rows; } Status get_schema(std::vector* schema); +<<<<<<< HEAD +======= + void set_invalid_as_null(bool invalid_as_null) { _invalid_as_null = invalid_as_null; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: Status column_indices(const std::vector& tuple_slot_descs); @@ -107,6 +111,11 @@ class ParquetReaderWrap { int64_t _read_size; std::string _filename; +<<<<<<< HEAD +======= + + bool _invalid_as_null{false}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; // Reader of broker parquet file diff --git a/be/src/exec/parquet_scanner.cpp b/be/src/exec/parquet_scanner.cpp index 500cba44b14b1..2868ae9d6605e 100644 --- a/be/src/exec/parquet_scanner.cpp +++ b/be/src/exec/parquet_scanner.cpp @@ -77,17 +77,32 @@ Status ParquetScanner::initialize_src_chunk(ChunkPtr* chunk) { SCOPED_RAW_TIMER(&_counter->init_chunk_ns); _pool.clear(); (*chunk) = std::make_shared(); +<<<<<<< HEAD size_t column_pos = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _chunk_filter.clear(); for (auto i = 0; i < _num_of_columns_from_file; ++i) { SlotDescriptor* slot_desc = _src_slot_descriptors[i]; if (slot_desc == nullptr) { continue; } +<<<<<<< HEAD auto* array = _batch->column(column_pos++).get(); ColumnPtr column; RETURN_IF_ERROR(new_column(array->type().get(), slot_desc, &column, _conv_funcs[i].get(), &_cast_exprs[i], _pool, _strict_mode)); +======= + ColumnPtr column; + auto array_ptr = _batch->GetColumnByName(slot_desc->col_name()); + if (array_ptr == nullptr) { + _cast_exprs[i] = _pool.add(new ColumnRef(slot_desc)); + column = ColumnHelper::create_column(slot_desc->type(), slot_desc->is_nullable()); + } else { + RETURN_IF_ERROR(new_column(array_ptr->type().get(), slot_desc, &column, _conv_funcs[i].get(), + &_cast_exprs[i], _pool, _strict_mode)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) column->reserve(_max_chunk_size); (*chunk)->append_column(column, slot_desc->id()); } @@ -98,7 +113,10 @@ Status ParquetScanner::append_batch_to_src_chunk(ChunkPtr* chunk) { SCOPED_RAW_TIMER(&_counter->fill_ns); size_t num_elements = std::min((_max_chunk_size - _chunk_start_idx), (_batch->num_rows() - _batch_start_idx)); +<<<<<<< HEAD size_t column_pos = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _chunk_filter.resize(_chunk_filter.size() + num_elements, 1); for (auto i = 0; i < _num_of_columns_from_file; ++i) { SlotDescriptor* slot_desc = _src_slot_descriptors[i]; @@ -106,10 +124,21 @@ Status ParquetScanner::append_batch_to_src_chunk(ChunkPtr* chunk) { continue; } _conv_ctx.current_slot = slot_desc; +<<<<<<< HEAD auto* array = _batch->column(column_pos++).get(); auto& column = (*chunk)->get_column_by_slot_id(slot_desc->id()); RETURN_IF_ERROR(convert_array_to_column(_conv_funcs[i].get(), num_elements, array, column, _batch_start_idx, _chunk_start_idx, &_chunk_filter, &_conv_ctx)); +======= + auto& column = (*chunk)->get_column_by_slot_id(slot_desc->id()); + auto array_ptr = _batch->GetColumnByName(slot_desc->col_name()); + if (array_ptr == nullptr) { + (void)column->append_nulls(_batch->num_rows()); + } else { + RETURN_IF_ERROR(convert_array_to_column(_conv_funcs[i].get(), num_elements, array_ptr.get(), column, + _batch_start_idx, _chunk_start_idx, &_chunk_filter, &_conv_ctx)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _chunk_start_idx += num_elements; @@ -460,6 +489,12 @@ Status ParquetScanner::open_next_reader() { auto parquet_file = std::make_shared(file, 0, _counter); auto parquet_reader = std::make_shared(std::move(parquet_file), _num_of_columns_from_file, range_desc.start_offset, range_desc.size); +<<<<<<< HEAD +======= + if (_scan_range.params.__isset.flexible_column_mapping && _scan_range.params.flexible_column_mapping) { + parquet_reader->set_invalid_as_null(true); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _next_file++; int64_t file_size; RETURN_IF_ERROR(parquet_reader->size(&file_size)); diff --git a/be/src/exec/partition/chunks_partitioner.cpp b/be/src/exec/partition/chunks_partitioner.cpp index f5ca59f6c6ac8..8a9032cd7812a 100644 --- a/be/src/exec/partition/chunks_partitioner.cpp +++ b/be/src/exec/partition/chunks_partitioner.cpp @@ -26,6 +26,7 @@ namespace starrocks { ChunksPartitioner::ChunksPartitioner(const bool has_nullable_partition_column, const std::vector& partition_exprs, +<<<<<<< HEAD std::vector partition_types) : _has_nullable_partition_column(has_nullable_partition_column), _partition_exprs(partition_exprs), @@ -36,6 +37,18 @@ ChunksPartitioner::ChunksPartitioner(const bool has_nullable_partition_column, Status ChunksPartitioner::prepare(RuntimeState* state, RuntimeProfile* runtime_profile) { _state = state; _mem_pool = std::make_unique(); +======= + std::vector partition_types, MemPool* mem_pool) + : _has_nullable_partition_column(has_nullable_partition_column), + _partition_exprs(partition_exprs), + _partition_types(std::move(partition_types)), + _mem_pool(mem_pool) { + _partition_columns.resize(partition_exprs.size()); +} + +Status ChunksPartitioner::prepare(RuntimeState* state, RuntimeProfile* runtime_profile, bool enable_pre_agg) { + _state = state; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _obj_pool = std::make_unique(); _init_hash_map_variant(); @@ -45,6 +58,12 @@ Status ChunksPartitioner::prepare(RuntimeState* state, RuntimeProfile* runtime_p _limited_buffer = std::make_unique>( &_statistics, 1, config::local_exchange_buffer_mem_limit_per_driver, state->chunk_size() * config::streaming_agg_chunk_buffer_size); +<<<<<<< HEAD +======= + if (enable_pre_agg) { + _hash_map_variant.set_enable_pre_agg(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } diff --git a/be/src/exec/partition/chunks_partitioner.h b/be/src/exec/partition/chunks_partitioner.h index f0ed42f5cb61d..42e589dae9e48 100644 --- a/be/src/exec/partition/chunks_partitioner.h +++ b/be/src/exec/partition/chunks_partitioner.h @@ -47,9 +47,15 @@ struct ChunksPartitionStatistics { class ChunksPartitioner { public: ChunksPartitioner(const bool has_nullable_partition_column, const std::vector& partition_exprs, +<<<<<<< HEAD std::vector partition_types); Status prepare(RuntimeState* state, RuntimeProfile* runtime_profile); +======= + std::vector partition_types, MemPool* mem_pool); + + Status prepare(RuntimeState* state, RuntimeProfile* runtime_profile, bool enable_pre_agg = false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Chunk is divided into multiple parts by partition columns, // and each partition corresponds to a key-value pair in the hash map. @@ -106,7 +112,11 @@ class ChunksPartitioner { // @consumer: bool consumer(int32_t partition_idx, const ChunkPtr& chunk) // The return value of the consumer denote whether to continue or not template +<<<<<<< HEAD [[nodiscard]] Status consume_from_hash_map(Consumer&& consumer) { +======= + Status consume_from_hash_map(Consumer&& consumer) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (is_hash_map_eos()) { return Status::OK(); } @@ -125,7 +135,10 @@ class ChunksPartitioner { if (is_hash_map_eos()) { _hash_map_variant.reset(); +<<<<<<< HEAD _mem_pool.reset(); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _obj_pool.reset(); } @@ -148,7 +161,11 @@ class ChunksPartitioner { PartitionChunkConsumer&& partition_chunk_consumer) { if (!_is_passthrough) { _is_passthrough = hash_map_with_key.template append_chunk( +<<<<<<< HEAD chunk, _partition_columns, _mem_pool.get(), _obj_pool.get(), +======= + chunk, _partition_columns, _mem_pool, _obj_pool.get(), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::forward(new_partition_cb), std::forward(partition_chunk_consumer)); } @@ -250,7 +267,11 @@ class ChunksPartitioner { const std::vector _partition_types; RuntimeState* _state = nullptr; +<<<<<<< HEAD std::unique_ptr _mem_pool = nullptr; +======= + MemPool* _mem_pool = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::unique_ptr _obj_pool = nullptr; Columns _partition_columns; diff --git a/be/src/exec/partition/partition_hash_map.h b/be/src/exec/partition/partition_hash_map.h index a4359a3b1811c..96a12f1f059d6 100644 --- a/be/src/exec/partition/partition_hash_map.h +++ b/be/src/exec/partition/partition_hash_map.h @@ -94,6 +94,11 @@ struct PartitionHashMapBase { bool init_null_key_partition = false; static constexpr size_t kNullKeyPartitionIdx = 0; +<<<<<<< HEAD +======= + bool enable_pre_agg = false; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) PartitionHashMapBase(int32_t chunk_size) : chunk_size(chunk_size) {} protected: @@ -148,7 +153,13 @@ struct PartitionHashMapBase { return; } auto partition_num = hash_map.size(); +<<<<<<< HEAD if (partition_num > 512 && total_num_rows < 10000 * partition_num) { +======= + size_t partition_num_hwm = enable_pre_agg ? 32768 : 512; + + if (partition_num > partition_num_hwm && total_num_rows < 10000 * partition_num) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) is_passthrough = true; } } diff --git a/be/src/exec/partition/partition_hash_variant.cpp b/be/src/exec/partition/partition_hash_variant.cpp index a7158bf520fc6..ac38568d7bc45 100644 --- a/be/src/exec/partition/partition_hash_variant.cpp +++ b/be/src/exec/partition/partition_hash_variant.cpp @@ -180,4 +180,14 @@ void PartitionHashMapVariant::set_passthrough() { }); } +<<<<<<< HEAD +======= +void PartitionHashMapVariant::set_enable_pre_agg() { + visit([](auto& hash_map_with_key) { + DCHECK(hash_map_with_key != nullptr); + hash_map_with_key->enable_pre_agg = true; + }); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/partition/partition_hash_variant.h b/be/src/exec/partition/partition_hash_variant.h index 64cc9648510cc..51b770ceafae8 100644 --- a/be/src/exec/partition/partition_hash_variant.h +++ b/be/src/exec/partition/partition_hash_variant.h @@ -202,5 +202,10 @@ struct PartitionHashMapVariant { bool is_nullable() const; void set_passthrough(); +<<<<<<< HEAD +======= + + void set_enable_pre_agg(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exec/pipeline/aggregate/aggregate_blocking_sink_operator.h b/be/src/exec/pipeline/aggregate/aggregate_blocking_sink_operator.h index 1a2415341ffab..21cb2182fdf61 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_blocking_sink_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_blocking_sink_operator.h @@ -40,6 +40,7 @@ class AggregateBlockingSinkOperator : public Operator { bool has_output() const override { return false; } bool need_input() const override { return !is_finished(); } bool is_finished() const override { return _is_finished || _aggregator->is_finished(); } +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; @@ -48,6 +49,16 @@ class AggregateBlockingSinkOperator : public Operator { [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +======= + Status set_finishing(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: DECLARE_ONCE_DETECTOR(_set_finishing_once); @@ -75,7 +86,11 @@ class AggregateBlockingSinkOperatorFactory final : public OperatorFactory { ~AggregateBlockingSinkOperatorFactory() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override; diff --git a/be/src/exec/pipeline/aggregate/aggregate_blocking_source_operator.h b/be/src/exec/pipeline/aggregate/aggregate_blocking_source_operator.h index cb4b2487130f4..9145a14e24183 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_blocking_source_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_blocking_source_operator.h @@ -35,11 +35,19 @@ class AggregateBlockingSourceOperator : public SourceOperator { bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finished(RuntimeState* state) override; void close(RuntimeState* state) override; [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; +======= + Status set_finished(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: // It is used to perform aggregation algorithms shared by diff --git a/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_sink_operator.h b/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_sink_operator.h index 0ff4c791b66bf..8bb41ed8733b9 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_sink_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_sink_operator.h @@ -39,6 +39,7 @@ class AggregateDistinctBlockingSinkOperator : public Operator { bool has_output() const override { return false; } bool need_input() const override { return !is_finished(); } bool is_finished() const override { return _is_finished || _aggregator->is_finished(); } +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; @@ -47,6 +48,16 @@ class AggregateDistinctBlockingSinkOperator : public Operator { [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +======= + Status set_finishing(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: // It is used to perform aggregation algorithms shared by @@ -73,7 +84,11 @@ class AggregateDistinctBlockingSinkOperatorFactory final : public OperatorFactor ~AggregateDistinctBlockingSinkOperatorFactory() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override { +======= + Status prepare(RuntimeState* state) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(OperatorFactory::prepare(state)); return Status::OK(); } diff --git a/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_source_operator.h b/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_source_operator.h index b4afe0b09d84a..9c2c8415166eb 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_source_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_distinct_blocking_source_operator.h @@ -35,11 +35,19 @@ class AggregateDistinctBlockingSourceOperator : public SourceOperator { bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finished(RuntimeState* state) override; void close(RuntimeState* state) override; [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; +======= + Status set_finished(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: // It is used to perform aggregation algorithms shared by diff --git a/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_sink_operator.h b/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_sink_operator.h index 82b416788b416..383106575033e 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_sink_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_sink_operator.h @@ -38,6 +38,7 @@ class AggregateDistinctStreamingSinkOperator : public Operator { return !is_finished() && !_aggregator->is_streaming_all_states() && !_aggregator->is_chunk_buffer_full(); } bool is_finished() const override { return _is_finished || _aggregator->is_finished(); } +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; @@ -46,12 +47,23 @@ class AggregateDistinctStreamingSinkOperator : public Operator { [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +======= + Status set_finishing(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool releaseable() const override { return true; } void set_execute_mode(int performance_level) override; private: // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::FORCE_STREAMING +<<<<<<< HEAD [[nodiscard]] Status _push_chunk_by_force_streaming(const ChunkPtr& chunk); // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::FORCE_PREAGGREGATION @@ -62,6 +74,18 @@ class AggregateDistinctStreamingSinkOperator : public Operator { // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::LIMITED [[nodiscard]] Status _push_chunk_by_limited_memory(const ChunkPtr& chunk, const size_t chunk_size); +======= + Status _push_chunk_by_force_streaming(const ChunkPtr& chunk); + + // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::FORCE_PREAGGREGATION + Status _push_chunk_by_force_preaggregation(const size_t chunk_size); + + // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::AUTO + Status _push_chunk_by_auto(const ChunkPtr& chunk, const size_t chunk_size); + + // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::LIMITED + Status _push_chunk_by_limited_memory(const ChunkPtr& chunk, const size_t chunk_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // It is used to perform aggregation algorithms shared by // AggregateDistinctStreamingSourceOperator. It is diff --git a/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_source_operator.h b/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_source_operator.h index 00fe03ed1f611..1e21b6cee5338 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_source_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_distinct_streaming_source_operator.h @@ -34,6 +34,7 @@ class AggregateDistinctStreamingSourceOperator : public SourceOperator { bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finished(RuntimeState* state) override; void close(RuntimeState* state) override; @@ -42,6 +43,16 @@ class AggregateDistinctStreamingSourceOperator : public SourceOperator { private: [[nodiscard]] Status _output_chunk_from_hash_set(ChunkPtr* chunk, RuntimeState* state); +======= + Status set_finished(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + +private: + Status _output_chunk_from_hash_set(ChunkPtr* chunk, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // It is used to perform aggregation algorithms shared by // AggregateDistinctStreamingSinkOperator. It is diff --git a/be/src/exec/pipeline/aggregate/aggregate_streaming_sink_operator.h b/be/src/exec/pipeline/aggregate/aggregate_streaming_sink_operator.h index 88d63bb225a6d..98ca0bfc9ce62 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_streaming_sink_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_streaming_sink_operator.h @@ -38,6 +38,7 @@ class AggregateStreamingSinkOperator : public Operator { return !is_finished() && !_aggregator->is_streaming_all_states() && !_aggregator->is_chunk_buffer_full(); } bool is_finished() const override { return _is_finished || _aggregator->is_finished(); } +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; @@ -46,11 +47,22 @@ class AggregateStreamingSinkOperator : public Operator { [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +======= + Status set_finishing(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool releaseable() const override { return true; } void set_execute_mode(int performance_level) override; private: // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::FORCE_STREAMING +<<<<<<< HEAD [[nodiscard]] Status _push_chunk_by_force_streaming(const ChunkPtr& chunk); // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::FORCE_PREAGGREGATION @@ -64,6 +76,20 @@ class AggregateStreamingSinkOperator : public Operator { // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::LIMITED [[nodiscard]] Status _push_chunk_by_limited_memory(const ChunkPtr& chunk, const size_t chunk_size); +======= + Status _push_chunk_by_force_streaming(const ChunkPtr& chunk); + + // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::FORCE_PREAGGREGATION + Status _push_chunk_by_force_preaggregation(const ChunkPtr& chunk, const size_t chunk_size); + + // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::AUTO + Status _push_chunk_by_auto(const ChunkPtr& chunk, const size_t chunk_size); + + Status _push_chunk_by_selective_preaggregation(const ChunkPtr& chunk, const size_t chunk_size, bool need_build); + + // Invoked by push_chunk if current mode is TStreamingPreaggregationMode::LIMITED + Status _push_chunk_by_limited_memory(const ChunkPtr& chunk, const size_t chunk_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // It is used to perform aggregation algorithms shared by // AggregateStreamingSourceOperator. It is diff --git a/be/src/exec/pipeline/aggregate/aggregate_streaming_source_operator.h b/be/src/exec/pipeline/aggregate/aggregate_streaming_source_operator.h index 74819b38eaa8b..ebd3beb981a66 100644 --- a/be/src/exec/pipeline/aggregate/aggregate_streaming_source_operator.h +++ b/be/src/exec/pipeline/aggregate/aggregate_streaming_source_operator.h @@ -33,6 +33,7 @@ class AggregateStreamingSourceOperator : public SourceOperator { bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finished(RuntimeState* state) override; void close(RuntimeState* state) override; @@ -41,6 +42,16 @@ class AggregateStreamingSourceOperator : public SourceOperator { private: [[nodiscard]] Status _output_chunk_from_hash_map(ChunkPtr* chunk, RuntimeState* state); +======= + Status set_finished(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + +private: + Status _output_chunk_from_hash_map(ChunkPtr* chunk, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // It is used to perform aggregation algorithms shared by // AggregateStreamingSinkOperator. It is diff --git a/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_sink_operator.h b/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_sink_operator.h index 44e317a32fe28..efe15ebea8c75 100644 --- a/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_sink_operator.h +++ b/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_sink_operator.h @@ -32,6 +32,7 @@ class SortedAggregateStreamingSinkOperator : public Operator { bool has_output() const override { return false; } bool need_input() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; @@ -39,6 +40,15 @@ class SortedAggregateStreamingSinkOperator : public Operator { [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +======= + Status set_finishing(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: bool _is_finished = false; diff --git a/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_source_operator.h b/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_source_operator.h index 6aab11ca4fecb..1a606c323d59f 100644 --- a/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_source_operator.h +++ b/be/src/exec/pipeline/aggregate/sorted_aggregate_streaming_source_operator.h @@ -26,12 +26,21 @@ class SortedAggregateStreamingSourceOperator : public SourceOperator { bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status set_finished(RuntimeState* state) override; void close(RuntimeState* state) override; [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; +======= + Status set_finishing(RuntimeState* state) override; + Status set_finished(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: mutable bool _is_finished = false; diff --git a/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_sink_operator.h b/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_sink_operator.h index ebd20c6475eb3..d07b62e607573 100644 --- a/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_sink_operator.h +++ b/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_sink_operator.h @@ -35,12 +35,21 @@ class SpillableAggregateBlockingSinkOperator : public AggregateBlockingSinkOpera bool need_input() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; void close(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +======= + Status set_finishing(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool spillable() const override { return true; } @@ -59,7 +68,11 @@ class SpillableAggregateBlockingSinkOperator : public AggregateBlockingSinkOpera return 0; } +<<<<<<< HEAD [[nodiscard]] Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +======= + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // only the prepare/open phase calls are valid. SpillProcessChannelPtr spill_channel() { return _aggregator->spill_channel(); } @@ -68,11 +81,19 @@ class SpillableAggregateBlockingSinkOperator : public AggregateBlockingSinkOpera bool spilled() const { return _aggregator->spiller()->spilled(); } private: +<<<<<<< HEAD [[nodiscard]] Status _try_to_spill_by_force(RuntimeState* state, const ChunkPtr& chunk); [[nodiscard]] Status _try_to_spill_by_auto(RuntimeState* state, const ChunkPtr& chunk); [[nodiscard]] Status _spill_all_data(RuntimeState* state, bool should_spill_hash_table); +======= + Status _try_to_spill_by_force(RuntimeState* state, const ChunkPtr& chunk); + + Status _try_to_spill_by_auto(RuntimeState* state, const ChunkPtr& chunk); + + Status _spill_all_data(RuntimeState* state, bool should_spill_hash_table); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _add_streaming_chunk(ChunkPtr chunk); @@ -106,7 +127,11 @@ class SpillableAggregateBlockingSinkOperatorFactory : public OperatorFactory { ~SpillableAggregateBlockingSinkOperatorFactory() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override; diff --git a/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_source_operator.h b/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_source_operator.h index 35229debf6185..474ea6ac86924 100644 --- a/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_source_operator.h +++ b/be/src/exec/pipeline/aggregate/spillable_aggregate_blocking_source_operator.h @@ -37,6 +37,7 @@ class SpillableAggregateBlockingSourceOperator final : public AggregateBlockingS bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status set_finished(RuntimeState* state) override; @@ -48,6 +49,19 @@ class SpillableAggregateBlockingSourceOperator final : public AggregateBlockingS private: [[nodiscard]] StatusOr _pull_spilled_chunk(RuntimeState* state); +======= + Status set_finishing(RuntimeState* state) override; + Status set_finished(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; + +private: + StatusOr _pull_spilled_chunk(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _is_finished = false; bool _has_last_chunk = true; @@ -64,7 +78,11 @@ class SpillableAggregateBlockingSourceOperatorFactory final : public SourceOpera ~SpillableAggregateBlockingSourceOperatorFactory() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override; diff --git a/be/src/exec/pipeline/aggregate/spillable_aggregate_distinct_blocking_operator.h b/be/src/exec/pipeline/aggregate/spillable_aggregate_distinct_blocking_operator.h index 857cd3271015b..e553aff83314e 100644 --- a/be/src/exec/pipeline/aggregate/spillable_aggregate_distinct_blocking_operator.h +++ b/be/src/exec/pipeline/aggregate/spillable_aggregate_distinct_blocking_operator.h @@ -35,12 +35,21 @@ class SpillableAggregateDistinctBlockingSinkOperator : public AggregateDistinctB bool need_input() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; void close(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +======= + Status set_finishing(RuntimeState* state) override; + + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool spillable() const override { return true; } void set_execute_mode(int performance_level) override { @@ -64,8 +73,13 @@ class SpillableAggregateDistinctBlockingSinkOperator : public AggregateDistinctB SpillProcessChannelPtr spill_channel() { return _aggregator->spill_channel(); } private: +<<<<<<< HEAD [[nodiscard]] Status _spill_all_inputs(RuntimeState* state, const ChunkPtr& chunk); [[nodiscard]] Status _spill_aggregated_data(RuntimeState* state); +======= + Status _spill_all_inputs(RuntimeState* state, const ChunkPtr& chunk); + Status _spill_aggregated_data(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::function()> _build_spill_task(RuntimeState* state); spill::SpillStrategy _spill_strategy = spill::SpillStrategy::NO_SPILL; @@ -84,7 +98,11 @@ class SpillableAggregateDistinctBlockingSinkOperatorFactory final : public Opera ~SpillableAggregateDistinctBlockingSinkOperatorFactory() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override; @@ -110,11 +128,16 @@ class SpillableAggregateDistinctBlockingSourceOperator : public AggregateDistinc ~SpillableAggregateDistinctBlockingSourceOperator() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool has_output() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finished(RuntimeState* state) override; void close(RuntimeState* state) override; @@ -124,6 +147,17 @@ class SpillableAggregateDistinctBlockingSourceOperator : public AggregateDistinc private: [[nodiscard]] StatusOr _pull_spilled_chunk(RuntimeState* state); +======= + Status set_finished(RuntimeState* state) override; + + void close(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; + +private: + StatusOr _pull_spilled_chunk(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _is_finished = false; bool _has_last_chunk = true; @@ -140,7 +174,11 @@ class SpillableAggregateDistinctBlockingSourceOperatorFactory final : public Sou ~SpillableAggregateDistinctBlockingSourceOperatorFactory() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override; diff --git a/be/src/exec/pipeline/audit_statistics_reporter.cpp b/be/src/exec/pipeline/audit_statistics_reporter.cpp index d0f316c288b1d..3b767e76193b5 100644 --- a/be/src/exec/pipeline/audit_statistics_reporter.cpp +++ b/be/src/exec/pipeline/audit_statistics_reporter.cpp @@ -20,6 +20,7 @@ #include "gen_cpp/FrontendService_types.h" #include "runtime/client_cache.h" #include "runtime/exec_env.h" +<<<<<<< HEAD namespace starrocks::pipeline { @@ -27,6 +28,12 @@ using apache::thrift::TException; using apache::thrift::TProcessor; using apache::thrift::transport::TTransportException; +======= +#include "util/thrift_rpc_helper.h" + +namespace starrocks::pipeline { + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AuditStatisticsReporter::AuditStatisticsReporter() { auto status = ThreadPoolBuilder("audit_report") .set_min_threads(1) @@ -42,6 +49,7 @@ AuditStatisticsReporter::AuditStatisticsReporter() { // including the final status when execution finishes. Status AuditStatisticsReporter::report_audit_statistics(const TReportAuditStatisticsParams& params, ExecEnv* exec_env, const TNetworkAddress& fe_addr) { +<<<<<<< HEAD Status fe_status; FrontendServiceConnection coord(exec_env->frontend_client_cache(), fe_addr, config::thrift_rpc_timeout_ms, &fe_status); @@ -83,6 +91,16 @@ Status AuditStatisticsReporter::report_audit_statistics(const TReportAuditStatis LOG(WARNING) << msg.str(); rpc_status = Status::InternalError(msg.str()); return rpc_status; +======= + TReportAuditStatisticsResult res; + Status rpc_status; + rpc_status = ThriftRpcHelper::rpc( + fe_addr.hostname, fe_addr.port, + [&res, ¶ms](FrontendServiceConnection& client) { client->reportAuditStatistics(res, params); }, + config::thrift_rpc_timeout_ms); + if (rpc_status.ok()) { + rpc_status = Status(res.status); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return rpc_status; } diff --git a/be/src/exec/pipeline/audit_statistics_reporter.h b/be/src/exec/pipeline/audit_statistics_reporter.h index bba5a5735445c..7bff26383f328 100644 --- a/be/src/exec/pipeline/audit_statistics_reporter.h +++ b/be/src/exec/pipeline/audit_statistics_reporter.h @@ -29,7 +29,11 @@ class AuditStatisticsReporter { static Status report_audit_statistics(const TReportAuditStatisticsParams& params, ExecEnv* exec_env, const TNetworkAddress& fe_addr); +<<<<<<< HEAD [[nodiscard]] Status submit(std::function&& report_task); +======= + Status submit(std::function&& report_task); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::unique_ptr _thread_pool; diff --git a/be/src/exec/pipeline/chunk_accumulate_operator.h b/be/src/exec/pipeline/chunk_accumulate_operator.h index 9a8741764e0c5..db5100ed56ac0 100644 --- a/be/src/exec/pipeline/chunk_accumulate_operator.h +++ b/be/src/exec/pipeline/chunk_accumulate_operator.h @@ -45,6 +45,10 @@ class ChunkAccumulateOperator final : public Operator { Status set_finished(RuntimeState* state) override; Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: ChunkPipelineAccumulator _acc; diff --git a/be/src/exec/pipeline/context_with_dependency.h b/be/src/exec/pipeline/context_with_dependency.h index 9946fcc8c7f2a..6f3591adfaa8b 100644 --- a/be/src/exec/pipeline/context_with_dependency.h +++ b/be/src/exec/pipeline/context_with_dependency.h @@ -57,7 +57,11 @@ class ContextWithDependency { } // When the output operator is finished, the context can be finished regardless of other running operators. +<<<<<<< HEAD [[nodiscard]] Status set_finished() { +======= + Status set_finished() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_finished.store(true, std::memory_order_release); return Status::OK(); } diff --git a/be/src/exec/pipeline/exchange/exchange_sink_operator.cpp b/be/src/exec/pipeline/exchange/exchange_sink_operator.cpp index 08ceb2a1194e4..cfd6415dd0f93 100644 --- a/be/src/exec/pipeline/exchange/exchange_sink_operator.cpp +++ b/be/src/exec/pipeline/exchange/exchange_sink_operator.cpp @@ -35,6 +35,10 @@ #include "service/brpc.h" #include "util/compression/block_compression.h" #include "util/compression/compression_utils.h" +<<<<<<< HEAD +======= +#include "util/internal_service_recoverable_stub.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::pipeline { @@ -72,8 +76,13 @@ class ExchangeSinkOperator::Channel { // Channel will sent input request directly without batch it. // This function is only used when broadcast, because request can be reused // by all the channels. +<<<<<<< HEAD [[nodiscard]] Status send_chunk_request(RuntimeState* state, PTransmitChunkParamsPtr chunk_request, const butil::IOBuf& attachment, int64_t attachment_physical_bytes); +======= + Status send_chunk_request(RuntimeState* state, PTransmitChunkParamsPtr chunk_request, + const butil::IOBuf& attachment, int64_t attachment_physical_bytes); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Used when doing shuffle. // This function will copy selective rows in chunks to batch. @@ -118,7 +127,11 @@ class ExchangeSinkOperator::Channel { PassThroughContext _pass_through_context; bool _is_first_chunk = true; +<<<<<<< HEAD PInternalService_Stub* _brpc_stub = nullptr; +======= + std::shared_ptr _brpc_stub = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // If pipeline level shuffle is enable, the size of the _chunks // equals with dop of dest pipeline @@ -316,9 +329,13 @@ Status ExchangeSinkOperator::Channel::_close_internal(RuntimeState* state, Fragm } Status ExchangeSinkOperator::Channel::close(RuntimeState* state, FragmentContext* fragment_ctx) { +<<<<<<< HEAD auto status = _close_internal(state, fragment_ctx); state->log_error(status); // Lock only when status is not ok. return status; +======= + return _close_internal(state, fragment_ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } ExchangeSinkOperator::ExchangeSinkOperator( diff --git a/be/src/exec/pipeline/exchange/local_exchange_sink_operator.h b/be/src/exec/pipeline/exchange/local_exchange_sink_operator.h index 8c89537852487..5a585c0dcd1fd 100644 --- a/be/src/exec/pipeline/exchange/local_exchange_sink_operator.h +++ b/be/src/exec/pipeline/exchange/local_exchange_sink_operator.h @@ -62,6 +62,11 @@ class LocalExchangeSinkOperator final : public Operator { Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: bool _is_finished = false; const std::shared_ptr& _exchanger; diff --git a/be/src/exec/pipeline/exchange/local_exchange_source_operator.h b/be/src/exec/pipeline/exchange/local_exchange_source_operator.h index b81b6ad6be924..7f351cd0cb15c 100644 --- a/be/src/exec/pipeline/exchange/local_exchange_source_operator.h +++ b/be/src/exec/pipeline/exchange/local_exchange_source_operator.h @@ -71,7 +71,11 @@ class LocalExchangeSourceOperator final : public SourceOperator { bool is_finished() const override; Status set_finished(RuntimeState* state) override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override { +======= + Status set_finishing(RuntimeState* state) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(_chunk_lock); _is_finished = true; return Status::OK(); @@ -81,7 +85,11 @@ class LocalExchangeSourceOperator final : public SourceOperator { std::lock_guard l(_chunk_lock); return _is_epoch_finished && _full_chunk_queue.empty() && !_partition_rows_num; } +<<<<<<< HEAD [[nodiscard]] Status set_epoch_finishing(RuntimeState* state) override { +======= + Status set_epoch_finishing(RuntimeState* state) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(_chunk_lock); _is_epoch_finished = true; return Status::OK(); @@ -97,6 +105,10 @@ class LocalExchangeSourceOperator final : public SourceOperator { void enter_release_memory_mode() override; void set_execute_mode(int performance_level) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: ChunkPtr _pull_passthrough_chunk(RuntimeState* state); diff --git a/be/src/exec/pipeline/exchange/mem_limited_chunk_queue.cpp b/be/src/exec/pipeline/exchange/mem_limited_chunk_queue.cpp index 07b03dc9f2791..844d5886e9cae 100644 --- a/be/src/exec/pipeline/exchange/mem_limited_chunk_queue.cpp +++ b/be/src/exec/pipeline/exchange/mem_limited_chunk_queue.cpp @@ -120,7 +120,10 @@ Status MemLimitedChunkQueue::push(const ChunkPtr& chunk) { #ifndef BE_TEST size_t in_memory_rows = _total_accumulated_rows - _flushed_accumulated_rows + _current_load_rows; size_t in_memory_bytes = _total_accumulated_bytes - _flushed_accumulated_bytes + _current_load_bytes; +<<<<<<< HEAD +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _peak_memory_rows_counter->set(in_memory_rows); _peak_memory_bytes_counter->set(in_memory_bytes); #endif diff --git a/be/src/exec/pipeline/exchange/multi_cast_local_exchange_sink_operator.h b/be/src/exec/pipeline/exchange/multi_cast_local_exchange_sink_operator.h index e23641942d7f4..d5e8c9444f3de 100644 --- a/be/src/exec/pipeline/exchange/multi_cast_local_exchange_sink_operator.h +++ b/be/src/exec/pipeline/exchange/multi_cast_local_exchange_sink_operator.h @@ -48,6 +48,11 @@ class MultiCastLocalExchangeSinkOperator : public Operator { void set_execute_mode(int performance_level) override { return _exchanger->enter_release_memory_mode(); } +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: bool _is_finished = false; const std::shared_ptr _exchanger; diff --git a/be/src/exec/pipeline/exchange/multi_cast_local_exchange_source_operator.h b/be/src/exec/pipeline/exchange/multi_cast_local_exchange_source_operator.h index c00d9968f26a4..95a5f02602d96 100644 --- a/be/src/exec/pipeline/exchange/multi_cast_local_exchange_source_operator.h +++ b/be/src/exec/pipeline/exchange/multi_cast_local_exchange_source_operator.h @@ -38,6 +38,11 @@ class MultiCastLocalExchangeSourceOperator final : public SourceOperator { StatusOr pull_chunk(RuntimeState* state) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: bool _is_finished = false; int32_t _mcast_consumer_index; diff --git a/be/src/exec/pipeline/exchange/sink_buffer.cpp b/be/src/exec/pipeline/exchange/sink_buffer.cpp index 854d7f96a64c7..8dfb7239a4cbd 100644 --- a/be/src/exec/pipeline/exchange/sink_buffer.cpp +++ b/be/src/exec/pipeline/exchange/sink_buffer.cpp @@ -17,6 +17,10 @@ #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include "fmt/core.h" @@ -42,6 +46,7 @@ SinkBuffer::SinkBuffer(FragmentContext* fragment_ctx, const std::vector(); _dest_addrs[instance_id.lo] = dest.brpc_server; +======= + if (_sink_ctxs.count(instance_id.lo) == 0) { + _sink_ctxs[instance_id.lo] = std::make_unique(); + auto& ctx = sink_ctx(instance_id.lo); + ctx.num_sinker = 0; + ctx.request_seq = -1; + ctx.max_continuous_acked_seqs = -1; + ctx.num_finished_rpcs = 0; + ctx.num_in_flight_rpcs = 0; + ctx.dest_addrs = dest.brpc_server; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) PUniqueId finst_id; finst_id.set_hi(instance_id.hi); finst_id.set_lo(instance_id.lo); +<<<<<<< HEAD _instance_id2finst_id[instance_id.lo] = std::move(finst_id); +======= + ctx.finst_id = std::move(finst_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } @@ -70,15 +90,26 @@ SinkBuffer::~SinkBuffer() { DCHECK(is_finished()); +<<<<<<< HEAD _buffers.clear(); +======= + _sink_ctxs.clear(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void SinkBuffer::incr_sinker(RuntimeState* state) { _num_uncancelled_sinkers++; +<<<<<<< HEAD for (auto& [_, num_sinkers_per_instance] : _num_sinkers) { num_sinkers_per_instance++; } _num_remaining_eos += _num_sinkers.size(); +======= + for (auto& [_, sink_ctx] : _sink_ctxs) { + sink_ctx->num_sinker++; + } + _num_remaining_eos += _sink_ctxs.size(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status SinkBuffer::add_request(TransmitChunkInfo& request) { @@ -105,7 +136,13 @@ Status SinkBuffer::add_request(TransmitChunkInfo& request) { } auto& instance_id = request.fragment_instance_id; +<<<<<<< HEAD RETURN_IF_ERROR(_try_to_send_rpc(instance_id, [&]() { _buffers[instance_id.lo].push(request); })); +======= + auto& context = sink_ctx(instance_id.lo); + + RETURN_IF_ERROR(_try_to_send_rpc(instance_id, [&]() { context.buffer.push(request); })); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); @@ -115,10 +152,17 @@ bool SinkBuffer::is_full() const { // std::queue' read is concurrent safe without mutex // Judgement may not that accurate because we do not known in advance which // instance the data to be sent corresponds to +<<<<<<< HEAD size_t max_buffer_size = config::pipeline_sink_buffer_size * _buffers.size(); size_t buffer_size = 0; for (auto& [_, buffer] : _buffers) { buffer_size += buffer.size(); +======= + size_t max_buffer_size = config::pipeline_sink_buffer_size * _sink_ctxs.size(); + size_t buffer_size = 0; + for (auto& [_, context] : _sink_ctxs) { + buffer_size += context->buffer.size(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } const bool is_full = buffer_size > max_buffer_size; @@ -195,7 +239,12 @@ void SinkBuffer::update_profile(RuntimeProfile* profile) { int64_t SinkBuffer::_network_time() { int64_t max = 0; +<<<<<<< HEAD for (auto& [_, time_trace] : _network_times) { +======= + for (auto& [_, context] : _sink_ctxs) { + auto& time_trace = context->network_time; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) double average_concurrency = static_cast(time_trace.accumulated_concurrency) / std::max(1, time_trace.times); int64_t average_accumulated_time = @@ -210,6 +259,7 @@ int64_t SinkBuffer::_network_time() { void SinkBuffer::cancel_one_sinker(RuntimeState* const state) { if (--_num_uncancelled_sinkers == 0) { _is_finishing = true; +<<<<<<< HEAD if (state != nullptr && state->query_ctx() && state->query_ctx()->is_query_expired()) { // how many in-flight rpcs and what exchange receivers are. if (_total_in_flight_rpc > 0) { @@ -239,6 +289,12 @@ void SinkBuffer::cancel_one_sinker(RuntimeState* const state) { if (state != nullptr && state->query_ctx() && state->query_ctx()->is_query_expired()) { // check how many cancel operations are issued, and show the state of that time. LOG(INFO) << fmt::format( +======= + } + if (state != nullptr && state->query_ctx() && state->query_ctx()->is_query_expired()) { + // check how many cancel operations are issued, and show the state of that time. + VLOG_OPERATOR << fmt::format( +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) "fragment_instance_id {}, _num_uncancelled_sinkers {}, _is_finishing {}, _num_remaining_eos {}, " "_num_sending_rpc {}, chunk is full {}", print_id(_fragment_ctx->fragment_instance_id()), _num_uncancelled_sinkers, _is_finishing, @@ -248,11 +304,20 @@ void SinkBuffer::cancel_one_sinker(RuntimeState* const state) { void SinkBuffer::_update_network_time(const TUniqueId& instance_id, const int64_t send_timestamp, const int64_t receiver_post_process_time) { +<<<<<<< HEAD const int64_t get_response_timestamp = MonotonicNanos(); _last_receive_time = get_response_timestamp; int32_t concurrency = _num_in_flight_rpcs[instance_id.lo]; int64_t time_usage = get_response_timestamp - send_timestamp - receiver_post_process_time; _network_times[instance_id.lo].update(time_usage, concurrency); +======= + auto& context = sink_ctx(instance_id.lo); + const int64_t get_response_timestamp = MonotonicNanos(); + _last_receive_time = get_response_timestamp; + int32_t concurrency = context.num_in_flight_rpcs; + int64_t time_usage = get_response_timestamp - send_timestamp - receiver_post_process_time; + context.network_time.update(time_usage, concurrency); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _rpc_cumulative_time += time_usage; _rpc_count++; } @@ -263,9 +328,16 @@ void SinkBuffer::_process_send_window(const TUniqueId& instance_id, const int64_ if (!_is_dest_merge) { return; } +<<<<<<< HEAD auto& seqs = _discontinuous_acked_seqs[instance_id.lo]; seqs.insert(sequence); auto& max_continuous_acked_seq = _max_continuous_acked_seqs[instance_id.lo]; +======= + auto& context = sink_ctx(instance_id.lo); + auto& seqs = context.discontinuous_acked_seqs; + seqs.insert(sequence); + auto& max_continuous_acked_seq = context.max_continuous_acked_seqs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::unordered_set::iterator it; while ((it = seqs.find(max_continuous_acked_seq + 1)) != seqs.end()) { seqs.erase(it); @@ -274,7 +346,12 @@ void SinkBuffer::_process_send_window(const TUniqueId& instance_id, const int64_ } Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::function& pre_works) { +<<<<<<< HEAD std::lock_guard l(*_mutexes[instance_id.lo]); +======= + auto& context = sink_ctx(instance_id.lo); + std::lock_guard guard(context.mutex); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pre_works(); DeferOp decrease_defer([this]() { --_num_sending_rpc; }); @@ -285,11 +362,16 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun return Status::OK(); } +<<<<<<< HEAD auto& buffer = _buffers[instance_id.lo]; +======= + auto& buffer = context.buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool too_much_brpc_process = false; if (_is_dest_merge) { // discontinuous_acked_window_size means that we are not received all the ack +<<<<<<< HEAD // with sequence from _max_continuous_acked_seqs[x] to _request_seqs[x] // Limit the size of the window to avoid buffering too much out-of-order data at the receiving side int64_t discontinuous_acked_window_size = @@ -297,6 +379,14 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun too_much_brpc_process = discontinuous_acked_window_size >= config::pipeline_sink_brpc_dop; } else { too_much_brpc_process = _num_in_flight_rpcs[instance_id.lo] >= config::pipeline_sink_brpc_dop; +======= + // with sequence from max_continuous_acked_seqs to request_seqs + // Limit the size of the window to avoid buffering too much out-of-order data at the receiving side + int64_t discontinuous_acked_window_size = context.request_seq - context.max_continuous_acked_seqs; + too_much_brpc_process = discontinuous_acked_window_size >= config::pipeline_sink_brpc_dop; + } else { + too_much_brpc_process = context.num_in_flight_rpcs >= config::pipeline_sink_brpc_dop; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if (buffer.empty() || too_much_brpc_process) { return Status::OK(); @@ -319,7 +409,11 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun // The order of data transmiting in IO level may not be strictly the same as // the order of submitting data packets // But we must guarantee that first packet must be received first +<<<<<<< HEAD if (_num_finished_rpcs[instance_id.lo] == 0 && _num_in_flight_rpcs[instance_id.lo] > 0) { +======= + if (context.num_finished_rpcs == 0 && context.num_in_flight_rpcs > 0) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) need_wait = true; return Status::OK(); } @@ -331,12 +425,20 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun if (--_num_remaining_eos == 0) { _is_finishing = true; } +<<<<<<< HEAD --_num_sinkers[instance_id.lo]; +======= + sink_ctx(instance_id.lo).num_sinker--; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }); // Only the last eos is sent to ExchangeSourceOperator. it must be guaranteed that // eos is the last packet to send to finish the input stream of the corresponding of // ExchangeSourceOperator and eos is sent exactly-once. +<<<<<<< HEAD if (_num_sinkers[instance_id.lo] > 1) { +======= + if (context.num_sinker > 1) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (request.params->chunks_size() == 0) { continue; } else { @@ -346,7 +448,11 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun // The order of data transmiting in IO level may not be strictly the same as // the order of submitting data packets // But we must guarantee that eos packent must be the last packet +<<<<<<< HEAD if (_num_in_flight_rpcs[instance_id.lo] > 0) { +======= + if (context.num_in_flight_rpcs > 0) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) need_wait = true; return Status::OK(); } @@ -357,8 +463,13 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun } } +<<<<<<< HEAD *request.params->mutable_finst_id() = _instance_id2finst_id[instance_id.lo]; request.params->set_sequence(++_request_seqs[instance_id.lo]); +======= + *request.params->mutable_finst_id() = context.finst_id; + request.params->set_sequence(++context.request_seq); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!request.attachment.empty()) { _bytes_sent += request.attachment.size(); @@ -374,6 +485,7 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun closure->addFailedHandler([this](const ClosureContext& ctx, std::string_view rpc_error_msg) noexcept { auto defer = DeferOp([this]() { --_total_in_flight_rpc; }); _is_finishing = true; +<<<<<<< HEAD { std::lock_guard l(*_mutexes[ctx.instance_id.lo]); ++_num_finished_rpcs[ctx.instance_id.lo]; @@ -381,6 +493,13 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun } const auto& dest_addr = _dest_addrs[ctx.instance_id.lo]; +======= + auto& context = sink_ctx(ctx.instance_id.lo); + ++context.num_finished_rpcs; + --context.num_in_flight_rpcs; + + const auto& dest_addr = context.dest_addrs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string err_msg = fmt::format("transmit chunk rpc failed [dest_instance_id={}] [dest={}:{}] detail:{}", print_id(ctx.instance_id), dest_addr.hostname, dest_addr.port, rpc_error_msg); @@ -392,16 +511,27 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun // when _total_in_flight_rpc desc to 0, _fragment_ctx may be destructed auto defer = DeferOp([this]() { --_total_in_flight_rpc; }); Status status(result.status()); +<<<<<<< HEAD { std::lock_guard l(*_mutexes[ctx.instance_id.lo]); ++_num_finished_rpcs[ctx.instance_id.lo]; --_num_in_flight_rpcs[ctx.instance_id.lo]; } +======= + auto& context = sink_ctx(ctx.instance_id.lo); + ++context.num_finished_rpcs; + --context.num_in_flight_rpcs; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!status.ok()) { _is_finishing = true; _fragment_ctx->cancel(status); +<<<<<<< HEAD const auto& dest_addr = _dest_addrs[ctx.instance_id.lo]; +======= + const auto& dest_addr = context.dest_addrs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) LOG(WARNING) << fmt::format("transmit chunk rpc failed [dest_instance_id={}] [dest={}:{}] [msg={}]", print_id(ctx.instance_id), dest_addr.hostname, dest_addr.port, status.message()); @@ -414,7 +544,11 @@ Status SinkBuffer::_try_to_send_rpc(const TUniqueId& instance_id, const std::fun }); ++_total_in_flight_rpc; +<<<<<<< HEAD ++_num_in_flight_rpcs[instance_id.lo]; +======= + ++context.num_in_flight_rpcs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Attachment will be released by process_mem_tracker in closure->Run() in bthread, when receiving the response, // so decrease the memory usage of attachment from instance_mem_tracker immediately before sending the request. diff --git a/be/src/exec/pipeline/exchange/sink_buffer.h b/be/src/exec/pipeline/exchange/sink_buffer.h index a6925934f4774..f7c7ee7645911 100644 --- a/be/src/exec/pipeline/exchange/sink_buffer.h +++ b/be/src/exec/pipeline/exchange/sink_buffer.h @@ -19,6 +19,10 @@ #include #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -33,6 +37,10 @@ #include "util/brpc_stub_cache.h" #include "util/defer_op.h" #include "util/disposable_closure.h" +<<<<<<< HEAD +======= +#include "util/internal_service_recoverable_stub.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/phmap/phmap.h" namespace starrocks::pipeline { @@ -49,7 +57,11 @@ struct TransmitChunkInfo { // a same exchange source fragment instance, so we should use fragment_instance_id // of the destination as the key of destination instead of channel_id. TUniqueId fragment_instance_id; +<<<<<<< HEAD PInternalService_Stub* brpc_stub; +======= + std::shared_ptr brpc_stub; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) PTransmitChunkParamsPtr params; butil::IOBuf attachment; int64_t attachment_physical_bytes; @@ -111,7 +123,11 @@ class SinkBuffer { // Try to send rpc if buffer is not empty and channel is not busy // And we need to put this function and other extra works(pre_works) together as an atomic operation +<<<<<<< HEAD [[nodiscard]] Status _try_to_send_rpc(const TUniqueId& instance_id, const std::function& pre_works); +======= + Status _try_to_send_rpc(const TUniqueId& instance_id, const std::function& pre_works); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // send by rpc or http Status _send_rpc(DisposableClosure* closure, const TransmitChunkInfo& req); @@ -133,6 +149,7 @@ class SinkBuffer { /// use int64_t as key, which is the field type of TUniqueId::lo /// because TUniqueId::hi is exactly the same in one query +<<<<<<< HEAD // num eos per instance phmap::flat_hash_map> _num_sinkers; phmap::flat_hash_map> _request_seqs; @@ -144,10 +161,42 @@ class SinkBuffer { // c. receive response-2, _max_continuous_acked_seqs[x]->3, _discontinuous_acked_seqs[x]->() phmap::flat_hash_map> _max_continuous_acked_seqs; phmap::flat_hash_map, StdHash> _discontinuous_acked_seqs; +======= + struct SinkContext { + // num eos per instance + int64_t num_sinker; + int64_t request_seq; + // Considering the following situation + // Sending request 1, 2, 3 in order with one possible order of response 1, 3, 2, + // and field transformation are as following + // a. receive response-1, _max_continuous_acked_seqs[x]->1, _discontinuous_acked_seqs[x]->() + // b. receive response-3, _max_continuous_acked_seqs[x]->1, _discontinuous_acked_seqs[x]->(3) + // c. receive response-2, _max_continuous_acked_seqs[x]->3, _discontinuous_acked_seqs[x]->() + int64_t max_continuous_acked_seqs; + std::unordered_set discontinuous_acked_seqs; + // The request needs the reference to the allocated finst id, + // so cache finst id for each dest fragment instance. + PUniqueId finst_id; + std::queue> buffer; + Mutex request_mutex; + + std::atomic_size_t num_finished_rpcs; + std::atomic_size_t num_in_flight_rpcs; + TimeTrace network_time; + + Mutex mutex; + + TNetworkAddress dest_addrs; + }; + phmap::flat_hash_map, StdHash> _sink_ctxs; + SinkContext& sink_ctx(int64_t instance_id) { return *_sink_ctxs[instance_id]; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::atomic _total_in_flight_rpc = 0; std::atomic _num_uncancelled_sinkers = 0; std::atomic _num_remaining_eos = 0; +<<<<<<< HEAD // The request needs the reference to the allocated finst id, // so cache finst id for each dest fragment instance. phmap::flat_hash_map> _instance_id2finst_id; @@ -159,6 +208,8 @@ class SinkBuffer { phmap::flat_hash_map, StdHash> _mutexes; phmap::flat_hash_map> _dest_addrs; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // True means that SinkBuffer needn't input chunk and send chunk anymore, // but there may be still in-flight RPC running. // It becomes true, when all sinkers have sent EOS, or been set_finished/cancelled, or RPC has returned error. diff --git a/be/src/exec/pipeline/exec_state_reporter.cpp b/be/src/exec/pipeline/exec_state_reporter.cpp index f6ddb3d9e5d65..868268f905da7 100644 --- a/be/src/exec/pipeline/exec_state_reporter.cpp +++ b/be/src/exec/pipeline/exec_state_reporter.cpp @@ -24,6 +24,10 @@ #include "runtime/exec_env.h" #include "service/backend_options.h" #include "util/network_util.h" +<<<<<<< HEAD +======= +#include "util/thrift_rpc_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::pipeline { std::string to_load_error_http_path(const std::string& file_name) { @@ -137,10 +141,13 @@ std::unique_ptr ExecStateReporter::create_report_exec_s params.sink_commit_infos.push_back(info); } } +<<<<<<< HEAD // Send new errors to coordinator runtime_state->get_unreported_errors(&(params.error_log)); params.__isset.error_log = (params.error_log.size() > 0); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } auto backend_id = get_backend_id(); @@ -150,6 +157,7 @@ std::unique_ptr ExecStateReporter::create_report_exec_s return res; } +<<<<<<< HEAD using apache::thrift::TException; using apache::thrift::TProcessor; using apache::thrift::transport::TTransportException; @@ -200,6 +208,22 @@ Status ExecStateReporter::report_exec_status(const TReportExecStatusParams& para rpc_status = Status::InternalError(msg.str()); return rpc_status; } +======= +// including the final status when execution finishes. +Status ExecStateReporter::report_exec_status(const TReportExecStatusParams& params, ExecEnv* exec_env, + const TNetworkAddress& fe_addr) { + TReportExecStatusResult res; + Status rpc_status; + + rpc_status = ThriftRpcHelper::rpc( + fe_addr, [&res, ¶ms](FrontendServiceConnection& client) { client->reportExecStatus(res, params); }, + config::thrift_rpc_timeout_ms); + + if (rpc_status.ok()) { + rpc_status = Status(res.status); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return rpc_status; } @@ -273,6 +297,7 @@ TMVMaintenanceTasks ExecStateReporter::create_report_epoch_params(const QueryCon Status ExecStateReporter::report_epoch(const TMVMaintenanceTasks& params, ExecEnv* exec_env, const TNetworkAddress& fe_addr) { Status fe_status; +<<<<<<< HEAD FrontendServiceConnection coord(exec_env->frontend_client_cache(), fe_addr, config::thrift_rpc_timeout_ms, &fe_status); if (!fe_status.ok()) { @@ -313,6 +338,15 @@ Status ExecStateReporter::report_epoch(const TMVMaintenanceTasks& params, ExecEn LOG(WARNING) << msg.str(); rpc_status = Status::InternalError(msg.str()); } +======= + TMVReportEpochResponse res; + Status rpc_status; + + rpc_status = ThriftRpcHelper::rpc( + fe_addr, [&res, ¶ms](FrontendServiceConnection& client) { client->mvReport(res, params); }, + config::thrift_rpc_timeout_ms); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return rpc_status; } diff --git a/be/src/exec/pipeline/fragment_context.cpp b/be/src/exec/pipeline/fragment_context.cpp index d09e740ffb701..55638029bea60 100644 --- a/be/src/exec/pipeline/fragment_context.cpp +++ b/be/src/exec/pipeline/fragment_context.cpp @@ -21,6 +21,10 @@ #include "exec/pipeline/pipeline_driver_executor.h" #include "exec/pipeline/stream_pipeline_driver.h" #include "exec/workgroup/work_group.h" +<<<<<<< HEAD +======= +#include "runtime/batch_write/batch_write_mgr.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/client_cache.h" #include "runtime/data_stream_mgr.h" #include "runtime/exec_env.h" @@ -35,6 +39,10 @@ namespace starrocks::pipeline { FragmentContext::FragmentContext() : _data_sink(nullptr) {} FragmentContext::~FragmentContext() { +<<<<<<< HEAD +======= + _close_stream_load_contexts(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _data_sink.reset(); _runtime_filter_hub.close_all_in_filters(_runtime_state.get()); close_all_execution_groups(); @@ -181,6 +189,7 @@ void FragmentContext::set_final_status(const Status& status) { if (_s_status.is_cancelled()) { auto detailed_message = _s_status.detailed_message(); +<<<<<<< HEAD std::stringstream ss; ss << "[Driver] Canceled, query_id=" << print_id(_query_id) << ", instance_id=" << print_id(_fragment_instance_id) << ", reason=" << detailed_message; @@ -188,6 +197,16 @@ void FragmentContext::set_final_status(const Status& status) { LOG(INFO) << ss.str(); } else { LOG(WARNING) << ss.str(); +======= + std::string cancel_msg = + fmt::format("[Driver] Canceled, query_id={}, instance_id={}, reason={}", print_id(_query_id), + print_id(_fragment_instance_id), detailed_message); + if (detailed_message == "QueryFinished" || detailed_message == "LimitReach" || + detailed_message == "UserCancel" || detailed_message == "TimeOut") { + LOG(INFO) << cancel_msg; + } else { + LOG(WARNING) << cancel_msg; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } const auto* executors = _workgroup != nullptr @@ -196,6 +215,15 @@ void FragmentContext::set_final_status(const Status& status) { auto* executor = executors->driver_executor(); iterate_drivers([executor](const DriverPtr& driver) { executor->cancel(driver.get()); }); } +<<<<<<< HEAD +======= + + for (const auto& stream_load_context : _stream_load_contexts) { + if (stream_load_context->body_sink) { + stream_load_context->body_sink->cancel(_s_status); + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -217,7 +245,10 @@ Status FragmentContext::prepare_all_pipelines() { void FragmentContext::set_stream_load_contexts(const std::vector& contexts) { _stream_load_contexts = std::move(contexts); +<<<<<<< HEAD _channel_stream_load = true; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void FragmentContext::cancel(const Status& status) { @@ -234,6 +265,7 @@ void FragmentContext::cancel(const Status& status) { query_options.load_job_type == TLoadJobType::INSERT_VALUES)) { ExecEnv::GetInstance()->profile_report_worker()->unregister_pipeline_load(_query_id, _fragment_instance_id); } +<<<<<<< HEAD if (_stream_load_contexts.size() > 0) { for (const auto& stream_load_context : _stream_load_contexts) { @@ -247,6 +279,8 @@ void FragmentContext::cancel(const Status& status) { } _stream_load_contexts.resize(0); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } FragmentContext* FragmentContextManager::get_or_register(const TUniqueId& fragment_id) { @@ -311,6 +345,7 @@ void FragmentContextManager::unregister(const TUniqueId& fragment_id) { ExecEnv::GetInstance()->profile_report_worker()->unregister_pipeline_load(it->second->query_id(), fragment_id); } +<<<<<<< HEAD const auto& stream_load_contexts = it->second->_stream_load_contexts; if (stream_load_contexts.size() > 0) { @@ -326,6 +361,8 @@ void FragmentContextManager::unregister(const TUniqueId& fragment_id) { } it->second->_stream_load_contexts.resize(0); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _fragment_contexts.erase(it); } } @@ -409,4 +446,22 @@ Status FragmentContext::submit_active_drivers(DriverExecutor* executor) { return Status::OK(); } +<<<<<<< HEAD +======= +void FragmentContext::acquire_runtime_filters() { + iterate_pipeline([this](Pipeline* pipeline) { pipeline->acquire_runtime_filter(this->runtime_state()); }); +} + +void FragmentContext::_close_stream_load_contexts() { + for (const auto& context : _stream_load_contexts) { + context->body_sink->cancel(Status::Cancelled("Close the stream load pipe")); + if (context->enable_batch_write) { + _runtime_state->exec_env()->batch_write_mgr()->unregister_stream_load_pipe(context); + } else { + _runtime_state->exec_env()->stream_context_mgr()->remove_channel_context(context); + } + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/fragment_context.h b/be/src/exec/pipeline/fragment_context.h index 9b1d79fab4caf..6b9b218357610 100644 --- a/be/src/exec/pipeline/fragment_context.h +++ b/be/src/exec/pipeline/fragment_context.h @@ -141,7 +141,11 @@ class FragmentContext { bool enable_resource_group() const { return _workgroup != nullptr; } // STREAM MV +<<<<<<< HEAD [[nodiscard]] Status reset_epoch(); +======= + Status reset_epoch(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_is_stream_pipeline(bool is_stream_pipeline) { _is_stream_pipeline = is_stream_pipeline; } bool is_stream_pipeline() const { return _is_stream_pipeline; } void count_down_epoch_pipeline(RuntimeState* state, size_t val = 1); @@ -171,7 +175,16 @@ class FragmentContext { void set_report_when_finish(bool report) { _report_when_finish = report; } +<<<<<<< HEAD private: +======= + // acquire runtime filter from cache + void acquire_runtime_filters(); + +private: + void _close_stream_load_contexts(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _enable_group_execution = false; // Id of this query TUniqueId _query_id; @@ -209,7 +222,10 @@ class FragmentContext { query_cache::CacheParam _cache_param; bool _enable_cache = false; std::vector _stream_load_contexts; +<<<<<<< HEAD bool _channel_stream_load = false; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // STREAM MV std::atomic _num_finished_epoch_pipelines = 0; @@ -246,7 +262,11 @@ class FragmentContextManager { FragmentContext* get_or_register(const TUniqueId& fragment_id); FragmentContextPtr get(const TUniqueId& fragment_id); +<<<<<<< HEAD [[nodiscard]] Status register_ctx(const TUniqueId& fragment_id, FragmentContextPtr fragment_ctx); +======= + Status register_ctx(const TUniqueId& fragment_id, FragmentContextPtr fragment_ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void unregister(const TUniqueId& fragment_id); void cancel(const Status& status); diff --git a/be/src/exec/pipeline/fragment_executor.cpp b/be/src/exec/pipeline/fragment_executor.cpp index 29a435b400dba..871830839f9a6 100644 --- a/be/src/exec/pipeline/fragment_executor.cpp +++ b/be/src/exec/pipeline/fragment_executor.cpp @@ -22,6 +22,10 @@ #include "exec/cross_join_node.h" #include "exec/exchange_node.h" #include "exec/exec_node.h" +<<<<<<< HEAD +======= +#include "exec/hash_join_node.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/multi_olap_table_sink.h" #include "exec/olap_scan_node.h" #include "exec/pipeline/adaptive/event.h" @@ -38,6 +42,10 @@ #include "exec/workgroup/work_group.h" #include "gutil/casts.h" #include "gutil/map_util.h" +<<<<<<< HEAD +======= +#include "runtime/batch_write/batch_write_mgr.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/data_stream_mgr.h" #include "runtime/data_stream_sender.h" #include "runtime/descriptors.h" @@ -141,6 +149,13 @@ Status FragmentExecutor::_prepare_query_ctx(ExecEnv* exec_env, const UnifiedExec } _query_ctx->set_query_trace(std::make_shared(query_id, enable_query_trace)); +<<<<<<< HEAD +======= + if (request.common().__isset.exec_stats_node_ids) { + _query_ctx->init_node_exec_stats(request.common().exec_stats_node_ids); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -156,6 +171,10 @@ Status FragmentExecutor::_prepare_fragment_ctx(const UnifiedExecPlanFragmentPara _fragment_ctx->set_fragment_instance_id(fragment_instance_id); _fragment_ctx->set_fe_addr(coord); _fragment_ctx->set_is_stream_pipeline(is_stream_pipeline); +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (request.common().__isset.adaptive_dop_param) { _fragment_ctx->set_enable_adaptive_dop(true); const auto& tadaptive_dop_param = request.common().adaptive_dop_param; @@ -164,6 +183,14 @@ Status FragmentExecutor::_prepare_fragment_ctx(const UnifiedExecPlanFragmentPara adaptive_dop_param.max_output_amplification_factor = tadaptive_dop_param.max_output_amplification_factor; } +<<<<<<< HEAD +======= + if (request.common().__isset.pred_tree_params) { + const auto& tpred_tree_params = request.common().pred_tree_params; + _fragment_ctx->set_pred_tree_params({tpred_tree_params.enable_or, tpred_tree_params.enable_show_in_profile}); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -358,6 +385,56 @@ static std::unordered_set collect_broadcast_join_right_offsprings( return offsprings; } +<<<<<<< HEAD +======= +// there will be partition values used by this batch of scan ranges and maybe following scan ranges +// so before process this batch of scan ranges, we have to put partition values into the table associated with. +static Status add_scan_ranges_partition_values(RuntimeState* runtime_state, + const std::vector& scan_ranges) { + auto* obj_pool = runtime_state->obj_pool(); + const DescriptorTbl& desc_tbl = runtime_state->desc_tbl(); + TTableId cache_table_id = -1; + TableDescriptor* table = nullptr; + + for (const auto& scan_range_params : scan_ranges) { + const TScanRange& scan_range = scan_range_params.scan_range; + if (!scan_range.__isset.hdfs_scan_range) continue; + const THdfsScanRange& hdfs_scan_range = scan_range.hdfs_scan_range; + if (!hdfs_scan_range.__isset.partition_value) continue; + DCHECK(hdfs_scan_range.__isset.table_id); + DCHECK(hdfs_scan_range.__isset.partition_id); + TTableId table_id = hdfs_scan_range.table_id; + if (table_id != cache_table_id) { + table = desc_tbl.get_table_descriptor(table_id); + cache_table_id = table_id; + } + if (table == nullptr) continue; + // only HiveTableDescriptor(includes hive,iceberg,hudi,deltalake etc) supports this feature. + HiveTableDescriptor* hive_table = down_cast(table); + RETURN_IF_ERROR(hive_table->add_partition_value(runtime_state, obj_pool, hdfs_scan_range.partition_id, + hdfs_scan_range.partition_value)); + } + return Status::OK(); +} + +static Status add_per_driver_scan_ranges_partition_values(RuntimeState* runtime_state, + const PerDriverScanRangesMap& map) { + for (const auto& [_, scan_ranges] : map) { + RETURN_IF_ERROR(add_scan_ranges_partition_values(runtime_state, scan_ranges)); + } + return Status::OK(); +} + +static bool has_more_per_driver_seq_scan_ranges(const PerDriverScanRangesMap& map) { + bool has_more = false; + for (const auto& [_, scan_ranges] : map) { + has_more |= ScanMorsel::has_more_scan_ranges(scan_ranges); + if (has_more) return has_more; + } + return has_more; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status FragmentExecutor::_prepare_exec_plan(ExecEnv* exec_env, const UnifiedExecPlanFragmentParams& request) { auto* runtime_state = _fragment_ctx->runtime_state(); auto* obj_pool = runtime_state->obj_pool(); @@ -424,6 +501,13 @@ Status FragmentExecutor::_prepare_exec_plan(ExecEnv* exec_env, const UnifiedExec cache_param.force_populate = tcache_param.force_populate; cache_param.entry_max_bytes = tcache_param.entry_max_bytes; cache_param.entry_max_rows = tcache_param.entry_max_rows; +<<<<<<< HEAD +======= + if (tcache_param.__isset.is_lake) { + cache_param.is_lake = tcache_param.is_lake; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto& [slot, remapped_slot] : tcache_param.slot_remapping) { cache_param.slot_remapping[slot] = remapped_slot; cache_param.reverse_slot_remapping[remapped_slot] = slot; @@ -483,11 +567,24 @@ Status FragmentExecutor::_prepare_exec_plan(ExecEnv* exec_env, const UnifiedExec enable_shared_scan = false; } +<<<<<<< HEAD +======= + RETURN_IF_ERROR(add_scan_ranges_partition_values(runtime_state, scan_ranges)); + RETURN_IF_ERROR(add_per_driver_scan_ranges_partition_values(runtime_state, scan_ranges_per_driver_seq)); + bool has_more_morsel = ScanMorsel::has_more_scan_ranges(scan_ranges) || + has_more_per_driver_seq_scan_ranges(scan_ranges_per_driver_seq); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ASSIGN_OR_RETURN(auto morsel_queue_factory, scan_node->convert_scan_range_to_morsel_queue_factory( scan_ranges, scan_ranges_per_driver_seq, scan_node->id(), group_execution_scan_dop, _is_in_colocate_exec_group(scan_node->id()), enable_tablet_internal_parallel, +<<<<<<< HEAD tablet_internal_parallel_mode)); +======= + tablet_internal_parallel_mode, enable_shared_scan)); + morsel_queue_factory->set_has_more(has_more_morsel); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) scan_node->enable_shared_scan(enable_shared_scan && morsel_queue_factory->is_shared()); morsel_queue_factories.emplace(scan_node->id(), std::move(morsel_queue_factory)); } @@ -555,6 +652,24 @@ Status FragmentExecutor::_prepare_stream_load_pipe(ExecEnv* exec_env, const Unif return Status::OK(); } std::vector stream_load_contexts; +<<<<<<< HEAD +======= + + bool success = false; + DeferOp defer_op([&] { + if (!success) { + for (auto& ctx : stream_load_contexts) { + ctx->body_sink->cancel(Status::Cancelled("Failed to prepare stream load pipe")); + if (ctx->enable_batch_write) { + exec_env->batch_write_mgr()->unregister_stream_load_pipe(ctx); + } else { + exec_env->stream_context_mgr()->remove_channel_context(ctx); + } + } + } + }); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (; iter != scan_range_map.end(); iter++) { for (; iter2 != iter->second.end(); iter2++) { for (const auto& scan_range : iter2->second) { @@ -566,6 +681,7 @@ Status FragmentExecutor::_prepare_stream_load_pipe(ExecEnv* exec_env, const Unif TFileFormatType::type format = broker_scan_range.ranges[0].format_type; TUniqueId load_id = broker_scan_range.ranges[0].load_id; long txn_id = broker_scan_range.params.txn_id; +<<<<<<< HEAD StreamLoadContext* ctx = nullptr; RETURN_IF_ERROR(exec_env->stream_context_mgr()->create_channel_context( exec_env, label, channel_id, db_name, table_name, format, ctx, load_id, txn_id)); @@ -575,10 +691,35 @@ Status FragmentExecutor::_prepare_stream_load_pipe(ExecEnv* exec_env, const Unif } }); RETURN_IF_ERROR(exec_env->stream_context_mgr()->put_channel_context(label, channel_id, ctx)); +======= + bool is_batch_write = + broker_scan_range.__isset.enable_batch_write && broker_scan_range.enable_batch_write; + StreamLoadContext* ctx = nullptr; + if (is_batch_write) { + ASSIGN_OR_RETURN(ctx, BatchWriteMgr::create_and_register_pipe( + exec_env, exec_env->batch_write_mgr(), db_name, table_name, + broker_scan_range.batch_write_parameters, label, txn_id, load_id, + broker_scan_range.batch_write_interval_ms)); + } else { + RETURN_IF_ERROR(exec_env->stream_context_mgr()->create_channel_context( + exec_env, label, channel_id, db_name, table_name, format, ctx, load_id, txn_id)); + DeferOp op([&] { + if (ctx->unref()) { + delete ctx; + } + }); + RETURN_IF_ERROR(exec_env->stream_context_mgr()->put_channel_context(label, channel_id, ctx)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) stream_load_contexts.push_back(ctx); } } } +<<<<<<< HEAD +======= + + success = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _fragment_ctx->set_stream_load_contexts(stream_load_contexts); return Status::OK(); } @@ -822,6 +963,10 @@ Status FragmentExecutor::execute(ExecEnv* exec_env) { { SCOPED_TIMER(prepare_instance_timer); SCOPED_TIMER(prepare_driver_timer); +<<<<<<< HEAD +======= + _fragment_ctx->acquire_runtime_filters(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_fragment_ctx->prepare_active_drivers()); } prepare_success = true; @@ -846,4 +991,67 @@ void FragmentExecutor::_fail_cleanup(bool fragment_has_registed) { } } +<<<<<<< HEAD +======= +Status FragmentExecutor::append_incremental_scan_ranges(ExecEnv* exec_env, const TExecPlanFragmentParams& request) { + DCHECK(!request.__isset.fragment); + DCHECK(request.__isset.params); + const TPlanFragmentExecParams& params = request.params; + const TUniqueId& query_id = params.query_id; + const TUniqueId& instance_id = params.fragment_instance_id; + + QueryContextPtr query_ctx = exec_env->query_context_mgr()->get(query_id); + if (query_ctx == nullptr) return Status::OK(); + FragmentContextPtr fragment_ctx = query_ctx->fragment_mgr()->get(instance_id); + if (fragment_ctx == nullptr) return Status::OK(); + RuntimeState* runtime_state = fragment_ctx->runtime_state(); + + for (const auto& [node_id, scan_ranges] : params.per_node_scan_ranges) { + if (scan_ranges.size() == 0) continue; + auto iter = fragment_ctx->morsel_queue_factories().find(node_id); + if (iter == fragment_ctx->morsel_queue_factories().end()) { + continue; + } + MorselQueueFactory* morsel_queue_factory = iter->second.get(); + if (morsel_queue_factory == nullptr) { + continue; + } + + RETURN_IF_ERROR(add_scan_ranges_partition_values(runtime_state, scan_ranges)); + pipeline::Morsels morsels; + bool has_more_morsel = false; + pipeline::ScanMorsel::build_scan_morsels(node_id, scan_ranges, true, &morsels, &has_more_morsel); + RETURN_IF_ERROR(morsel_queue_factory->append_morsels(0, std::move(morsels))); + morsel_queue_factory->set_has_more(has_more_morsel); + } + + if (params.__isset.node_to_per_driver_seq_scan_ranges) { + UnifiedExecPlanFragmentParams uf_request{request, request}; + for (const auto& [node_id, per_driver_scan_ranges] : params.node_to_per_driver_seq_scan_ranges) { + auto iter = fragment_ctx->morsel_queue_factories().find(node_id); + if (iter == fragment_ctx->morsel_queue_factories().end()) { + continue; + } + MorselQueueFactory* morsel_queue_factory = iter->second.get(); + if (morsel_queue_factory == nullptr) { + continue; + } + + bool has_more_morsel = has_more_per_driver_seq_scan_ranges(per_driver_scan_ranges); + for (const auto& [driver_seq, scan_ranges] : per_driver_scan_ranges) { + if (scan_ranges.size() == 0) continue; + RETURN_IF_ERROR(add_scan_ranges_partition_values(runtime_state, scan_ranges)); + pipeline::Morsels morsels; + [[maybe_unused]] bool local_has_more; + pipeline::ScanMorsel::build_scan_morsels(node_id, scan_ranges, true, &morsels, &local_has_more); + RETURN_IF_ERROR(morsel_queue_factory->append_morsels(driver_seq, std::move(morsels))); + } + morsel_queue_factory->set_has_more(has_more_morsel); + } + } + + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/fragment_executor.h b/be/src/exec/pipeline/fragment_executor.h index fd9faf899a25d..3631e1af756e5 100644 --- a/be/src/exec/pipeline/fragment_executor.h +++ b/be/src/exec/pipeline/fragment_executor.h @@ -105,6 +105,11 @@ class FragmentExecutor { const TExecPlanFragmentParams& unique_request); Status execute(ExecEnv* exec_env); +<<<<<<< HEAD +======= + static Status append_incremental_scan_ranges(ExecEnv* exec_env, const TExecPlanFragmentParams& request); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: void _fail_cleanup(bool fragment_has_registed); uint32_t _calc_dop(ExecEnv* exec_env, const UnifiedExecPlanFragmentParams& request) const; diff --git a/be/src/exec/pipeline/hash_partition_context.cpp b/be/src/exec/pipeline/hash_partition_context.cpp index 5a0d91045a709..3afa8f63a6ebe 100644 --- a/be/src/exec/pipeline/hash_partition_context.cpp +++ b/be/src/exec/pipeline/hash_partition_context.cpp @@ -38,7 +38,13 @@ Status HashPartitionContext::prepare(RuntimeState* state, RuntimeProfile* profil } _acc.set_max_size(state->chunk_size()); +<<<<<<< HEAD _chunks_partitioner = std::make_unique(_has_nullable_key, _partition_exprs, _partition_types); +======= + _mem_pool = std::make_unique(); + _chunks_partitioner = + std::make_unique(_has_nullable_key, _partition_exprs, _partition_types, _mem_pool.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return _chunks_partitioner->prepare(state, profile); } @@ -47,6 +53,10 @@ Status HashPartitionContext::push_one_chunk_to_partitioner(RuntimeState* state, } void HashPartitionContext::sink_complete() { +<<<<<<< HEAD +======= + _mem_pool.reset(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_sink_complete = true; } diff --git a/be/src/exec/pipeline/hash_partition_context.h b/be/src/exec/pipeline/hash_partition_context.h index 1d9af24ffc353..aaf14d5c2a48e 100644 --- a/be/src/exec/pipeline/hash_partition_context.h +++ b/be/src/exec/pipeline/hash_partition_context.h @@ -59,6 +59,10 @@ class HashPartitionContext { bool _is_sink_complete = false; ChunksPartitionerPtr _chunks_partitioner; +<<<<<<< HEAD +======= + std::unique_ptr _mem_pool; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkPipelineAccumulator _acc; }; diff --git a/be/src/exec/pipeline/hashjoin/hash_join_build_operator.cpp b/be/src/exec/pipeline/hashjoin/hash_join_build_operator.cpp index 316f3ac4c9191..98d99af132f03 100644 --- a/be/src/exec/pipeline/hashjoin/hash_join_build_operator.cpp +++ b/be/src/exec/pipeline/hashjoin/hash_join_build_operator.cpp @@ -17,11 +17,20 @@ #include #include +<<<<<<< HEAD +======= +#include "exec/hash_joiner.h" +#include "exec/pipeline/hashjoin/hash_joiner_factory.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/query_context.h" #include "exprs/runtime_filter_bank.h" #include "runtime/current_thread.h" #include "runtime/runtime_filter_worker.h" #include "util/race_detect.h" +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::pipeline { HashJoinBuildOperator::HashJoinBuildOperator(OperatorFactory* factory, int32_t id, const string& name, @@ -55,7 +64,11 @@ Status HashJoinBuildOperator::prepare(RuntimeState* state) { } void HashJoinBuildOperator::close(RuntimeState* state) { COUNTER_SET(_join_builder->build_metrics().hash_table_memory_usage, +<<<<<<< HEAD _join_builder->hash_join_builder()->hash_table_mem_usage()); +======= + _join_builder->hash_join_builder()->ht_mem_usage()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _join_builder->unref(state); Operator::close(state); @@ -107,15 +120,27 @@ Status HashJoinBuildOperator::set_finishing(RuntimeState* state) { ((HashJoinBuildOperatorFactory*)_factory) ->retain_string_key_columns(_driver_sequence, _join_builder->string_key_columns()); +<<<<<<< HEAD +======= + if (partial_bloom_filters.size() != partial_bloom_filter_build_params.size()) { + // if in short-circuit mode, phase is EOS. partial_bloom_filter_build_params is empty. + DCHECK(_join_builder->is_done()); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // push colocate partial runtime filter bool is_colocate_runtime_filter = runtime_filter_hub()->is_colocate_runtime_filters(_plan_node_id); if (is_colocate_runtime_filter) { // init local colocate in/bloom filters RuntimeInFilterList in_filter_lists(partial_in_filters.begin(), partial_in_filters.end()); +<<<<<<< HEAD if (partial_bloom_filters.size() != partial_bloom_filter_build_params.size()) { // if in short-circuit mode, phase is EOS. partial_bloom_filter_build_params is empty. DCHECK(_join_builder->is_done()); } else { +======= + if (partial_bloom_filters.size() == partial_bloom_filter_build_params.size()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < partial_bloom_filters.size(); ++i) { if (partial_bloom_filter_build_params[i].has_value()) { partial_bloom_filters[i]->set_or_concat(partial_bloom_filter_build_params[i]->runtime_filter.get(), @@ -167,6 +192,13 @@ Status HashJoinBuildOperator::set_finishing(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD +======= +bool HashJoinBuildOperator::is_finished() const { + return _is_finished || _join_builder->is_finished(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) HashJoinBuildOperatorFactory::HashJoinBuildOperatorFactory( int32_t id, int32_t plan_node_id, HashJoinerFactoryPtr hash_joiner_factory, std::unique_ptr&& partial_rf_merger, diff --git a/be/src/exec/pipeline/hashjoin/hash_join_build_operator.h b/be/src/exec/pipeline/hashjoin/hash_join_build_operator.h index 5d7443585cd73..2c478e3da145c 100644 --- a/be/src/exec/pipeline/hashjoin/hash_join_build_operator.h +++ b/be/src/exec/pipeline/hashjoin/hash_join_build_operator.h @@ -18,12 +18,22 @@ #include +<<<<<<< HEAD #include "exec/hash_joiner.h" #include "exec/pipeline/hashjoin/hash_joiner_factory.h" #include "exec/pipeline/operator.h" #include "exec/pipeline/pipeline_fwd.h" #include "exprs/expr.h" #include "runtime/descriptors.h" +======= +#include "exec/pipeline/hashjoin/hash_joiner_fwd.h" +#include "exec/pipeline/operator.h" +#include "exec/pipeline/pipeline_fwd.h" +#include "exec/pipeline/spill_process_channel.h" +#include "exprs/expr.h" +#include "runtime/descriptors.h" +#include "util/race_detect.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::pipeline { @@ -48,7 +58,11 @@ class HashJoinBuildOperator : public Operator { bool need_input() const override { return !is_finished(); } Status set_finishing(RuntimeState* state) override; +<<<<<<< HEAD bool is_finished() const override { return _is_finished || _join_builder->is_finished(); } +======= + bool is_finished() const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; StatusOr pull_chunk(RuntimeState* state) override; @@ -58,6 +72,10 @@ class HashJoinBuildOperator : public Operator { } size_t output_amplification_factor() const override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: HashJoinerPtr _join_builder; diff --git a/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.cpp b/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.cpp index f3ca5ce906afd..9919c2874bce5 100644 --- a/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.cpp +++ b/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.cpp @@ -14,6 +14,11 @@ #include "exec/pipeline/hashjoin/hash_join_probe_operator.h" +<<<<<<< HEAD +======= +#include "exec/hash_joiner.h" +#include "exec/pipeline/hashjoin/hash_joiner_factory.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/current_thread.h" namespace starrocks::pipeline { @@ -58,7 +63,11 @@ bool HashJoinProbeOperator::need_input() const { return true; } +<<<<<<< HEAD if (_join_prober != _join_builder && is_ready()) { +======= + if (is_ready()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // If hasn't referenced hash table, return true to reference hash table in push_chunk. return !_join_prober->has_referenced_hash_table(); } @@ -80,10 +89,18 @@ Status HashJoinProbeOperator::push_chunk(RuntimeState* state, const ChunkPtr& ch } StatusOr HashJoinProbeOperator::pull_chunk(RuntimeState* state) { +<<<<<<< HEAD +======= + RETURN_IF_ERROR(_reference_builder_hash_table_once()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return _join_prober->pull_chunk(state); } Status HashJoinProbeOperator::set_finishing(RuntimeState* state) { +<<<<<<< HEAD +======= + RETURN_IF_ERROR(_join_prober->probe_input_finished(state)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _join_prober->enter_post_probe_phase(); return Status::OK(); } @@ -95,12 +112,15 @@ Status HashJoinProbeOperator::set_finished(RuntimeState* state) { } Status HashJoinProbeOperator::_reference_builder_hash_table_once() { +<<<<<<< HEAD // non-broadcast join directly return as _join_prober == _join_builder, // but broadcast should refer to the shared join builder if (_join_prober == _join_builder) { return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!is_ready()) { return Status::OK(); } @@ -124,6 +144,25 @@ Status HashJoinProbeOperator::reset_state(RuntimeState* state, const vectorquery_ctx(); + if (ctx != nullptr) { + ctx->update_pull_rows_stats(_plan_node_id, _pull_row_num_counter->value()); + if (_conjuncts_input_counter != nullptr && _conjuncts_output_counter != nullptr) { + ctx->update_pred_filter_stats(_plan_node_id, + _conjuncts_input_counter->value() - _conjuncts_output_counter->value()); + } + if (_bloom_filter_eval_context.join_runtime_filter_input_counter != nullptr) { + int64_t input_rows = _bloom_filter_eval_context.join_runtime_filter_input_counter->value(); + int64_t output_rows = _bloom_filter_eval_context.join_runtime_filter_output_counter->value(); + ctx->update_rf_filter_stats(_plan_node_id, input_rows - output_rows); + } + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) HashJoinProbeOperatorFactory::HashJoinProbeOperatorFactory(int32_t id, int32_t plan_node_id, HashJoinerFactoryPtr hash_joiner_factory) : OperatorFactory(id, "hash_join_probe", plan_node_id), _hash_joiner_factory(std::move(hash_joiner_factory)) {} diff --git a/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.h b/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.h index 9d26193336874..c9e010f6d7294 100644 --- a/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.h +++ b/be/src/exec/pipeline/hashjoin/hash_join_probe_operator.h @@ -14,8 +14,12 @@ #pragma once +<<<<<<< HEAD #include "exec/hash_joiner.h" #include "exec/pipeline/hashjoin/hash_joiner_factory.h" +======= +#include "exec/pipeline/hashjoin/hash_joiner_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/operator.h" #include "exec/pipeline/operator_with_dependency.h" #include "exec/pipeline/pipeline_fwd.h" @@ -51,6 +55,10 @@ class HashJoinProbeOperator : public OperatorWithDependency { StatusOr pull_chunk(RuntimeState* state) override; Status reset_state(starrocks::RuntimeState* state, const std::vector& refill_chunks) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: /// Reference the read-only hash table from builder in the first pull_chunk. diff --git a/be/src/exec/pipeline/hashjoin/hash_joiner_fwd.h b/be/src/exec/pipeline/hashjoin/hash_joiner_fwd.h new file mode 100644 index 0000000000000..089643478fe5b --- /dev/null +++ b/be/src/exec/pipeline/hashjoin/hash_joiner_fwd.h @@ -0,0 +1,31 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +namespace starrocks { +static inline constexpr size_t kHashJoinKeyColumnOffset = 1; +class HashJoiner; +class JoinHashTable; +using HashJoinerPtr = std::shared_ptr; +class HashJoinBuilder; + +namespace pipeline { +class HashJoinerFactory; +using HashJoinerFactoryPtr = std::shared_ptr; +} // namespace pipeline + +} // namespace starrocks diff --git a/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.cpp b/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.cpp index 49e31c596b44d..fe0cb385c26aa 100644 --- a/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.cpp +++ b/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.cpp @@ -20,9 +20,18 @@ #include "column/column_helper.h" #include "column/vectorized_fwd.h" #include "common/statusor.h" +<<<<<<< HEAD #include "exec/hash_join_node.h" #include "exec/join_hash_map.h" #include "exec/pipeline/hashjoin/hash_join_build_operator.h" +======= +#include "exec/hash_join_components.h" +#include "exec/hash_join_node.h" +#include "exec/hash_joiner.h" +#include "exec/join_hash_map.h" +#include "exec/pipeline/hashjoin/hash_join_build_operator.h" +#include "exec/pipeline/hashjoin/hash_joiner_factory.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/query_context.h" #include "exec/spill/options.h" #include "exec/spill/spiller.h" @@ -54,13 +63,21 @@ void SpillableHashJoinBuildOperator::close(RuntimeState* state) { size_t SpillableHashJoinBuildOperator::estimated_memory_reserved(const ChunkPtr& chunk) { if (chunk && !chunk->is_empty()) { +<<<<<<< HEAD return chunk->memory_usage() + _join_builder->hash_join_builder()->hash_table().mem_usage(); +======= + return chunk->memory_usage() + _join_builder->hash_join_builder()->ht_mem_usage(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return 0; } size_t SpillableHashJoinBuildOperator::estimated_memory_reserved() { +<<<<<<< HEAD return _join_builder->hash_join_builder()->hash_table().mem_usage() * 2; +======= + return _join_builder->hash_join_builder()->ht_mem_usage() * 2; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } bool SpillableHashJoinBuildOperator::need_input() const { @@ -72,8 +89,12 @@ Status SpillableHashJoinBuildOperator::set_finishing(RuntimeState* state) { auto defer_set_finishing = DeferOp([this]() { _join_builder->spill_channel()->set_finishing(); }); if (spill_strategy() == spill::SpillStrategy::NO_SPILL || +<<<<<<< HEAD (!_join_builder->spiller()->spilled() && _join_builder->hash_join_builder()->hash_table().get_row_count() == 0)) { +======= + (!_join_builder->spiller()->spilled() && _join_builder->hash_join_builder()->hash_table_row_count() == 0)) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return HashJoinBuildOperator::set_finishing(state); } @@ -83,10 +104,15 @@ Status SpillableHashJoinBuildOperator::set_finishing(RuntimeState* state) { if (!_join_builder->spiller()->spilled()) { DCHECK(_is_first_time_spill); _is_first_time_spill = false; +<<<<<<< HEAD auto& ht = _join_builder->hash_join_builder()->hash_table(); RETURN_IF_ERROR(init_spiller_partitions(state, ht)); _hash_table_slice_iterator = _convert_hash_map_to_chunk(); +======= + RETURN_IF_ERROR(init_spiller_partitions(state, _join_builder->hash_join_builder())); + ASSIGN_OR_RETURN(_hash_table_slice_iterator, _convert_hash_map_to_chunk()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_join_builder->append_spill_task(state, _hash_table_slice_iterator)); } @@ -173,10 +199,18 @@ Status SpillableHashJoinBuildOperator::append_hash_columns(const ChunkPtr& chunk return Status::OK(); } +<<<<<<< HEAD Status SpillableHashJoinBuildOperator::init_spiller_partitions(RuntimeState* state, JoinHashTable& ht) { if (ht.get_row_count() > 0) { // We estimate the size of the hash table to be twice the size of the already input hash table auto num_partitions = ht.mem_usage() * 2 / _join_builder->spiller()->options().spill_mem_table_bytes_size; +======= +Status SpillableHashJoinBuildOperator::init_spiller_partitions(RuntimeState* state, HashJoinBuilder* builder) { + if (builder->hash_table_row_count() > 0) { + // We estimate the size of the hash table to be twice the size of the already input hash table + auto num_partitions = + builder->ht_mem_usage() * 2 / _join_builder->spiller()->options().spill_mem_table_bytes_size; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _join_builder->spiller()->set_partition(state, num_partitions); } return Status::OK(); @@ -188,7 +222,11 @@ bool SpillableHashJoinBuildOperator::is_finished() const { Status SpillableHashJoinBuildOperator::push_chunk(RuntimeState* state, const ChunkPtr& chunk) { DeferOp update_revocable_bytes{ +<<<<<<< HEAD [this]() { set_revocable_mem_bytes(_join_builder->hash_join_builder()->hash_table().mem_usage()); }}; +======= + [this]() { set_revocable_mem_bytes(_join_builder->hash_join_builder()->ht_mem_usage()); }}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (spill_strategy() == spill::SpillStrategy::NO_SPILL) { return HashJoinBuildOperator::push_chunk(state, chunk); @@ -198,6 +236,7 @@ Status SpillableHashJoinBuildOperator::push_chunk(RuntimeState* state, const Chu return Status::OK(); } +<<<<<<< HEAD auto& ht = _join_builder->hash_join_builder()->hash_table(); // Estimate the appropriate number of partitions if (_is_first_time_spill) { @@ -205,13 +244,25 @@ Status SpillableHashJoinBuildOperator::push_chunk(RuntimeState* state, const Chu } ASSIGN_OR_RETURN(auto spill_chunk, ht.convert_to_spill_schema(chunk)); +======= + // Estimate the appropriate number of partitions + if (_is_first_time_spill) { + RETURN_IF_ERROR(init_spiller_partitions(state, _join_builder->hash_join_builder())); + } + + auto spill_chunk = _join_builder->hash_join_builder()->convert_to_spill_schema(chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(append_hash_columns(spill_chunk)); RETURN_IF_ERROR(_join_builder->append_chunk_to_spill_buffer(state, spill_chunk)); if (_is_first_time_spill) { _is_first_time_spill = false; +<<<<<<< HEAD _hash_table_slice_iterator = _convert_hash_map_to_chunk(); +======= + ASSIGN_OR_RETURN(_hash_table_slice_iterator, _convert_hash_map_to_chunk()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_join_builder->append_spill_task(state, _hash_table_slice_iterator)); } @@ -224,6 +275,7 @@ void SpillableHashJoinBuildOperator::set_execute_mode(int performance_level) { } } +<<<<<<< HEAD std::function()> SpillableHashJoinBuildOperator::_convert_hash_map_to_chunk() { auto build_chunk = _join_builder->hash_join_builder()->hash_table().get_build_chunk(); DCHECK_GT(build_chunk->num_rows(), 0); @@ -239,6 +291,49 @@ std::function()> SpillableHashJoinBuildOperator::_convert_has return Status::EndOfFile("eos"); } auto chunk = _hash_table_build_chunk_slice.cutoff(runtime_state()->chunk_size()); +======= +void SpillableHashJoinBuildOperator::set_spill_strategy(spill::SpillStrategy strategy) { + _join_builder->set_spill_strategy(strategy); +} + +spill::SpillStrategy SpillableHashJoinBuildOperator::spill_strategy() const { + return _join_builder->spill_strategy(); +} + +StatusOr()>> SpillableHashJoinBuildOperator::_convert_hash_map_to_chunk() { + _hash_tables.clear(); + _hash_table_iterate_idx = 0; + + _join_builder->hash_join_builder()->visitHt([this](JoinHashTable* ht) { _hash_tables.push_back(ht); }); + + for (auto* ht : _hash_tables) { + auto build_chunk = ht->get_build_chunk(); + DCHECK_GT(build_chunk->num_rows(), 0); + RETURN_IF_ERROR(build_chunk->upgrade_if_overflow()); + } + + _hash_table_build_chunk_slice.reset(_hash_tables[_hash_table_iterate_idx]->get_build_chunk()); + _hash_table_build_chunk_slice.skip(kHashJoinKeyColumnOffset); + + return [this]() -> StatusOr { + if (_hash_table_build_chunk_slice.empty()) { + _hash_table_iterate_idx++; + for (; _hash_table_iterate_idx < _hash_tables.size(); _hash_table_iterate_idx++) { + auto build_chunk = _hash_tables[_hash_table_iterate_idx]->get_build_chunk(); + if (build_chunk->num_rows() > 0) { + _hash_table_build_chunk_slice.reset(build_chunk); + _hash_table_build_chunk_slice.skip(kHashJoinKeyColumnOffset); + break; + } + } + if (_hash_table_build_chunk_slice.empty()) { + _join_builder->hash_join_builder()->reset(_join_builder->hash_table_param()); + return Status::EndOfFile("eos"); + } + } + + ChunkPtr chunk = _hash_table_build_chunk_slice.cutoff(runtime_state()->chunk_size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(chunk->downgrade()); RETURN_IF_ERROR(append_hash_columns(chunk)); _join_builder->update_build_rows(chunk->num_rows()); diff --git a/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.h b/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.h index 59170004d8d9d..2b5b0743ded7f 100644 --- a/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.h +++ b/be/src/exec/pipeline/hashjoin/spillable_hash_join_build_operator.h @@ -20,12 +20,21 @@ #include #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exec/pipeline/hashjoin/hash_join_build_operator.h" +======= +#include "exec/join_hash_map.h" +#include "exec/pipeline/hashjoin/hash_join_build_operator.h" +#include "exec/pipeline/hashjoin/hash_joiner_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/spill/spiller.h" #include "exprs/expr_context.h" namespace starrocks::pipeline { +<<<<<<< HEAD +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class SpillableHashJoinBuildOperator final : public HashJoinBuildOperator { public: template @@ -52,6 +61,7 @@ class SpillableHashJoinBuildOperator final : public HashJoinBuildOperator { size_t estimated_memory_reserved() override; private: +<<<<<<< HEAD void set_spill_strategy(spill::SpillStrategy strategy) { _join_builder->set_spill_strategy(strategy); } spill::SpillStrategy spill_strategy() const { return _join_builder->spill_strategy(); } @@ -63,6 +73,21 @@ class SpillableHashJoinBuildOperator final : public HashJoinBuildOperator { Status init_spiller_partitions(RuntimeState* state, JoinHashTable& ht); +======= + void set_spill_strategy(spill::SpillStrategy strategy); + spill::SpillStrategy spill_strategy() const; + + StatusOr()>> _convert_hash_map_to_chunk(); + + Status publish_runtime_filters(RuntimeState* state); + + Status append_hash_columns(const ChunkPtr& chunk); + + Status init_spiller_partitions(RuntimeState* state, HashJoinBuilder* builder); + + size_t _hash_table_iterate_idx = 0; + std::vector _hash_tables; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkSharedSlice _hash_table_build_chunk_slice; std::function()> _hash_table_slice_iterator; bool _is_first_time_spill = true; diff --git a/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.cpp b/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.cpp index bf6bace124eef..7a3ea71e02df5 100644 --- a/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.cpp +++ b/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.cpp @@ -22,8 +22,13 @@ #include "common/config.h" #include "exec/hash_joiner.h" +<<<<<<< HEAD #include "exec/join_hash_map.h" #include "exec/pipeline/hashjoin/hash_join_probe_operator.h" +======= +#include "exec/pipeline/hashjoin/hash_join_probe_operator.h" +#include "exec/pipeline/hashjoin/hash_joiner_factory.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/query_context.h" #include "exec/spill/executor.h" #include "exec/spill/partition.h" @@ -253,8 +258,14 @@ Status SpillableHashJoinProbeOperator::_load_partition_build_side(workgroup::Yie TRY_CATCH_ALLOC_SCOPE_START() SCOPED_THREAD_LOCAL_MEM_TRACKER_SETTER(state->instance_mem_tracker()); auto builder = _builders[idx]; +<<<<<<< HEAD bool finish = false; int64_t hash_table_mem_usage = builder->hash_table_mem_usage(); +======= + auto prober = _probers[idx]; + bool finish = false; + int64_t hash_table_mem_usage = builder->ht_mem_usage(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) enum SpillLoadPartitionStage { BEGIN = 0, FINISH = 1 }; ctx.total_yield_point_cnt = FINISH; auto wg = ctx.wg; @@ -272,10 +283,18 @@ Status SpillableHashJoinProbeOperator::_load_partition_build_side(workgroup::Yie if (chunk_st.ok() && chunk_st.value() != nullptr && !chunk_st.value()->is_empty()) { int64_t old_mem_usage = hash_table_mem_usage; RETURN_IF_ERROR(builder->append_chunk(std::move(chunk_st.value()))); +<<<<<<< HEAD hash_table_mem_usage = builder->hash_table_mem_usage(); COUNTER_ADD(metrics.build_partition_peak_memory_usage, hash_table_mem_usage - old_mem_usage); } else if (chunk_st.status().is_end_of_file()) { RETURN_IF_ERROR(builder->build(state)); +======= + hash_table_mem_usage = builder->ht_mem_usage(); + COUNTER_ADD(metrics.build_partition_peak_memory_usage, hash_table_mem_usage - old_mem_usage); + } else if (chunk_st.status().is_end_of_file()) { + RETURN_IF_ERROR(builder->build(state)); + prober->attach(builder, _join_prober->probe_metrics()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) finish = true; } else if (!chunk_st.ok()) { return chunk_st.status(); @@ -414,7 +433,11 @@ StatusOr SpillableHashJoinProbeOperator::pull_chunk(RuntimeState* stat // probe chunk for (size_t i = 0; i < _probers.size(); ++i) { if (!_probers[i]->probe_chunk_empty()) { +<<<<<<< HEAD ASSIGN_OR_RETURN(auto res, _probers[i]->probe_chunk(state, &_builders[i]->hash_table())); +======= + ASSIGN_OR_RETURN(auto res, _probers[i]->probe_chunk(state)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return res; } } @@ -426,8 +449,12 @@ StatusOr SpillableHashJoinProbeOperator::pull_chunk(RuntimeState* stat for (size_t i = 0; i < _probers.size(); ++i) { if (!_probe_post_eofs[i] && _probe_read_eofs[i]) { bool has_remain = false; +<<<<<<< HEAD ASSIGN_OR_RETURN(auto res, _probers[i]->probe_remain(state, &_builders[i]->hash_table(), &has_remain)); +======= + ASSIGN_OR_RETURN(auto res, _probers[i]->probe_remain(state, &has_remain)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _probe_post_eofs[i] = !has_remain; if (res && !res->is_empty()) { return res; @@ -458,6 +485,13 @@ StatusOr SpillableHashJoinProbeOperator::pull_chunk(RuntimeState* stat return nullptr; } +<<<<<<< HEAD +======= +bool SpillableHashJoinProbeOperator::spilled() const { + return _join_builder->spiller()->spilled(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void SpillableHashJoinProbeOperator::_acquire_next_partitions() { // get all spill partition if (_build_partitions.empty()) { diff --git a/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.h b/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.h index 7d90358164e97..918f480ca5dc9 100644 --- a/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.h +++ b/be/src/exec/pipeline/hashjoin/spillable_hash_join_probe_operator.h @@ -17,7 +17,10 @@ #include #include #include +<<<<<<< HEAD #include +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -26,6 +29,11 @@ #include "exec/hash_join_components.h" #include "exec/pipeline/hashjoin/hash_join_probe_operator.h" #include "exec/spill/partition.h" +<<<<<<< HEAD +======= +#include "exec/spill/spill_components.h" +#include "exec/spill/spiller_factory.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/runtime_state.h" #include "util/runtime_profile.h" @@ -79,7 +87,11 @@ class SpillableHashJoinProbeOperator final : public HashJoinProbeOperator { void set_probe_spiller(std::shared_ptr spiller) { _probe_spiller = std::move(spiller); } private: +<<<<<<< HEAD bool spilled() const { return _join_builder->spiller()->spilled(); } +======= + bool spilled() const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SpillableHashJoinProbeOperator* as_mutable() const { return const_cast(this); } diff --git a/be/src/exec/pipeline/limit_operator.cpp b/be/src/exec/pipeline/limit_operator.cpp index 570658cce8163..89c0644ecc789 100644 --- a/be/src/exec/pipeline/limit_operator.cpp +++ b/be/src/exec/pipeline/limit_operator.cpp @@ -15,6 +15,10 @@ #include "exec/pipeline/limit_operator.h" #include "column/chunk.h" +<<<<<<< HEAD +======= +#include "exec/pipeline/query_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/runtime_state.h" namespace starrocks::pipeline { @@ -40,4 +44,24 @@ Status LimitOperator::push_chunk(RuntimeState* state, const ChunkPtr& chunk) { return Status::OK(); } +<<<<<<< HEAD +======= +void LimitOperator::update_exec_stats(RuntimeState* state) { + auto ctx = state->query_ctx(); + if (!_is_subordinate && ctx != nullptr) { + ctx->force_set_pull_rows_stats(_plan_node_id, _pull_row_num_counter->value()); + if (_conjuncts_input_counter != nullptr && _conjuncts_output_counter != nullptr) { + ctx->update_pred_filter_stats(_plan_node_id, + _conjuncts_input_counter->value() - _conjuncts_output_counter->value()); + } + + if (_bloom_filter_eval_context.join_runtime_filter_input_counter != nullptr) { + int64_t input_rows = _bloom_filter_eval_context.join_runtime_filter_input_counter->value(); + int64_t output_rows = _bloom_filter_eval_context.join_runtime_filter_output_counter->value(); + ctx->update_rf_filter_stats(_plan_node_id, input_rows - output_rows); + } + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/limit_operator.h b/be/src/exec/pipeline/limit_operator.h index 1c08c40c5b342..6a5031984d16f 100644 --- a/be/src/exec/pipeline/limit_operator.h +++ b/be/src/exec/pipeline/limit_operator.h @@ -42,6 +42,11 @@ class LimitOperator final : public Operator { Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: bool _is_finished = false; std::atomic& _limit; diff --git a/be/src/exec/pipeline/nljoin/nljoin_build_operator.h b/be/src/exec/pipeline/nljoin/nljoin_build_operator.h index 24ce48a181683..92e00f4c268da 100644 --- a/be/src/exec/pipeline/nljoin/nljoin_build_operator.h +++ b/be/src/exec/pipeline/nljoin/nljoin_build_operator.h @@ -49,6 +49,10 @@ class NLJoinBuildOperator : public Operator { OutputAmplificationType intra_pipeline_amplification_type() const override; size_t output_amplification_factor() const override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::atomic _is_finished = false; diff --git a/be/src/exec/pipeline/nljoin/nljoin_context.cpp b/be/src/exec/pipeline/nljoin/nljoin_context.cpp index ac6fb844b5f1c..b27a14ebb6e2c 100644 --- a/be/src/exec/pipeline/nljoin/nljoin_context.cpp +++ b/be/src/exec/pipeline/nljoin/nljoin_context.cpp @@ -188,7 +188,11 @@ void NLJoinContext::_notify_runtime_filter_collector(RuntimeState* state) { std::make_unique(RuntimeInFilterList{}, RuntimeBloomFilterList{})); } +<<<<<<< HEAD bool NLJoinContext::finish_probe(int32_t driver_seq, const std::vector& build_match_flags) { +======= +bool NLJoinContext::finish_probe(int32_t driver_seq, const Filter& build_match_flags) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard guard(_join_stage_mutex); ++_num_post_probers; @@ -210,7 +214,11 @@ bool NLJoinContext::finish_probe(int32_t driver_seq, const std::vector& return is_last; } +<<<<<<< HEAD const std::vector NLJoinContext::get_shared_build_match_flag() const { +======= +const Filter NLJoinContext::get_shared_build_match_flag() const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(_num_post_probers, _num_left_probers) << "all probers should share their states"; std::lock_guard guard(_join_stage_mutex); return _shared_build_match_flag; diff --git a/be/src/exec/pipeline/nljoin/nljoin_context.h b/be/src/exec/pipeline/nljoin/nljoin_context.h index 7c0bbaf0c13f9..6fa70b4228b3d 100644 --- a/be/src/exec/pipeline/nljoin/nljoin_context.h +++ b/be/src/exec/pipeline/nljoin/nljoin_context.h @@ -177,9 +177,15 @@ class NLJoinContext final : public ContextWithDependency { bool is_right_finished() const { return _all_right_finished.load(std::memory_order_acquire); } // Return true if it's the last prober, which need to perform the right join task +<<<<<<< HEAD bool finish_probe(int32_t driver_seq, const std::vector& build_match_flags); const std::vector get_shared_build_match_flag() const; +======= + bool finish_probe(int32_t driver_seq, const Filter& build_match_flags); + + const Filter get_shared_build_match_flag() const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const SpillProcessChannelFactoryPtr& spill_channel_factory() { return _spill_process_factory_ptr; } NLJoinBuildChunkStreamBuilder& builder() { return _build_stream_builder; } @@ -206,7 +212,11 @@ class NLJoinContext final : public ContextWithDependency { std::vector _build_chunks; // Normalized chunks of _input_chunks int _build_chunk_desired_size = 0; int _num_post_probers = 0; +<<<<<<< HEAD std::vector _shared_build_match_flag; +======= + Filter _shared_build_match_flag; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // conjuncts in cross join, used for generate runtime_filter std::vector _rf_conjuncts_ctx; diff --git a/be/src/exec/pipeline/nljoin/nljoin_probe_operator.cpp b/be/src/exec/pipeline/nljoin/nljoin_probe_operator.cpp index b8e3b48549f1f..fd96b1fbef20d 100644 --- a/be/src/exec/pipeline/nljoin/nljoin_probe_operator.cpp +++ b/be/src/exec/pipeline/nljoin/nljoin_probe_operator.cpp @@ -548,7 +548,11 @@ void NLJoinProbeOperator::_permute_left_join(const ChunkPtr& chunk, size_t probe // Permute build side for right join Status NLJoinProbeOperator::_permute_right_join(size_t chunk_size) { +<<<<<<< HEAD const std::vector& build_match_flag = _cross_join_context->get_shared_build_match_flag(); +======= + const Filter& build_match_flag = _cross_join_context->get_shared_build_match_flag(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!SIMD::contain_zero(build_match_flag)) { return Status::OK(); } @@ -697,6 +701,26 @@ Status NLJoinProbeOperator::push_chunk(RuntimeState* state, const ChunkPtr& chun return Status::OK(); } +<<<<<<< HEAD +======= +void NLJoinProbeOperator::update_exec_stats(RuntimeState* state) { + auto ctx = state->query_ctx(); + if (ctx != nullptr) { + ctx->update_pull_rows_stats(_plan_node_id, _pull_row_num_counter->value()); + if (_conjuncts_input_counter != nullptr && _conjuncts_output_counter != nullptr) { + ctx->update_pred_filter_stats(_plan_node_id, + _conjuncts_input_counter->value() - _conjuncts_output_counter->value()); + } + + if (_bloom_filter_eval_context.join_runtime_filter_input_counter != nullptr) { + int64_t input_rows = _bloom_filter_eval_context.join_runtime_filter_input_counter->value(); + int64_t output_rows = _bloom_filter_eval_context.join_runtime_filter_output_counter->value(); + ctx->update_rf_filter_stats(_plan_node_id, input_rows - output_rows); + } + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void NLJoinProbeOperatorFactory::_init_row_desc() { for (auto& tuple_desc : _left_row_desc.tuple_descriptors()) { for (auto& slot : tuple_desc->slots()) { diff --git a/be/src/exec/pipeline/nljoin/nljoin_probe_operator.h b/be/src/exec/pipeline/nljoin/nljoin_probe_operator.h index f4d48af831834..5884c57314945 100644 --- a/be/src/exec/pipeline/nljoin/nljoin_probe_operator.h +++ b/be/src/exec/pipeline/nljoin/nljoin_probe_operator.h @@ -59,6 +59,10 @@ class NLJoinProbeOperator final : public OperatorWithDependency { Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: enum JoinStage { @@ -123,7 +127,11 @@ class NLJoinProbeOperator final : public OperatorWithDependency { size_t _prev_chunk_start = 0; size_t _prev_chunk_size = 0; size_t _build_row_current = 0; +<<<<<<< HEAD mutable std::vector _self_build_match_flag; +======= + mutable Filter _self_build_match_flag; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Probe states ChunkPtr _probe_chunk = nullptr; @@ -167,7 +175,11 @@ class NLJoinProbeOperatorFactory final : public OperatorWithDependencyFactory { const RowDescriptor& _left_row_desc; const RowDescriptor& _right_row_desc; +<<<<<<< HEAD Buffer _col_types; +======= + std::vector _col_types; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t _probe_column_count = 0; size_t _build_column_count = 0; diff --git a/be/src/exec/pipeline/nljoin/spillable_nljoin_probe_operator.h b/be/src/exec/pipeline/nljoin/spillable_nljoin_probe_operator.h index a8c2bfc287cee..30e2b3f77ba7e 100644 --- a/be/src/exec/pipeline/nljoin/spillable_nljoin_probe_operator.h +++ b/be/src/exec/pipeline/nljoin/spillable_nljoin_probe_operator.h @@ -177,7 +177,11 @@ class SpillableNLJoinProbeOperatorFactory final : public OperatorWithDependencyF const RowDescriptor& _left_row_desc; const RowDescriptor& _right_row_desc; +<<<<<<< HEAD Buffer _col_types; +======= + std::vector _col_types; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t _probe_column_count = 0; size_t _build_column_count = 0; diff --git a/be/src/exec/pipeline/operator.cpp b/be/src/exec/pipeline/operator.cpp index bf2390fa6d903..44e9a5a38a828 100644 --- a/be/src/exec/pipeline/operator.cpp +++ b/be/src/exec/pipeline/operator.cpp @@ -275,6 +275,27 @@ void Operator::_init_conjuct_counters() { } } +<<<<<<< HEAD +======= +void Operator::update_exec_stats(RuntimeState* state) { + auto ctx = state->query_ctx(); + if (!_is_subordinate && ctx != nullptr && ctx->need_record_exec_stats(_plan_node_id)) { + ctx->update_push_rows_stats(_plan_node_id, _push_row_num_counter->value()); + ctx->update_pull_rows_stats(_plan_node_id, _pull_row_num_counter->value()); + if (_conjuncts_input_counter != nullptr && _conjuncts_output_counter != nullptr) { + ctx->update_pred_filter_stats(_plan_node_id, + _conjuncts_input_counter->value() - _conjuncts_output_counter->value()); + } + if (_bloom_filter_eval_context.join_runtime_filter_input_counter != nullptr && + _bloom_filter_eval_context.join_runtime_filter_output_counter != nullptr) { + int64_t input_rows = _bloom_filter_eval_context.join_runtime_filter_input_counter->value(); + int64_t output_rows = _bloom_filter_eval_context.join_runtime_filter_output_counter->value(); + ctx->update_rf_filter_stats(_plan_node_id, input_rows - output_rows); + } + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) OperatorFactory::OperatorFactory(int32_t id, std::string name, int32_t plan_node_id) : _id(id), _name(std::move(name)), _plan_node_id(plan_node_id) { std::string upper_name(_name); @@ -290,6 +311,7 @@ Status OperatorFactory::prepare(RuntimeState* state) { if (_runtime_filter_collector) { // TODO(hcf) no proper profile for rf_filter_collector attached to RETURN_IF_ERROR(_runtime_filter_collector->prepare(state, _runtime_profile.get())); +<<<<<<< HEAD auto& descriptors = _runtime_filter_collector->get_rf_probe_collector()->descriptors(); for (auto& [filter_id, desc] : descriptors) { if (desc->is_local() || desc->runtime_filter(-1) != nullptr) { @@ -306,6 +328,9 @@ Status OperatorFactory::prepare(RuntimeState* state) { desc->set_shared_runtime_filter(grf); } +======= + acquire_runtime_filter(state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } @@ -368,4 +393,29 @@ bool OperatorFactory::has_topn_filter() const { return global_rf_collector != nullptr && global_rf_collector->has_topn_filter(); } +<<<<<<< HEAD +======= +void OperatorFactory::acquire_runtime_filter(RuntimeState* state) { + if (_runtime_filter_collector == nullptr) { + return; + } + auto& descriptors = _runtime_filter_collector->get_rf_probe_collector()->descriptors(); + for (auto& [filter_id, desc] : descriptors) { + if (desc->is_local() || desc->runtime_filter(-1) != nullptr) { + continue; + } + auto grf = state->exec_env()->runtime_filter_cache()->get(state->query_id(), filter_id); + ExecEnv::GetInstance()->add_rf_event({state->query_id(), filter_id, BackendOptions::get_localhost(), + strings::Substitute("INSTALL_GRF_TO_OPERATOR(op_id=$0, success=$1", + this->_plan_node_id, grf != nullptr)}); + + if (grf == nullptr) { + continue; + } + + desc->set_shared_runtime_filter(grf); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/operator.h b/be/src/exec/pipeline/operator.h index b913d0a2fce15..8ccf6a9c345c5 100644 --- a/be/src/exec/pipeline/operator.h +++ b/be/src/exec/pipeline/operator.h @@ -267,6 +267,11 @@ class Operator { // apply operation for each child operator virtual void for_each_child_operator(const std::function& apply) {} +<<<<<<< HEAD +======= + virtual void update_exec_stats(RuntimeState* state); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: OperatorFactory* _factory; const int32_t _id; @@ -403,6 +408,12 @@ class OperatorFactory { // Whether it has any runtime filter built by TopN node. bool has_topn_filter() const; +<<<<<<< HEAD +======= + // try to get runtime filter from cache + void acquire_runtime_filter(RuntimeState* state); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: void _prepare_runtime_in_filters(RuntimeState* state); void _prepare_runtime_holders(const std::vector& holders, diff --git a/be/src/exec/pipeline/pipeline.h b/be/src/exec/pipeline/pipeline.h index 7348501f574c4..8c3c766f34b08 100644 --- a/be/src/exec/pipeline/pipeline.h +++ b/be/src/exec/pipeline/pipeline.h @@ -80,6 +80,15 @@ class Pipeline { } } +<<<<<<< HEAD +======= + void acquire_runtime_filter(RuntimeState* state) { + for (auto& op : _op_factories) { + op->acquire_runtime_filter(state); + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string to_readable_string() const { std::stringstream ss; ss << "operator-chain: ["; diff --git a/be/src/exec/pipeline/pipeline_driver.cpp b/be/src/exec/pipeline/pipeline_driver.cpp index 31a8fdcce91e8..9fe9908168fc3 100644 --- a/be/src/exec/pipeline/pipeline_driver.cpp +++ b/be/src/exec/pipeline/pipeline_driver.cpp @@ -18,6 +18,10 @@ #include #include "column/chunk.h" +<<<<<<< HEAD +======= +#include "common/status.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/statusor.h" #include "exec/pipeline/adaptive/event.h" #include "exec/pipeline/exchange/exchange_sink_operator.h" @@ -289,6 +293,10 @@ StatusOr PipelineDriver::process(RuntimeState* runtime_state, int w _update_scan_statistics(runtime_state); RETURN_IF_ERROR(return_status = _mark_operator_finishing(curr_op, runtime_state)); } +<<<<<<< HEAD +======= + curr_op->update_exec_stats(runtime_state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _adjust_memory_usage(runtime_state, query_mem_tracker.get(), next_op, nullptr); RELEASE_RESERVED_GUARD(); RETURN_IF_ERROR(return_status = _mark_operator_finishing(next_op, runtime_state)); @@ -378,6 +386,10 @@ StatusOr PipelineDriver::process(RuntimeState* runtime_state, int w _update_scan_statistics(runtime_state); RETURN_IF_ERROR(return_status = _mark_operator_finishing(curr_op, runtime_state)); } +<<<<<<< HEAD +======= + curr_op->update_exec_stats(runtime_state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _adjust_memory_usage(runtime_state, query_mem_tracker.get(), next_op, nullptr); RELEASE_RESERVED_GUARD(); RETURN_IF_ERROR(return_status = _mark_operator_finishing(next_op, runtime_state)); @@ -412,6 +424,10 @@ StatusOr PipelineDriver::process(RuntimeState* runtime_state, int w _first_unfinished = new_first_unfinished; if (sink_operator()->is_finished()) { +<<<<<<< HEAD +======= + sink_operator()->update_exec_stats(runtime_state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) finish_operators(runtime_state); set_driver_state(is_still_pending_finish() ? DriverState::PENDING_FINISH : DriverState::FINISH); return _state; diff --git a/be/src/exec/pipeline/pipeline_driver.h b/be/src/exec/pipeline/pipeline_driver.h index 5b112b23a68b3..d2cb486e198a3 100644 --- a/be/src/exec/pipeline/pipeline_driver.h +++ b/be/src/exec/pipeline/pipeline_driver.h @@ -31,6 +31,10 @@ #include "exec/pipeline/scan/scan_operator.h" #include "exec/pipeline/source_operator.h" #include "exec/workgroup/work_group_fwd.h" +<<<<<<< HEAD +======= +#include "exprs/runtime_filter_bank.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fmt/printf.h" #include "runtime/mem_tracker.h" #include "util/phmap/phmap.h" @@ -225,8 +229,13 @@ class PipelineDriver { int32_t driver_id() const { return _driver_id; } DriverPtr clone() { return std::make_shared(*this); } void set_morsel_queue(MorselQueue* morsel_queue) { _morsel_queue = morsel_queue; } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* runtime_state); [[nodiscard]] virtual StatusOr process(RuntimeState* runtime_state, int worker_id); +======= + Status prepare(RuntimeState* runtime_state); + virtual StatusOr process(RuntimeState* runtime_state, int worker_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void finalize(RuntimeState* runtime_state, DriverState state, int64_t schedule_count, int64_t execution_time); DriverAcct& driver_acct() { return _driver_acct; } DriverState driver_state() const { return _state; } @@ -422,7 +431,11 @@ class PipelineDriver { } // Check whether an operator can be short-circuited, when is_precondition_block() becomes false from true. +<<<<<<< HEAD [[nodiscard]] Status check_short_circuit(); +======= + Status check_short_circuit(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool need_report_exec_state(); void report_exec_state_if_necessary(); @@ -474,10 +487,17 @@ class PipelineDriver { // check whether fragment is cancelled. It is used before pull_chunk and push_chunk. bool _check_fragment_is_canceled(RuntimeState* runtime_state); +<<<<<<< HEAD [[nodiscard]] Status _mark_operator_finishing(OperatorPtr& op, RuntimeState* runtime_state); [[nodiscard]] Status _mark_operator_finished(OperatorPtr& op, RuntimeState* runtime_state); [[nodiscard]] Status _mark_operator_cancelled(OperatorPtr& op, RuntimeState* runtime_state); [[nodiscard]] Status _mark_operator_closed(OperatorPtr& op, RuntimeState* runtime_state); +======= + Status _mark_operator_finishing(OperatorPtr& op, RuntimeState* runtime_state); + Status _mark_operator_finished(OperatorPtr& op, RuntimeState* runtime_state); + Status _mark_operator_cancelled(OperatorPtr& op, RuntimeState* runtime_state); + Status _mark_operator_closed(OperatorPtr& op, RuntimeState* runtime_state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _close_operators(RuntimeState* runtime_state); void _adjust_memory_usage(RuntimeState* state, MemTracker* tracker, OperatorPtr& op, const ChunkPtr& chunk); diff --git a/be/src/exec/pipeline/pipeline_fwd.h b/be/src/exec/pipeline/pipeline_fwd.h index 1605aaf4a34dd..1799f2eb7fc55 100644 --- a/be/src/exec/pipeline/pipeline_fwd.h +++ b/be/src/exec/pipeline/pipeline_fwd.h @@ -50,4 +50,13 @@ class DriverExecutor; using DriverExecutorPtr = std::shared_ptr; class GlobalDriverExecutor; class ExecStateReporter; +<<<<<<< HEAD } // namespace starrocks::pipeline +======= +class PipelineBuilderContext; +} // namespace starrocks::pipeline + +namespace starrocks { +using OperatorFactoryPtr = pipeline::OpFactoryPtr; +} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/exec/pipeline/query_context.cpp b/be/src/exec/pipeline/query_context.cpp index 7d395b44b3296..1474826562dab 100644 --- a/be/src/exec/pipeline/query_context.cpp +++ b/be/src/exec/pipeline/query_context.cpp @@ -30,6 +30,7 @@ #include "runtime/query_statistics.h" #include "runtime/runtime_filter_cache.h" #include "util/thread.h" +<<<<<<< HEAD namespace starrocks::pipeline { @@ -37,6 +38,12 @@ using apache::thrift::TException; using apache::thrift::TProcessor; using apache::thrift::transport::TTransportException; +======= +#include "util/thrift_rpc_helper.h" + +namespace starrocks::pipeline { + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) QueryContext::QueryContext() : _fragment_mgr(new FragmentContextManager()), _total_fragments(0), @@ -224,6 +231,15 @@ std::shared_ptr QueryContext::intermediate_query_statistic() { query_statistic->add_stats_item(stats_item); } } +<<<<<<< HEAD +======= + for (const auto& [node_id, exec_stats] : _node_exec_stats) { + query_statistic->add_exec_stats_item( + node_id, exec_stats->push_rows.exchange(0), exec_stats->pull_rows.exchange(0), + exec_stats->pred_filter_rows.exchange(0), exec_stats->index_filter_rows.exchange(0), + exec_stats->rf_filter_rows.exchange(0)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _sub_plan_query_statistics_recvr->aggregate(query_statistic.get()); return query_statistic; } @@ -245,6 +261,15 @@ std::shared_ptr QueryContext::final_query_statistic() { res->add_stats_item(stats_item); } } +<<<<<<< HEAD +======= + + for (const auto& [node_id, exec_stats] : _node_exec_stats) { + res->add_exec_stats_item(node_id, exec_stats->push_rows, exec_stats->pull_rows, exec_stats->pred_filter_rows, + exec_stats->index_filter_rows, exec_stats->rf_filter_rows); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _sub_plan_query_statistics_recvr->aggregate(res.get()); return res; } @@ -267,6 +292,18 @@ void QueryContext::update_scan_stats(int64_t table_id, int64_t scan_rows_num, in stats->delta_scan_bytes += scan_bytes; } +<<<<<<< HEAD +======= +void QueryContext::init_node_exec_stats(const std::vector& exec_stats_node_ids) { + std::call_once(_node_exec_stats_init_flag, [this, &exec_stats_node_ids]() { + for (int32_t node_id : exec_stats_node_ids) { + auto node_exec_stats = std::make_shared(); + _node_exec_stats[node_id] = node_exec_stats; + } + }); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) QueryContextManager::QueryContextManager(size_t log2_num_slots) : _num_slots(1 << log2_num_slots), _slot_mask(_num_slots - 1), @@ -371,8 +408,13 @@ QueryContext* QueryContextManager::get_or_register(const TUniqueId& query_id) { // lookup query context for the second chance in sc_map if (sc_it != sc_map.end()) { auto ctx = std::move(sc_it->second); +<<<<<<< HEAD RETURN_NULL_IF_CTX_CANCELLED(ctx); sc_map.erase(sc_it); +======= + sc_map.erase(sc_it); + RETURN_NULL_IF_CTX_CANCELLED(ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* raw_ctx_ptr = ctx.get(); context_map.emplace(query_id, std::move(ctx)); return raw_ctx_ptr; @@ -499,7 +541,10 @@ void QueryContextManager::report_fragments_with_same_host( continue; } +<<<<<<< HEAD Status fe_connection_status; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto fe_addr = fragment_ctx->fe_addr(); auto fragment_id = fragment_ctx->fragment_instance_id(); auto* runtime_state = fragment_ctx->runtime_state(); @@ -600,13 +645,18 @@ void QueryContextManager::report_fragments( continue; } +<<<<<<< HEAD Status fe_connection_status; auto fe_addr = fragment_ctx->fe_addr(); auto exec_env = fragment_ctx->runtime_state()->exec_env(); +======= + auto fe_addr = fragment_ctx->fe_addr(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto fragment_id = fragment_ctx->fragment_instance_id(); auto* runtime_state = fragment_ctx->runtime_state(); DCHECK(runtime_state != nullptr); +<<<<<<< HEAD FrontendServiceConnection fe_connection(exec_env->frontend_client_cache(), fe_addr, config::thrift_rpc_timeout_ms, &fe_connection_status); if (!fe_connection_status.ok()) { @@ -619,6 +669,8 @@ void QueryContextManager::report_fragments( continue; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector report_exec_status_params_vector; TReportExecStatusParams params; @@ -655,6 +707,7 @@ void QueryContextManager::report_fragments( Status rpc_status; VLOG_ROW << "debug: reportExecStatus params is " << apache::thrift::ThriftDebugString(params).c_str(); +<<<<<<< HEAD // TODO: refactor me try { @@ -676,6 +729,17 @@ void QueryContextManager::report_fragments( std::stringstream msg; msg << "ReportExecStatus() to " << fe_addr << " failed:\n" << e.what(); LOG(WARNING) << msg.str(); +======= + rpc_status = ThriftRpcHelper::rpc( + fe_addr, + [&res, &report_batch](FrontendServiceConnection& client) { + client->batchReportExecStatus(res, report_batch); + }, + config::thrift_rpc_timeout_ms); + if (!rpc_status.ok()) { + LOG(WARNING) << "thrift rpc error:" << rpc_status; + continue; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } const std::vector& status_list = res.status_list; diff --git a/be/src/exec/pipeline/query_context.h b/be/src/exec/pipeline/query_context.h index 027135936406d..52615da3dc5c1 100644 --- a/be/src/exec/pipeline/query_context.h +++ b/be/src/exec/pipeline/query_context.h @@ -191,7 +191,58 @@ class QueryContext : public std::enable_shared_from_this { _delta_scan_bytes += scan_bytes; } +<<<<<<< HEAD void update_scan_stats(int64_t table_id, int64_t scan_rows_num, int64_t scan_bytes); +======= + void init_node_exec_stats(const std::vector& exec_stats_node_ids); + bool need_record_exec_stats(int32_t plan_node_id) { + auto it = _node_exec_stats.find(plan_node_id); + return it != _node_exec_stats.end(); + } + + void update_scan_stats(int64_t table_id, int64_t scan_rows_num, int64_t scan_bytes); + void update_push_rows_stats(int32_t plan_node_id, int64_t push_rows) { + auto it = _node_exec_stats.find(plan_node_id); + if (it != _node_exec_stats.end()) { + it->second->push_rows += push_rows; + } + } + + void update_pull_rows_stats(int32_t plan_node_id, int64_t pull_rows) { + auto it = _node_exec_stats.find(plan_node_id); + if (it != _node_exec_stats.end()) { + it->second->pull_rows += pull_rows; + } + } + + void update_pred_filter_stats(int32_t plan_node_id, int64_t pred_filter_rows) { + auto it = _node_exec_stats.find(plan_node_id); + if (it != _node_exec_stats.end()) { + it->second->pred_filter_rows += pred_filter_rows; + } + } + + void update_index_filter_stats(int32_t plan_node_id, int64_t index_filter_rows) { + auto it = _node_exec_stats.find(plan_node_id); + if (it != _node_exec_stats.end()) { + it->second->index_filter_rows += index_filter_rows; + } + } + + void update_rf_filter_stats(int32_t plan_node_id, int64_t rf_filter_rows) { + auto it = _node_exec_stats.find(plan_node_id); + if (it != _node_exec_stats.end()) { + it->second->rf_filter_rows += rf_filter_rows; + } + } + + void force_set_pull_rows_stats(int32_t plan_node_id, int64_t pull_rows) { + auto it = _node_exec_stats.find(plan_node_id); + if (it != _node_exec_stats.end()) { + it->second->pull_rows.exchange(pull_rows); + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t cpu_cost() const { return _total_cpu_cost_ns; } int64_t cur_scan_rows_num() const { return _total_scan_rows_num; } @@ -284,6 +335,19 @@ class QueryContext : public std::enable_shared_from_this { std::atomic delta_scan_rows_num = 0; std::atomic delta_scan_bytes = 0; }; +<<<<<<< HEAD +======= + + std::once_flag _node_exec_stats_init_flag; + struct NodeExecStats { + std::atomic_int64_t push_rows; + std::atomic_int64_t pull_rows; + std::atomic_int64_t pred_filter_rows; + std::atomic_int64_t index_filter_rows; + std::atomic_int64_t rf_filter_rows; + }; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // @TODO(silverbullet233): // our phmap's version is too old and it doesn't provide a thread-safe iteration interface, // we use spinlock + flat_hash_map here, after upgrading, we can change it to parallel_flat_hash_map @@ -291,6 +355,11 @@ class QueryContext : public std::enable_shared_from_this { // table level scan stats phmap::flat_hash_map, StdHash> _scan_stats; +<<<<<<< HEAD +======= + std::unordered_map> _node_exec_stats; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _is_final_sink = false; std::shared_ptr _sub_plan_query_statistics_recvr; // For receive diff --git a/be/src/exec/pipeline/result_sink_operator.cpp b/be/src/exec/pipeline/result_sink_operator.cpp index 9eaae391e3d78..f8fce23c8b2d7 100644 --- a/be/src/exec/pipeline/result_sink_operator.cpp +++ b/be/src/exec/pipeline/result_sink_operator.cpp @@ -14,7 +14,14 @@ #include "exec/pipeline/result_sink_operator.h" +<<<<<<< HEAD #include "exprs/expr.h" +======= +#include + +#include "exprs/expr.h" +#include "runtime/arrow_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/buffer_control_block.h" #include "runtime/customized_result_writer.h" #include "runtime/http_result_writer.h" @@ -31,12 +38,18 @@ Status ResultSinkOperator::prepare(RuntimeState* state) { RETURN_IF_ERROR(Operator::prepare(state)); // Create profile +<<<<<<< HEAD _profile = std::make_unique("result sink"); _unique_metrics->add_child(_profile.get(), true, nullptr); +======= + _unique_metrics->add_info_string("SinkType", to_string(_sink_type)); + auto profile = _unique_metrics.get(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Create writer based on sink type switch (_sink_type) { case TResultSinkType::MYSQL_PROTOCAL: +<<<<<<< HEAD _writer = std::make_shared(_sender.get(), _output_expr_ctxs, _is_binary_format, _profile.get()); break; @@ -51,13 +64,35 @@ Status ResultSinkOperator::prepare(RuntimeState* state) { break; case TResultSinkType::METADATA_ICEBERG: _writer = std::make_shared(_sender.get(), _output_expr_ctxs, _profile.get(), _sink_type); +======= + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, _is_binary_format, profile); + break; + case TResultSinkType::STATISTIC: + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, profile); + break; + case TResultSinkType::VARIABLE: + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, profile); + break; + case TResultSinkType::HTTP_PROTOCAL: + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, profile, _format_type); + break; + case TResultSinkType::METADATA_ICEBERG: + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, profile, _sink_type); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) break; case TResultSinkType::CUSTOMIZED: // CustomizedResultWriter is a general-purposed result writer that used by FE to executing internal // query, the result is serialized in packed binary format. FE can parse the result row into object // via ORM(Object-Relation Mapping) mechanism. In the future, all the internal queries should be // unified to adopt this result sink type. +<<<<<<< HEAD _writer = std::make_shared(_sender.get(), _output_expr_ctxs, _profile.get()); +======= + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, profile); + break; + case TResultSinkType::ARROW_FLIGHT_PROTOCAL: + _writer = std::make_shared(_sender.get(), _output_expr_ctxs, profile, _row_desc); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) break; default: return Status::InternalError("Unknown result sink type"); @@ -107,8 +142,12 @@ StatusOr ResultSinkOperator::pull_chunk(RuntimeState* state) { Status ResultSinkOperator::set_cancelled(RuntimeState* state) { SCOPED_THREAD_LOCAL_MEM_TRACKER_SETTER(nullptr); +<<<<<<< HEAD _fetch_data_result.clear(); +======= + _writer->cancel(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -118,6 +157,7 @@ bool ResultSinkOperator::need_input() const { if (is_finished()) { return false; } +<<<<<<< HEAD if (_fetch_data_result.empty()) { return true; } @@ -129,6 +169,10 @@ bool ResultSinkOperator::need_input() const { _last_error = status.status(); return true; } +======= + + return !_writer->is_full(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status ResultSinkOperator::push_chunk(RuntimeState* state, const ChunkPtr& chunk) { @@ -144,6 +188,7 @@ Status ResultSinkOperator::push_chunk(RuntimeState* state, const ChunkPtr& chunk if (!_last_error.ok()) { return _last_error; } +<<<<<<< HEAD DCHECK(_fetch_data_result.empty()); auto status = _writer->process_chunk(chunk.get()); @@ -153,6 +198,10 @@ Status ResultSinkOperator::push_chunk(RuntimeState* state, const ChunkPtr& chunk } else { return status.status(); } +======= + + return _writer->add_to_write_buffer(chunk.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status ResultSinkOperatorFactory::prepare(RuntimeState* state) { diff --git a/be/src/exec/pipeline/result_sink_operator.h b/be/src/exec/pipeline/result_sink_operator.h index 1877146ab9043..a265f87f0cf96 100644 --- a/be/src/exec/pipeline/result_sink_operator.h +++ b/be/src/exec/pipeline/result_sink_operator.h @@ -33,7 +33,11 @@ class ResultSinkOperator final : public Operator { TResultSinkType::type sink_type, bool is_binary_format, TResultSinkFormatType::type format_type, std::vector output_expr_ctxs, const std::shared_ptr& sender, std::atomic& num_sinks, std::atomic& num_written_rows, +<<<<<<< HEAD FragmentContext* const fragment_ctx) +======= + FragmentContext* const fragment_ctx, const RowDescriptor& row_desc) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : Operator(factory, id, "result_sink", plan_node_id, false, driver_sequence), _sink_type(sink_type), _is_binary_format(is_binary_format), @@ -42,7 +46,12 @@ class ResultSinkOperator final : public Operator { _sender(sender), _num_sinkers(num_sinks), _num_written_rows(num_written_rows), +<<<<<<< HEAD _fragment_ctx(fragment_ctx) {} +======= + _fragment_ctx(fragment_ctx), + _row_desc(row_desc) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~ResultSinkOperator() override = default; @@ -56,7 +65,11 @@ class ResultSinkOperator final : public Operator { bool need_input() const override; +<<<<<<< HEAD bool is_finished() const override { return _is_finished && _fetch_data_result.empty(); } +======= + bool is_finished() const override { return _is_finished; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status set_finishing(RuntimeState* state) override { _is_finished = true; @@ -82,27 +95,43 @@ class ResultSinkOperator final : public Operator { std::atomic& _num_written_rows; std::shared_ptr _writer; +<<<<<<< HEAD mutable TFetchDataResultPtrs _fetch_data_result; std::unique_ptr _profile = nullptr; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) mutable Status _last_error; bool _is_finished = false; FragmentContext* const _fragment_ctx; +<<<<<<< HEAD +======= + const RowDescriptor& _row_desc; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class ResultSinkOperatorFactory final : public OperatorFactory { public: ResultSinkOperatorFactory(int32_t id, TResultSinkType::type sink_type, bool is_binary_format, TResultSinkFormatType::type format_type, std::vector t_output_expr, +<<<<<<< HEAD FragmentContext* const fragment_ctx) +======= + FragmentContext* const fragment_ctx, const RowDescriptor& row_desc) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : OperatorFactory(id, "result_sink", Operator::s_pseudo_plan_node_id_for_final_sink), _sink_type(sink_type), _is_binary_format(is_binary_format), _format_type(format_type), _t_output_expr(std::move(t_output_expr)), +<<<<<<< HEAD _fragment_ctx(fragment_ctx) {} +======= + _fragment_ctx(fragment_ctx), + _row_desc(row_desc) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~ResultSinkOperatorFactory() override = default; @@ -114,7 +143,11 @@ class ResultSinkOperatorFactory final : public OperatorFactory { _increment_num_sinkers_no_barrier(); return std::make_shared(this, _id, _plan_node_id, driver_sequence, _sink_type, _is_binary_format, _format_type, _output_expr_ctxs, _sender, +<<<<<<< HEAD _num_sinkers, _num_written_rows, _fragment_ctx); +======= + _num_sinkers, _num_written_rows, _fragment_ctx, _row_desc); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status prepare(RuntimeState* state) override; @@ -138,6 +171,10 @@ class ResultSinkOperatorFactory final : public OperatorFactory { std::atomic _num_written_rows = 0; FragmentContext* const _fragment_ctx; +<<<<<<< HEAD +======= + const RowDescriptor& _row_desc; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace pipeline diff --git a/be/src/exec/pipeline/runtime_filter_types.h b/be/src/exec/pipeline/runtime_filter_types.h index 3db7d24616eec..b30372513d893 100644 --- a/be/src/exec/pipeline/runtime_filter_types.h +++ b/be/src/exec/pipeline/runtime_filter_types.h @@ -18,11 +18,19 @@ #include #include "common/statusor.h" +<<<<<<< HEAD #include "exec/hash_join_node.h" +======= +#include "exec/pipeline/hashjoin/hash_joiner_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr_context.h" #include "exprs/predicate.h" #include "exprs/runtime_filter_bank.h" #include "gen_cpp/Types_types.h" +<<<<<<< HEAD +======= +#include "util/defer_op.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::pipeline { class RuntimeFilterHolder; @@ -47,6 +55,7 @@ struct RuntimeBloomFilterBuildParam; using OptRuntimeBloomFilterBuildParams = std::vector>; // Parameters used to build runtime bloom-filters. struct RuntimeBloomFilterBuildParam { +<<<<<<< HEAD RuntimeBloomFilterBuildParam(bool multi_partitioned, bool eq_null, ColumnPtr column, MutableJoinRuntimeFilterPtr runtime_filter) : multi_partitioned(multi_partitioned), @@ -56,6 +65,19 @@ struct RuntimeBloomFilterBuildParam { bool multi_partitioned; bool eq_null; ColumnPtr column; +======= + RuntimeBloomFilterBuildParam(bool multi_partitioned, bool eq_null, bool is_empty, std::vector columns, + MutableJoinRuntimeFilterPtr runtime_filter) + : multi_partitioned(multi_partitioned), + eq_null(eq_null), + is_empty(is_empty), + columns(std::move(columns)), + runtime_filter(std::move(runtime_filter)) {} + bool multi_partitioned; + bool eq_null; + bool is_empty; + std::vector columns; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MutableJoinRuntimeFilterPtr runtime_filter; }; @@ -143,11 +165,21 @@ class RuntimeFilterHub { } void set_collector(TPlanNodeId id, RuntimeFilterCollectorPtr&& collector) { +<<<<<<< HEAD get_holder(id, -1)->set_collector(std::move(collector)); } void set_collector(TPlanNodeId id, int32_t sequence_id, RuntimeFilterCollectorPtr&& collector) { get_holder(id, sequence_id)->set_collector(std::move(collector)); +======= + auto holder = get_holder(id, -1); + holder->set_collector(std::move(collector)); + } + + void set_collector(TPlanNodeId id, int32_t sequence_id, RuntimeFilterCollectorPtr&& collector) { + auto holder = get_holder(id, sequence_id); + holder->set_collector(std::move(collector)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void close_all_in_filters(RuntimeState* state) { @@ -275,10 +307,16 @@ class PartialRuntimeFilterMerger { // HashJoinBuildOperator call add_partial_filters to gather partial runtime filters. the last HashJoinBuildOperator // will merge partial runtime filters into total one finally. +<<<<<<< HEAD [[nodiscard]] StatusOr add_partial_filters( size_t idx, size_t ht_row_count, RuntimeInFilters&& partial_in_filters, OptRuntimeBloomFilterBuildParams&& partial_bloom_filter_build_params, RuntimeBloomFilters&& bloom_filter_descriptors) { +======= + StatusOr add_partial_filters(size_t idx, size_t ht_row_count, RuntimeInFilters&& partial_in_filters, + OptRuntimeBloomFilterBuildParams&& partial_bloom_filter_build_params, + RuntimeBloomFilters&& bloom_filter_descriptors) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(idx < _partial_bloom_filter_build_params.size()); // both _ht_row_counts, _partial_in_filters, _partial_bloom_filter_build_params are reserved beforehand, // each HashJoinBuildOperator mutates its corresponding slot indexed by driver_sequence, so concurrent @@ -300,7 +338,11 @@ class PartialRuntimeFilterMerger { return {_bloom_filter_descriptors.begin(), _bloom_filter_descriptors.end()}; } +<<<<<<< HEAD [[nodiscard]] Status merge_local_in_filters() { +======= + Status merge_local_in_filters() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool can_merge_in_filters = true; size_t num_rows = 0; ssize_t k = -1; @@ -359,7 +401,11 @@ class PartialRuntimeFilterMerger { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status merge_local_bloom_filters() { +======= + Status merge_local_bloom_filters() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_bloom_filter_descriptors.empty()) { return Status::OK(); } @@ -371,7 +417,11 @@ class PartialRuntimeFilterMerger { } } +<<<<<<< HEAD [[nodiscard]] Status merge_singleton_local_bloom_filters() { +======= + Status merge_singleton_local_bloom_filters() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_partial_bloom_filter_build_params.empty()) { return Status::OK(); } @@ -438,12 +488,17 @@ class PartialRuntimeFilterMerger { auto& opt_param = opt_params[i]; DCHECK(opt_param.has_value()); auto& param = opt_param.value(); +<<<<<<< HEAD if (param.column == nullptr || param.column->empty()) { continue; } auto status = RuntimeFilterHelper::fill_runtime_bloom_filter(param.column, desc->build_expr_type(), desc->runtime_filter(), kHashJoinKeyColumnOffset, param.eq_null); +======= + auto status = RuntimeFilterHelper::fill_runtime_bloom_filter( + param, desc->build_expr_type(), desc->runtime_filter(), kHashJoinKeyColumnOffset); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!status.ok()) { desc->set_runtime_filter(nullptr); break; @@ -453,7 +508,11 @@ class PartialRuntimeFilterMerger { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status merge_multi_partitioned_local_bloom_filters() { +======= + Status merge_multi_partitioned_local_bloom_filters() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_partial_bloom_filter_build_params.empty()) { return Status::OK(); } @@ -519,7 +578,11 @@ class PartialRuntimeFilterMerger { auto& opt_param = opt_params[i]; DCHECK(opt_param.has_value()); auto& param = opt_param.value(); +<<<<<<< HEAD if (param.column == nullptr || param.column->empty()) { +======= + if (param.is_empty) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) continue; } rf->concat(param.runtime_filter.get()); diff --git a/be/src/exec/pipeline/scan/chunk_source.h b/be/src/exec/pipeline/scan/chunk_source.h index 240dcdfe454f0..5c22514372bbc 100644 --- a/be/src/exec/pipeline/scan/chunk_source.h +++ b/be/src/exec/pipeline/scan/chunk_source.h @@ -77,6 +77,10 @@ class ChunkSource { virtual bool reach_limit() { return false; } +<<<<<<< HEAD +======= + virtual void update_chunk_exec_stats(RuntimeState* state) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Used to print custom error msg in be.out when coredmp // Don't do heavey work, it calls frequently virtual const std::string get_custom_coredump_msg() const { return ""; } diff --git a/be/src/exec/pipeline/scan/connector_scan_operator.cpp b/be/src/exec/pipeline/scan/connector_scan_operator.cpp index 2afc83a102a63..a2972094d2260 100644 --- a/be/src/exec/pipeline/scan/connector_scan_operator.cpp +++ b/be/src/exec/pipeline/scan/connector_scan_operator.cpp @@ -312,6 +312,7 @@ bool ConnectorScanOperator::has_shared_chunk_source() const { return !active_inputs.empty(); } +<<<<<<< HEAD size_t ConnectorScanOperator::num_buffered_chunks() const { auto* factory = down_cast(_factory); auto& buffer = factory->get_chunk_buffer(); @@ -370,6 +371,8 @@ void ConnectorScanOperator::set_buffer_finished() { buffer.set_finished(_driver_sequence); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) connector::ConnectorType ConnectorScanOperator::connector_type() { auto* scan_node = down_cast(_scan_node); return scan_node->connector_type(); @@ -585,7 +588,11 @@ int ConnectorScanOperator::available_pickup_morsel_count() { return io_tasks; } +<<<<<<< HEAD void ConnectorScanOperator::append_morsels(std::vector&& morsels) { +======= +Status ConnectorScanOperator::append_morsels(std::vector&& morsels) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) query_cache::TicketChecker* ticket_checker = _ticket_checker.get(); if (ticket_checker != nullptr) { int64_t cached_owner_id = -1; @@ -598,7 +605,12 @@ void ConnectorScanOperator::append_morsels(std::vector&& morsels) { } } } +<<<<<<< HEAD _morsel_queue->append_morsels(std::move(morsels)); +======= + RETURN_IF_ERROR(_morsel_queue->append_morsels(std::move(morsels))); + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // ==================== ConnectorChunkSource ==================== @@ -617,9 +629,12 @@ ConnectorChunkSource::ConnectorChunkSource(ScanOperator* op, RuntimeProfile* run TScanRange* scan_range = scan_morsel->get_scan_range(); ScanSplitContext* split_context = scan_morsel->get_split_context(); +<<<<<<< HEAD if (scan_range->__isset.broker_scan_range) { scan_range->broker_scan_range.params.__set_non_blocking_read(true); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _data_source = scan_node->data_source_provider()->create_data_source(*scan_range); _data_source->set_driver_sequence(op->get_driver_sequence()); _data_source->set_split_context(split_context); @@ -713,10 +728,17 @@ Status ConnectorChunkSource::_open_data_source(RuntimeState* state, bool* mem_al ConnectorScanOperator* scan_op = down_cast(_scan_op); if (scan_op->enable_adaptive_io_tasks()) { +<<<<<<< HEAD +======= + ConnectorScanOperatorIOTasksMemLimiter* limiter = _get_io_tasks_mem_limiter(); + MemTracker* mem_tracker = state->query_ctx()->connector_scan_mem_tracker(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [[maybe_unused]] auto build_debug_string = [&](const std::string& action) { std::stringstream ss; ss << "try_mem_tracker. query_id = " << print_id(state->query_id()) << ", op_id = " << _scan_op->get_plan_node_id() << "/" << _scan_op->get_driver_sequence() << ", " +<<<<<<< HEAD << action << ". this = " << (void*)this << ", value = " << _request_mem_tracker_bytes; return ss.str(); }; @@ -724,6 +746,13 @@ Status ConnectorChunkSource::_open_data_source(RuntimeState* state, bool* mem_al ConnectorScanOperatorIOTasksMemLimiter* limiter = _get_io_tasks_mem_limiter(); MemTracker* mem_tracker = state->query_ctx()->connector_scan_mem_tracker(); +======= + << action << ". this = " << (void*)this << ", value = " << _request_mem_tracker_bytes + << ", running = " << limiter->update_running_chunk_source_count(0); + return ss.str(); + }; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int retry = 3; while (retry > 0) { retry--; @@ -862,7 +891,11 @@ Status ConnectorChunkSource::_read_chunk(RuntimeState* state, ChunkPtr* chunk) { split_morsels.emplace_back(std::move(m)); } +<<<<<<< HEAD scan_op->append_morsels(std::move(split_morsels)); +======= + RETURN_IF_ERROR(scan_op->append_morsels(std::move(split_morsels))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } return Status::EndOfFile(""); diff --git a/be/src/exec/pipeline/scan/connector_scan_operator.h b/be/src/exec/pipeline/scan/connector_scan_operator.h index 943555b058d78..1e3a91a9ec797 100644 --- a/be/src/exec/pipeline/scan/connector_scan_operator.h +++ b/be/src/exec/pipeline/scan/connector_scan_operator.h @@ -97,6 +97,7 @@ class ConnectorScanOperator : public ScanOperator { void attach_chunk_source(int32_t source_index) override; void detach_chunk_source(int32_t source_index) override; bool has_shared_chunk_source() const override; +<<<<<<< HEAD ChunkPtr get_chunk_from_buffer() override; size_t num_buffered_chunks() const override; size_t buffer_size() const override; @@ -106,13 +107,23 @@ class ConnectorScanOperator : public ScanOperator { ChunkBufferTokenPtr pin_chunk(int num_chunks) override; bool is_buffer_full() const override; void set_buffer_finished() override; +======= + BalancedChunkBuffer& get_chunk_buffer() const override { + auto* factory = down_cast(_factory); + return factory->get_chunk_buffer(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int available_pickup_morsel_count() override; void begin_driver_process() override; void end_driver_process(PipelineDriver* driver) override; bool is_running_all_io_tasks() const override; +<<<<<<< HEAD void append_morsels(std::vector&& morsels); +======= + Status append_morsels(std::vector&& morsels); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ConnectorScanOperatorAdaptiveProcessor* adaptive_processor() const { return _adaptive_processor; } bool enable_adaptive_io_tasks() const { return _enable_adaptive_io_tasks; } diff --git a/be/src/exec/pipeline/scan/meta_scan_operator.cpp b/be/src/exec/pipeline/scan/meta_scan_operator.cpp index 83a5b55e08beb..d43da7d9a6ea0 100644 --- a/be/src/exec/pipeline/scan/meta_scan_operator.cpp +++ b/be/src/exec/pipeline/scan/meta_scan_operator.cpp @@ -23,7 +23,11 @@ namespace starrocks::pipeline { MetaScanOperatorFactory::MetaScanOperatorFactory(int32_t id, ScanNode* meta_scan_node, size_t dop, std::shared_ptr ctx_factory) +<<<<<<< HEAD : ScanOperatorFactory(id, meta_scan_node), _ctx_factory(std::move(std::move(ctx_factory))) {} +======= + : ScanOperatorFactory(id, meta_scan_node), _ctx_factory(std::move(ctx_factory)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status MetaScanOperatorFactory::do_prepare(RuntimeState* state) { return Status::OK(); @@ -38,7 +42,11 @@ OperatorPtr MetaScanOperatorFactory::do_create(int32_t dop, int32_t driver_seque MetaScanOperator::MetaScanOperator(OperatorFactory* factory, int32_t id, int32_t driver_sequence, int32_t dop, ScanNode* meta_scan_node, MetaScanContextPtr ctx) +<<<<<<< HEAD : ScanOperator(factory, id, driver_sequence, dop, meta_scan_node), _ctx(std::move(std::move(ctx))) {} +======= + : ScanOperator(factory, id, driver_sequence, dop, meta_scan_node), _ctx(std::move(ctx)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool MetaScanOperator::has_output() const { if (!_ctx->is_prepare_finished()) { @@ -64,6 +72,7 @@ ChunkSourcePtr MetaScanOperator::create_chunk_source(MorselPtr morsel, int32_t c return std::make_shared(this, _runtime_profile.get(), std::move(morsel), _ctx); } +<<<<<<< HEAD ChunkPtr MetaScanOperator::get_chunk_from_buffer() { ChunkPtr chunk = nullptr; if (_ctx->get_chunk_buffer().try_get(_driver_sequence, &chunk)) { @@ -104,4 +113,6 @@ void MetaScanOperator::set_buffer_finished() { _ctx->get_chunk_buffer().set_finished(_driver_sequence); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::pipeline \ No newline at end of file diff --git a/be/src/exec/pipeline/scan/meta_scan_operator.h b/be/src/exec/pipeline/scan/meta_scan_operator.h index f52ed436a18aa..ae5c230d132f8 100644 --- a/be/src/exec/pipeline/scan/meta_scan_operator.h +++ b/be/src/exec/pipeline/scan/meta_scan_operator.h @@ -58,6 +58,7 @@ class MetaScanOperator final : public ScanOperator { void attach_chunk_source(int32_t source_index) override {} void detach_chunk_source(int32_t source_index) override {} bool has_shared_chunk_source() const override { return false; } +<<<<<<< HEAD ChunkPtr get_chunk_from_buffer() override; size_t num_buffered_chunks() const override; size_t buffer_size() const override; @@ -67,6 +68,9 @@ class MetaScanOperator final : public ScanOperator { ChunkBufferTokenPtr pin_chunk(int num_chunks) override; bool is_buffer_full() const override; void set_buffer_finished() override; +======= + BalancedChunkBuffer& get_chunk_buffer() const override { return _ctx->get_chunk_buffer(); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MetaScanContextPtr _ctx; }; diff --git a/be/src/exec/pipeline/scan/meta_scan_prepare_operator.cpp b/be/src/exec/pipeline/scan/meta_scan_prepare_operator.cpp index 9f759ce7ca2b8..d8139fae24f0e 100644 --- a/be/src/exec/pipeline/scan/meta_scan_prepare_operator.cpp +++ b/be/src/exec/pipeline/scan/meta_scan_prepare_operator.cpp @@ -30,7 +30,11 @@ MetaScanPrepareOperator::MetaScanPrepareOperator(OperatorFactory* factory, int32 int32_t driver_sequence, const std::string& operator_name, MetaScanContextPtr scan_ctx) : SourceOperator(factory, id, operator_name, plan_node_id, true, driver_sequence), +<<<<<<< HEAD _scan_ctx(std::move(std::move(scan_ctx))) {} +======= + _scan_ctx(std::move(scan_ctx)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status MetaScanPrepareOperator::prepare(RuntimeState* state) { RETURN_IF_ERROR(SourceOperator::prepare(state)); @@ -58,8 +62,12 @@ StatusOr MetaScanPrepareOperator::pull_chunk(RuntimeState* state) { MetaScanPrepareOperatorFactory::MetaScanPrepareOperatorFactory(int32_t id, int32_t plan_node_id, const std::string& operator_name, std::shared_ptr scan_ctx_factory) +<<<<<<< HEAD : SourceOperatorFactory(id, operator_name, plan_node_id), _scan_ctx_factory(std::move(std::move(scan_ctx_factory))) {} +======= + : SourceOperatorFactory(id, operator_name, plan_node_id), _scan_ctx_factory(std::move(scan_ctx_factory)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status MetaScanPrepareOperatorFactory::prepare(RuntimeState* state) { return Status::OK(); diff --git a/be/src/exec/pipeline/scan/morsel.cpp b/be/src/exec/pipeline/scan/morsel.cpp index dd21288355c57..474c0cabbc334 100644 --- a/be/src/exec/pipeline/scan/morsel.cpp +++ b/be/src/exec/pipeline/scan/morsel.cpp @@ -35,6 +35,40 @@ namespace starrocks::pipeline { const std::vector ScanMorselX::kEmptyRowsets; +<<<<<<< HEAD +======= +void ScanMorsel::build_scan_morsels(int node_id, const std::vector& scan_ranges, + bool accept_empty_scan_ranges, pipeline::Morsels* ptr_morsels, + bool* has_more_morsel) { + pipeline::Morsels& morsels = *ptr_morsels; + *has_more_morsel = false; + for (const auto& scan_range : scan_ranges) { + if (scan_range.__isset.empty && scan_range.empty) { + if (scan_range.__isset.has_more) { + *has_more_morsel = scan_range.has_more; + } + continue; + } + morsels.emplace_back(std::make_unique(node_id, scan_range)); + } + + if (morsels.empty() && !accept_empty_scan_ranges) { + morsels.emplace_back(std::make_unique(node_id, TScanRangeParams())); + } +} +bool ScanMorsel::has_more_scan_ranges(const std::vector& scan_ranges) { + bool has_more = false; + for (const auto& scan_range : scan_ranges) { + if (scan_range.__isset.empty && scan_range.empty) { + if (scan_range.__isset.has_more) { + has_more = scan_range.has_more; + } + } + } + return has_more; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void PhysicalSplitScanMorsel::init_tablet_reader_params(TabletReaderParams* params) { params->rowid_range_option = _rowid_range_option; } @@ -48,6 +82,18 @@ size_t SharedMorselQueueFactory::num_original_morsels() const { return _queue->num_original_morsels(); } +<<<<<<< HEAD +======= +Status SharedMorselQueueFactory::append_morsels([[maybe_unused]] int driver_seq, Morsels&& morsels) { + RETURN_IF_ERROR(_queue->append_morsels(std::move(morsels))); + return Status::OK(); +} + +void SharedMorselQueueFactory::set_has_more(bool v) { + _queue->set_has_more(v); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t IndividualMorselQueueFactory::num_original_morsels() const { size_t total = 0; for (const auto& queue : _queue_per_driver_seq) { @@ -56,6 +102,13 @@ size_t IndividualMorselQueueFactory::num_original_morsels() const { return total; } +<<<<<<< HEAD +======= +Status MorselQueueFactory::append_morsels(int driver_seq, Morsels&& morsels) { + return Status::NotSupported("MorselQueueFactory::append_morsels not supported"); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) IndividualMorselQueueFactory::IndividualMorselQueueFactory(std::map&& queue_per_driver_seq, bool could_local_shuffle) : _could_local_shuffle(could_local_shuffle) { @@ -76,6 +129,33 @@ IndividualMorselQueueFactory::IndividualMorselQueueFactory(std::map& _queue_per_driver_seq, int driver_seq) { + int size = _queue_per_driver_seq.size(); + if (driver_seq >= size) { + for (int i = 0; i < (driver_seq - size) + 1; i++) { + _queue_per_driver_seq.emplace_back(create_empty_morsel_queue()); + } + } +} + +Status IndividualMorselQueueFactory::append_morsels(int driver_seq, Morsels&& morsels) { + ensure_size_of_queue_per_drive_seq(_queue_per_driver_seq, driver_seq); + RETURN_IF_ERROR(_queue_per_driver_seq[driver_seq]->append_morsels(std::move(morsels))); + return Status::OK(); +} + +void IndividualMorselQueueFactory::set_has_more(bool v) { + for (auto& q : _queue_per_driver_seq) { + q->set_has_more(v); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) BucketSequenceMorselQueueFactory::BucketSequenceMorselQueueFactory(std::map&& queue_per_driver_seq, bool could_local_shuffle) : _could_local_shuffle(could_local_shuffle) { @@ -96,6 +176,21 @@ BucketSequenceMorselQueueFactory::BucketSequenceMorselQueueFactory(std::mapappend_morsels(std::move(morsels))); + return Status::OK(); +} + +void BucketSequenceMorselQueueFactory::set_has_more(bool v) { + for (auto& q : _queue_per_driver_seq) { + q->set_has_more(v); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t BucketSequenceMorselQueueFactory::num_original_morsels() const { size_t total = 0; for (const auto& queue : _queue_per_driver_seq) { @@ -124,6 +219,13 @@ void MorselQueue::unget(MorselPtr&& morsel) { _unget_morsel = std::move(morsel); } +<<<<<<< HEAD +======= +Status MorselQueue::append_morsels(Morsels&& morsels) { + return Status::NotSupported("MorselQueue::append_morsels not supported"); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr FixedMorselQueue::try_get() { if (_unget_morsel != nullptr) { return std::move(_unget_morsel); @@ -835,7 +937,14 @@ bool LogicalSplitMorselQueue::_is_last_split_of_current_morsel() { } MorselQueuePtr create_empty_morsel_queue() { +<<<<<<< HEAD return std::make_unique(std::vector{}); +======= + // instead of creating FixedMorselQueue, DynamicMorselQueue permits to add scan ranges dynamically + // because if we have incremental scan ranges delivery, some driver maybe does not have any scan ranges at first + // but in the next round, it will have scan ranges to process. + return std::make_unique(std::vector{}, true); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr DynamicMorselQueue::try_get() { @@ -857,12 +966,20 @@ void DynamicMorselQueue::unget(MorselPtr&& morsel) { _queue.emplace_front(std::move(morsel)); } +<<<<<<< HEAD void DynamicMorselQueue::append_morsels(std::vector&& morsels) { +======= +Status DynamicMorselQueue::append_morsels(std::vector&& morsels) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard _l(_mutex); _size += morsels.size(); // add split morsels to front of this queue. // so this new morsels share same owner_id with recently processed morsel. _queue.insert(_queue.begin(), std::make_move_iterator(morsels.begin()), std::make_move_iterator(morsels.end())); +<<<<<<< HEAD +======= + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/scan/morsel.h b/be/src/exec/pipeline/scan/morsel.h index e425d3ad08678..4c794feed76b5 100644 --- a/be/src/exec/pipeline/scan/morsel.h +++ b/be/src/exec/pipeline/scan/morsel.h @@ -151,11 +151,19 @@ class ScanMorsel : public ScanMorselX { } } +<<<<<<< HEAD ~ScanMorsel() override = default; ScanMorsel(int32_t plan_node_id, const TScanRangeParams& scan_range) : ScanMorsel(plan_node_id, scan_range.scan_range) {} +======= + ScanMorsel(int32_t plan_node_id, const TScanRangeParams& scan_range) + : ScanMorsel(plan_node_id, scan_range.scan_range) {} + + ~ScanMorsel() override = default; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TScanRange* get_scan_range() { return _scan_range.get(); } TInternalScanRange* get_olap_scan_range() { return &(_scan_range->internal_scan_range); } @@ -181,6 +189,13 @@ class ScanMorsel : public ScanMorselX { bool is_ticket_checker_entered() const { return _ticket_checker_entered; } void set_ticket_checker_entered(bool v) { _ticket_checker_entered = v; } +<<<<<<< HEAD +======= + static void build_scan_morsels(int node_id, const std::vector& scan_ranges, + bool accept_empty_scan_ranges, pipeline::Morsels* morsels, bool* has_more_morsel); + static bool has_more_scan_ranges(const std::vector& scan_ranges); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::unique_ptr _scan_range; ScanSplitContextPtr _split_context = nullptr; @@ -244,6 +259,12 @@ class MorselQueueFactory { virtual bool is_shared() const = 0; virtual bool could_local_shuffle() const = 0; +<<<<<<< HEAD +======= + + virtual Status append_morsels(int driver_seq, Morsels&& morsels); + virtual void set_has_more(bool v) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class SharedMorselQueueFactory final : public MorselQueueFactory { @@ -258,6 +279,12 @@ class SharedMorselQueueFactory final : public MorselQueueFactory { bool is_shared() const override { return true; } bool could_local_shuffle() const override { return true; } +<<<<<<< HEAD +======= + Status append_morsels(int driver_seq, Morsels&& morsels) override; + void set_has_more(bool v) override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: MorselQueuePtr _queue; const int _size; @@ -280,6 +307,12 @@ class IndividualMorselQueueFactory final : public MorselQueueFactory { bool is_shared() const override { return false; } bool could_local_shuffle() const override { return _could_local_shuffle; } +<<<<<<< HEAD +======= + Status append_morsels(int driver_seq, Morsels&& morsels) override; + void set_has_more(bool v) override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::vector _queue_per_driver_seq; const bool _could_local_shuffle; @@ -303,6 +336,12 @@ class BucketSequenceMorselQueueFactory final : public MorselQueueFactory { bool could_local_shuffle() const override { return _could_local_shuffle; } +<<<<<<< HEAD +======= + Status append_morsels(int driver_seq, Morsels&& morsels) override; + void set_has_more(bool v) override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::vector _queue_per_driver_seq; const bool _could_local_shuffle; @@ -342,10 +381,20 @@ class MorselQueue { virtual void unget(MorselPtr&& morsel); virtual std::string name() const = 0; virtual StatusOr ready_for_next() const { return true; } +<<<<<<< HEAD virtual void append_morsels(Morsels&& morsels) {} virtual Type type() const = 0; protected: +======= + virtual Status append_morsels(Morsels&& morsels); + virtual Type type() const = 0; + bool has_more() const { return _has_more; } + void set_has_more(bool v) { _has_more = v; } + +protected: + std::atomic _has_more = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Morsels _morsels; size_t _num_morsels = 0; MorselPtr _unget_morsel = nullptr; @@ -394,7 +443,11 @@ class BucketSequenceMorselQueue : public MorselQueue { StatusOr try_get() override; std::string name() const override; StatusOr ready_for_next() const override; +<<<<<<< HEAD void append_morsels(Morsels&& morsels) override { _morsel_queue->append_morsels(std::move(morsels)); } +======= + Status append_morsels(Morsels&& morsels) override { return _morsel_queue->append_morsels(std::move(morsels)); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Type type() const override { return BUCKET_SEQUENCE; } private: @@ -555,10 +608,18 @@ class LogicalSplitMorselQueue final : public SplitMorselQueue { class DynamicMorselQueue final : public MorselQueue { public: +<<<<<<< HEAD explicit DynamicMorselQueue(Morsels&& morsels) { append_morsels(std::move(morsels)); _size = _num_morsels = _queue.size(); _degree_of_parallelism = _num_morsels; +======= + explicit DynamicMorselQueue(Morsels&& morsels, bool has_more) { + (void)append_morsels(std::move(morsels)); + _size = _num_morsels = _queue.size(); + _degree_of_parallelism = _num_morsels; + _has_more = has_more; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } ~DynamicMorselQueue() override = default; @@ -566,7 +627,11 @@ class DynamicMorselQueue final : public MorselQueue { StatusOr try_get() override; void unget(MorselPtr&& morsel) override; std::string name() const override { return "dynamic_morsel_queue"; } +<<<<<<< HEAD void append_morsels(Morsels&& morsels) override; +======= + Status append_morsels(Morsels&& morsels) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_ticket_checker(const query_cache::TicketCheckerPtr& ticket_checker) override { _ticket_checker = ticket_checker; } diff --git a/be/src/exec/pipeline/scan/olap_chunk_source.cpp b/be/src/exec/pipeline/scan/olap_chunk_source.cpp index 119834707b24f..3428400d6f4da 100644 --- a/be/src/exec/pipeline/scan/olap_chunk_source.cpp +++ b/be/src/exec/pipeline/scan/olap_chunk_source.cpp @@ -36,6 +36,10 @@ #include "runtime/exec_env.h" #include "storage/chunk_helper.h" #include "storage/column_predicate_rewriter.h" +<<<<<<< HEAD +======= +#include "storage/index/vector/vector_search_option.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "storage/olap_runtime_range_pruner.hpp" #include "storage/predicate_parser.h" #include "storage/projection_iterator.h" @@ -76,6 +80,16 @@ Status OlapChunkSource::prepare(RuntimeState* state) { RETURN_IF_ERROR(ChunkSource::prepare(state)); _runtime_state = state; const TOlapScanNode& thrift_olap_scan_node = _scan_node->thrift_olap_scan_node(); +<<<<<<< HEAD +======= + const TVectorSearchOptions& vector_search_options = thrift_olap_scan_node.vector_search_options; + _use_vector_index = thrift_olap_scan_node.__isset.vector_search_options && vector_search_options.enable_use_ann; + if (_use_vector_index) { + _use_ivfpq = vector_search_options.use_ivfpq; + _vector_distance_column_name = vector_search_options.vector_distance_column_name; + _params.vector_search_option = std::make_shared(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TupleDescriptor* tuple_desc = state->desc_tbl().get_tuple_descriptor(thrift_olap_scan_node.tuple_id); _slots = &tuple_desc->slots(); @@ -94,6 +108,23 @@ Status OlapChunkSource::prepare(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD +======= +void OlapChunkSource::update_chunk_exec_stats(RuntimeState* state) { + if (state->query_ctx()) { + auto* ctx = _runtime_state->query_ctx(); + int32_t node_id = _scan_op->get_plan_node_id(); + int64_t total_index_filter = _reader->stats().rows_bf_filtered + _reader->stats().rows_bitmap_index_filtered + + _reader->stats().segment_stats_filtered + + _reader->stats().rows_key_range_filtered + _reader->stats().rows_stats_filtered; + ctx->update_index_filter_stats(node_id, total_index_filter); + ctx->update_rf_filter_stats(node_id, _reader->stats().runtime_stats_filtered); + ctx->update_pred_filter_stats(node_id, _reader->stats().rows_vec_cond_filtered); + ctx->update_push_rows_stats(node_id, _reader->stats().raw_rows_read + total_index_filter); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TCounterMinMaxType::type OlapChunkSource::_get_counter_min_max_type(const std::string& metric_name) { const auto& skip_min_max_metrics = _morsel->skip_min_max_metrics(); if (skip_min_max_metrics.find(metric_name) != skip_min_max_metrics.end()) { @@ -129,6 +160,14 @@ void OlapChunkSource::_init_counter(RuntimeState* state) { const std::string segment_init_name = "SegmentInit"; _seg_init_timer = ADD_CHILD_TIMER(_runtime_profile, segment_init_name, IO_TASK_EXEC_TIMER_NAME); _bi_filter_timer = ADD_CHILD_TIMER(_runtime_profile, "BitmapIndexFilter", segment_init_name); +<<<<<<< HEAD +======= + _get_row_ranges_by_vector_index_timer = + ADD_CHILD_TIMER(_runtime_profile, "GetVectorRowRangesTime", segment_init_name); + _vector_search_timer = ADD_CHILD_TIMER(_runtime_profile, "VectorSearchTime", segment_init_name); + _process_vector_distance_and_id_timer = + ADD_CHILD_TIMER(_runtime_profile, "ProcessVectorDistanceAndIdTime", segment_init_name); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _bi_filtered_counter = ADD_CHILD_COUNTER(_runtime_profile, "BitmapIndexFilterRows", TUnit::UNIT, segment_init_name); _bf_filtered_counter = ADD_CHILD_COUNTER(_runtime_profile, "BloomFilterFilterRows", TUnit::UNIT, segment_init_name); _gin_filtered_counter = ADD_CHILD_COUNTER(_runtime_profile, "GinFilterRows", TUnit::UNIT, segment_init_name); @@ -140,6 +179,11 @@ void OlapChunkSource::_init_counter(RuntimeState* state) { ADD_CHILD_COUNTER(_runtime_profile, "SegmentRuntimeZoneMapFilterRows", TUnit::UNIT, segment_init_name); _zm_filtered_counter = ADD_CHILD_COUNTER(_runtime_profile, "ZoneMapIndexFilterRows", TUnit::UNIT, segment_init_name); +<<<<<<< HEAD +======= + _vector_index_filtered_counter = + ADD_CHILD_COUNTER(_runtime_profile, "VectorIndexFilterRows", TUnit::UNIT, segment_init_name); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _sk_filtered_counter = ADD_CHILD_COUNTER_SKIP_MIN_MAX(_runtime_profile, "ShortKeyFilterRows", TUnit::UNIT, _get_counter_min_max_type("ShortKeyFilterRows"), segment_init_name); @@ -199,7 +243,11 @@ Status OlapChunkSource::_init_reader_params(const std::vector& reader_columns) { const TOlapScanNode& thrift_olap_scan_node = _scan_node->thrift_olap_scan_node(); bool skip_aggregation = thrift_olap_scan_node.is_preaggregation; +<<<<<<< HEAD auto parser = _obj_pool.add(new PredicateParser(_tablet_schema)); +======= + auto parser = _obj_pool.add(new OlapPredicateParser(_tablet_schema)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _params.is_pipeline = true; _params.reader_type = READER_QUERY; _params.skip_aggregation = skip_aggregation; @@ -207,12 +255,37 @@ Status OlapChunkSource::_init_reader_params(const std::vectoruse_page_cache(); _params.use_pk_index = thrift_olap_scan_node.use_pk_index; +<<<<<<< HEAD +======= + _params.sample_options = thrift_olap_scan_node.sample_options; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (thrift_olap_scan_node.__isset.enable_prune_column_after_index_filter) { _params.prune_column_after_index_filter = thrift_olap_scan_node.enable_prune_column_after_index_filter; } if (thrift_olap_scan_node.__isset.enable_gin_filter) { _params.enable_gin_filter = thrift_olap_scan_node.enable_gin_filter; } +<<<<<<< HEAD +======= + _params.use_vector_index = _use_vector_index; + if (_use_vector_index) { + const TVectorSearchOptions& vector_options = thrift_olap_scan_node.vector_search_options; + + _params.vector_search_option->vector_distance_column_name = _vector_distance_column_name; + _params.vector_search_option->k = vector_options.vector_limit_k; + for (const std::string& str : vector_options.query_vector) { + _params.vector_search_option->query_vector.push_back(std::stof(str)); + } + if (_runtime_state->query_options().__isset.ann_params) { + _params.vector_search_option->query_params = _runtime_state->query_options().ann_params; + } + _params.vector_search_option->vector_range = vector_options.vector_range; + _params.vector_search_option->result_order = vector_options.result_order; + _params.vector_search_option->use_ivfpq = _use_ivfpq; + _params.vector_search_option->k_factor = _runtime_state->query_options().k_factor; + _params.vector_search_option->pq_refine_factor = _runtime_state->query_options().pq_refine_factor; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (thrift_olap_scan_node.__isset.sorted_by_keys_per_tablet) { _params.sorted_by_keys_per_tablet = thrift_olap_scan_node.sorted_by_keys_per_tablet; } @@ -229,6 +302,7 @@ Status OlapChunkSource::_init_reader_params(const std::vector>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // Range @@ -280,7 +359,20 @@ Status OlapChunkSource::_init_reader_params(const std::vector& scanner_columns) { for (auto slot : *_slots) { DCHECK(slot->is_materialized()); +<<<<<<< HEAD int32_t index = _tablet_schema->field_index(slot->col_name()); +======= + int32_t index; + if (_use_vector_index && !_use_ivfpq) { + index = _tablet_schema->field_index(slot->col_name(), _vector_distance_column_name); + if (slot->col_name() == _vector_distance_column_name) { + _params.vector_search_option->vector_column_id = index; + _params.vector_search_option->vector_slot_id = slot->id(); + } + } else { + index = _tablet_schema->field_index(slot->col_name()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (index < 0) { std::stringstream ss; ss << "invalid field name: " << slot->col_name(); @@ -304,7 +396,16 @@ Status OlapChunkSource::_init_scanner_columns(std::vector& scanner_col Status OlapChunkSource::_init_unused_output_columns(const std::vector& unused_output_columns) { for (const auto& col_name : unused_output_columns) { +<<<<<<< HEAD int32_t index = _tablet_schema->field_index(col_name); +======= + int32_t index; + if (_use_vector_index && !_use_ivfpq) { + index = _tablet_schema->field_index(col_name, _vector_distance_column_name); + } else { + index = _tablet_schema->field_index(col_name); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (index < 0) { std::stringstream ss; ss << "invalid field name: " << col_name; @@ -455,6 +556,10 @@ Status OlapChunkSource::_init_olap_reader(RuntimeState* runtime_state) { _reader = std::make_shared(_tablet, Version(_morsel->from_version(), _version), std::move(child_schema), std::move(rowsets), &_tablet_schema); +<<<<<<< HEAD +======= + _reader->set_use_gtid(_morsel->get_olap_scan_range()->__isset.gtid); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (reader_columns.size() == scanner_columns.size()) { _prj_iter = _reader; } else { @@ -462,8 +567,23 @@ Status OlapChunkSource::_init_olap_reader(RuntimeState* runtime_state) { _prj_iter = new_projection_iterator(output_schema, _reader); } +<<<<<<< HEAD if (!_scan_ctx->not_push_down_conjuncts().empty() || !_not_push_down_predicates.empty()) { _expr_filter_timer = ADD_CHILD_TIMER(_runtime_profile, "ExprFilterTime", IO_TASK_EXEC_TIMER_NAME); +======= + if (!_scan_ctx->not_push_down_conjuncts().empty() || !_non_pushdown_pred_tree.empty()) { + _expr_filter_timer = ADD_CHILD_TIMER(_runtime_profile, "ExprFilterTime", IO_TASK_EXEC_TIMER_NAME); + + _non_pushdown_predicates_counter = ADD_COUNTER_SKIP_MERGE(_runtime_profile, "NonPushdownPredicates", + TUnit::UNIT, TCounterMergeType::SKIP_ALL); + COUNTER_SET(_non_pushdown_predicates_counter, + static_cast(_scan_ctx->not_push_down_conjuncts().size() + _non_pushdown_pred_tree.size())); + if (runtime_state->fragment_ctx()->pred_tree_params().enable_show_in_profile) { + _runtime_profile->add_info_string( + "NonPushdownPredicateTree", + _non_pushdown_pred_tree.visit([](const auto& node) { return node.debug_string(); })); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } DCHECK(_params.global_dictmaps != nullptr); @@ -478,8 +598,12 @@ Status OlapChunkSource::_init_olap_reader(RuntimeState* runtime_state) { } Status OlapChunkSource::_read_chunk(RuntimeState* state, ChunkPtr* chunk) { +<<<<<<< HEAD chunk->reset(ChunkHelper::new_chunk_pooled(_prj_iter->output_schema(), _runtime_state->chunk_size(), _runtime_state->use_column_pool())); +======= + chunk->reset(ChunkHelper::new_chunk_pooled(_prj_iter->output_schema(), _runtime_state->chunk_size())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto scope = IOProfiler::scope(IOProfiler::TAG_QUERY, _tablet->tablet_id()); return _read_chunk_from_storage(_runtime_state, (*chunk).get()); } @@ -498,7 +622,16 @@ Status OlapChunkSource::_init_global_dicts(TabletReaderParams* params) { auto iter = global_dict_map.find(slot->id()); if (iter != global_dict_map.end()) { auto& dict_map = iter->second.first; +<<<<<<< HEAD int32_t index = _tablet_schema->field_index(slot->col_name()); +======= + int32_t index; + if (_use_vector_index && !_use_ivfpq) { + index = _tablet_schema->field_index(slot->col_name(), _vector_distance_column_name); + } else { + index = _tablet_schema->field_index(slot->col_name()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(index >= 0); global_dict->emplace(index, const_cast(&dict_map)); } @@ -524,11 +657,19 @@ Status OlapChunkSource::_read_chunk_from_storage(RuntimeState* state, Chunk* chu chunk->set_slot_id_to_index(slot->id(), column_index); } +<<<<<<< HEAD if (!_not_push_down_predicates.empty()) { SCOPED_TIMER(_expr_filter_timer); size_t nrows = chunk->num_rows(); _selection.resize(nrows); RETURN_IF_ERROR(_not_push_down_predicates.evaluate(chunk, _selection.data(), 0, nrows)); +======= + if (!_non_pushdown_pred_tree.empty()) { + SCOPED_TIMER(_expr_filter_timer); + size_t nrows = chunk->num_rows(); + _selection.resize(nrows); + RETURN_IF_ERROR(_non_pushdown_pred_tree.evaluate(chunk, _selection.data(), 0, nrows)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) chunk->filter(_selection); DCHECK_CHUNK(chunk); } @@ -608,6 +749,10 @@ void OlapChunkSource::_update_counter() { COUNTER_UPDATE(_seg_zm_filtered_counter, _reader->stats().segment_stats_filtered); COUNTER_UPDATE(_seg_rt_filtered_counter, _reader->stats().runtime_stats_filtered); COUNTER_UPDATE(_zm_filtered_counter, _reader->stats().rows_stats_filtered); +<<<<<<< HEAD +======= + COUNTER_UPDATE(_vector_index_filtered_counter, _reader->stats().rows_vector_index_filtered); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) COUNTER_UPDATE(_bf_filtered_counter, _reader->stats().rows_bf_filtered); COUNTER_UPDATE(_sk_filtered_counter, _reader->stats().rows_key_range_filtered); COUNTER_UPDATE(_rows_after_sk_filtered_counter, _reader->stats().rows_after_key_range); @@ -620,6 +765,12 @@ void OlapChunkSource::_update_counter() { COUNTER_UPDATE(_bi_filter_timer, _reader->stats().bitmap_index_filter_timer); COUNTER_UPDATE(_gin_filtered_counter, _reader->stats().rows_gin_filtered); COUNTER_UPDATE(_gin_filtered_timer, _reader->stats().gin_index_filter_ns); +<<<<<<< HEAD +======= + COUNTER_UPDATE(_get_row_ranges_by_vector_index_timer, _reader->stats().get_row_ranges_by_vector_index_timer); + COUNTER_UPDATE(_vector_search_timer, _reader->stats().vector_search_timer); + COUNTER_UPDATE(_process_vector_distance_and_id_timer, _reader->stats().process_vector_distance_and_id_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) COUNTER_UPDATE(_block_seek_counter, _reader->stats().block_seek_num); COUNTER_UPDATE(_rowsets_read_count, _reader->stats().rowsets_read_count); @@ -628,6 +779,14 @@ void OlapChunkSource::_update_counter() { COUNTER_SET(_pushdown_predicates_counter, (int64_t)_params.pred_tree.size()); +<<<<<<< HEAD +======= + if (_runtime_state->fragment_ctx()->pred_tree_params().enable_show_in_profile) { + _runtime_profile->add_info_string( + "PushdownPredicateTree", _params.pred_tree.visit([](const auto& node) { return node.debug_string(); })); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StarRocksMetrics::instance()->query_scan_bytes.increment(_scan_bytes); StarRocksMetrics::instance()->query_scan_rows.increment(_scan_rows_num); @@ -701,6 +860,26 @@ void OlapChunkSource::_update_counter() { RuntimeProfile::Counter* c = ADD_CHILD_TIMER(_runtime_profile, "FlatJsonFlatten", parent_name); COUNTER_UPDATE(c, _reader->stats().json_flatten_ns); } +<<<<<<< HEAD +======= + + // Data sampling + if (_params.sample_options.enable_sampling) { + _runtime_profile->add_info_string("SampleMethod", to_string(_params.sample_options.sample_method)); + _runtime_profile->add_info_string("SamplePercent", + std::to_string(_params.sample_options.probability_percent) + "%"); + COUNTER_UPDATE(ADD_CHILD_TIMER(_runtime_profile, "SampleTime", parent_name), + _reader->stats().sample_population_size); + COUNTER_UPDATE(ADD_CHILD_TIMER(_runtime_profile, "SampleBuildHistogramTime", parent_name), + _reader->stats().sample_build_histogram_time_ns); + COUNTER_UPDATE(ADD_CHILD_COUNTER(_runtime_profile, "SampleSize", TUnit::UNIT, parent_name), + _reader->stats().sample_size); + COUNTER_UPDATE(ADD_CHILD_COUNTER(_runtime_profile, "SamplePopulationSize", TUnit::UNIT, parent_name), + _reader->stats().sample_population_size); + COUNTER_UPDATE(ADD_CHILD_COUNTER(_runtime_profile, "SampleBuildHistogramCount", TUnit::UNIT, parent_name), + _reader->stats().sample_build_histogram_count); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/scan/olap_chunk_source.h b/be/src/exec/pipeline/scan/olap_chunk_source.h index 5e3b8c95ddac3..549cf26eb89ff 100644 --- a/be/src/exec/pipeline/scan/olap_chunk_source.h +++ b/be/src/exec/pipeline/scan/olap_chunk_source.h @@ -49,6 +49,10 @@ class OlapChunkSource final : public ChunkSource { Status prepare(RuntimeState* state) override; void close(RuntimeState* state) override; +<<<<<<< HEAD +======= + void update_chunk_exec_stats(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: Status _read_chunk(RuntimeState* state, ChunkPtr* chunk) override; @@ -74,12 +78,20 @@ class OlapChunkSource final : public ChunkSource { OlapScanNode* _scan_node; OlapScanContext* _scan_ctx; +<<<<<<< HEAD const int64_t _limit; // -1: no limit TInternalScanRange* _scan_range; PredicateTree _non_pushdown_pred_tree; ConjunctivePredicates _not_push_down_predicates; std::vector _selection; +======= + int64_t _limit; // -1: no limit + TInternalScanRange* _scan_range; + + PredicateTree _non_pushdown_pred_tree; + Filter _selection; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ObjectPool _obj_pool; TabletSharedPtr _tablet; @@ -105,6 +117,15 @@ class OlapChunkSource final : public ChunkSource { std::vector _column_access_paths; +<<<<<<< HEAD +======= + bool _use_vector_index = false; + + bool _use_ivfpq = false; + + std::string _vector_distance_column_name; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The following are profile meatures int64_t _num_rows_read = 0; @@ -133,6 +154,10 @@ class OlapChunkSource final : public ChunkSource { RuntimeProfile::Counter* _rows_key_range_counter = nullptr; RuntimeProfile::Counter* _bf_filter_timer = nullptr; RuntimeProfile::Counter* _zm_filtered_counter = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* _vector_index_filtered_counter = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* _bf_filtered_counter = nullptr; RuntimeProfile::Counter* _seg_zm_filtered_counter = nullptr; RuntimeProfile::Counter* _seg_rt_filtered_counter = nullptr; @@ -149,7 +174,15 @@ class OlapChunkSource final : public ChunkSource { RuntimeProfile::Counter* _bi_filter_timer = nullptr; RuntimeProfile::Counter* _gin_filtered_counter = nullptr; RuntimeProfile::Counter* _gin_filtered_timer = nullptr; +<<<<<<< HEAD + RuntimeProfile::Counter* _pushdown_predicates_counter = nullptr; +======= + RuntimeProfile::Counter* _get_row_ranges_by_vector_index_timer = nullptr; + RuntimeProfile::Counter* _vector_search_timer = nullptr; + RuntimeProfile::Counter* _process_vector_distance_and_id_timer = nullptr; RuntimeProfile::Counter* _pushdown_predicates_counter = nullptr; + RuntimeProfile::Counter* _non_pushdown_predicates_counter = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* _rowsets_read_count = nullptr; RuntimeProfile::Counter* _segments_read_count = nullptr; RuntimeProfile::Counter* _total_columns_data_page_count = nullptr; diff --git a/be/src/exec/pipeline/scan/olap_scan_context.cpp b/be/src/exec/pipeline/scan/olap_scan_context.cpp index 39eb0f3bc51b4..d90e052ae9273 100644 --- a/be/src/exec/pipeline/scan/olap_scan_context.cpp +++ b/be/src/exec/pipeline/scan/olap_scan_context.cpp @@ -15,6 +15,10 @@ #include "exec/pipeline/scan/olap_scan_context.h" #include "exec/olap_scan_node.h" +<<<<<<< HEAD +======= +#include "exec/pipeline/fragment_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/runtime_filter_bank.h" #include "storage/tablet.h" @@ -89,7 +93,11 @@ Status OlapScanContext::capture_tablet_rowsets(const std::vectorfull_name() << ", rowsets: " << tablet_rowsets[i].size() +<<<<<<< HEAD << ", version: " << scan_range->version; +======= + << ", version: " << scan_range->version << ", gtid: " << scan_range->gtid; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _tablets[i] = std::move(tablet); } @@ -110,12 +118,17 @@ Status OlapScanContext::parse_conjuncts(RuntimeState* state, const std::vector>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!status.ok()) { return status; } // Init _conjuncts_manager. +<<<<<<< HEAD OlapScanConjunctsManager& cm = _conjuncts_manager; cm.conjunct_ctxs_ptr = &_conjunct_ctxs; cm.tuple_desc = tuple_desc; @@ -125,6 +138,8 @@ Status OlapScanContext::parse_conjuncts(RuntimeState* state, const std::vector>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TQueryOptions& query_options = state->query_options(); int32_t max_scan_key_num; if (query_options.__isset.max_scan_key_num && query_options.max_scan_key_num > 0) { @@ -137,12 +152,37 @@ Status OlapScanContext::parse_conjuncts(RuntimeState* state, const std::vectorfragment_ctx()->pred_tree_params(); + + _conjuncts_manager = std::make_unique(std::move(opts)); + ScanConjunctsManager& cm = *_conjuncts_manager; + + // Parse conjuncts via _conjuncts_manager. + RETURN_IF_ERROR(cm.parse_conjuncts()); + + // Get key_ranges and not_push_down_conjuncts from _conjuncts_manager. + RETURN_IF_ERROR(cm.get_key_ranges(&_key_ranges)); + cm.get_not_push_down_conjuncts(&_not_push_down_conjuncts); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // rewrite after push down scan predicate, scan predicate should rewrite by local-dict RETURN_IF_ERROR(state->mutable_dict_optimize_parser()->rewrite_conjuncts(&_not_push_down_conjuncts)); diff --git a/be/src/exec/pipeline/scan/olap_scan_context.h b/be/src/exec/pipeline/scan/olap_scan_context.h index 000867e0a478f..7c9fc1c8edd57 100644 --- a/be/src/exec/pipeline/scan/olap_scan_context.h +++ b/be/src/exec/pipeline/scan/olap_scan_context.h @@ -101,7 +101,11 @@ class OlapScanContext final : public ContextWithDependency { RuntimeFilterProbeCollector* runtime_bloom_filters, int32_t driver_sequence); OlapScanNode* scan_node() const { return _scan_node; } +<<<<<<< HEAD OlapScanConjunctsManager& conjuncts_manager() { return _conjuncts_manager; } +======= + ScanConjunctsManager& conjuncts_manager() { return *_conjuncts_manager; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& not_push_down_conjuncts() const { return _not_push_down_conjuncts; } const std::vector>& key_ranges() const { return _key_ranges; } BalancedChunkBuffer& get_chunk_buffer() { return _chunk_buffer; } @@ -129,7 +133,11 @@ class OlapScanContext final : public ContextWithDependency { int64_t _scan_table_id; std::vector _conjunct_ctxs; +<<<<<<< HEAD OlapScanConjunctsManager _conjuncts_manager; +======= + std::unique_ptr _conjuncts_manager = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The conjuncts couldn't push down to storage engine std::vector _not_push_down_conjuncts; std::vector> _key_ranges; diff --git a/be/src/exec/pipeline/scan/olap_scan_operator.cpp b/be/src/exec/pipeline/scan/olap_scan_operator.cpp index ca6654cf0de6e..653aaba820919 100644 --- a/be/src/exec/pipeline/scan/olap_scan_operator.cpp +++ b/be/src/exec/pipeline/scan/olap_scan_operator.cpp @@ -122,6 +122,7 @@ bool OlapScanOperator::has_shared_chunk_source() const { return _ctx->has_active_input(); } +<<<<<<< HEAD size_t OlapScanOperator::num_buffered_chunks() const { return _ctx->get_chunk_buffer().size(_driver_sequence); } @@ -160,6 +161,10 @@ bool OlapScanOperator::is_buffer_full() const { void OlapScanOperator::set_buffer_finished() { _ctx->get_chunk_buffer().set_finished(_driver_sequence); +======= +BalancedChunkBuffer& OlapScanOperator::get_chunk_buffer() const { + return _ctx->get_chunk_buffer(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/scan/olap_scan_operator.h b/be/src/exec/pipeline/scan/olap_scan_operator.h index 1a374707d0cc2..ed863f06acbc3 100644 --- a/be/src/exec/pipeline/scan/olap_scan_operator.h +++ b/be/src/exec/pipeline/scan/olap_scan_operator.h @@ -67,6 +67,7 @@ class OlapScanOperator final : public ScanOperator { void attach_chunk_source(int32_t source_index) override; void detach_chunk_source(int32_t source_index) override; bool has_shared_chunk_source() const override; +<<<<<<< HEAD ChunkPtr get_chunk_from_buffer() override; size_t num_buffered_chunks() const override; size_t buffer_size() const override; @@ -76,6 +77,9 @@ class OlapScanOperator final : public ScanOperator { ChunkBufferTokenPtr pin_chunk(int num_chunks) override; bool is_buffer_full() const override; void set_buffer_finished() override; +======= + BalancedChunkBuffer& get_chunk_buffer() const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: OlapScanContextPtr _ctx; diff --git a/be/src/exec/pipeline/scan/scan_operator.cpp b/be/src/exec/pipeline/scan/scan_operator.cpp index b6829190b39c3..1f2a1ccc960ec 100644 --- a/be/src/exec/pipeline/scan/scan_operator.cpp +++ b/be/src/exec/pipeline/scan/scan_operator.cpp @@ -203,7 +203,11 @@ bool ScanOperator::is_finished() const { } // Any io task is running or needs to run. +<<<<<<< HEAD if (_num_running_io_tasks > 0 || !_morsel_queue->empty()) { +======= + if (_num_running_io_tasks > 0 || _morsel_queue->has_more() || !_morsel_queue->empty()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return false; } @@ -228,6 +232,21 @@ void ScanOperator::_detach_chunk_sources() { } } +<<<<<<< HEAD +======= +void ScanOperator::update_exec_stats(RuntimeState* state) { + auto ctx = state->query_ctx(); + if (ctx != nullptr) { + ctx->update_pull_rows_stats(_plan_node_id, _pull_row_num_counter->value()); + if (_bloom_filter_eval_context.join_runtime_filter_input_counter != nullptr) { + int64_t input_rows = _bloom_filter_eval_context.join_runtime_filter_input_counter->value(); + int64_t output_rows = _bloom_filter_eval_context.join_runtime_filter_output_counter->value(); + ctx->update_rf_filter_stats(_plan_node_id, input_rows - output_rows); + } + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status ScanOperator::set_finishing(RuntimeState* state) { // check when expired, are there running io tasks or submitted tasks if (UNLIKELY(state != nullptr && state->query_ctx()->is_query_expired() && @@ -373,6 +392,10 @@ void ScanOperator::_finish_chunk_source_task(RuntimeState* state, int chunk_sour // must be protected by lock std::lock_guard guard(_task_mutex); if (!_chunk_sources[chunk_source_index]->has_next_chunk() || _is_finished) { +<<<<<<< HEAD +======= + _chunk_sources[chunk_source_index]->update_chunk_exec_stats(state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _close_chunk_source_unlocked(state, chunk_source_index); } _is_io_task_running[chunk_source_index] = false; diff --git a/be/src/exec/pipeline/scan/scan_operator.h b/be/src/exec/pipeline/scan/scan_operator.h index 0c6e701bc3435..862bad9e44238 100644 --- a/be/src/exec/pipeline/scan/scan_operator.h +++ b/be/src/exec/pipeline/scan/scan_operator.h @@ -14,6 +14,11 @@ #pragma once +<<<<<<< HEAD +======= +#include "exec/pipeline/pipeline_fwd.h" +#include "exec/pipeline/scan/balanced_chunk_buffer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/source_operator.h" #include "exec/query_cache/cache_operator.h" #include "exec/query_cache/lane_arbiter.h" @@ -38,7 +43,11 @@ class ScanOperator : public SourceOperator { static size_t max_buffer_capacity() { return kIOTaskBatchSize; } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The running I/O task committed by ScanOperator holds the reference of query context, // so it can prevent the scan operator from deconstructored, but cannot prevent it from closed. @@ -52,9 +61,15 @@ class ScanOperator : public SourceOperator { bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; +======= + Status set_finishing(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void update_metrics(RuntimeState* state) override { _merge_chunk_source_profiles(state); } @@ -67,7 +82,11 @@ class ScanOperator : public SourceOperator { int64_t global_rf_wait_timeout_ns() const override; /// interface for different scan node +<<<<<<< HEAD [[nodiscard]] virtual Status do_prepare(RuntimeState* state) = 0; +======= + virtual Status do_prepare(RuntimeState* state) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void do_close(RuntimeState* state) = 0; virtual ChunkSourcePtr create_chunk_source(MorselPtr morsel, int32_t chunk_source_index) = 0; @@ -94,6 +113,11 @@ class ScanOperator : public SourceOperator { virtual int64_t get_scan_table_id() const { return -1; } +<<<<<<< HEAD +======= + void update_exec_stats(RuntimeState* state) override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: static constexpr size_t kIOTaskBatchSize = 64; @@ -102,6 +126,7 @@ class ScanOperator : public SourceOperator { virtual void attach_chunk_source(int32_t source_index) = 0; virtual void detach_chunk_source(int32_t source_index) {} virtual bool has_shared_chunk_source() const = 0; +<<<<<<< HEAD virtual ChunkPtr get_chunk_from_buffer() = 0; virtual size_t num_buffered_chunks() const = 0; virtual size_t buffer_size() const = 0; @@ -117,6 +142,34 @@ class ScanOperator : public SourceOperator { [[nodiscard]] virtual Status _pickup_morsel(RuntimeState* state, int chunk_source_index); [[nodiscard]] Status _trigger_next_scan(RuntimeState* state, int chunk_source_index); [[nodiscard]] Status _try_to_trigger_next_scan(RuntimeState* state); +======= + + virtual BalancedChunkBuffer& get_chunk_buffer() const = 0; + + ChunkPtr get_chunk_from_buffer() { + auto& chunk_buffer = get_chunk_buffer(); + ChunkPtr chunk = nullptr; + if (chunk_buffer.try_get(_driver_sequence, &chunk)) { + return chunk; + } + return nullptr; + } + + size_t num_buffered_chunks() const { return get_chunk_buffer().size(_driver_sequence); } + size_t buffer_size() const { return get_chunk_buffer().size(_driver_sequence); } + size_t buffer_capacity() const { return get_chunk_buffer().limiter()->capacity(); } + size_t buffer_memory_usage() const { return get_chunk_buffer().memory_usage(); } + size_t default_buffer_capacity() const { return get_chunk_buffer().limiter()->default_capacity(); } + ChunkBufferTokenPtr pin_chunk(int num_chunks) { return get_chunk_buffer().limiter()->pin(num_chunks); } + bool is_buffer_full() const { return get_chunk_buffer().limiter()->is_full(); } + void set_buffer_finished() { get_chunk_buffer().set_finished(_driver_sequence); } + + // This method is only invoked when current morsel is reached eof + // and all cached chunk of this morsel has benn read out + virtual Status _pickup_morsel(RuntimeState* state, int chunk_source_index); + Status _trigger_next_scan(RuntimeState* state, int chunk_source_index); + Status _try_to_trigger_next_scan(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void _close_chunk_source_unlocked(RuntimeState* state, int index); void _close_chunk_source(RuntimeState* state, int index); virtual void _finish_chunk_source_task(RuntimeState* state, int chunk_source_index, int64_t cpu_time_ns, @@ -136,7 +189,11 @@ class ScanOperator : public SourceOperator { } } +<<<<<<< HEAD [[nodiscard]] inline Status _get_scan_status() const { +======= + inline Status _get_scan_status() const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(_scan_status_mutex); return _scan_status; } @@ -215,11 +272,19 @@ class ScanOperatorFactory : public SourceOperatorFactory { bool with_morsels() const override { return true; } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; void close(RuntimeState* state) override; // interface for different scan node [[nodiscard]] virtual Status do_prepare(RuntimeState* state) = 0; +======= + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + // interface for different scan node + virtual Status do_prepare(RuntimeState* state) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void do_close(RuntimeState* state) = 0; virtual OperatorPtr do_create(int32_t dop, int32_t driver_sequence) = 0; diff --git a/be/src/exec/pipeline/scan/schema_scan_operator.cpp b/be/src/exec/pipeline/scan/schema_scan_operator.cpp index a5490b06ceb16..d875709531cd3 100644 --- a/be/src/exec/pipeline/scan/schema_scan_operator.cpp +++ b/be/src/exec/pipeline/scan/schema_scan_operator.cpp @@ -58,6 +58,7 @@ ChunkSourcePtr SchemaScanOperator::create_chunk_source(MorselPtr morsel, int32_t std::move(morsel), _ctx); } +<<<<<<< HEAD ChunkPtr SchemaScanOperator::get_chunk_from_buffer() { ChunkPtr chunk = nullptr; if (_ctx->get_chunk_buffer().try_get(_driver_sequence, &chunk)) { @@ -98,4 +99,6 @@ void SchemaScanOperator::set_buffer_finished() { _ctx->get_chunk_buffer().set_finished(_driver_sequence); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::pipeline diff --git a/be/src/exec/pipeline/scan/schema_scan_operator.h b/be/src/exec/pipeline/scan/schema_scan_operator.h index 8b9bc1651e306..d47f2390459f1 100644 --- a/be/src/exec/pipeline/scan/schema_scan_operator.h +++ b/be/src/exec/pipeline/scan/schema_scan_operator.h @@ -59,6 +59,7 @@ class SchemaScanOperator final : public ScanOperator { void attach_chunk_source(int32_t source_index) override {} void detach_chunk_source(int32_t source_index) override {} bool has_shared_chunk_source() const override { return false; } +<<<<<<< HEAD ChunkPtr get_chunk_from_buffer() override; size_t num_buffered_chunks() const override; size_t buffer_size() const override; @@ -68,6 +69,9 @@ class SchemaScanOperator final : public ScanOperator { ChunkBufferTokenPtr pin_chunk(int num_chunks) override; bool is_buffer_full() const override; void set_buffer_finished() override; +======= + BalancedChunkBuffer& get_chunk_buffer() const override { return _ctx->get_chunk_buffer(); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) workgroup::ScanSchedEntityType sched_entity_type() const override { return workgroup::ScanSchedEntityType::CONNECTOR; diff --git a/be/src/exec/pipeline/select_operator.cpp b/be/src/exec/pipeline/select_operator.cpp index efbb8dfe0162f..f7fe30bfeb27d 100644 --- a/be/src/exec/pipeline/select_operator.cpp +++ b/be/src/exec/pipeline/select_operator.cpp @@ -85,8 +85,31 @@ bool SelectOperator::need_input() const { } Status SelectOperator::push_chunk(RuntimeState* state, const ChunkPtr& chunk) { +<<<<<<< HEAD RETURN_IF_ERROR(eval_conjuncts_and_in_filters(_conjunct_ctxs, chunk.get())); _curr_chunk = chunk; +======= + if (!_common_exprs.empty()) { + _curr_chunk = std::make_shared(); + for (const auto& [slot_id, _] : chunk->get_slot_id_to_index_map()) { + _curr_chunk->append_column(chunk->get_column_by_slot_id(slot_id), slot_id); + } + SCOPED_TIMER(_conjuncts_timer); + for (const auto& [slot_id, expr] : _common_exprs) { + ASSIGN_OR_RETURN(auto col, expr->evaluate(_curr_chunk.get())); + _curr_chunk->append_column(col, slot_id); + } + } else { + _curr_chunk = chunk; + } + RETURN_IF_ERROR(eval_conjuncts_and_in_filters(_conjunct_ctxs, _curr_chunk.get())); + { + // common_exprs' slots are only needed inside this operator, no need to pass it downsteam + for (const auto& [slot_id, _] : _common_exprs) { + _curr_chunk->remove_column_by_slot_id(slot_id); + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -100,7 +123,18 @@ Status SelectOperator::reset_state(starrocks::RuntimeState* state, const std::ve Status SelectOperatorFactory::prepare(RuntimeState* state) { RETURN_IF_ERROR(OperatorFactory::prepare(state)); RETURN_IF_ERROR(Expr::prepare(_conjunct_ctxs, state)); +<<<<<<< HEAD + RETURN_IF_ERROR(Expr::open(_conjunct_ctxs, state)); +======= + std::vector common_expr_ctxs; + for (const auto& [_, ctx] : _common_exprs) { + common_expr_ctxs.emplace_back(ctx); + } + RETURN_IF_ERROR(Expr::prepare(common_expr_ctxs, state)); + RETURN_IF_ERROR(Expr::open(_conjunct_ctxs, state)); + RETURN_IF_ERROR(Expr::open(common_expr_ctxs, state)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } diff --git a/be/src/exec/pipeline/select_operator.h b/be/src/exec/pipeline/select_operator.h index edc6c5390baf2..0ce51ae924200 100644 --- a/be/src/exec/pipeline/select_operator.h +++ b/be/src/exec/pipeline/select_operator.h @@ -25,8 +25,15 @@ namespace pipeline { class SelectOperator final : public Operator { public: SelectOperator(OperatorFactory* factory, int32_t id, int32_t plan_node_id, int32_t driver_sequence, +<<<<<<< HEAD const std::vector& conjunct_ctxs) : Operator(factory, id, "select", plan_node_id, false, driver_sequence), _conjunct_ctxs(conjunct_ctxs) {} +======= + const std::vector& conjunct_ctxs, const std::map& common_exprs) + : Operator(factory, id, "select", plan_node_id, false, driver_sequence), + _conjunct_ctxs(conjunct_ctxs), + _common_exprs(common_exprs) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~SelectOperator() override = default; Status prepare(RuntimeState* state) override; @@ -53,19 +60,36 @@ class SelectOperator final : public Operator { ChunkPtr _pre_output_chunk = nullptr; const std::vector& _conjunct_ctxs; +<<<<<<< HEAD +======= + const std::map& _common_exprs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _is_finished = false; }; class SelectOperatorFactory final : public OperatorFactory { public: +<<<<<<< HEAD SelectOperatorFactory(int32_t id, int32_t plan_node_id, std::vector&& conjunct_ctxs) : OperatorFactory(id, "select", plan_node_id), _conjunct_ctxs(std::move(conjunct_ctxs)) {} +======= + SelectOperatorFactory(int32_t id, int32_t plan_node_id, std::vector&& conjunct_ctxs, + std::map&& common_exprs) + : OperatorFactory(id, "select", plan_node_id), + _conjunct_ctxs(std::move(conjunct_ctxs)), + _common_exprs(std::move(common_exprs)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~SelectOperatorFactory() override = default; OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override { +<<<<<<< HEAD return std::make_shared(this, _id, _plan_node_id, driver_sequence, _conjunct_ctxs); +======= + return std::make_shared(this, _id, _plan_node_id, driver_sequence, _conjunct_ctxs, + _common_exprs); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status prepare(RuntimeState* state) override; @@ -73,6 +97,10 @@ class SelectOperatorFactory final : public OperatorFactory { private: std::vector _conjunct_ctxs; +<<<<<<< HEAD +======= + std::map _common_exprs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace pipeline diff --git a/be/src/exec/pipeline/sort/local_partition_topn_context.cpp b/be/src/exec/pipeline/sort/local_partition_topn_context.cpp index aa6368aba7fbf..af67542948062 100644 --- a/be/src/exec/pipeline/sort/local_partition_topn_context.cpp +++ b/be/src/exec/pipeline/sort/local_partition_topn_context.cpp @@ -22,19 +22,35 @@ namespace starrocks::pipeline { +<<<<<<< HEAD LocalPartitionTopnContext::LocalPartitionTopnContext(const std::vector& t_partition_exprs, +======= +LocalPartitionTopnContext::LocalPartitionTopnContext(const std::vector& t_partition_exprs, bool enable_pre_agg, + const std::vector& t_pre_agg_exprs, + const std::vector& t_pre_agg_output_slot_id, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& sort_exprs, std::vector is_asc_order, std::vector is_null_first, std::string sort_keys, int64_t offset, int64_t partition_limit, const TTopNType::type topn_type) : _t_partition_exprs(t_partition_exprs), +<<<<<<< HEAD +======= + _enable_pre_agg(enable_pre_agg), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _sort_exprs(sort_exprs), _is_asc_order(std::move(is_asc_order)), _is_null_first(std::move(is_null_first)), _sort_keys(std::move(sort_keys)), _offset(offset), _partition_limit(partition_limit), +<<<<<<< HEAD _topn_type(topn_type) {} +======= + _topn_type(topn_type) { + _pre_agg = std::make_unique(t_pre_agg_exprs, t_pre_agg_output_slot_id); +} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status LocalPartitionTopnContext::prepare(RuntimeState* state, RuntimeProfile* runtime_profile) { RETURN_IF_ERROR(Expr::create_expr_trees(state->obj_pool(), _t_partition_exprs, &_partition_exprs, state)); @@ -55,8 +71,123 @@ Status LocalPartitionTopnContext::prepare(RuntimeState* state, RuntimeProfile* r _has_nullable_key = _has_nullable_key || _partition_types[i].is_nullable; } +<<<<<<< HEAD _chunks_partitioner = std::make_unique(_has_nullable_key, _partition_exprs, _partition_types); return _chunks_partitioner->prepare(state, runtime_profile); +======= + _mem_pool = std::make_unique(); + if (_enable_pre_agg) { + RETURN_IF_ERROR(prepare_pre_agg(state)); + } + + _chunks_partitioner = + std::make_unique(_has_nullable_key, _partition_exprs, _partition_types, _mem_pool.get()); + return _chunks_partitioner->prepare(state, runtime_profile, _enable_pre_agg); +} + +Status LocalPartitionTopnContext::prepare_pre_agg(RuntimeState* state) { + size_t agg_size = _pre_agg->_t_pre_agg_exprs.size(); + _pre_agg->_agg_fn_ctxs.resize(agg_size); + _pre_agg->_agg_functions.resize(agg_size); + _pre_agg->_agg_expr_ctxs.resize(agg_size); + _pre_agg->_agg_input_columns.resize(agg_size); + _pre_agg->_agg_input_raw_columns.resize(agg_size); + _pre_agg->_agg_fn_types.resize(agg_size); + _pre_agg->_agg_states_offsets.resize(agg_size); + for (int i = 0; i < agg_size; ++i) { + const TExpr& desc = _pre_agg->_t_pre_agg_exprs[i]; + const TFunction& fn = desc.nodes[0].fn; + + auto num_args = desc.nodes[0].num_children; + _pre_agg->_agg_input_columns[i].resize(num_args); + _pre_agg->_agg_input_raw_columns[i].resize(num_args); + int node_idx = 0; + for (int j = 0; j < desc.nodes[0].num_children; ++j) { + ++node_idx; + Expr* expr = nullptr; + ExprContext* ctx = nullptr; + RETURN_IF_ERROR(Expr::create_tree_from_thrift_with_jit(state->obj_pool(), desc.nodes, nullptr, &node_idx, + &expr, &ctx, state)); + _pre_agg->_agg_expr_ctxs[i].emplace_back(ctx); + } + + TypeDescriptor return_type = TypeDescriptor::from_thrift(fn.ret_type); + TypeDescriptor serde_type = TypeDescriptor::from_thrift(fn.aggregate_fn.intermediate_type); + + TypeDescriptor arg_type = TypeDescriptor::from_thrift(fn.arg_types[0]); + + // Collect arg_typedescs for aggregate function. + std::vector arg_typedescs; + for (auto& type : fn.arg_types) { + arg_typedescs.push_back(TypeDescriptor::from_thrift(type)); + } + + _pre_agg->_agg_fn_ctxs[i] = FunctionContext::create_context(state, _mem_pool.get(), return_type, arg_typedescs); + state->obj_pool()->add(_pre_agg->_agg_fn_ctxs[i]); + + bool is_input_nullable = false; + const AggregateFunction* func = nullptr; + if (fn.name.function_name == "count") { + return_type.type = TYPE_BIGINT; + arg_type.type = TYPE_BIGINT; + serde_type.type = TYPE_BIGINT; + is_input_nullable = !fn.arg_types.empty() && (desc.nodes[0].has_nullable_child); + _pre_agg->_agg_fn_types[i] = {serde_type, false, false}; + } else { + // For nullable aggregate function(sum, max, min, avg), + // we should always use nullable aggregate function. + is_input_nullable = true; + _pre_agg->_agg_fn_types[i] = {serde_type, is_input_nullable, desc.nodes[0].is_nullable}; + } + + func = get_window_function(fn.name.function_name, arg_type.type, return_type.type, is_input_nullable, + fn.binary_type, state->func_version()); + if (func == nullptr) { + return Status::InternalError(strings::Substitute("Invalid window function plan: ($0, $1, $2, $3, $4, $5)", + fn.name.function_name, arg_type.type, return_type.type, + is_input_nullable, fn.binary_type, state->func_version())); + } + _pre_agg->_agg_functions[i] = func; + } + + // Compute agg state total size and offsets. + for (int i = 0; i < agg_size; ++i) { + _pre_agg->_agg_states_offsets[i] = _pre_agg->_agg_states_total_size; + _pre_agg->_agg_states_total_size += _pre_agg->_agg_functions[i]->size(); + _pre_agg->_max_agg_state_align_size = + std::max(_pre_agg->_max_agg_state_align_size, _pre_agg->_agg_functions[i]->alignof_size()); + + // If not the last aggregate_state, we need pad it so that next aggregate_state will be aligned. + if (i + 1 < _pre_agg->_agg_fn_ctxs.size()) { + size_t next_state_align_size = _pre_agg->_agg_functions[i + 1]->alignof_size(); + // Extend total_size to next alignment requirement + // Add padding by rounding up '_agg_states_total_size' to be a multiplier of next_state_align_size. + _pre_agg->_agg_states_total_size = (_pre_agg->_agg_states_total_size + next_state_align_size - 1) / + next_state_align_size * next_state_align_size; + } + } + + for (const auto& ctx : _pre_agg->_agg_expr_ctxs) { + RETURN_IF_ERROR(Expr::prepare(ctx, state)); + RETURN_IF_ERROR(Expr::open(ctx, state)); + } + + return Status::OK(); +} + +Status LocalPartitionTopnContext::compute_agg_state(Chunk* chunk, size_t partition_idx) { + DCHECK(_enable_pre_agg); + + RETURN_IF_ERROR(_evaluate_agg_input_columns(chunk)); + + for (size_t i = 0; i < _pre_agg->_agg_fn_ctxs.size(); i++) { + _pre_agg->_agg_functions[i]->update_batch_single_state( + _pre_agg->_agg_fn_ctxs[i], chunk->num_rows(), _pre_agg->_agg_input_raw_columns[i].data(), + _pre_agg->_managed_fn_states[partition_idx]->mutable_data() + _pre_agg->_agg_states_offsets[i]); + } + + return Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status LocalPartitionTopnContext::push_one_chunk_to_partitioner(RuntimeState* state, const ChunkPtr& chunk) { @@ -66,9 +197,25 @@ Status LocalPartitionTopnContext::push_one_chunk_to_partitioner(RuntimeState* st _chunks_sorters.emplace_back(std::make_shared( state, &_sort_exprs, &_is_asc_order, &_is_null_first, _sort_keys, _offset, _partition_limit, _topn_type, ChunksSorterTopn::tunning_buffered_chunks(_partition_limit))); +<<<<<<< HEAD + }, + [this, state](size_t partition_idx, const ChunkPtr& chunk) { + (void)_chunks_sorters[partition_idx]->update(state, chunk); +======= + // create agg state for new partition + if (_enable_pre_agg) { + AggDataPtr agg_states = _mem_pool->allocate_aligned(_pre_agg->_agg_states_total_size, + _pre_agg->_max_agg_state_align_size); + _pre_agg->_managed_fn_states.emplace_back(std::make_unique>( + &_pre_agg->_agg_fn_ctxs, agg_states, _pre_agg.get())); + } }, [this, state](size_t partition_idx, const ChunkPtr& chunk) { (void)_chunks_sorters[partition_idx]->update(state, chunk); + if (_enable_pre_agg) { + (void)compute_agg_state(chunk.get(), partition_idx); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) })); if (_chunks_partitioner->is_passthrough()) { RETURN_IF_ERROR(transfer_all_chunks_from_partitioner_to_sorters(state)); @@ -77,6 +224,13 @@ Status LocalPartitionTopnContext::push_one_chunk_to_partitioner(RuntimeState* st } void LocalPartitionTopnContext::sink_complete() { +<<<<<<< HEAD +======= + // when enable_pre_agg, mempool will allocate agg state which is used for source op + if (!_enable_pre_agg) { + _mem_pool.reset(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_sink_complete = true; } @@ -89,6 +243,12 @@ Status LocalPartitionTopnContext::transfer_all_chunks_from_partitioner_to_sorter RETURN_IF_ERROR( _chunks_partitioner->consume_from_hash_map([this, state](int32_t partition_idx, const ChunkPtr& chunk) { (void)_chunks_sorters[partition_idx]->update(state, chunk); +<<<<<<< HEAD +======= + if (_enable_pre_agg) { + (void)compute_agg_state(chunk.get(), partition_idx); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; })); @@ -123,6 +283,12 @@ StatusOr LocalPartitionTopnContext::pull_one_chunk() { } } chunk = _chunks_partitioner->consume_from_passthrough_buffer(); +<<<<<<< HEAD +======= + if (_enable_pre_agg && chunk != nullptr) { + RETURN_IF_ERROR(output_agg_streaming(chunk.get())); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return chunk; } @@ -131,23 +297,137 @@ StatusOr LocalPartitionTopnContext::pull_one_chunk_from_sorters() { ChunkPtr chunk = nullptr; bool eos = false; RETURN_IF_ERROR(chunks_sorter->get_next(&chunk, &eos)); +<<<<<<< HEAD if (eos) { +======= + + if (_enable_pre_agg) { + output_agg_result(chunk.get(), eos, _pre_agg->_is_first_chunk_of_current_sorter); + } + _pre_agg->_is_first_chunk_of_current_sorter = false; + + if (eos) { + _pre_agg->_is_first_chunk_of_current_sorter = true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Current sorter has no output, try to get chunk from next sorter _sorter_index++; } return chunk; } +<<<<<<< HEAD LocalPartitionTopnContextFactory::LocalPartitionTopnContextFactory( RuntimeState*, const TTopNType::type topn_type, bool is_merging, const std::vector& sort_exprs, std::vector is_asc_order, std::vector is_null_first, const std::vector& t_partition_exprs, int64_t offset, int64_t limit, std::string sort_keys, const std::vector& order_by_types, const std::vector&) +======= +Columns LocalPartitionTopnContext::_create_agg_result_columns(size_t num_rows) { + Columns agg_result_columns(_pre_agg->_agg_fn_types.size()); + for (size_t i = 0; i < _pre_agg->_agg_fn_types.size(); ++i) { + // For count, count distinct, bitmap_union_int such as never return null function, + // we need to create a not-nullable column. + agg_result_columns[i] = ColumnHelper::create_column(_pre_agg->_agg_fn_types[i].result_type, + _pre_agg->_agg_fn_types[i].is_nullable); + agg_result_columns[i]->reserve(num_rows); + } + return agg_result_columns; +} + +void LocalPartitionTopnContext::output_agg_result(Chunk* chunk, bool eos, bool is_first_chunk) { + // when eos, chunk is nullptr, just do nothing + if (eos || chunk == nullptr || chunk->num_rows() < 1) return; + + auto agg_state = _pre_agg->_managed_fn_states[_sorter_index]->mutable_data(); + + Columns agg_result_columns = _create_agg_result_columns(chunk->num_rows()); + + if (is_first_chunk) { + for (size_t i = 0; i < _pre_agg->_agg_fn_ctxs.size(); i++) { + // add agg result into first row + _pre_agg->_agg_functions[i]->serialize_to_column(_pre_agg->_agg_fn_ctxs[i], + agg_state + _pre_agg->_agg_states_offsets[i], + agg_result_columns[i].get()); + // reset agg result, after first row, we only append 'reset' result + _pre_agg->_agg_functions[i]->reset(_pre_agg->_agg_fn_ctxs[i], _pre_agg->_agg_input_columns[i], + agg_state + _pre_agg->_agg_states_offsets[i]); + } + } + + size_t num_default_rows = is_first_chunk ? chunk->num_rows() - 1 : chunk->num_rows(); + + for (size_t i = 0; i < _pre_agg->_agg_fn_types.size(); ++i) { + // add 'reset' rows + for (size_t j = 0; j < num_default_rows; j++) { + _pre_agg->_agg_functions[i]->serialize_to_column(_pre_agg->_agg_fn_ctxs[i], + agg_state + _pre_agg->_agg_states_offsets[i], + agg_result_columns[i].get()); + } + } + + for (size_t i = 0; i < _pre_agg->_agg_fn_ctxs.size(); i++) { + chunk->append_column(std::move(agg_result_columns[i]), _pre_agg->_t_pre_agg_output_slot_id[i]); + } +} + +Status LocalPartitionTopnContext::output_agg_streaming(Chunk* chunk) { + RETURN_IF_ERROR(_evaluate_agg_input_columns(chunk)); + Columns agg_result_column = _create_agg_result_columns(chunk->num_rows()); + for (size_t i = 0; i < _pre_agg->_agg_fn_ctxs.size(); i++) { + auto slot_id = _pre_agg->_t_pre_agg_output_slot_id[i]; + _pre_agg->_agg_functions[i]->convert_to_serialize_format( + _pre_agg->_agg_fn_ctxs[i], _pre_agg->_agg_input_columns[i], chunk->num_rows(), &agg_result_column[i]); + chunk->append_column(std::move(agg_result_column[i]), slot_id); + } + return Status::OK(); +} + +Status LocalPartitionTopnContext::_evaluate_agg_input_columns(Chunk* chunk) { + for (size_t i = 0; i < _pre_agg->_agg_fn_ctxs.size(); i++) { + for (size_t j = 0; j < _pre_agg->_agg_expr_ctxs[i].size(); j++) { + // For simplicity and don't change the overall processing flow, + // We handle const column as normal data column + // TODO(kks): improve const column aggregate later + ASSIGN_OR_RETURN(auto&& col, _pre_agg->_agg_expr_ctxs[i][j]->evaluate(chunk)); + // if first column is const, we have to unpack it. Most agg function only has one arg, and treat it as non-const column + if (j == 0) { + _pre_agg->_agg_input_columns[i][j] = + ColumnHelper::unpack_and_duplicate_const_column(chunk->num_rows(), col); + } else { + // if function has at least two argument, unpack const column selectively + // for function like corr, FE forbid second args to be const, we will always unpack const column for it + // for function like percentile_disc, the second args is const, do not unpack it + if (_pre_agg->_agg_expr_ctxs[i][j]->root()->is_constant()) { + _pre_agg->_agg_input_columns[i][j] = std::move(col); + } else { + _pre_agg->_agg_input_columns[i][j] = + ColumnHelper::unpack_and_duplicate_const_column(chunk->num_rows(), col); + } + } + _pre_agg->_agg_input_raw_columns[i][j] = _pre_agg->_agg_input_columns[i][j].get(); + } + } + return Status::OK(); +} + +LocalPartitionTopnContextFactory::LocalPartitionTopnContextFactory( + RuntimeState*, const TTopNType::type topn_type, bool is_merging, const std::vector& sort_exprs, + std::vector is_asc_order, std::vector is_null_first, const std::vector& t_partition_exprs, + bool enable_pre_agg, const std::vector& t_pre_agg_exprs, + const std::vector& t_pre_agg_output_slot_id, int64_t offset, int64_t limit, std::string sort_keys, + const std::vector& order_by_types, const std::vector&) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : _topn_type(topn_type), _sort_exprs(sort_exprs), _is_asc_order(std::move(is_asc_order)), _is_null_first(std::move(is_null_first)), _t_partition_exprs(t_partition_exprs), +<<<<<<< HEAD +======= + enable_pre_agg(enable_pre_agg), + _t_pre_agg_exprs(t_pre_agg_exprs), + _t_pre_agg_output_slot_id(t_pre_agg_output_slot_id), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _offset(offset), _partition_limit(limit), _sort_keys(std::move(sort_keys)) {} @@ -157,9 +437,15 @@ LocalPartitionTopnContext* LocalPartitionTopnContextFactory::create(int32_t driv return it->second.get(); } +<<<<<<< HEAD auto ctx = std::make_shared(_t_partition_exprs, _sort_exprs, _is_asc_order, _is_null_first, _sort_keys, _offset, _partition_limit, _topn_type); +======= + auto ctx = std::make_shared( + _t_partition_exprs, enable_pre_agg, _t_pre_agg_exprs, _t_pre_agg_output_slot_id, _sort_exprs, _is_asc_order, + _is_null_first, _sort_keys, _offset, _partition_limit, _topn_type); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* ctx_raw_ptr = ctx.get(); _ctxs.emplace(driver_sequence, std::move(ctx)); return ctx_raw_ptr; diff --git a/be/src/exec/pipeline/sort/local_partition_topn_context.h b/be/src/exec/pipeline/sort/local_partition_topn_context.h index 403fb0db649c2..a8cc23a3f25cd 100644 --- a/be/src/exec/pipeline/sort/local_partition_topn_context.h +++ b/be/src/exec/pipeline/sort/local_partition_topn_context.h @@ -16,22 +16,65 @@ #include +<<<<<<< HEAD +======= +#include "exec/analytor.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/chunks_sorter.h" #include "exec/partition/chunks_partitioner.h" #include "runtime/runtime_state.h" namespace starrocks { class RuntimeFilterBuildDescriptor; +<<<<<<< HEAD } namespace starrocks::pipeline { +======= + +struct FunctionTypes; +} // namespace starrocks + +namespace starrocks::pipeline { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class LocalPartitionTopnContext; class LocalPartitionTopnContextFactory; using LocalPartitionTopnContextPtr = std::shared_ptr; using LocalPartitionTopnContextFactoryPtr = std::shared_ptr; +<<<<<<< HEAD +======= +using AggDataPtr = uint8_t*; + +struct PreAggState { + PreAggState(const std::vector& t_pre_agg_exprs, const std::vector& t_pre_agg_output_slot_id) + : _t_pre_agg_exprs(t_pre_agg_exprs), _t_pre_agg_output_slot_id(t_pre_agg_output_slot_id) {} + + bool _is_first_chunk_of_current_sorter = true; + const std::vector& _t_pre_agg_exprs; + const std::vector& _t_pre_agg_output_slot_id; + + // The offset of the n-th aggregate function in a row of aggregate functions. + std::vector _agg_states_offsets; + // The total size of the row for the aggregate function state. + size_t _agg_states_total_size = 0; + // The max align size for all aggregate state + size_t _max_agg_state_align_size = 1; + // The followings are aggregate function information: + std::vector _agg_fn_ctxs; + std::vector _agg_functions; + std::vector> _agg_expr_ctxs; + std::vector> _agg_input_columns; + //raw pointers in order to get multi-column values + std::vector> _agg_input_raw_columns; + std::vector _agg_fn_types; + // every partition has one Agg State + std::vector> _managed_fn_states; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // LocalPartitionTopnContext is the bridge of each pair of LocalPartitionTopn{Sink/Source}Operators // The purpose of LocalPartitionTopn{Sink/Source}Operator is to reduce the amount of data, // so the output chunks are still remain unordered @@ -43,21 +86,41 @@ using LocalPartitionTopnContextFactoryPtr = std::shared_ptr& t_partition_exprs, const std::vector& sort_exprs, std::vector is_asc_order, std::vector is_null_first, std::string sort_keys, int64_t offset, int64_t partition_limit, const TTopNType::type topn_type); +======= + friend class ManagedFunctionStates; + +public: + LocalPartitionTopnContext(const std::vector& t_partition_exprs, bool enable_pre_agg, + const std::vector& t_pre_agg_exprs, + const std::vector& t_pre_agg_output_slot_id, + const std::vector& sort_exprs, std::vector is_asc_order, + std::vector is_null_first, std::string sort_keys, int64_t offset, + int64_t partition_limit, const TTopNType::type topn_type); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status prepare(RuntimeState* state, RuntimeProfile* runtime_profile); // Add one chunk to partitioner +<<<<<<< HEAD [[nodiscard]] Status push_one_chunk_to_partitioner(RuntimeState* state, const ChunkPtr& chunk); +======= + Status push_one_chunk_to_partitioner(RuntimeState* state, const ChunkPtr& chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Notify that there is no further input for partitiner void sink_complete(); // Pull chunks form partitioner of each partition to correspondent sorter +<<<<<<< HEAD [[nodiscard]] Status transfer_all_chunks_from_partitioner_to_sorters(RuntimeState* state); +======= + Status transfer_all_chunks_from_partitioner_to_sorters(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Return true if at least one of the sorters has remaining data bool has_output(); @@ -66,7 +129,11 @@ class LocalPartitionTopnContext { bool is_finished(); // Pull one chunk from sorters or passthrough_buffer +<<<<<<< HEAD [[nodiscard]] StatusOr pull_one_chunk(); +======= + StatusOr pull_one_chunk(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_passthrough() const { return _chunks_partitioner->is_passthrough(); } @@ -79,13 +146,59 @@ class LocalPartitionTopnContext { private: // Pull one chunk from one of the sorters // The output chunk stream is unordered +<<<<<<< HEAD [[nodiscard]] StatusOr pull_one_chunk_from_sorters(); +======= + StatusOr pull_one_chunk_from_sorters(); + + // prepare all stuff for pre agg + Status prepare_pre_agg(RuntimeState* state); + + // calculate agg for the ‘partition_idx' partition + Status compute_agg_state(Chunk* chunk, size_t partition_idx); + + // when call chunk_sorter->get_next(), if this is first chunk it has, is_first_chunk is true + void output_agg_result(Chunk* chunk, bool eos, bool is_first_chunk); + + Status output_agg_streaming(Chunk* chunk); + + Status _evaluate_agg_input_columns(Chunk* chunk); + + Columns _create_agg_result_columns(size_t num_rows); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& _t_partition_exprs; std::vector _partition_exprs; std::vector _partition_types; bool _has_nullable_key = false; +<<<<<<< HEAD +======= + // only set when _enable_pre_agg=true + bool _enable_pre_agg; + std::unique_ptr _pre_agg; + // bool _is_first_chunk_of_current_sorter = true; + // const std::vector& _t_pre_agg_exprs; + // const std::vector& _t_pre_agg_output_slot_id; + + // // The offset of the n-th aggregate function in a row of aggregate functions. + // std::vector _agg_states_offsets; + // // The total size of the row for the aggregate function state. + // size_t _agg_states_total_size = 0; + // // The max align size for all aggregate state + // size_t _max_agg_state_align_size = 1; + // // The followings are aggregate function information: + // std::vector _agg_fn_ctxs; + // std::vector _agg_functions; + // std::vector> _agg_expr_ctxs; + // std::vector> _agg_input_columns; + // //raw pointers in order to get multi-column values + // std::vector> _agg_input_raw_columns; + // std::vector _agg_fn_types; + // // every partition has one Agg State + // std::vector> _managed_fn_states; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // No more input chunks if after _is_sink_complete is set to true bool _is_sink_complete = false; @@ -104,6 +217,11 @@ class LocalPartitionTopnContext { const TTopNType::type _topn_type; int32_t _sorter_index = 0; +<<<<<<< HEAD +======= + + std::unique_ptr _mem_pool = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; using LocalPartitionTopnContextPtr = std::shared_ptr; @@ -113,11 +231,21 @@ class LocalPartitionTopnContextFactory { LocalPartitionTopnContextFactory(RuntimeState* state, const TTopNType::type topn_type, bool is_merging, const std::vector& sort_exprs, std::vector is_asc_order, std::vector is_null_first, const std::vector& t_partition_exprs, +<<<<<<< HEAD int64_t offset, int64_t limit, std::string sort_keys, const std::vector& order_by_types, const std::vector& rfs); [[nodiscard]] Status prepare(RuntimeState* state); +======= + bool enable_pre_agg, const std::vector& t_pre_agg_exprs, + const std::vector& t_pre_agg_output_slot_id, int64_t offset, + int64_t limit, std::string sort_keys, + const std::vector& order_by_types, + const std::vector& rfs); + + Status prepare(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) LocalPartitionTopnContext* create(int32_t driver_sequence); private: @@ -130,6 +258,12 @@ class LocalPartitionTopnContextFactory { std::vector _is_asc_order; std::vector _is_null_first; const std::vector& _t_partition_exprs; +<<<<<<< HEAD +======= + bool enable_pre_agg; + const std::vector& _t_pre_agg_exprs; + const std::vector& _t_pre_agg_output_slot_id; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t _offset; int64_t _partition_limit; const std::string _sort_keys; diff --git a/be/src/exec/pipeline/sort/sort_context.cpp b/be/src/exec/pipeline/sort/sort_context.cpp index 0d8cb672e4b97..e20a8c7ad8a80 100644 --- a/be/src/exec/pipeline/sort/sort_context.cpp +++ b/be/src/exec/pipeline/sort/sort_context.cpp @@ -137,8 +137,16 @@ Status SortContext::_init_merger() { SortContextFactory::SortContextFactory(RuntimeState* state, const TTopNType::type topn_type, bool is_merging, std::vector sort_exprs, const std::vector& is_asc_order, const std::vector& is_null_first, +<<<<<<< HEAD [[maybe_unused]] const std::vector& partition_exprs, int64_t offset, int64_t limit, const std::string& sort_keys, +======= + [[maybe_unused]] const std::vector& partition_exprs, + [[maybe_unused]] bool enable_pre_agg, + [[maybe_unused]] const std::vector& t_pre_agg_exprs, + [[maybe_unused]] const std::vector& t_pre_agg_output_slot_id, + int64_t offset, int64_t limit, const std::string& sort_keys, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& order_by_types, const std::vector& build_runtime_filters) : _state(state), diff --git a/be/src/exec/pipeline/sort/sort_context.h b/be/src/exec/pipeline/sort/sort_context.h index 207ae9ffe9bd0..7ae0d111697ff 100644 --- a/be/src/exec/pipeline/sort/sort_context.h +++ b/be/src/exec/pipeline/sort/sort_context.h @@ -69,13 +69,21 @@ class SortContext final : public ContextWithDependency { bool is_partition_ready() const; void cancel(); +<<<<<<< HEAD [[nodiscard]] StatusOr pull_chunk(); +======= + StatusOr pull_chunk(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_runtime_filter_collector(RuntimeFilterHub* hub, int32_t plan_node_id, std::unique_ptr&& collector); private: +<<<<<<< HEAD [[nodiscard]] Status _init_merger(); +======= + Status _init_merger(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeState* _state; const TTopNType::type _topn_type; @@ -104,8 +112,14 @@ class SortContextFactory { SortContextFactory(RuntimeState* state, const TTopNType::type topn_type, bool is_merging, std::vector sort_exprs, const std::vector& is_asc_order, const std::vector& is_null_first, const std::vector& partition_exprs, +<<<<<<< HEAD int64_t offset, int64_t limit, const std::string& sort_keys, const std::vector& order_by_types, +======= + bool enable_pre_agg, const std::vector& t_pre_agg_exprs, + const std::vector& t_pre_agg_output_slot_id, int64_t offset, int64_t limit, + const std::string& sort_keys, const std::vector& order_by_types, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& build_runtime_filters); SortContextPtr create(int32_t idx); diff --git a/be/src/exec/pipeline/stream_epoch_manager.h b/be/src/exec/pipeline/stream_epoch_manager.h index b84e58a0737aa..4a5f1ad18f3f7 100644 --- a/be/src/exec/pipeline/stream_epoch_manager.h +++ b/be/src/exec/pipeline/stream_epoch_manager.h @@ -50,6 +50,7 @@ class StreamEpochManager { ~StreamEpochManager() = default; // Start the new epoch from input epoch info +<<<<<<< HEAD [[nodiscard]] Status start_epoch(ExecEnv* exec_env, const QueryContext* query_ctx, const std::vector& fragment_ctxs, const EpochInfo& epoch_info, const ScanRangeInfo& scan_info); @@ -60,6 +61,18 @@ class StreamEpochManager { [[nodiscard]] Status activate_parked_driver(ExecEnv* exec_env, const TUniqueId& query_id, int64_t expected_num_drivers, bool enable_resource_group); [[nodiscard]] Status set_finished(ExecEnv* exec_env, const QueryContext* query_ctx); +======= + Status start_epoch(ExecEnv* exec_env, const QueryContext* query_ctx, + const std::vector& fragment_ctxs, const EpochInfo& epoch_info, + const ScanRangeInfo& scan_info); + Status prepare(const MVMaintenanceTaskInfo& maintenance_task_info, + const std::vector& fragment_ctxs); + Status update_binlog_offset(const TUniqueId& fragment_instance_id, int64_t scan_node_id, int64_t tablet_id, + BinlogOffset binlog_offset); + Status activate_parked_driver(ExecEnv* exec_env, const TUniqueId& query_id, int64_t expected_num_drivers, + bool enable_resource_group); + Status set_finished(ExecEnv* exec_env, const QueryContext* query_ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const BinlogOffset* get_binlog_offset(const TUniqueId& fragment_instance_id, int64_t scan_node_id, int64_t tablet_id) const; diff --git a/be/src/exec/pipeline/stream_pipeline_driver.h b/be/src/exec/pipeline/stream_pipeline_driver.h index b2b1c6c37b9f3..7125034dd0d9e 100644 --- a/be/src/exec/pipeline/stream_pipeline_driver.h +++ b/be/src/exec/pipeline/stream_pipeline_driver.h @@ -39,13 +39,22 @@ class StreamPipelineDriver final : public PipelineDriver { bool is_query_never_expired() override { return true; } void epoch_finalize(RuntimeState* runtime_state, DriverState state); +<<<<<<< HEAD [[nodiscard]] Status reset_epoch(RuntimeState* state); +======= + Status reset_epoch(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: StatusOr _handle_finish_operators(RuntimeState* runtime_state); +<<<<<<< HEAD [[nodiscard]] Status _mark_operator_epoch_finishing(OperatorPtr& op, RuntimeState* state); [[nodiscard]] Status _mark_operator_epoch_finished(OperatorPtr& op, RuntimeState* state); +======= + Status _mark_operator_epoch_finishing(OperatorPtr& op, RuntimeState* state); + Status _mark_operator_epoch_finished(OperatorPtr& op, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: // index of the first epoch-unfisheded operator diff --git a/be/src/exec/pipeline/table_function_operator.h b/be/src/exec/pipeline/table_function_operator.h index 463af6fc89aa3..6c6f08173c3a6 100644 --- a/be/src/exec/pipeline/table_function_operator.h +++ b/be/src/exec/pipeline/table_function_operator.h @@ -30,7 +30,11 @@ class TableFunctionOperator final : public Operator { ~TableFunctionOperator() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state) override; @@ -40,6 +44,7 @@ class TableFunctionOperator final : public Operator { bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; StatusOr pull_chunk(RuntimeState* state) override; @@ -51,6 +56,19 @@ class TableFunctionOperator final : public Operator { private: ChunkPtr _build_chunk(const std::vector& output_columns); [[nodiscard]] Status _process_table_function(RuntimeState* state); +======= + Status set_finishing(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + + Status reset_state(RuntimeState* state, const std::vector& refill_chunks) override; + +private: + ChunkPtr _build_chunk(const std::vector& output_columns); + Status _process_table_function(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _copy_result(const std::vector& columns, uint32_t max_column_size); const TPlanNode& _tnode; diff --git a/be/src/exec/query_cache/cache_manager.h b/be/src/exec/query_cache/cache_manager.h index 5b120f2054544..4e22da174eea0 100644 --- a/be/src/exec/query_cache/cache_manager.h +++ b/be/src/exec/query_cache/cache_manager.h @@ -65,7 +65,11 @@ class CacheManager { explicit CacheManager(size_t capacity); ~CacheManager() = default; void populate(const std::string& key, const CacheValue& value); +<<<<<<< HEAD [[nodiscard]] StatusOr probe(const std::string& key); +======= + StatusOr probe(const std::string& key); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t memory_usage(); size_t capacity(); size_t lookup_count(); diff --git a/be/src/exec/query_cache/cache_operator.cpp b/be/src/exec/query_cache/cache_operator.cpp index 86921a45af482..f195d6b578b7e 100644 --- a/be/src/exec/query_cache/cache_operator.cpp +++ b/be/src/exec/query_cache/cache_operator.cpp @@ -21,10 +21,20 @@ #include "column/vectorized_fwd.h" #include "common/compiler_util.h" #include "exec/pipeline/pipeline_driver.h" +<<<<<<< HEAD #include "storage/rowset/rowset.h" #include "storage/storage_engine.h" #include "storage/tablet_manager.h" #include "util/time.h" +======= +#include "storage/lake/tablet.h" +#include "storage/lake/tablet_manager.h" +#include "storage/rowset/base_rowset.h" +#include "storage/storage_engine.h" +#include "storage/tablet_manager.h" +#include "util/time.h" + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::query_cache { enum PerLaneBufferState { PLBS_INIT, @@ -40,8 +50,13 @@ struct PerLaneBuffer { LaneOwnerType lane_owner{-1}; int lane; PerLaneBufferState state; +<<<<<<< HEAD TabletSharedPtr tablet; std::vector rowsets; +======= + BaseTabletSharedPtr tablet; + std::vector rowsets; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RowsetsAcqRelPtr rowsets_acq_rel; int64_t required_version; int64_t cached_version; @@ -55,7 +70,13 @@ struct PerLaneBuffer { lane = -1; state = PLBS_INIT; tablet.reset(); +<<<<<<< HEAD rowsets_acq_rel.reset(); +======= + if (rowsets_acq_rel != nullptr) { + rowsets_acq_rel.reset(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) rowsets.clear(); required_version = 0; cached_version = 0; @@ -233,6 +254,7 @@ void CacheOperator::_handle_stale_cache_value_for_non_pk(int64_t tablet_id, Cach PerLaneBufferPtr& buffer, int64_t version) { // Try to reuse partial cache result when cached version is less than required version, delta versions // should be captured at first. +<<<<<<< HEAD auto status = StorageEngine::instance()->tablet_manager()->capture_tablet_and_rowsets( tablet_id, cache_value.version + 1, version); @@ -259,6 +281,66 @@ void CacheOperator::_handle_stale_cache_value_for_non_pk(int64_t tablet_id, Cach // case 1: there exist delete predicates in delta versions, or data model can not support multiversion cache and // the tablet has non-empty delta rowsets; then cache result is not reuse, so cache miss. if (has_delete_predicates || (!_cache_param.can_use_multiversion && !all_rs_empty)) { +======= + std::shared_ptr base_tablet; + std::vector base_rowsets; + RowsetsAcqRelPtr rowsets_acq_rel = nullptr; + + if (!_cache_param.is_lake) { + auto status = StorageEngine::instance()->tablet_manager()->capture_tablet_and_rowsets( + tablet_id, cache_value.version + 1, version); + if (!status.ok()) { + buffer->state = PLBS_MISS; + buffer->cached_version = 0; + return; + } + + auto& [tablet, rowsets, acq_rel] = status.value(); + base_tablet = std::static_pointer_cast(tablet); + for (auto const& rowset_ptr : rowsets) { + base_rowsets.emplace_back(std::static_pointer_cast(rowset_ptr)); + } + rowsets_acq_rel = std::move(acq_rel); + + } else { + auto status = ExecEnv::GetInstance()->lake_tablet_manager()->capture_tablet_and_rowsets( + tablet_id, cache_value.version + 1, version); + // Cache MISS if delta versions are not captured, because aggressive cumulative compactions. + if (!status.ok()) { + buffer->state = PLBS_MISS; + buffer->cached_version = 0; + return; + } + + auto& [tablet, rowsets] = status.value(); + base_tablet = std::static_pointer_cast(tablet); + base_rowsets = std::move(rowsets); + } + + // Delta versions are captured, several situations should be taken into consideration. + auto all_rs_empty = true; + auto min_version = std::numeric_limits::max(); + auto max_version = std::numeric_limits::min(); + if (!_cache_param.is_lake) { + for (const auto& rs : base_rowsets) { + all_rs_empty &= !rs->has_data_files(); + min_version = std::min(min_version, rs->start_version()); + max_version = std::max(max_version, rs->end_version()); + } + } else { + all_rs_empty = base_rowsets.empty(); + min_version = cache_value.version + 1; + max_version = version; + } + + Version delta_versions(min_version, max_version); + buffer->tablet = base_tablet; + auto has_delete_predicates = base_tablet->has_delete_predicates(delta_versions); + // case 1: there exist delete predicates in delta versions, or data model can not support multiversion cache and + // the tablet has non-empty delta rowsets; then cache result is not reuse, so cache miss. + if (!has_delete_predicates.ok() || has_delete_predicates.value() || + (!_cache_param.can_use_multiversion && !all_rs_empty)) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) buffer->state = PLBS_MISS; buffer->cached_version = 0; return; @@ -274,11 +356,18 @@ void CacheOperator::_handle_stale_cache_value_for_non_pk(int64_t tablet_id, Cach buffer->chunks.back()->owner_info().set_last_chunk(true); return; } +<<<<<<< HEAD // case 3: otherwise, the cache result is partial result of per-tablet computation, so delta versions must // be scanned and merged with cache result to generate total result. buffer->state = PLBS_HIT_PARTIAL; buffer->rowsets = std::move(rowsets); +======= + // case 3: otherwise, the cache result is partial result of per-tablet computation, so delta versions must + // be scanned and merged with cache result to generate total result. + buffer->state = PLBS_HIT_PARTIAL; + buffer->rowsets = std::move(base_rowsets); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) buffer->rowsets_acq_rel = std::move(rowsets_acq_rel); buffer->num_rows = 0; buffer->num_bytes = 0; @@ -293,6 +382,7 @@ void CacheOperator::_handle_stale_cache_value_for_pk(int64_t tablet_id, starrock starrocks::query_cache::PerLaneBufferPtr& buffer, int64_t version) { DCHECK(_cache_param.keys_type == TKeysType::PRIMARY_KEYS); +<<<<<<< HEAD // At the present, PRIMARY_KEYS can not support merge-on-read, so we can not merge stale cache values and delta // rowsets. Capturing delta rowsets is meaningless and unsupported, thus we capture all rowsets of the PK tablet. auto status = StorageEngine::instance()->tablet_manager()->capture_tablet_and_rowsets(tablet_id, 0, version); @@ -313,6 +403,47 @@ void CacheOperator::_handle_stale_cache_value_for_pk(int64_t tablet_id, starrock buffer->state = PLBS_MISS; buffer->cached_version = 0; return; +======= + if (!_cache_param.is_lake) { + // At the present, PRIMARY_KEYS can not support merge-on-read, so we can not merge stale cache values and delta + // rowsets. Capturing delta rowsets is meaningless and unsupported, thus we capture all rowsets of the PK tablet. + auto status = StorageEngine::instance()->tablet_manager()->capture_tablet_and_rowsets(tablet_id, 0, version); + if (!status.ok()) { + buffer->state = PLBS_MISS; + buffer->cached_version = 0; + return; + } + auto& [tablet, rowsets, rowsets_acq_rel] = status.value(); + const auto snapshot_version = cache_value.version; + bool can_pickup_delta_rowsets = false; + bool exists_non_empty_delta_rowsets = false; + for (auto& rs : rowsets) { + can_pickup_delta_rowsets |= rs->start_version() == snapshot_version + 1; + exists_non_empty_delta_rowsets |= rs->start_version() > snapshot_version && rs->has_data_files(); + } + if (exists_non_empty_delta_rowsets || !can_pickup_delta_rowsets) { + buffer->state = PLBS_MISS; + buffer->cached_version = 0; + return; + } + + } else { + auto status = ExecEnv::GetInstance()->lake_tablet_manager()->capture_tablet_and_rowsets( + tablet_id, cache_value.version + 1, version); + // Cache MISS if delta versions are not captured, because aggressive cumulative compactions. + if (!status.ok()) { + buffer->state = PLBS_MISS; + buffer->cached_version = 0; + return; + } + + auto& [tablet, rowsets] = status.value(); + if (!rowsets.empty()) { + buffer->state = PLBS_MISS; + buffer->cached_version = 0; + return; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } buffer->cached_version = cache_value.version; @@ -428,10 +559,17 @@ int64_t CacheOperator::cached_version(int64_t tablet_id) { } } +<<<<<<< HEAD std::tuple> CacheOperator::delta_version_and_rowsets(int64_t tablet_id) { auto lane_it = _owner_to_lanes.find(tablet_id); if (lane_it == _owner_to_lanes.end()) { return make_tuple(0, vector{}); +======= +std::tuple> CacheOperator::delta_version_and_rowsets(int64_t tablet_id) { + auto lane_it = _owner_to_lanes.find(tablet_id); + if (lane_it == _owner_to_lanes.end()) { + return make_tuple(0, vector{}); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { auto& buffer = _per_lane_buffers[lane_it->second]; return make_tuple(buffer->cached_version + 1, buffer->rowsets); diff --git a/be/src/exec/query_cache/cache_operator.h b/be/src/exec/query_cache/cache_operator.h index 4e50bfd22b352..5a5a37ddbc233 100644 --- a/be/src/exec/query_cache/cache_operator.h +++ b/be/src/exec/query_cache/cache_operator.h @@ -51,7 +51,11 @@ class CacheOperator final : public pipeline::Operator { Status reset_lane(RuntimeState* state, LaneOwnerType lane_owner); void populate_cache(int64_t tablet_id); int64_t cached_version(int64_t tablet_id); +<<<<<<< HEAD std::tuple> delta_version_and_rowsets(int64_t tablet_id); +======= + std::tuple> delta_version_and_rowsets(int64_t tablet_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; StatusOr pull_chunk(RuntimeState* state) override; bool has_output() const override; diff --git a/be/src/exec/query_cache/cache_param.h b/be/src/exec/query_cache/cache_param.h index 30e912889dd92..ca8c15d2e4c28 100644 --- a/be/src/exec/query_cache/cache_param.h +++ b/be/src/exec/query_cache/cache_param.h @@ -36,5 +36,9 @@ struct CacheParam { bool can_use_multiversion; TKeysType::type keys_type; std::unordered_set cached_plan_node_ids; +<<<<<<< HEAD +======= + bool is_lake = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks::query_cache diff --git a/be/src/exec/query_cache/multilane_operator.h b/be/src/exec/query_cache/multilane_operator.h index 7d727b39d6c49..c0abc7e8a7102 100644 --- a/be/src/exec/query_cache/multilane_operator.h +++ b/be/src/exec/query_cache/multilane_operator.h @@ -21,6 +21,10 @@ #include "common/status.h" #include "common/statusor.h" #include "exec/pipeline/operator.h" +<<<<<<< HEAD +======= +#include "exec/pipeline/pipeline_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/query_cache/lane_arbiter.h" #include "runtime/runtime_state.h" @@ -56,22 +60,40 @@ class MultilaneOperator final : public pipeline::Operator { pipeline::Operators&& processors, bool can_passthrough); ~MultilaneOperator() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; void close(RuntimeState* state) override; [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status set_finished(RuntimeState* state) override; [[nodiscard]] Status set_cancelled(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; + void close(RuntimeState* state) override; + + Status set_finishing(RuntimeState* state) override; + Status set_finished(RuntimeState* state) override; + Status set_cancelled(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool has_output() const override; bool need_input() const override; bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; void set_lane_arbiter(const LaneArbiterPtr& lane_arbiter) { _lane_arbiter = lane_arbiter; } [[nodiscard]] Status reset_lane(RuntimeState* state, LaneOwnerType lane_id, const std::vector& chunks); +======= + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + + void set_lane_arbiter(const LaneArbiterPtr& lane_arbiter) { _lane_arbiter = lane_arbiter; } + + Status reset_lane(RuntimeState* state, LaneOwnerType lane_id, const std::vector& chunks); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pipeline::OperatorPtr get_internal_op(size_t i); @@ -85,9 +107,15 @@ class MultilaneOperator final : public pipeline::Operator { bool ignore_empty_eos() const override { return false; } private: +<<<<<<< HEAD [[nodiscard]] StatusOr _pull_chunk_from_lane(RuntimeState* state, Lane& lane, bool passthrough_mode); using FinishCallback = std::function; [[nodiscard]] Status _finish(RuntimeState* state, const FinishCallback& finish_cb); +======= + StatusOr _pull_chunk_from_lane(RuntimeState* state, Lane& lane, bool passthrough_mode); + using FinishCallback = std::function; + Status _finish(RuntimeState* state, const FinishCallback& finish_cb); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const size_t _num_lanes; LaneArbiterPtr _lane_arbiter = nullptr; std::vector _lanes; @@ -102,7 +130,11 @@ class MultilaneOperatorFactory final : public pipeline::OperatorFactory { public: MultilaneOperatorFactory(int32_t id, const OperatorFactoryPtr& factory, size_t num_lanes); pipeline::OperatorPtr create(int32_t degree_of_parallelism, int32_t driver_sequence) override; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state) override; // can_passthrough should be true for the operator that precedes cache_operator immediately. // because only this operator is computation-intensive, so its input chunks must be pass through diff --git a/be/src/exec/scan_node.cpp b/be/src/exec/scan_node.cpp index 8045d936c2298..2fb2ee9113df5 100644 --- a/be/src/exec/scan_node.cpp +++ b/be/src/exec/scan_node.cpp @@ -116,7 +116,12 @@ static std::map uniform_distribute_morsels(pipeli } } else { for (auto& [operator_seq, morsels] : morsels_per_driver) { +<<<<<<< HEAD queue_per_driver.emplace(operator_seq, std::make_unique(std::move(morsels))); +======= + queue_per_driver.emplace(operator_seq, std::make_unique( + std::move(morsels), morsel_queue->has_more())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -127,7 +132,11 @@ StatusOr ScanNode::convert_scan_range_to_morsel const std::vector& global_scan_ranges, const std::map>& scan_ranges_per_driver_seq, int node_id, int pipeline_dop, bool in_colocate_exec_group, bool enable_tablet_internal_parallel, +<<<<<<< HEAD TTabletInternalParallelMode::type tablet_internal_parallel_mode) { +======= + TTabletInternalParallelMode::type tablet_internal_parallel_mode, bool enable_shared_scan) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (scan_ranges_per_driver_seq.empty() && !in_colocate_exec_group) { ASSIGN_OR_RETURN(auto morsel_queue, convert_scan_range_to_morsel_queue(global_scan_ranges, node_id, pipeline_dop, @@ -147,6 +156,12 @@ StatusOr ScanNode::convert_scan_range_to_morsel return std::make_unique(std::move(morsel_queue_map), /*could_local_shuffle*/ true); } else { +<<<<<<< HEAD +======= + if (config::use_default_dop_when_shared_scan && enable_shared_scan && is_fixed_or_dynamic_morsel_queue) { + scan_dop = pipeline_dop; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return std::make_unique(std::move(morsel_queue), scan_dop); } } else { @@ -183,6 +198,7 @@ StatusOr ScanNode::convert_scan_range_to_morsel_queue( bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, size_t num_total_scan_ranges) { pipeline::Morsels morsels; +<<<<<<< HEAD // If this scan node does not accept non-empty scan ranges, create a placeholder one. if (!accept_empty_scan_ranges() && scan_ranges.empty()) { morsels.emplace_back(std::make_unique(node_id, TScanRangeParams())); @@ -192,6 +208,12 @@ StatusOr ScanNode::convert_scan_range_to_morsel_queue( } } +======= + [[maybe_unused]] bool has_more_morsel = false; + pipeline::ScanMorsel::build_scan_morsels(node_id, scan_ranges, accept_empty_scan_ranges(), &morsels, + &has_more_morsel); + DCHECK(has_more_morsel == false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return std::make_unique(std::move(morsels)); } diff --git a/be/src/exec/scan_node.h b/be/src/exec/scan_node.h index c0951f735daf0..64099901f75c0 100644 --- a/be/src/exec/scan_node.h +++ b/be/src/exec/scan_node.h @@ -87,7 +87,11 @@ class ScanNode : public ExecNode { const std::vector& scan_ranges, const std::map>& scan_ranges_per_driver_seq, int node_id, int pipeline_dop, bool in_colocate_exec_group, bool enable_tablet_internal_parallel, +<<<<<<< HEAD TTabletInternalParallelMode::type tablet_internal_parallel_mode); +======= + TTabletInternalParallelMode::type tablet_internal_parallel_mode, bool enable_shared_scan = false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual StatusOr convert_scan_range_to_morsel_queue( const std::vector& scan_ranges, int node_id, int32_t pipeline_dop, bool enable_tablet_internal_parallel, TTabletInternalParallelMode::type tablet_internal_parallel_mode, diff --git a/be/src/exec/schema_scan_node.cpp b/be/src/exec/schema_scan_node.cpp index ed5f72d51acd4..42172cdb03f26 100644 --- a/be/src/exec/schema_scan_node.cpp +++ b/be/src/exec/schema_scan_node.cpp @@ -302,8 +302,12 @@ std::vector> SchemaScanNode::decompos pipeline::PipelineBuilderContext* context) { auto exec_group = context->find_exec_group_by_plan_node_id(_id); context->set_current_execution_group(exec_group); +<<<<<<< HEAD // the dop of SchemaScanOperator should always be 1. size_t dop = 1; +======= + size_t dop = context->dop_of_source_operator(_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t buffer_capacity = pipeline::ScanOperator::max_buffer_capacity() * dop; pipeline::ChunkBufferLimiterPtr buffer_limiter = std::make_unique( diff --git a/be/src/exec/select_node.cpp b/be/src/exec/select_node.cpp index 98df4eb96576a..07302bf806b5a 100644 --- a/be/src/exec/select_node.cpp +++ b/be/src/exec/select_node.cpp @@ -51,6 +51,21 @@ SelectNode::~SelectNode() { } } +<<<<<<< HEAD +======= +Status SelectNode::init(const TPlanNode& tnode, RuntimeState* state) { + RETURN_IF_ERROR(ExecNode::init(tnode, state)); + if (tnode.__isset.select_node && tnode.select_node.__isset.common_slot_map) { + for (const auto& [key, val] : tnode.select_node.common_slot_map) { + ExprContext* context; + RETURN_IF_ERROR(Expr::create_expr_tree(_pool, val, &context, state, true)); + _common_expr_ctxs.insert({key, context}); + } + } + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status SelectNode::prepare(RuntimeState* state) { RETURN_IF_ERROR(ExecNode::prepare(state)); _conjunct_evaluate_timer = ADD_TIMER(_runtime_profile, "ConjunctEvaluateTime"); @@ -108,8 +123,13 @@ pipeline::OpFactories SelectNode::decompose_to_pipeline(pipeline::PipelineBuilde OpFactories operators = _children[0]->decompose_to_pipeline(context); +<<<<<<< HEAD operators.emplace_back( std::make_shared(context->next_operator_id(), id(), std::move(_conjunct_ctxs))); +======= + operators.emplace_back(std::make_shared( + context->next_operator_id(), id(), std::move(_conjunct_ctxs), std::move(_common_expr_ctxs))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Create a shared RefCountedRuntimeFilterCollector auto&& rc_rf_probe_collector = std::make_shared(1, std::move(this->runtime_filter_collector())); diff --git a/be/src/exec/select_node.h b/be/src/exec/select_node.h index d0d67d52fbe41..aa93b9f38d9dc 100644 --- a/be/src/exec/select_node.h +++ b/be/src/exec/select_node.h @@ -47,6 +47,10 @@ class SelectNode final : public ExecNode { SelectNode(ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs); ~SelectNode() override; +<<<<<<< HEAD +======= + Status init(const TPlanNode& tnode, RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status prepare(RuntimeState* state) override; Status open(RuntimeState* state) override; Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos) override; @@ -55,6 +59,11 @@ class SelectNode final : public ExecNode { pipeline::PipelineBuilderContext* context) override; private: +<<<<<<< HEAD +======= + std::map _common_expr_ctxs; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeProfile::Counter* _conjunct_evaluate_timer = nullptr; }; diff --git a/be/src/exec/sorted_streaming_aggregator.cpp b/be/src/exec/sorted_streaming_aggregator.cpp index 3766e70bff2b9..c5af4db3ef4dc 100644 --- a/be/src/exec/sorted_streaming_aggregator.cpp +++ b/be/src/exec/sorted_streaming_aggregator.cpp @@ -165,7 +165,12 @@ class ColumnSelfComparator : public ColumnVisitorAdapter { // class AppendWithMask : public ColumnVisitorMutableAdapter { public: +<<<<<<< HEAD using SelMask = std::vector; +======= + using SelMask = Filter; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AppendWithMask(Column* column, SelMask sel_mask, size_t selected_size) : ColumnVisitorMutableAdapter(this), _column(column), @@ -214,7 +219,11 @@ class AppendWithMask : public ColumnVisitorMutableAdapter { } DCHECK_EQ(_selected_size, offsets); datas.resize(_selected_size); +<<<<<<< HEAD column->append_strings(datas); +======= + column->append_strings(datas.data(), datas.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -326,7 +335,11 @@ StatusOr SortedStreamingAggregator::streaming_compute_agg_state(size_t RETURN_IF_ERROR(_update_states(chunk_size, is_update_phase)); // selector[i] == 0 means selected +<<<<<<< HEAD std::vector selector(chunk_size); +======= + Filter selector(chunk_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t selected_size = _init_selector(selector, chunk_size); // finalize state @@ -373,7 +386,11 @@ StatusOr SortedStreamingAggregator::streaming_compute_distinct(size_t RETURN_IF_ERROR(_compute_group_by(chunk_size)); // selector[i] == 0 means selected +<<<<<<< HEAD std::vector selector(chunk_size); +======= + Filter selector(chunk_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t selected_size = _init_selector(selector, chunk_size); auto res_group_by_columns = _create_group_by_columns(chunk_size); RETURN_IF_ERROR(_build_group_by_columns(chunk_size, selected_size, selector, res_group_by_columns)); @@ -390,7 +407,11 @@ StatusOr SortedStreamingAggregator::streaming_compute_distinct(size_t return result_chunk; } +<<<<<<< HEAD size_t SortedStreamingAggregator::_init_selector(std::vector& selector, size_t chunk_size) { +======= +size_t SortedStreamingAggregator::_init_selector(Filter& selector, size_t chunk_size) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t selected_size = 0; { SCOPED_TIMER(_agg_stat->agg_compute_timer); @@ -409,7 +430,11 @@ Status SortedStreamingAggregator::_compute_group_by(size_t chunk_size) { // _cmp_vector[i] = group[i - 1].equals(group[i]) // _cmp_vector[i] == 0 means group[i - 1].equals(group[i]) _cmp_vector.assign(chunk_size, 0); +<<<<<<< HEAD const std::vector dummy; +======= + const Buffer dummy; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(_agg_stat->agg_compute_timer); for (size_t i = 0; i < _group_by_columns.size(); ++i) { ColumnSelfComparator cmp(_last_columns[i], _cmp_vector, dummy); @@ -438,7 +463,11 @@ Status SortedStreamingAggregator::_update_states(size_t chunk_size, bool is_upda } // only create the state when selector == 0 +<<<<<<< HEAD std::vector create_selector(chunk_size); +======= + Filter create_selector(chunk_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < _cmp_vector.size(); ++i) { create_selector[i] = _cmp_vector[i] == 0; } @@ -469,7 +498,11 @@ Status SortedStreamingAggregator::_update_states(size_t chunk_size, bool is_upda return Status::OK(); } +<<<<<<< HEAD Status SortedStreamingAggregator::_get_agg_result_columns(size_t chunk_size, const std::vector& selector, +======= +Status SortedStreamingAggregator::_get_agg_result_columns(size_t chunk_size, const Buffer& selector, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Columns& agg_result_columns) { TRY_CATCH_ALLOC_SCOPE_START() auto use_intermediate = _use_intermediate_as_output(); @@ -497,7 +530,11 @@ Status SortedStreamingAggregator::_get_agg_result_columns(size_t chunk_size, con return Status::OK(); } +<<<<<<< HEAD void SortedStreamingAggregator::_close_group_by(size_t chunk_size, const std::vector& selector) { +======= +void SortedStreamingAggregator::_close_group_by(size_t chunk_size, const Filter& selector) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // close stage SCOPED_TIMER(_agg_stat->state_destroy_timer); if (_cmp_vector[0] != 0 && _last_state) { @@ -511,8 +548,12 @@ void SortedStreamingAggregator::_close_group_by(size_t chunk_size, const std::ve } Status SortedStreamingAggregator::_build_group_by_columns(size_t chunk_size, size_t selected_size, +<<<<<<< HEAD const std::vector& selector, Columns& agg_group_by_columns) { +======= + const Filter& selector, Columns& agg_group_by_columns) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(_agg_stat->agg_append_timer); if (_cmp_vector[0] != 0 && !_last_columns.empty() && !_last_columns.back()->empty()) { for (size_t i = 0; i < agg_group_by_columns.size(); ++i) { diff --git a/be/src/exec/sorted_streaming_aggregator.h b/be/src/exec/sorted_streaming_aggregator.h index dd5cf7d2962f9..1edb9076c751c 100644 --- a/be/src/exec/sorted_streaming_aggregator.h +++ b/be/src/exec/sorted_streaming_aggregator.h @@ -42,6 +42,7 @@ class SortedStreamingAggregator final : public Aggregator { Status _update_states(size_t chunk_size, bool is_update_phase); // init selector by _cmp_vector // return selected_size (distinct num_rows) +<<<<<<< HEAD size_t _init_selector(std::vector& selector, size_t chunk_size); Status _get_agg_result_columns(size_t chunk_size, const std::vector& selector, @@ -49,6 +50,14 @@ class SortedStreamingAggregator final : public Aggregator { void _close_group_by(size_t chunk_size, const std::vector& selector); Status _build_group_by_columns(size_t chunk_size, size_t selected_size, const std::vector& selector, +======= + size_t _init_selector(Filter& selector, size_t chunk_size); + + Status _get_agg_result_columns(size_t chunk_size, const Filter& selector, Columns& agg_result_columns); + void _close_group_by(size_t chunk_size, const Filter& selector); + + Status _build_group_by_columns(size_t chunk_size, size_t selected_size, const Filter& selector, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Columns& agg_group_by_columns); AggDataPtr _last_state = nullptr; diff --git a/be/src/exec/sorting/compare_column.cpp b/be/src/exec/sorting/compare_column.cpp index e57810d2cace1..f982e18688610 100644 --- a/be/src/exec/sorting/compare_column.cpp +++ b/be/src/exec/sorting/compare_column.cpp @@ -327,7 +327,11 @@ int compare_column(const ColumnPtr& column, CompareVector& cmp_vector, Datum rhs return compare.get_equal_count(); } +<<<<<<< HEAD void compare_columns(const Columns& columns, std::vector& cmp_vector, const std::vector& rhs_values, +======= +void compare_columns(const Columns& columns, CompareVector& cmp_vector, const Buffer& rhs_values, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const SortDescs& sort_desc) { if (columns.empty()) { return; diff --git a/be/src/exec/sorting/merge.h b/be/src/exec/sorting/merge.h index 312301b196ae1..f8784b0a8e93f 100644 --- a/be/src/exec/sorting/merge.h +++ b/be/src/exec/sorting/merge.h @@ -152,16 +152,28 @@ class MergeTwoCursor { // Use it as iterator // Return nullptr if no output +<<<<<<< HEAD [[nodiscard]] StatusOr next(); [[nodiscard]] Status consume_all(const ChunkConsumer& output); +======= + StatusOr next(); + + Status consume_all(const ChunkConsumer& output); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::unique_ptr as_chunk_cursor(); private: ChunkProvider& as_provider() { return _chunk_provider; } +<<<<<<< HEAD [[nodiscard]] StatusOr merge_sorted_cursor_two_way(); // merge two runs [[nodiscard]] StatusOr merge_sorted_intersected_cursor(SortedRun& run1, SortedRun& run2); +======= + StatusOr merge_sorted_cursor_two_way(); + // merge two runs + StatusOr merge_sorted_intersected_cursor(SortedRun& run1, SortedRun& run2); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool move_cursor(); @@ -184,12 +196,20 @@ class MergeCursorsCascade { MergeCursorsCascade() = default; ~MergeCursorsCascade() = default; +<<<<<<< HEAD [[nodiscard]] Status init(const SortDescs& sort_desc, std::vector>&& cursors); bool is_data_ready(); bool is_eos(); ChunkUniquePtr try_get_next(); [[nodiscard]] Status consume_all(const ChunkConsumer& consumer); +======= + Status init(const SortDescs& sort_desc, std::vector>&& cursors); + bool is_data_ready(); + bool is_eos(); + ChunkUniquePtr try_get_next(); + Status consume_all(const ChunkConsumer& consumer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::vector> _mergers; @@ -200,6 +220,7 @@ class SimpleChunkSortCursor; // Merge implementations // Underlying algorithm is multi-level cascade-merge, which could be streaming and short-circuit +<<<<<<< HEAD [[nodiscard]] Status merge_sorted_chunks_two_way(const SortDescs& sort_desc, const SortedRun& left, const SortedRun& right, Permutation* output); [[nodiscard]] Status merge_sorted_chunks(const SortDescs& descs, const std::vector* sort_exprs, @@ -211,5 +232,18 @@ class SimpleChunkSortCursor; // Merge in rowwise, which is slow and used only in benchmark [[nodiscard]] Status merge_sorted_chunks_two_way_rowwise(const SortDescs& descs, const Columns& left, const Columns& right, Permutation* output, size_t limit); +======= +Status merge_sorted_chunks_two_way(const SortDescs& sort_desc, const SortedRun& left, const SortedRun& right, + Permutation* output); +Status merge_sorted_chunks(const SortDescs& descs, const std::vector* sort_exprs, + std::vector& chunks, SortedRuns* output); +Status merge_sorted_cursor_cascade(const SortDescs& sort_desc, + std::vector>&& cursors, + const ChunkConsumer& consumer); + +// Merge in rowwise, which is slow and used only in benchmark +Status merge_sorted_chunks_two_way_rowwise(const SortDescs& descs, const Columns& left, const Columns& right, + Permutation* output, size_t limit); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/sorting/merge_column.cpp b/be/src/exec/sorting/merge_column.cpp index 3c7d0d8a331d6..5be070bfbaddf 100644 --- a/be/src/exec/sorting/merge_column.cpp +++ b/be/src/exec/sorting/merge_column.cpp @@ -53,7 +53,11 @@ class MergeTwoColumn final : public ColumnVisitorAdapter { _perm(perm) {} template +<<<<<<< HEAD [[nodiscard]] Status do_merge(Cmp cmp, LeftEqual equal_left, RightEqual equal_right) { +======= + Status do_merge(Cmp cmp, LeftEqual equal_left, RightEqual equal_right) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector next_ranges; next_ranges.reserve(_equal_ranges->size()); @@ -117,7 +121,11 @@ class MergeTwoColumn final : public ColumnVisitorAdapter { // General implementation template +<<<<<<< HEAD [[nodiscard]] Status do_visit_slow(const ColumnType&) { +======= + Status do_visit_slow(const ColumnType&) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto cmp = [&](size_t lhs_index, size_t rhs_index) { int x = _left_col->compare_at(lhs_index, rhs_index, *_right_col, _null_first); if (_sort_order == -1) { @@ -135,7 +143,11 @@ class MergeTwoColumn final : public ColumnVisitorAdapter { } template +<<<<<<< HEAD [[nodiscard]] Status merge_ordinary_column(const Container& left_data, const Container& right_data) { +======= + Status merge_ordinary_column(const Container& left_data, const Container& right_data) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto cmp = [&](size_t lhs_index, size_t rhs_index) { int x = SorterComparator::compare(left_data[lhs_index], right_data[rhs_index]); if (_sort_order == -1) { @@ -153,13 +165,21 @@ class MergeTwoColumn final : public ColumnVisitorAdapter { } template +<<<<<<< HEAD [[nodiscard]] Status do_visit(const ColumnType& _) { +======= + Status do_visit(const ColumnType& _) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return do_visit_slow(_); } // Specific version for FixedlengthColumn template +<<<<<<< HEAD [[nodiscard]] Status do_visit(const FixedLengthColumn& _) { +======= + Status do_visit(const FixedLengthColumn& _) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using ColumnType = const FixedLengthColumn; using Container = typename ColumnType::Container; auto& left_data = down_cast(_left_col)->get_data(); @@ -168,7 +188,11 @@ class MergeTwoColumn final : public ColumnVisitorAdapter { } template +<<<<<<< HEAD [[nodiscard]] Status do_visit(const BinaryColumnBase& _) { +======= + Status do_visit(const BinaryColumnBase& _) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using ColumnType = const BinaryColumnBase; using Container = typename BinaryColumnBase::BinaryDataProxyContainer; auto& left_data = down_cast(_left_col)->get_proxy_data(); @@ -176,7 +200,11 @@ class MergeTwoColumn final : public ColumnVisitorAdapter { return merge_ordinary_column(left_data, right_data); } +<<<<<<< HEAD [[nodiscard]] Status do_visit(const NullableColumn& _) { +======= + Status do_visit(const NullableColumn& _) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Fast path if (!_left_col->has_null() && !_right_col->has_null()) { DCHECK(_left_col->is_nullable() && _right_col->is_nullable()); @@ -211,8 +239,13 @@ class MergeTwoChunk { static constexpr int kLeftChunkIndex = 0; static constexpr int kRightChunkIndex = 1; +<<<<<<< HEAD [[nodiscard]] static Status merge_sorted_chunks_two_way(const SortDescs& sort_desc, const SortedRun& left_run, const SortedRun& right_run, Permutation* output) { +======= + static Status merge_sorted_chunks_two_way(const SortDescs& sort_desc, const SortedRun& left_run, + const SortedRun& right_run, Permutation* output) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(!!left_run.chunk); DCHECK(!!right_run.chunk); DCHECK_EQ(left_run.num_columns(), right_run.num_columns()); diff --git a/be/src/exec/sorting/sort_permute.h b/be/src/exec/sorting/sort_permute.h index 4441eda06ca5b..4679b53475bf3 100644 --- a/be/src/exec/sorting/sort_permute.h +++ b/be/src/exec/sorting/sort_permute.h @@ -141,6 +141,10 @@ struct TieIterator { }; // Compare result of column, value must be -1,0,1 +<<<<<<< HEAD using CompareVector = std::vector; +======= +using CompareVector = Buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exec/sorting/sorting.h b/be/src/exec/sorting/sorting.h index cc7d45de0bfcc..83d74dc480ba9 100644 --- a/be/src/exec/sorting/sorting.h +++ b/be/src/exec/sorting/sorting.h @@ -75,8 +75,13 @@ Status sort_vertical_chunks(const std::atomic& cancel, const std::vector& cmp_result, Datum rhs_value, const SortDesc& desc); void compare_columns(const Columns& columns, std::vector& cmp_result, const std::vector& rhs_values, +======= +int compare_column(const ColumnPtr& column, Buffer& cmp_result, Datum rhs_value, const SortDesc& desc); +void compare_columns(const Columns& columns, Buffer& cmp_result, const Buffer& rhs_values, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const SortDescs& sort_desc); // Build tie by comparison of adjacent rows in column. diff --git a/be/src/exec/spill/common.h b/be/src/exec/spill/common.h index 4c9a8d389286d..074c4d31bbda4 100644 --- a/be/src/exec/spill/common.h +++ b/be/src/exec/spill/common.h @@ -15,8 +15,16 @@ #pragma once // #define TRACE_SPILL_LOG VLOG_QUERY +<<<<<<< HEAD #define TRACE_SPILL_LOG VLOG(1) #define AUTO_DEL_SPILL_FILE true #define AUTO_DEL_SPILL_DIR true +======= +#define TRACE_SPILL_LOG VLOG(10) + +#define AUTO_DEL_SPILL_FILE true + +#define AUTO_DEL_SPILL_DIR true +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/exec/spill/mem_table.cpp b/be/src/exec/spill/mem_table.cpp index 2aae436cd16ed..e3a7972ba1470 100644 --- a/be/src/exec/spill/mem_table.cpp +++ b/be/src/exec/spill/mem_table.cpp @@ -167,7 +167,11 @@ Status OrderedMemTable::finalize(workgroup::YieldContext& yield_ctx, const Spill return Status::OK(); } SCOPED_RAW_TIMER(&yield_ctx.time_spent_ns); +<<<<<<< HEAD auto chunk = _chunk_slice.cutoff(_runtime_state->chunk_size()); +======= + ChunkPtr chunk = _chunk_slice.cutoff(_runtime_state->chunk_size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool need_aligned = _runtime_state->spill_enable_direct_io(); RETURN_IF_ERROR(serde->serialize(_runtime_state, serde_ctx, chunk, output, need_aligned)); diff --git a/be/src/exec/spill/mem_table.h b/be/src/exec/spill/mem_table.h index 4f119b82192b2..d383a4521a4eb 100644 --- a/be/src/exec/spill/mem_table.h +++ b/be/src/exec/spill/mem_table.h @@ -60,9 +60,14 @@ class SpillableMemTable { virtual bool is_empty() = 0; size_t mem_usage() { return _tracker->consumption(); } // append data to mem table +<<<<<<< HEAD [[nodiscard]] virtual Status append(ChunkPtr chunk) = 0; [[nodiscard]] virtual Status append_selective(const Chunk& src, const uint32_t* indexes, uint32_t from, uint32_t size) = 0; +======= + virtual Status append(ChunkPtr chunk) = 0; + virtual Status append_selective(const Chunk& src, const uint32_t* indexes, uint32_t from, uint32_t size) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Theoretically, the implementation of done and finalize interfaces only have calculation logic, and there is no need to do them separately. // However, there are some limitations at this stage: @@ -109,9 +114,14 @@ class UnorderedMemTable final : public SpillableMemTable { ~UnorderedMemTable() override = default; bool is_empty() override; +<<<<<<< HEAD [[nodiscard]] Status append(ChunkPtr chunk) override; [[nodiscard]] Status append_selective(const Chunk& src, const uint32_t* indexes, uint32_t from, uint32_t size) override; +======= + Status append(ChunkPtr chunk) override; + Status append_selective(const Chunk& src, const uint32_t* indexes, uint32_t from, uint32_t size) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status finalize(workgroup::YieldContext& yield_ctx, const SpillOutputDataStreamPtr& output) override; void reset() override; @@ -131,9 +141,14 @@ class OrderedMemTable final : public SpillableMemTable { ~OrderedMemTable() override = default; bool is_empty() override; +<<<<<<< HEAD [[nodiscard]] Status append(ChunkPtr chunk) override; [[nodiscard]] Status append_selective(const Chunk& src, const uint32_t* indexes, uint32_t from, uint32_t size) override; +======= + Status append(ChunkPtr chunk) override; + Status append_selective(const Chunk& src, const uint32_t* indexes, uint32_t from, uint32_t size) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status done() override; Status finalize(workgroup::YieldContext& yield_ctx, const SpillOutputDataStreamPtr& output) override; diff --git a/be/src/exec/spill/spiller.h b/be/src/exec/spill/spiller.h index 9854cc0534d46..fb5183eda83b6 100644 --- a/be/src/exec/spill/spiller.h +++ b/be/src/exec/spill/spiller.h @@ -40,13 +40,21 @@ #include "util/compression/block_compression.h" #include "util/runtime_profile.h" +<<<<<<< HEAD +======= +#define GET_METRICS(remote, metrics, key) (remote ? metrics.remote_##key : metrics.local_##key) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #define RETURN_TRUE_IF_SPILL_TASK_ERROR(spiller) \ if (!(spiller)->task_status().ok()) { \ return true; \ } +<<<<<<< HEAD #define GET_METRICS(remote, metrics, key) (remote ? metrics.remote_##key : metrics.local_##key) +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::spill { // some metrics for spill diff --git a/be/src/exec/stream/aggregate/agg_group_state.cpp b/be/src/exec/stream/aggregate/agg_group_state.cpp index 1d4ddac318790..6c6258f65c75b 100644 --- a/be/src/exec/stream/aggregate/agg_group_state.cpp +++ b/be/src/exec/stream/aggregate/agg_group_state.cpp @@ -133,9 +133,14 @@ Status AggGroupState::open(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD Status AggGroupState::process_chunk(size_t chunk_size, const Columns& group_by_columns, const Buffer& keys_not_in_map, const StreamRowOp* ops, const std::vector>& agg_columns, +======= +Status AggGroupState::process_chunk(size_t chunk_size, const Columns& group_by_columns, const Filter& keys_not_in_map, + const StreamRowOp* ops, const std::vector>& agg_columns, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector>& raw_columns, const Buffer& agg_group_state) const { DCHECK(!_agg_states.empty()); @@ -253,7 +258,11 @@ Status AggGroupState::output_changes(size_t chunk_size, const Columns& group_by_ RETURN_IF_ERROR(agg_state->output_detail(chunk_size, agg_group_state, detail_cols, result_count.get())); auto result_count_data = reinterpret_cast(result_count.get())->get_data(); +<<<<<<< HEAD std::vector replicate_offsets; +======= + Buffer replicate_offsets; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) replicate_offsets.reserve(result_count_data.size() + 1); int offset = 0; for (auto count : result_count_data) { diff --git a/be/src/exec/stream/aggregate/agg_group_state.h b/be/src/exec/stream/aggregate/agg_group_state.h index 0b93eb8e08020..bdfbbf66638ca 100644 --- a/be/src/exec/stream/aggregate/agg_group_state.h +++ b/be/src/exec/stream/aggregate/agg_group_state.h @@ -32,6 +32,7 @@ class AggGroupState { const std::vector& agg_states() const { return _agg_states; } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state); [[nodiscard]] Status open(RuntimeState* state); @@ -63,6 +64,34 @@ class AggGroupState { [[nodiscard]] Status _prepare_imt_state_tables(RuntimeState* state, const std::vector& intermediate_agg_states, const std::vector& detail_agg_states); +======= + Status prepare(RuntimeState* state); + Status open(RuntimeState* state); + + Status process_chunk(size_t chunk_size, const Columns& group_by_columns, const Buffer& keys_not_in_map, + const StreamRowOp* ops, const std::vector>& agg_columns, + std::vector>& raw_columns, + const Buffer& agg_group_state) const; + + Status output_results(size_t chunk_size, const Columns& group_by_columns, const Buffer& agg_group_data, + Columns output_columns) const; + + Status output_changes(size_t chunk_size, const Columns& group_by_columns, const Buffer& agg_group_state, + ChunkPtr* agg_intermediate_chunk, std::vector* detail_chunks) const; + + Status output_prev_state_results(const Columns& group_by_columns, StateTableResult& prev_state_result); + + Status write(RuntimeState* state, StreamChunkPtr* result_chunk, ChunkPtr* intermediate_chunk, + std::vector& detail_chunk); + Status commit_epoch(RuntimeState* state); + Status reset_epoch(RuntimeState* state); + +private: + Status _prepare_mem_state_tables(RuntimeState* state, const std::vector& intermediate_agg_states, + const std::vector& detail_agg_states); + Status _prepare_imt_state_tables(RuntimeState* state, const std::vector& intermediate_agg_states, + const std::vector& detail_agg_states); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StateTable* _find_detail_state_table(const AggStateDataUPtr& agg_state) const; ChunkPtr _build_intermediate_chunk(const Columns& group_by_columns, const Columns& agg_intermediate_columns) const; diff --git a/be/src/exec/stream/aggregate/agg_state_data.cpp b/be/src/exec/stream/aggregate/agg_state_data.cpp index 25de89d603b42..fb3987ecebea3 100644 --- a/be/src/exec/stream/aggregate/agg_state_data.cpp +++ b/be/src/exec/stream/aggregate/agg_state_data.cpp @@ -22,7 +22,11 @@ namespace starrocks::stream { +<<<<<<< HEAD Status AggStateData::allocate_intermediate_state(size_t chunk_size, const std::vector& keys_not_in_map, +======= +Status AggStateData::allocate_intermediate_state(size_t chunk_size, const Filter& keys_not_in_map, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const StateTableResult* state_result, const Buffer& agg_group_state) const { DCHECK(state_result); diff --git a/be/src/exec/stream/aggregate/agg_state_data.h b/be/src/exec/stream/aggregate/agg_state_data.h index 13c12bf1dcb3f..e0454147700b5 100644 --- a/be/src/exec/stream/aggregate/agg_state_data.h +++ b/be/src/exec/stream/aggregate/agg_state_data.h @@ -53,6 +53,7 @@ class AggStateData { // Restore intermediate state if needed by using last run state table's results from // result/intermediate state table. +<<<<<<< HEAD [[nodiscard]] Status allocate_intermediate_state(size_t chunk_size, const std::vector& keys_not_in_map, const StateTableResult* state_result, const Buffer& agg_group_state) const; @@ -73,6 +74,26 @@ class AggStateData { [[nodiscard]] Status output_detail(size_t chunk_size, const Buffer& agg_group_state, const Columns& to, Column* count) const; +======= + Status allocate_intermediate_state(size_t chunk_size, const Filter& keys_not_in_map, + const StateTableResult* state_result, + const Buffer& agg_group_state) const; + + // Restore detail state if needed by using last run state's result from + // detail state table + Status allocate_detail_state(size_t chunk_size, const Column* raw_column, const StateTableResult* state_result, + const Buffer& agg_group_state) const; + + Status process_chunk(size_t chunk_size, const StreamRowOp* ops, + std::vector>& raw_columns, + const Buffer& agg_group_state) const; + + Status output_result(size_t chunk_size, const Columns& group_by_columns, const Buffer& agg_group_data, + const StateTable* detail_state_table, Column* to) const; + + Status output_detail(size_t chunk_size, const Buffer& agg_group_state, const Columns& to, + Column* count) const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const AggregateFunction* agg_function() const { return _agg_function; } FunctionContext* agg_fn_ctx() const { return _agg_fn_ctx; } diff --git a/be/src/exec/stream/aggregate/stream_aggregate_operator.h b/be/src/exec/stream/aggregate/stream_aggregate_operator.h index 56255b72ad252..708a235f5cb74 100644 --- a/be/src/exec/stream/aggregate/stream_aggregate_operator.h +++ b/be/src/exec/stream/aggregate/stream_aggregate_operator.h @@ -42,6 +42,7 @@ class StreamAggregateOperator : public pipeline::SourceOperator { bool has_output() const override; bool need_input() const override { return !is_finished(); } bool is_finished() const override; +<<<<<<< HEAD [[nodiscard]] Status set_finishing(RuntimeState* state) override; [[nodiscard]] Status set_finished(RuntimeState* state) override; @@ -53,6 +54,19 @@ class StreamAggregateOperator : public pipeline::SourceOperator { [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; [[nodiscard]] Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; [[nodiscard]] Status prepare(RuntimeState* state) override; +======= + Status set_finishing(RuntimeState* state) override; + Status set_finished(RuntimeState* state) override; + + bool is_epoch_finished() const override; + Status set_epoch_finishing(RuntimeState* state) override; + Status set_epoch_finished(RuntimeState* state) override; + Status reset_epoch(RuntimeState* state) override; + + StatusOr pull_chunk(RuntimeState* state) override; + Status push_chunk(RuntimeState* state, const ChunkPtr& chunk) override; + Status prepare(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state) override; private: diff --git a/be/src/exec/stream/aggregate/stream_aggregator.h b/be/src/exec/stream/aggregate/stream_aggregator.h index e7b8f2718f061..37e86f45ed86a 100644 --- a/be/src/exec/stream/aggregate/stream_aggregator.h +++ b/be/src/exec/stream/aggregate/stream_aggregator.h @@ -57,6 +57,7 @@ class StreamAggregator final : public Aggregator { } } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* runtime_profile); [[nodiscard]] Status open(RuntimeState* state); @@ -90,10 +91,45 @@ class StreamAggregator final : public Aggregator { // Output incremental result changes based on previous outputs and new incremental outputs. [[nodiscard]] Status _output_result_changes(int32_t chunk_size, const Columns& group_by_columns, StreamChunkPtr* result_chunk); +======= + Status prepare(RuntimeState* state, ObjectPool* pool, RuntimeProfile* runtime_profile); + + Status open(RuntimeState* state); + + // Process input's chunks util `Epoch` chunk is received. + Status process_chunk(StreamChunk* chunk); + + // Called when need to generate incremental outputs and Output agg_states for the next batch. + Status output_changes(int32_t chunk_size, StreamChunkPtr* result_chunk); + + // Called when need to generate incremental outputs and Output agg_states for the next batch. + Status output_changes_internal(int32_t chunk_size, StreamChunkPtr* result_chunk, ChunkPtr* intermediate_chunk, + std::vector& detail_chunks); + + // Reset the aggregator's state to avoid hashmap too large. + Status reset_state(RuntimeState* state); + + // When the epoch is finished, commit the state table. + Status commit_epoch(RuntimeState* state); + + // When the epoch starts, reset stream aggreator's state in the new epoch. + Status reset_epoch(RuntimeState* state); + +private: + Status _prepare_state_tables(RuntimeState* state); + + // Output intermediate(same to OLAP's agg_state) chunks. + Status _output_intermediate_changes(int32_t chunk_size, const Columns& group_by_columns, + ChunkPtr* intermediate_chunk); + + // Output incremental result changes based on previous outputs and new incremental outputs. + Status _output_result_changes(int32_t chunk_size, const Columns& group_by_columns, StreamChunkPtr* result_chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Use history(prev) output and final count to generate UPDATE_BEFORE/DELETE Ops: // If prev output exists and final count > 0: generate UPDATE_BEFORE // If prev output exists and final count = 0: generate DELETE +<<<<<<< HEAD [[nodiscard]] Status _output_result_changes_with_retract(size_t chunk_size, const Columns& group_by_columns, StreamChunkPtr* result_chunk_with_ops); @@ -104,6 +140,18 @@ class StreamAggregator final : public Aggregator { // Output results without generating retract messages. [[nodiscard]] Status _output_result_changes_without_retract(size_t chunk_size, const Columns& group_by_columns, StreamChunkPtr* result_chunk); +======= + Status _output_result_changes_with_retract(size_t chunk_size, const Columns& group_by_columns, + StreamChunkPtr* result_chunk_with_ops); + + // output results by calling retract functions + Status _output_final_result_with_retract(size_t chunk_size, const Columns& group_by_columns, + ChunkPtr* post_chunk_result); + + // Output results without generating retract messages. + Status _output_result_changes_without_retract(size_t chunk_size, const Columns& group_by_columns, + StreamChunkPtr* result_chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: // Store buffers which can be reused in the incremental compute. diff --git a/be/src/exec/stream/scan/stream_scan_operator.h b/be/src/exec/stream/scan/stream_scan_operator.h index 2987d6b302b50..8795c5042a461 100644 --- a/be/src/exec/stream/scan/stream_scan_operator.h +++ b/be/src/exec/stream/scan/stream_scan_operator.h @@ -52,28 +52,47 @@ class StreamScanOperator final : public ConnectorScanOperator { bool is_stream_pipeline); ~StreamScanOperator() override; +<<<<<<< HEAD [[nodiscard]] Status set_epoch_finishing(RuntimeState* state) override { +======= + Status set_epoch_finishing(RuntimeState* state) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard guard(_task_mutex); _detach_chunk_sources(); _is_epoch_finished = true; return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status set_epoch_finished(RuntimeState* state) override; [[nodiscard]] Status do_prepare(RuntimeState* state) override { +======= + Status set_epoch_finished(RuntimeState* state) override; + + Status do_prepare(RuntimeState* state) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(ConnectorScanOperator::do_prepare(state)); _stream_epoch_manager = state->query_ctx()->stream_epoch_manager(); DCHECK(_stream_epoch_manager); return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status _pickup_morsel(RuntimeState* state, int chunk_source_index) override; [[nodiscard]] Status reset_epoch(RuntimeState* runtime_state) override; bool is_finished() const override; bool has_output() const override; [[nodiscard]] StatusOr pull_chunk(RuntimeState* state) override; +======= + Status _pickup_morsel(RuntimeState* state, int chunk_source_index) override; + + Status reset_epoch(RuntimeState* runtime_state) override; + bool is_finished() const override; + bool has_output() const override; + StatusOr pull_chunk(RuntimeState* state) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _close_chunk_source_unlocked(RuntimeState* state, int index) override; void _finish_chunk_source_task(RuntimeState* state, int chunk_source_index, int64_t cpu_time_ns, int64_t scan_rows, @@ -84,8 +103,13 @@ class StreamScanOperator final : public ConnectorScanOperator { ChunkSourcePtr create_chunk_source(MorselPtr morsel, int32_t chunk_source_index) override; private: +<<<<<<< HEAD [[nodiscard]] StatusOr _mark_mock_data_finished(); [[nodiscard]] Status _reset_chunk_source(RuntimeState* state, int chunk_source_index); +======= + StatusOr _mark_mock_data_finished(); + Status _reset_chunk_source(RuntimeState* state, int chunk_source_index); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::atomic _chunk_num{0}; bool _is_epoch_start{false}; @@ -105,9 +129,15 @@ class StreamChunkSource : public ConnectorChunkSource { StreamChunkSource(ScanOperator* op, RuntimeProfile* runtime_profile, MorselPtr&& morsel, ConnectorScanNode* scan_node, BalancedChunkBuffer& chunk_buffer, bool enable_adaptive_io_task); +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; [[nodiscard]] Status set_stream_offset(int64_t table_version, int64_t changelog_id); +======= + Status prepare(RuntimeState* state) override; + + Status set_stream_offset(int64_t table_version, int64_t changelog_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_epoch_limit(int64_t epoch_rows_limit, int64_t epoch_time_limit); Status reset_status(); int64_t get_lane_owner() { diff --git a/be/src/exec/stream/state/mem_state_table.cpp b/be/src/exec/stream/state/mem_state_table.cpp index c042e608dc430..408493835a6d7 100644 --- a/be/src/exec/stream/state/mem_state_table.cpp +++ b/be/src/exec/stream/state/mem_state_table.cpp @@ -34,7 +34,11 @@ void convert_datum_rows_to_chunk(const std::vector& rows, Chunk* chunk } // namespace +<<<<<<< HEAD [[nodiscard]] Status DatumRowIterator::do_get_next(Chunk* chunk) { +======= +Status DatumRowIterator::do_get_next(Chunk* chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!_is_eos) { convert_datum_rows_to_chunk(_rows, chunk); _is_eos = true; @@ -43,6 +47,7 @@ void convert_datum_rows_to_chunk(const std::vector& rows, Chunk* chunk return Status::EndOfFile("end of empty iterator"); } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::prepare(RuntimeState* state) { return Status::OK(); } @@ -52,6 +57,17 @@ void convert_datum_rows_to_chunk(const std::vector& rows, Chunk* chunk } [[nodiscard]] Status MemStateTable::commit(RuntimeState* state) { +======= +Status MemStateTable::prepare(RuntimeState* state) { + return Status::OK(); +} + +Status MemStateTable::open(RuntimeState* state) { + return Status::OK(); +} + +Status MemStateTable::commit(RuntimeState* state) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -65,7 +81,11 @@ bool MemStateTable::_equal_keys(const DatumKeyRow& m_k, const DatumKeyRow& keys) return true; } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::seek(const Columns& keys, StateTableResult& values) const { +======= +Status MemStateTable::seek(const Columns& keys, StateTableResult& values) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto num_rows = keys[0]->size(); auto& found = values.found; auto& result_chunk = values.result_chunk; @@ -81,14 +101,22 @@ bool MemStateTable::_equal_keys(const DatumKeyRow& m_k, const DatumKeyRow& keys) return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::_append_null_to_chunk(ChunkPtr& result_chunk) const { +======= +Status MemStateTable::_append_null_to_chunk(ChunkPtr& result_chunk) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto& column : result_chunk->columns()) { column->append_nulls(1); } return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::_append_datum_row_to_chunk(const DatumRow& v_row, ChunkPtr& result_chunk) const { +======= +Status MemStateTable::_append_datum_row_to_chunk(const DatumRow& v_row, ChunkPtr& result_chunk) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_EQ(v_row.size(), result_chunk->num_columns()); auto& columns = result_chunk->columns(); for (size_t i = 0; i < result_chunk->num_columns(); i++) { @@ -97,8 +125,12 @@ bool MemStateTable::_equal_keys(const DatumKeyRow& m_k, const DatumKeyRow& keys) return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::seek(const Columns& keys, const std::vector& selection, StateTableResult& values) const { +======= +Status MemStateTable::seek(const Columns& keys, const Filter& selection, StateTableResult& values) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_LT(0, keys.size()); auto num_rows = keys[0]->size(); DCHECK_EQ(selection.size(), num_rows); @@ -126,8 +158,13 @@ bool MemStateTable::_equal_keys(const DatumKeyRow& m_k, const DatumKeyRow& keys) return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::seek(const Columns& keys, const std::vector& projection_columns, StateTableResult& values) const { +======= +Status MemStateTable::seek(const Columns& keys, const std::vector& projection_columns, + StateTableResult& values) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::NotSupported("Seek with projection columns is not supported yet."); } @@ -204,7 +241,11 @@ DatumKeyRow MemStateTable::_convert_columns_to_key(const Columns& cols, size_t i return key_row; } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::write(RuntimeState* state, const StreamChunkPtr& chunk) { +======= +Status MemStateTable::write(RuntimeState* state, const StreamChunkPtr& chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(chunk); auto chunk_size = chunk->num_rows(); if (StreamChunkConverter::has_ops_column(chunk)) { @@ -231,7 +272,11 @@ DatumKeyRow MemStateTable::_convert_columns_to_key(const Columns& cols, size_t i return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status MemStateTable::reset_epoch(RuntimeState* state) { +======= +Status MemStateTable::reset_epoch(RuntimeState* state) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } diff --git a/be/src/exec/stream/state/mem_state_table.h b/be/src/exec/stream/state/mem_state_table.h index cd957f33b1820..1c87bdcbe57d6 100644 --- a/be/src/exec/stream/state/mem_state_table.h +++ b/be/src/exec/stream/state/mem_state_table.h @@ -35,8 +35,13 @@ class DatumRowIterator final : public ChunkIterator { void close() override {} protected: +<<<<<<< HEAD [[nodiscard]] Status do_get_next(Chunk* chunk) override; [[nodiscard]] Status do_get_next(Chunk* chunk, vector* rowid) override { +======= + Status do_get_next(Chunk* chunk) override; + Status do_get_next(Chunk* chunk, vector* rowid) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::EndOfFile("end of empty iterator"); } @@ -64,6 +69,7 @@ class MemStateTable : public StateTable { } ~MemStateTable() override = default; +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state) override; [[nodiscard]] Status open(RuntimeState* state) override; @@ -73,10 +79,21 @@ class MemStateTable : public StateTable { [[nodiscard]] Status seek(const Columns& keys, const std::vector& projection_columns, StateTableResult& values) const override; +======= + Status prepare(RuntimeState* state) override; + Status open(RuntimeState* state) override; + + Status seek(const Columns& keys, StateTableResult& values) const override; + Status seek(const Columns& keys, const Filter& selection, StateTableResult& values) const override; + + Status seek(const Columns& keys, const std::vector& projection_columns, + StateTableResult& values) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkIteratorPtrOr prefix_scan(const Columns& keys, size_t row_idx) const override; ChunkIteratorPtrOr prefix_scan(const std::vector& projection_columns, const Columns& keys, size_t row_idx) const override; +<<<<<<< HEAD [[nodiscard]] Status write(RuntimeState* state, const StreamChunkPtr& chunk) override; [[nodiscard]] Status commit(RuntimeState* state) override; [[nodiscard]] Status reset_epoch(RuntimeState* state) override; @@ -85,6 +102,16 @@ class MemStateTable : public StateTable { DatumKeyRow _convert_columns_to_key(const Columns& cols, size_t idx) const; [[nodiscard]] Status _append_datum_row_to_chunk(const DatumRow& v_row, ChunkPtr& result_chunk) const; [[nodiscard]] Status _append_null_to_chunk(ChunkPtr& result_chunk) const; +======= + Status write(RuntimeState* state, const StreamChunkPtr& chunk) override; + Status commit(RuntimeState* state) override; + Status reset_epoch(RuntimeState* state) override; + +private: + DatumKeyRow _convert_columns_to_key(const Columns& cols, size_t idx) const; + Status _append_datum_row_to_chunk(const DatumRow& v_row, ChunkPtr& result_chunk) const; + Status _append_null_to_chunk(ChunkPtr& result_chunk) const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Schema _make_schema_from_slots(const std::vector& slots) const; static DatumKeyRow _make_datum_key_row(const ChunkPtr& chunk, size_t start, size_t end, int row_idx); diff --git a/be/src/exec/stream/state/state_table.h b/be/src/exec/stream/state/state_table.h index fd11490dcb690..fe41c2da2509a 100644 --- a/be/src/exec/stream/state/state_table.h +++ b/be/src/exec/stream/state/state_table.h @@ -40,13 +40,19 @@ class StateTable { public: virtual ~StateTable() = default; +<<<<<<< HEAD [[nodiscard]] virtual Status prepare(RuntimeState* state) = 0; [[nodiscard]] virtual Status open(RuntimeState* state) = 0; +======= + virtual Status prepare(RuntimeState* state) = 0; + virtual Status open(RuntimeState* state) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The batch api of `seek` which all the keys must be primary keys of state table. // NOTE: The count of the result of `seek` must be exactly same to the input keys' count. // NOTE: The queried key must be the primary keys of state table which may contain multi columns. // `seek` must only return one row for the primary keys. +<<<<<<< HEAD [[nodiscard]] virtual Status seek(const Columns& keys, StateTableResult& values) const = 0; // Seek with selection, only seek values when selection's flag is true. @@ -56,6 +62,16 @@ class StateTable { // If `projection_columns` is not empty, only output all needed projection_columns in values. [[nodiscard]] virtual Status seek(const Columns& keys, const std::vector& projection_columns, StateTableResult& values) const = 0; +======= + virtual Status seek(const Columns& keys, StateTableResult& values) const = 0; + + // Seek with selection, only seek values when selection's flag is true. + virtual Status seek(const Columns& keys, const Filter& selection, StateTableResult& values) const = 0; + + // If `projection_columns` is not empty, only output all needed projection_columns in values. + virtual Status seek(const Columns& keys, const std::vector& projection_columns, + StateTableResult& values) const = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The queried key must be the prefix of the primary keys. Result may contain multi rows, so // use ChunkIterator to fetch all results. result will output all non-key columns. @@ -66,12 +82,21 @@ class StateTable { size_t row_idx) const = 0; // Flush the input chunk into the state table: StreamChunk contains the ops columns. +<<<<<<< HEAD [[nodiscard]] virtual Status write(RuntimeState* state, const StreamChunkPtr& chunk) = 0; // Commit the flushed state data to be used in the later transaction. [[nodiscard]] virtual Status commit(RuntimeState* state) = 0; [[nodiscard]] virtual Status reset_epoch(RuntimeState* state) = 0; +======= + virtual Status write(RuntimeState* state, const StreamChunkPtr& chunk) = 0; + + // Commit the flushed state data to be used in the later transaction. + virtual Status commit(RuntimeState* state) = 0; + + virtual Status reset_epoch(RuntimeState* state) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks::stream diff --git a/be/src/exec/tablet_info.cpp b/be/src/exec/tablet_info.cpp index f83e8eda7f8be..f6dea6da1c09a 100644 --- a/be/src/exec/tablet_info.cpp +++ b/be/src/exec/tablet_info.cpp @@ -24,7 +24,10 @@ namespace starrocks { +<<<<<<< HEAD static const std::string LOAD_OP_COLUMN = "__op"; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // NOTE: This value should keep the same with the value in FE's `STARROCKS_DEFAULT_PARTITION_VALUE` constant. static const std::string STARROCKS_DEFAULT_PARTITION_VALUE = "__STARROCKS_DEFAULT_PARTITION__"; @@ -72,6 +75,10 @@ void OlapTableIndexSchema::to_protobuf(POlapTableIndexSchema* pindex) const { pindex->set_id(index_id); pindex->set_schema_hash(schema_hash); pindex->set_schema_id(schema_id); +<<<<<<< HEAD +======= + pindex->set_is_shadow(is_shadow); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto slot : slots) { pindex->add_columns(slot->col_name()); } @@ -129,6 +136,16 @@ Status OlapTableSchemaParam::init(const POlapTableSchemaParam& pschema) { index->column_to_expr_value.insert({entry.first, entry.second}); } +<<<<<<< HEAD +======= + if (p_index.has_is_shadow()) { + index->is_shadow = p_index.is_shadow(); + if (index->is_shadow) { + _shadow_indexes++; + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _indexes.emplace_back(index); } @@ -188,6 +205,15 @@ Status OlapTableSchemaParam::init(const TOlapTableSchemaParam& tschema, RuntimeS index->column_to_expr_value.insert({entry.first, entry.second}); } } +<<<<<<< HEAD +======= + if (t_index.__isset.is_shadow) { + index->is_shadow = t_index.is_shadow; + if (index->is_shadow) { + _shadow_indexes++; + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _indexes.emplace_back(index); } @@ -478,10 +504,18 @@ Status OlapTablePartitionParam::add_partitions(const std::vectornum_buckets = t_part.num_buckets; auto num_indexes = _schema->indexes().size(); +<<<<<<< HEAD if (t_part.indexes.size() != num_indexes) { std::stringstream ss; ss << "number of partition's index is not equal with schema's" << ", num_part_indexes=" << t_part.indexes.size() << ", num_schema_indexes=" << num_indexes; +======= + if (t_part.indexes.size() != num_indexes - _schema->shadow_index_size()) { + std::stringstream ss; + ss << "number of partition's index is not equal with schema's" + << ", num_part_indexes=" << t_part.indexes.size() << ", num_schema_indexes=" << num_indexes + << ", num_shadow_indexes=" << _schema->shadow_index_size(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) LOG(WARNING) << ss.str(); return Status::InternalError(ss.str()); } @@ -491,6 +525,7 @@ Status OlapTablePartitionParam::add_partitions(const std::vectorindexes[j].index_id != _schema->indexes()[j]->index_id) { std::stringstream ss; @@ -501,6 +536,27 @@ Status OlapTablePartitionParam::add_partitions(const std::vectorindexes()[i]->is_shadow) { + continue; + } + if (part->indexes[j].index_id != _schema->indexes()[i]->index_id) { + std::stringstream ss; + ss << "partition's index is not equal with schema's" + << ", part_index=" << part->indexes[j].index_id + << ", schema_index=" << _schema->indexes()[i]->index_id; + LOG(WARNING) << ss.str(); + return Status::InternalError(ss.str()); + } + j++; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _partitions.emplace(part->id, part); if (t_part.__isset.in_keys) { for (auto& in_key : part->in_keys) { diff --git a/be/src/exec/tablet_info.h b/be/src/exec/tablet_info.h index a86963b0c4098..e858a6924a00b 100644 --- a/be/src/exec/tablet_info.h +++ b/be/src/exec/tablet_info.h @@ -51,6 +51,10 @@ struct OlapTableIndexSchema { OlapTableColumnParam* column_param; ExprContext* where_clause = nullptr; std::map column_to_expr_value; +<<<<<<< HEAD +======= + bool is_shadow = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void to_protobuf(POlapTableIndexSchema* pindex) const; }; @@ -81,6 +85,10 @@ class OlapTableSchemaParam { return _proto_schema; } +<<<<<<< HEAD +======= + int64_t shadow_index_size() const { return _shadow_indexes; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const; private: @@ -92,6 +100,11 @@ class OlapTableSchemaParam { mutable POlapTableSchemaParam* _proto_schema = nullptr; std::vector _indexes; mutable ObjectPool _obj_pool; +<<<<<<< HEAD +======= + + int64_t _shadow_indexes = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; using OlapTableIndexTablets = TOlapTableIndexTablets; diff --git a/be/src/exec/tablet_scanner.cpp b/be/src/exec/tablet_scanner.cpp index 1a72a87d6e8ae..fc0d4eaaaa1f8 100644 --- a/be/src/exec/tablet_scanner.cpp +++ b/be/src/exec/tablet_scanner.cpp @@ -17,7 +17,10 @@ #include #include +<<<<<<< HEAD #include "column/column_pool.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/vectorized_fwd.h" #include "common/status.h" #include "exec/olap_scan_node.h" @@ -70,7 +73,11 @@ Status TabletScanner::init(RuntimeState* runtime_state, const TabletScannerParam _prj_iter = new_projection_iterator(output_schema, _reader); } +<<<<<<< HEAD if (!_conjunct_ctxs.empty() || !_predicates.empty()) { +======= + if (!_conjunct_ctxs.empty() || !_pred_tree.empty()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _expr_filter_timer = ADD_TIMER(_parent->_runtime_profile, "ExprFilterTime"); } @@ -118,8 +125,11 @@ void TabletScanner::close(RuntimeState* state) { _reader.reset(); _predicate_free_pool.clear(); Expr::close(_conjunct_ctxs, state); +<<<<<<< HEAD // Reduce the memory usage if the the average string size is greater than 512. release_large_columns(state->chunk_size() * 512); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_closed = true; } @@ -147,9 +157,15 @@ Status TabletScanner::_init_reader_params(const std::vector* key // to avoid the unnecessary SerDe and improve query performance _params.need_agg_finalize = _need_agg_finalize; _params.use_page_cache = _runtime_state->use_page_cache(); +<<<<<<< HEAD auto parser = _pool.add(new PredicateParser(_tablet_schema)); ASSIGN_OR_RETURN(auto pred_tree, _parent->_conjuncts_manager.get_predicate_tree(parser, _predicate_free_pool)); +======= + auto parser = _pool.add(new OlapPredicateParser(_tablet_schema)); + + ASSIGN_OR_RETURN(auto pred_tree, _parent->_conjuncts_manager->get_predicate_tree(parser, _predicate_free_pool)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Improve for select * from table limit x, x is small if (pred_tree.empty() && _parent->_limit != -1 && _parent->_limit < runtime_state()->chunk_size()) { @@ -165,6 +181,7 @@ Status TabletScanner::_init_reader_params(const std::vector* key _params.pred_tree = PredicateTree::create(std::move(pushdown_pred_root)); _pred_tree = PredicateTree::create(std::move(non_pushdown_pred_root)); +<<<<<<< HEAD for (const auto& [_, col_nodes] : _pred_tree.root().col_children_map()) { for (const auto& col_node : col_nodes) { _predicates.add(col_node.col_pred()); @@ -175,6 +192,10 @@ Status TabletScanner::_init_reader_params(const std::vector* key GlobalDictPredicatesRewriter not_pushdown_predicate_rewriter(_predicates, *_params.global_dictmaps); RETURN_IF_ERROR(not_pushdown_predicate_rewriter.rewrite_predicate(&_pool)); +======= + GlobalDictPredicatesRewriter not_pushdown_predicate_rewriter(*_params.global_dictmaps); + RETURN_IF_ERROR(not_pushdown_predicate_rewriter.rewrite_predicate(&_pool, _pred_tree)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Range for (auto key_range : *key_ranges) { @@ -287,11 +308,19 @@ Status TabletScanner::get_chunk(RuntimeState* state, Chunk* chunk) { chunk->set_slot_id_to_index(slot->id(), column_index); } +<<<<<<< HEAD if (!_predicates.empty()) { SCOPED_TIMER(_expr_filter_timer); size_t nrows = chunk->num_rows(); _selection.resize(nrows); RETURN_IF_ERROR(_predicates.evaluate(chunk, _selection.data(), 0, nrows)); +======= + if (!_pred_tree.empty()) { + SCOPED_TIMER(_expr_filter_timer); + size_t nrows = chunk->num_rows(); + _selection.resize(nrows); + RETURN_IF_ERROR(_pred_tree.evaluate(chunk, _selection.data(), 0, nrows)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) chunk->filter(_selection); DCHECK_CHUNK(chunk); } diff --git a/be/src/exec/tablet_scanner.h b/be/src/exec/tablet_scanner.h index f77b52dd820d8..8b0248ee733f2 100644 --- a/be/src/exec/tablet_scanner.h +++ b/be/src/exec/tablet_scanner.h @@ -87,8 +87,12 @@ class TabletScanner { ObjectPool _pool; std::vector _conjunct_ctxs; PredicateTree _pred_tree; +<<<<<<< HEAD ConjunctivePredicates _predicates; std::vector _selection; +======= + Filter _selection; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // for release memory. using PredicatePtr = std::unique_ptr; diff --git a/be/src/exec/tablet_sink.cpp b/be/src/exec/tablet_sink.cpp index 70e416fd03ae9..fe2f5584c5763 100644 --- a/be/src/exec/tablet_sink.cpp +++ b/be/src/exec/tablet_sink.cpp @@ -138,6 +138,12 @@ Status OlapTableSink::init(const TDataSink& t_sink, RuntimeState* state) { _load_channel_timeout_s = config::streaming_load_rpc_max_alive_time_sec; } +<<<<<<< HEAD +======= + if (table_sink.__isset.dynamic_overwrite) { + _dynamic_overwrite = table_sink.dynamic_overwrite; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (table_sink.__isset.ignore_out_of_partition) { _ignore_out_of_partition = table_sink.ignore_out_of_partition; } @@ -175,6 +181,10 @@ void OlapTableSink::_prepare_profile(RuntimeState* state) { _profile->add_info_string("ReplicatedStorage", fmt::format("{}", _enable_replicated_storage)); _profile->add_info_string("AutomaticPartition", fmt::format("{}", _enable_automatic_partition)); _profile->add_info_string("AutomaticBucketSize", fmt::format("{}", _automatic_bucket_size)); +<<<<<<< HEAD +======= + _profile->add_info_string("DynamicOverwrite", fmt::format("{}", _dynamic_overwrite)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _ts_profile = state->obj_pool()->add(new TabletSinkProfile()); _ts_profile->runtime_profile = _profile; @@ -196,6 +206,10 @@ void OlapTableSink::_prepare_profile(RuntimeState* state) { _ts_profile->server_rpc_timer = ADD_TIMER(_profile, "RpcServerSideTime"); _ts_profile->server_wait_flush_timer = ADD_TIMER(_profile, "RpcServerWaitFlushTime"); _ts_profile->alloc_auto_increment_timer = ADD_TIMER(_profile, "AllocAutoIncrementTime"); +<<<<<<< HEAD +======= + _ts_profile->update_load_channel_profile_timer = ADD_TIMER(_profile, "UpdateLoadChannelProfileTime"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void OlapTableSink::set_profile(RuntimeProfile* profile) { @@ -220,9 +234,12 @@ Status OlapTableSink::prepare(RuntimeState* state) { _sender_id = state->per_fragment_instance_idx(); _num_senders = state->num_per_fragment_instances(); +<<<<<<< HEAD if (UNLIKELY(_write_txn_log && _num_senders > 1)) { return Status::NotSupported("This data loading task has multiple senders and does not support merge txn logs"); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Prepare the exprs to run. RETURN_IF_ERROR(Expr::prepare(_output_expr_ctxs, state)); @@ -410,9 +427,18 @@ Status OlapTableSink::_automatic_create_partition() { request.__set_db_id(_vectorized_partition->db_id()); request.__set_table_id(_vectorized_partition->table_id()); request.__set_partition_values(_partition_not_exist_row_values); +<<<<<<< HEAD LOG(INFO) << "load_id=" << print_id(_load_id) << ", txn_id: " << std::to_string(_txn_id) << "automatic partition rpc begin request " << request; +======= + if (_dynamic_overwrite) { + request.__set_is_temp(true); + } + + LOG(INFO) << "load_id=" << print_id(_load_id) << ", txn_id: " << std::to_string(_txn_id) + << " automatic partition rpc begin request " << request; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TNetworkAddress master_addr = get_master_address(); auto timeout_ms = _runtime_state->query_options().query_timeout * 1000 / 2; int retry_times = 0; @@ -432,7 +458,11 @@ Status OlapTableSink::_automatic_create_partition() { butil::gettimeofday_s() - start_ts < timeout_ms / 1000); LOG(INFO) << "load_id=" << print_id(_load_id) << ", txn_id: " << std::to_string(_txn_id) +<<<<<<< HEAD << "automatic partition rpc end response " << result; +======= + << " automatic partition rpc end response " << result; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (result.status.status_code == TStatusCode::OK) { // add new created partitions RETURN_IF_ERROR(_vectorized_partition->add_partitions(result.partitions)); @@ -767,9 +797,15 @@ Status OlapTableSink::_fill_auto_increment_id_internal(Chunk* chunk, SlotDescrip } ColumnPtr& data_col = std::dynamic_pointer_cast(col)->data_column(); +<<<<<<< HEAD std::vector filter(std::dynamic_pointer_cast(col)->immutable_null_column_data()); std::vector init_filter(chunk->num_rows(), 0); +======= + Filter filter(std::dynamic_pointer_cast(col)->immutable_null_column_data()); + + Filter init_filter(chunk->num_rows(), 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_keys_type == TKeysType::PRIMARY_KEYS && _output_tuple_desc->slots().back()->col_name() == "__op") { size_t op_column_id = chunk->num_columns() - 1; @@ -1065,7 +1101,11 @@ void OlapTableSink::_validate_data(RuntimeState* state, Chunk* chunk) { case TYPE_DECIMALV2: { column = ColumnHelper::get_data_column(column); auto* decimal = down_cast(column); +<<<<<<< HEAD std::vector& datas = decimal->get_data(); +======= + Buffer& datas = decimal->get_data(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int scale = desc->type().scale; for (size_t j = 0; j < num_rows; ++j) { if (_validate_selection[j] == VALID_SEL_OK) { diff --git a/be/src/exec/tablet_sink.h b/be/src/exec/tablet_sink.h index 936352b4cdcde..871d82da81eb6 100644 --- a/be/src/exec/tablet_sink.h +++ b/be/src/exec/tablet_sink.h @@ -244,6 +244,10 @@ class OlapTableSink : public AsyncDataSink { std::unique_ptr _automatic_partition_token; std::vector> _partition_not_exist_row_values; bool _enable_automatic_partition = false; +<<<<<<< HEAD +======= + bool _dynamic_overwrite = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _has_automatic_partition = false; std::atomic _is_automatic_partition_running = false; Status _automatic_partition_status; diff --git a/be/src/exec/tablet_sink_index_channel.cpp b/be/src/exec/tablet_sink_index_channel.cpp index 8ab82a821e195..e48d2894cb1f3 100644 --- a/be/src/exec/tablet_sink_index_channel.cpp +++ b/be/src/exec/tablet_sink_index_channel.cpp @@ -18,12 +18,20 @@ #include "column/column_viewer.h" #include "column/nullable_column.h" #include "common/statusor.h" +<<<<<<< HEAD +======= +#include "common/utils.h" +#include "config.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/tablet_sink.h" #include "exprs/expr_context.h" #include "gutil/strings/fastmem.h" #include "gutil/strings/join.h" #include "runtime/current_thread.h" +<<<<<<< HEAD #include "runtime/exec_env.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/runtime_state.h" #include "serde/protobuf_serde.h" #include "util/brpc_stub_cache.h" @@ -832,6 +840,10 @@ Status NodeChannel::_wait_request(ReusableClosure* } if (closure->result.has_load_channel_profile()) { +<<<<<<< HEAD +======= + SCOPED_TIMER(_ts_profile->update_load_channel_profile_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const auto* buf = (const uint8_t*)(closure->result.load_channel_profile().data()); uint32_t len = closure->result.load_channel_profile().size(); TRuntimeProfileTree thrift_profile; diff --git a/be/src/exec/tablet_sink_index_channel.h b/be/src/exec/tablet_sink_index_channel.h index 911480301b7d8..ec45fe88c5509 100644 --- a/be/src/exec/tablet_sink_index_channel.h +++ b/be/src/exec/tablet_sink_index_channel.h @@ -28,10 +28,17 @@ #include "exec/async_data_sink.h" #include "exec/tablet_info.h" #include "gen_cpp/Types_types.h" +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" #include "gen_cpp/internal_service.pb.h" #include "runtime/mem_tracker.h" #include "util/compression/block_compression.h" +======= +#include "gen_cpp/internal_service.pb.h" +#include "runtime/mem_tracker.h" +#include "util/compression/block_compression.h" +#include "util/internal_service_recoverable_stub.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/raw_container.h" #include "util/ref_count_closure.h" #include "util/reusable_closure.h" @@ -96,6 +103,10 @@ struct TabletSinkProfile { RuntimeProfile::Counter* server_rpc_timer = nullptr; RuntimeProfile::Counter* alloc_auto_increment_timer = nullptr; RuntimeProfile::Counter* server_wait_flush_timer = nullptr; +<<<<<<< HEAD +======= + RuntimeProfile::Counter* update_load_channel_profile_timer = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; // map index_id to TabletBEMap(map tablet_id to backend id) @@ -218,7 +229,11 @@ class NodeChannel { std::unique_ptr _row_desc; +<<<<<<< HEAD PInternalService_Stub* _stub = nullptr; +======= + std::shared_ptr _stub; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector*> _open_closures; std::map> _index_tablets_map; diff --git a/be/src/exec/tablet_sink_sender.cpp b/be/src/exec/tablet_sink_sender.cpp index 23851703838ab..e78c7db423eea 100644 --- a/be/src/exec/tablet_sink_sender.cpp +++ b/be/src/exec/tablet_sink_sender.cpp @@ -29,7 +29,11 @@ TabletSinkSender::TabletSinkSender(PUniqueId load_id, int64_t txn_id, IndexIdToT std::unordered_map node_channels, std::vector output_expr_ctxs, bool enable_replicated_storage, TWriteQuorumType::type write_quorum_type, int num_repicas) +<<<<<<< HEAD : _load_id(std::move(std::move(load_id))), +======= + : _load_id(std::move(load_id)), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _txn_id(txn_id), _index_id_to_tablet_be_map(std::move(index_id_to_tablet_be_map)), _partition_params(partition_params), diff --git a/be/src/exec/topn_node.cpp b/be/src/exec/topn_node.cpp index dbe96de9139f3..404213d22dcff 100644 --- a/be/src/exec/topn_node.cpp +++ b/be/src/exec/topn_node.cpp @@ -72,6 +72,16 @@ Status TopNNode::init(const TPlanNode& tnode, RuntimeState* state) { } } } +<<<<<<< HEAD +======= + + // create analytic_partition_exprs for pipeline execution engine to speedup AnalyticNode evaluation. + if (tnode.sort_node.__isset.partition_exprs) { + RETURN_IF_ERROR( + Expr::create_expr_trees(_pool, tnode.sort_node.partition_exprs, &_local_partition_exprs, state)); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _is_asc_order = tnode.sort_node.sort_info.is_asc_order; _is_null_first = tnode.sort_node.sort_info.nulls_first; bool has_outer_join_child = tnode.sort_node.__isset.has_outer_join_child && tnode.sort_node.has_outer_join_child; @@ -271,9 +281,17 @@ std::vector> TopNNode::_decompose_to_ if (is_partition_topn) { partition_limit = _tnode.sort_node.partition_limit; +<<<<<<< HEAD } if (need_merge) { +======= + if (_tnode.sort_node.__isset.pre_agg_insert_local_shuffle && _tnode.sort_node.pre_agg_insert_local_shuffle) { + ops_sink_with_sort = context->maybe_interpolate_local_shuffle_exchange( + runtime_state(), id(), ops_sink_with_sort, _local_partition_exprs); + } + } else if (need_merge) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (enable_parallel_merge) { ops_sink_with_sort = context->maybe_interpolate_local_passthrough_exchange( runtime_state(), id(), ops_sink_with_sort, context->degree_of_parallelism(), is_partition_skewed); @@ -301,10 +319,19 @@ std::vector> TopNNode::_decompose_to_ } // create context factory +<<<<<<< HEAD auto context_factory = std::make_shared( runtime_state(), _tnode.sort_node.topn_type, need_merge, _sort_exec_exprs.lhs_ordering_expr_ctxs(), _is_asc_order, _is_null_first, _tnode.sort_node.partition_exprs, _offset, partition_limit, _sort_keys, _order_by_types, _build_runtime_filters); +======= + bool enable_pre_agg = _tnode.sort_node.__isset.pre_agg_exprs && (!_tnode.sort_node.pre_agg_exprs.empty()); + auto context_factory = std::make_shared( + runtime_state(), _tnode.sort_node.topn_type, need_merge, _sort_exec_exprs.lhs_ordering_expr_ctxs(), + _is_asc_order, _is_null_first, _tnode.sort_node.partition_exprs, enable_pre_agg, + _tnode.sort_node.pre_agg_exprs, _tnode.sort_node.pre_agg_output_slot_id, _offset, partition_limit, + _sort_keys, _order_by_types, _build_runtime_filters); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Create a shared RefCountedRuntimeFilterCollector auto&& rc_rf_probe_collector = std::make_shared(2, std::move(this->runtime_filter_collector())); diff --git a/be/src/exec/topn_node.h b/be/src/exec/topn_node.h index 8135b41bb6c81..f93d60cdcdaf6 100644 --- a/be/src/exec/topn_node.h +++ b/be/src/exec/topn_node.h @@ -65,6 +65,11 @@ class TopNNode final : public ::starrocks::ExecNode { // order to eliminate merging operation in pipeline execution engine. std::vector _analytic_partition_exprs; +<<<<<<< HEAD +======= + std::vector _local_partition_exprs; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Cached descriptor for the materialized tuple. Assigned in Prepare(). TupleDescriptor* _materialized_tuple_desc; diff --git a/be/src/exec/union_node.h b/be/src/exec/union_node.h index 6a4131857fb66..0dd8877dd1094 100644 --- a/be/src/exec/union_node.h +++ b/be/src/exec/union_node.h @@ -25,10 +25,17 @@ class UnionNode final : public ExecNode { UnionNode(ObjectPool* pool, const TPlanNode& tnode, const DescriptorTbl& descs); ~UnionNode() override; +<<<<<<< HEAD [[nodiscard]] Status init(const TPlanNode& tnode, RuntimeState* state) override; [[nodiscard]] Status prepare(RuntimeState* state) override; [[nodiscard]] Status open(RuntimeState* state) override; [[nodiscard]] Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos) override; +======= + Status init(const TPlanNode& tnode, RuntimeState* state) override; + Status prepare(RuntimeState* state) override; + Status open(RuntimeState* state) override; + Status get_next(RuntimeState* state, ChunkPtr* chunk, bool* eos) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state) override; pipeline::OpFactories decompose_to_pipeline(pipeline::PipelineBuilderContext* context) override; @@ -36,6 +43,7 @@ class UnionNode final : public ExecNode { private: void _convert_pass_through_slot_map(const std::map& slot_map); +<<<<<<< HEAD [[nodiscard]] Status _get_next_passthrough(RuntimeState* state, ChunkPtr* chunk); [[nodiscard]] Status _get_next_materialize(RuntimeState* state, ChunkPtr* chunk); [[nodiscard]] Status _get_next_const(RuntimeState* state, ChunkPtr* chunk); @@ -43,6 +51,15 @@ class UnionNode final : public ExecNode { void _move_passthrough_chunk(ChunkPtr& src_chunk, ChunkPtr& dest_chunk); [[nodiscard]] Status _move_materialize_chunk(ChunkPtr& src_chunk, ChunkPtr& dest_chunk); [[nodiscard]] Status _move_const_chunk(ChunkPtr& dest_chunk); +======= + Status _get_next_passthrough(RuntimeState* state, ChunkPtr* chunk); + Status _get_next_materialize(RuntimeState* state, ChunkPtr* chunk); + Status _get_next_const(RuntimeState* state, ChunkPtr* chunk); + + void _move_passthrough_chunk(ChunkPtr& src_chunk, ChunkPtr& dest_chunk); + Status _move_materialize_chunk(ChunkPtr& src_chunk, ChunkPtr& dest_chunk); + Status _move_const_chunk(ChunkPtr& dest_chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static void _clone_column(ChunkPtr& dest_chunk, const ColumnPtr& src_column, const SlotDescriptor* dest_slot, size_t row_count); diff --git a/be/src/exec/write_combined_txn_log.h b/be/src/exec/write_combined_txn_log.h index b55a9dcbd48bc..78e972edeb95f 100644 --- a/be/src/exec/write_combined_txn_log.h +++ b/be/src/exec/write_combined_txn_log.h @@ -18,6 +18,10 @@ namespace starrocks { class CombinedTxnLogPB; +<<<<<<< HEAD +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status write_combined_txn_log(const CombinedTxnLogPB& logs); } // namespace starrocks diff --git a/be/src/exprs/CMakeLists.txt b/be/src/exprs/CMakeLists.txt index f8b8945b2ae80..327fb78792d9c 100644 --- a/be/src/exprs/CMakeLists.txt +++ b/be/src/exprs/CMakeLists.txt @@ -21,6 +21,10 @@ set(EXPR_FILES agg/factory/aggregate_factory.cpp agg/factory/aggregate_resolver_approx.cpp agg/factory/aggregate_resolver_avg.cpp +<<<<<<< HEAD +======= + agg/factory/aggregate_resolver_hypothesis_testing.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) agg/factory/aggregate_resolver_minmaxany.cpp agg/factory/aggregate_resolver_others.cpp agg/factory/aggregate_resolver_sumcount.cpp @@ -28,10 +32,13 @@ set(EXPR_FILES agg/factory/aggregate_resolver_utility.cpp agg/factory/aggregate_resolver_variance.cpp agg/factory/aggregate_resolver_window.cpp +<<<<<<< HEAD jit/ir_helper.cpp jit/jit_engine.cpp jit/jit_expr.cpp anyval_util.cpp +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) base64.cpp binary_functions.cpp expr_context.cpp @@ -44,12 +51,20 @@ set(EXPR_FILES array_element_expr.cpp array_expr.cpp array_functions.cpp +<<<<<<< HEAD +======= + arrow_function_call.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) binary_predicate.cpp bitmap_functions.cpp case_expr.cpp cast_expr.cpp cast_expr_array.cpp cast_expr_json.cpp +<<<<<<< HEAD +======= + cast_expr_struct.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) cast_nested.cpp column_ref.cpp placeholder_ref.cpp @@ -66,6 +81,10 @@ set(EXPR_FILES hyperloglog_functions.cpp in_const_predicate.cpp info_func.cpp +<<<<<<< HEAD +======= + inet_aton.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) in_predicate.cpp is_null_predicate.cpp json_functions.cpp @@ -81,6 +100,10 @@ set(EXPR_FILES runtime_filter_bank.cpp runtime_filter.cpp split.cpp +<<<<<<< HEAD +======= + regexp_split.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) split_part.cpp str_to_map.cpp string_functions.cpp @@ -103,4 +126,15 @@ set(EXPR_FILES match_expr.cpp ) +<<<<<<< HEAD +======= +if(STARROCKS_JIT_ENABLE) + set(EXPR_FILES ${EXPR_FILES} + jit/ir_helper.cpp + jit/jit_engine.cpp + jit/jit_expr.cpp) + +endif() + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_library(Exprs ${EXPR_FILES}) diff --git a/be/src/exprs/agg/agg_state_merge.h b/be/src/exprs/agg/agg_state_merge.h new file mode 100644 index 0000000000000..5d8e3b5d3648b --- /dev/null +++ b/be/src/exprs/agg/agg_state_merge.h @@ -0,0 +1,90 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "column/vectorized_fwd.h" +#include "exprs/agg/aggregate.h" + +namespace starrocks { +struct AggStateMergeState {}; + +/** + * @brief Merge combinator for aggregate function to merge the agg state to return the final result of aggregate function. + * DESC: return_type {agg_func}_merge(immediate_type) + * input type : aggregate function's immediate_type + * intermediate type : aggregate function's immediate_type + * return type : aggregate function's return type + */ +class AggStateMerge final : public AggregateFunctionBatchHelper { +public: + AggStateMerge(AggStateDesc agg_state_desc, const AggregateFunction* function) + : _agg_state_desc(std::move(agg_state_desc)), _function(function) { + DCHECK(_function != nullptr); + } + const AggStateDesc* get_agg_state_desc() const { return &_agg_state_desc; } + + void create(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { _function->create(ctx, ptr); } + + void destroy(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { _function->destroy(ctx, ptr); } + + size_t size() const override { return _function->size(); } + + size_t alignof_size() const override { return _function->alignof_size(); } + + bool is_pod_state() const override { return _function->is_pod_state(); } + + void reset(FunctionContext* ctx, const Columns& args, AggDataPtr state) const override { + _function->reset(ctx, args, state); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + _function->merge(ctx, columns[0], state, row_num); + } + + void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { + _function->merge(ctx, column, state, row_num); + } + + void get_values(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* dst, size_t start, + size_t end) const override { + DCHECK_GT(end, start); + _function->get_values(ctx, state, dst, start, end); + } + + void serialize_to_column([[maybe_unused]] FunctionContext* ctx, ConstAggDataPtr __restrict state, + Column* to) const override { + _function->serialize_to_column(ctx, state, to); + } + + void convert_to_serialize_format([[maybe_unused]] FunctionContext* ctx, const Columns& srcs, size_t chunk_size, + ColumnPtr* dst) const override { + DCHECK_EQ(1, srcs.size()); + *dst = srcs[0]; + } + + void finalize_to_column(FunctionContext* ctx __attribute__((unused)), ConstAggDataPtr __restrict state, + Column* to) const override { + _function->finalize_to_column(ctx, state, to); + } + + std::string get_name() const override { return "agg_state_merge"; } + +private: + const AggStateDesc _agg_state_desc; + const AggregateFunction* _function; +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/agg_state_union.h b/be/src/exprs/agg/agg_state_union.h new file mode 100644 index 0000000000000..03c7a101f04a4 --- /dev/null +++ b/be/src/exprs/agg/agg_state_union.h @@ -0,0 +1,84 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "column/vectorized_fwd.h" +#include "exprs/agg/aggregate.h" + +namespace starrocks { +struct AggStateUnionState {}; + +/** + * @brief Union combinator for aggregate function to union the agg state to return the immediate result of aggregate function. + * DESC: immediate_type {agg_func}_union(immediate_type) + * input type : aggregate function's immediate_type + * intermediate type : aggregate function's immediate_type + * return type : aggregate function's immediate_type + */ +class AggStateUnion final : public AggregateFunctionBatchHelper { +public: + AggStateUnion(AggStateDesc agg_state_desc, const AggregateFunction* function) + : _agg_state_desc(std::move(agg_state_desc)), _function(function) { + DCHECK(_function != nullptr); + } + const AggStateDesc* get_agg_state_desc() const { return &_agg_state_desc; } + + void create(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { _function->create(ctx, ptr); } + + void destroy(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { _function->destroy(ctx, ptr); } + + size_t size() const override { return _function->size(); } + + size_t alignof_size() const override { return _function->alignof_size(); } + + bool is_pod_state() const override { return _function->is_pod_state(); } + + void reset(FunctionContext* ctx, const Columns& args, AggDataPtr state) const override { + _function->reset(ctx, args, state); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + _function->merge(ctx, columns[0], state, row_num); + } + + void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { + _function->merge(ctx, column, state, row_num); + } + + void serialize_to_column([[maybe_unused]] FunctionContext* ctx, ConstAggDataPtr __restrict state, + Column* to) const override { + _function->serialize_to_column(ctx, state, to); + } + + void convert_to_serialize_format([[maybe_unused]] FunctionContext* ctx, const Columns& srcs, size_t chunk_size, + ColumnPtr* dst) const override { + DCHECK_EQ(1, srcs.size()); + *dst = srcs[0]; + } + + void finalize_to_column(FunctionContext* ctx __attribute__((unused)), ConstAggDataPtr __restrict state, + Column* to) const override { + _function->serialize_to_column(ctx, state, to); + } + + std::string get_name() const override { return "agg_state_union"; } + +private: + const AggStateDesc _agg_state_desc; + const AggregateFunction* _function; +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/aggregate.h b/be/src/exprs/agg/aggregate.h index f240d0fc85baf..4b4eb9964855a 100644 --- a/be/src/exprs/agg/aggregate.h +++ b/be/src/exprs/agg/aggregate.h @@ -117,7 +117,11 @@ class AggregateFunction { virtual void destroy(FunctionContext* ctx, AggDataPtr __restrict ptr) const = 0; virtual void batch_create_with_selection(FunctionContext* ctx, size_t chunk_size, Buffer& states, +<<<<<<< HEAD size_t state_offset, const std::vector& selection) const { +======= + size_t state_offset, const Filter& selection) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { create(ctx, states[i] + state_offset); @@ -126,7 +130,11 @@ class AggregateFunction { } virtual void batch_destroy_with_selection(FunctionContext* ctx, size_t chunk_size, Buffer& states, +<<<<<<< HEAD size_t state_offset, const std::vector& selection) const { +======= + size_t state_offset, const Filter& selection) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { destroy(ctx, states[i] + state_offset); @@ -136,7 +144,11 @@ class AggregateFunction { virtual void batch_finalize_with_selection(FunctionContext* ctx, size_t chunk_size, const Buffer& agg_states, size_t state_offset, Column* to, +<<<<<<< HEAD const std::vector& selection) const { +======= + const Filter& selection) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { this->finalize_to_column(ctx, agg_states[i] + state_offset, to); @@ -146,7 +158,11 @@ class AggregateFunction { virtual void batch_serialize_with_selection(FunctionContext* ctx, size_t chunk_size, const Buffer& agg_states, size_t state_offset, Column* to, +<<<<<<< HEAD const std::vector& selection) const { +======= + const Filter& selection) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { this->serialize_to_column(ctx, agg_states[i] + state_offset, to); @@ -162,8 +178,12 @@ class AggregateFunction { // filter[i] = 0, will be update virtual void update_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, +<<<<<<< HEAD const Column** columns, AggDataPtr* states, const std::vector& filter) const = 0; +======= + const Column** columns, AggDataPtr* states, const Filter& filter) const = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // update result to single state virtual void update_batch_single_state(FunctionContext* ctx, size_t chunk_size, const Column** columns, @@ -204,8 +224,12 @@ class AggregateFunction { // filter[i] = 0, will be merged virtual void merge_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, +<<<<<<< HEAD const Column* column, AggDataPtr* states, const std::vector& filter) const = 0; +======= + const Column* column, AggDataPtr* states, const Filter& filter) const = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Merge some continuous portion of a chunk to a given state. // This will be useful for sorted streaming aggregation. @@ -302,11 +326,19 @@ class AggregateFunctionStateHelper : public AggregateFunction { void create(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { new (ptr) State; } +<<<<<<< HEAD void destroy(FunctionContext* ctx, AggDataPtr __restrict ptr) const final { data(ptr).~State(); } size_t size() const final { return sizeof(State); } size_t alignof_size() const final { return alignof(State); } +======= + void destroy(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { data(ptr).~State(); } + + size_t size() const override { return sizeof(State); } + + size_t alignof_size() const override { return alignof(State); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_pod_state() const override { return pod_state(); } }; @@ -315,7 +347,11 @@ template class AggregateFunctionBatchHelper : public AggregateFunctionStateHelper { public: void batch_create_with_selection(FunctionContext* ctx, size_t chunk_size, Buffer& states, +<<<<<<< HEAD size_t state_offset, const std::vector& selection) const override { +======= + size_t state_offset, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { static_cast(this)->create(ctx, states[i] + state_offset); @@ -324,7 +360,11 @@ class AggregateFunctionBatchHelper : public AggregateFunctionStateHelper } void batch_destroy_with_selection(FunctionContext* ctx, size_t chunk_size, Buffer& states, +<<<<<<< HEAD size_t state_offset, const std::vector& selection) const override { +======= + size_t state_offset, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (AggregateFunctionStateHelper::pod_state()) { // nothing TODO } else { @@ -337,8 +377,12 @@ class AggregateFunctionBatchHelper : public AggregateFunctionStateHelper } void batch_finalize_with_selection(FunctionContext* ctx, size_t chunk_size, const Buffer& agg_states, +<<<<<<< HEAD size_t state_offset, Column* to, const std::vector& selection) const override { +======= + size_t state_offset, Column* to, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { static_cast(this)->finalize_to_column(ctx, agg_states[i] + state_offset, to); @@ -347,8 +391,12 @@ class AggregateFunctionBatchHelper : public AggregateFunctionStateHelper } void batch_serialize_with_selection(FunctionContext* ctx, size_t chunk_size, const Buffer& agg_states, +<<<<<<< HEAD size_t state_offset, Column* to, const std::vector& selection) const override { +======= + size_t state_offset, Column* to, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { if (selection[i] == 0) { static_cast(this)->serialize_to_column(ctx, agg_states[i] + state_offset, to); @@ -364,7 +412,11 @@ class AggregateFunctionBatchHelper : public AggregateFunctionStateHelper } void update_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column** columns, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { // TODO: optimize with simd ? if (filter[i] == 0) { @@ -388,7 +440,11 @@ class AggregateFunctionBatchHelper : public AggregateFunctionStateHelper } void merge_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column* column, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { // TODO: optimize with simd ? if (filter[i] == 0) { diff --git a/be/src/exprs/agg/aggregate_factory.h b/be/src/exprs/agg/aggregate_factory.h index 65ac3deda2352..c8c07ad30511d 100644 --- a/be/src/exprs/agg/aggregate_factory.h +++ b/be/src/exprs/agg/aggregate_factory.h @@ -29,4 +29,10 @@ const AggregateFunction* get_window_function(const std::string& name, LogicalTyp TFunctionBinaryType::type binary_type = TFunctionBinaryType::BUILTIN, int func_version = 1); +<<<<<<< HEAD +======= +const AggregateFunction* get_aggregate_function(const std::string& agg_func_name, const TypeDescriptor& return_type, + const std::vector& arg_types, bool is_input_nullable, + TFunctionBinaryType::type binary_type, int func_version = 1); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exprs/agg/aggregate_state_allocator.h b/be/src/exprs/agg/aggregate_state_allocator.h new file mode 100644 index 0000000000000..b57e07e078755 --- /dev/null +++ b/be/src/exprs/agg/aggregate_state_allocator.h @@ -0,0 +1,112 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "column/hash_set.h" +#include "common/config.h" +#include "runtime/memory/allocator.h" +#include "runtime/memory/roaring_hook.h" + +namespace starrocks { + +inline thread_local Allocator* tls_agg_state_allocator = nullptr; + +template +class AggregateStateAllocator { +public: + typedef T value_type; + typedef size_t size_type; + using propagate_on_container_copy_assignment = std::true_type; // for consistency + using propagate_on_container_move_assignment = std::true_type; // to avoid the pessimization + using propagate_on_container_swap = std::true_type; // to avoid the undefined behavior + + template + struct rebind { + using other = AggregateStateAllocator; + }; + AggregateStateAllocator() = default; + template + AggregateStateAllocator(const AggregateStateAllocator& other) {} + + ~AggregateStateAllocator() = default; + + T* allocate(size_t n) { + DCHECK(tls_agg_state_allocator != nullptr); + return static_cast(tls_agg_state_allocator->checked_alloc(n * sizeof(T))); + } + + void deallocate(T* ptr, size_t n) { + DCHECK(tls_agg_state_allocator != nullptr); + tls_agg_state_allocator->free(ptr); + } + + AggregateStateAllocator& operator=(const AggregateStateAllocator& rhs) = default; + + template + AggregateStateAllocator& operator=(const AggregateStateAllocator& rhs) { + return *this; + } + + bool operator==(const AggregateStateAllocator& rhs) const { return true; } + + bool operator!=(const AggregateStateAllocator& rhs) const { return false; } + + void swap(AggregateStateAllocator& rhs) {} +}; +template +void swap(AggregateStateAllocator& lhs, AggregateStateAllocator& rhs) { + lhs.swap(rhs); +} + +class ThreadLocalAggregateStateAllocatorSetter { +public: + ThreadLocalAggregateStateAllocatorSetter(Allocator* allocator) { + _prev = tls_agg_state_allocator; + tls_agg_state_allocator = allocator; + } + ~ThreadLocalAggregateStateAllocatorSetter() { tls_agg_state_allocator = _prev; } + +private: + Allocator* _prev = nullptr; +}; +#define SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(allocator) \ + auto VARNAME_LINENUM(alloc_setter) = ThreadLocalAggregateStateAllocatorSetter(allocator) + +template +using HashSetWithAggStateAllocator = + phmap::flat_hash_set, phmap::priv::hash_default_eq, AggregateStateAllocator>; + +using SliceHashSetWithAggStateAllocator = phmap::flat_hash_set>; + +template +using VectorWithAggStateAllocator = std::vector>; + +// Thread local aggregate state allocator setter with roaring allocator +class ThreadLocalStateAllocatorSetter { +public: + ThreadLocalStateAllocatorSetter(Allocator* allocator) + : _agg_state_allocator_setter(allocator), _roaring_allocator_setter(allocator) {} + ~ThreadLocalStateAllocatorSetter() = default; + +private: + ThreadLocalAggregateStateAllocatorSetter _agg_state_allocator_setter; + ThreadLocalRoaringAllocatorSetter _roaring_allocator_setter; +}; + +#define SCOPED_THREAD_LOCAL_STATE_ALLOCATOR_SETTER(allocator) \ + auto VARNAME_LINENUM(alloc_setter) = ThreadLocalStateAllocatorSetter(allocator) + +} // namespace starrocks diff --git a/be/src/exprs/agg/approx_top_k.h b/be/src/exprs/agg/approx_top_k.h index 4219e03b86aa7..2673691441765 100644 --- a/be/src/exprs/agg/approx_top_k.h +++ b/be/src/exprs/agg/approx_top_k.h @@ -22,6 +22,10 @@ #include "column/struct_column.h" #include "column/type_traits.h" #include "exprs/agg/aggregate.h" +<<<<<<< HEAD +======= +#include "exprs/agg/aggregate_state_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/agg/aggregate_traits.h" #include "runtime/mem_pool.h" #include "types/logical_type.h" @@ -50,7 +54,11 @@ struct ApproxTopKState { int32_t k = 0; int32_t counter_num = 0; int32_t unused_idx = 0; +<<<<<<< HEAD mutable std::vector counters; +======= + mutable VectorWithAggStateAllocator counters; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) mutable Counter null_counter{0}; using EQ = std::conditional_t, SliceEqual, phmap::priv::hash_default_eq>; phmap::flat_hash_map, EQ> table; diff --git a/be/src/exprs/agg/array_agg.h b/be/src/exprs/agg/array_agg.h index 449c103cd12c4..8ab1a3572bdb9 100644 --- a/be/src/exprs/agg/array_agg.h +++ b/be/src/exprs/agg/array_agg.h @@ -40,8 +40,17 @@ struct ArrayAggAggregateState { for (int i = 0; i < count; i++) { auto raw_key = column.get_slice(offset + i); KeyType key(raw_key); +<<<<<<< HEAD set.template lazy_emplace(key, [&](const auto& ctor) { uint8_t* pos = mem_pool->allocate(key.size); +======= +#if defined(__clang__) && (__clang_major__ >= 16) + set.lazy_emplace(key, [&](const auto& ctor) { +#else + set.template lazy_emplace(key, [&](const auto& ctor) { +#endif + uint8_t* pos = mem_pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) assert(pos != nullptr); memcpy(pos, key.data, key.size); ctor(pos, key.size, key.hash); @@ -94,6 +103,7 @@ struct ArrayAggAggregateState { return &data_column; } +<<<<<<< HEAD bool check_overflow(FunctionContext* ctx) const { std::string err_msg; if (UNLIKELY(data_column.capacity_limit_reached(&err_msg))) { @@ -107,6 +117,14 @@ struct ArrayAggAggregateState { std::string err_msg; if (UNLIKELY(col.capacity_limit_reached(&err_msg))) { ctx->set_error(fmt::format("The column generated by array_agg is overflow: {}", err_msg).c_str()); +======= + bool check_overflow(FunctionContext* ctx) const { return check_overflow(data_column, ctx); } + + static bool check_overflow(const Column& col, FunctionContext* ctx) { + Status st = col.capacity_limit_reached(); + if (!st.ok()) { + ctx->set_error(fmt::format("The column generated by array_agg is overflow: {}", st.message()).c_str()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } return false; @@ -195,8 +213,14 @@ struct ArrayAggAggregateStateV2 { bool check_overflow(FunctionContext* ctx) const { std::string err_msg; for (size_t i = 0; i < data_columns.size(); i++) { +<<<<<<< HEAD if (UNLIKELY(data_columns[i]->capacity_limit_reached(&err_msg))) { ctx->set_error(fmt::format("The column generated by array_agg is overflow: {}", err_msg).c_str()); +======= + Status st = data_columns[i]->capacity_limit_reached(); + if (!st.ok()) { + ctx->set_error(fmt::format("The column generated by array_agg is overflow: {}", st.message()).c_str()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } } @@ -204,9 +228,15 @@ struct ArrayAggAggregateStateV2 { } static bool check_overflow(const Column& col, FunctionContext* ctx) { +<<<<<<< HEAD std::string err_msg; if (UNLIKELY(col.capacity_limit_reached(&err_msg))) { ctx->set_error(fmt::format("The column generated by array_agg is overflow: {}", err_msg).c_str()); +======= + Status st = col.capacity_limit_reached(); + if (!st.ok()) { + ctx->set_error(fmt::format("The column generated by array_agg is overflow: {}", st.message()).c_str()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } return false; diff --git a/be/src/exprs/agg/array_union_agg.h b/be/src/exprs/agg/array_union_agg.h index bea832432301e..82c8c0ba85c54 100644 --- a/be/src/exprs/agg/array_union_agg.h +++ b/be/src/exprs/agg/array_union_agg.h @@ -40,8 +40,17 @@ struct ArrayUnionAggAggregateState { for (int i = 0; i < count; i++) { auto raw_key = column.get_slice(offset + i); KeyType key(raw_key); +<<<<<<< HEAD set.template lazy_emplace(key, [&](const auto& ctor) { uint8_t* pos = mem_pool->allocate(key.size); +======= +#if defined(__clang__) && (__clang_major__ >= 16) + set.lazy_emplace(key, [&](const auto& ctor) { +#else + set.template lazy_emplace(key, [&](const auto& ctor) { +#endif + uint8_t* pos = mem_pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) assert(pos != nullptr); memcpy(pos, key.data, key.size); ctor(pos, key.size, key.hash); @@ -156,7 +165,12 @@ class ArrayUnionAggAggregateFunction void convert_to_serialize_format(FunctionContext* ctx, const Columns& src, size_t chunk_size, ColumnPtr* dst) const override { +<<<<<<< HEAD (*dst)->append(*(src[0].get())); +======= + const Column* src_data = ColumnHelper::get_data_column(src[0].get()); + (*dst)->append(*src_data); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } std::string get_name() const override { return is_distinct ? "array_unique_agg" : "array_union_agg"; } diff --git a/be/src/exprs/agg/avg.h b/be/src/exprs/agg/avg.h index d3608501c302d..703a994289054 100644 --- a/be/src/exprs/agg/avg.h +++ b/be/src/exprs/agg/avg.h @@ -211,6 +211,7 @@ class AvgAggregateFunction final void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { DCHECK(!to->is_nullable()); +<<<<<<< HEAD // In fact, for StarRocks real query, we don't need this check. // But for robust, we add this check. if (this->data(state).count == 0) { @@ -218,6 +219,16 @@ class AvgAggregateFunction final } auto* column = down_cast(to); +======= + auto* column = down_cast(to); + // In fact, for StarRocks real query, we don't need this check. + // But for robust, we add this check. + if (this->data(state).count == 0) { + column->append_default(); + return; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ResultType result; if constexpr (lt_is_decimalv2) { result = this->data(state).sum / DecimalV2Value(this->data(state).count, 0); diff --git a/be/src/exprs/agg/bitmap_agg.h b/be/src/exprs/agg/bitmap_agg.h index ab6c6d66f3865..6066009412310 100644 --- a/be/src/exprs/agg/bitmap_agg.h +++ b/be/src/exprs/agg/bitmap_agg.h @@ -38,7 +38,11 @@ class BitmapAggAggregateFunction final } } +<<<<<<< HEAD bool check_valid(const std::vector& values, size_t count) const { +======= + bool check_valid(const Buffer& values, size_t count) const { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < count; i++) { auto value = values[i]; if (!(value >= 0 && value <= std::numeric_limits::max())) { diff --git a/be/src/exprs/agg/count.h b/be/src/exprs/agg/count.h index 94f68f635d66f..980d249286188 100644 --- a/be/src/exprs/agg/count.h +++ b/be/src/exprs/agg/count.h @@ -129,8 +129,12 @@ class CountAggregateFunction final : public AggregateFunctionBatchHelper& agg_states, +<<<<<<< HEAD size_t state_offset, Column* to, const std::vector& selection) const override { +======= + size_t state_offset, Column* to, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(to->is_numeric()); int64_t values[chunk_size]; size_t selected_length = 0; @@ -180,7 +184,11 @@ class CountNullableAggregateFunction final } void update_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column** columns, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (columns[0]->has_null()) { const auto* nullable_column = down_cast(columns[0]); const uint8_t* null_data = nullable_column->immutable_null_column_data().data(); diff --git a/be/src/exprs/agg/distinct.h b/be/src/exprs/agg/distinct.h index 7c9c61281c41d..71d19176ca2f8 100644 --- a/be/src/exprs/agg/distinct.h +++ b/be/src/exprs/agg/distinct.h @@ -22,17 +22,29 @@ #include "column/array_column.h" #include "column/binary_column.h" +<<<<<<< HEAD +======= +#include "column/column_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/fixed_length_column.h" #include "column/hash_set.h" #include "column/type_traits.h" #include "column/vectorized_fwd.h" #include "exprs/agg/aggregate.h" +<<<<<<< HEAD +======= +#include "exprs/agg/aggregate_state_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/agg/sum.h" #include "exprs/function_context.h" #include "gen_cpp/Data_types.h" #include "glog/logging.h" #include "gutil/casts.h" #include "runtime/mem_pool.h" +<<<<<<< HEAD +======= +#include "runtime/memory/counting_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "thrift/protocol/TJSONProtocol.h" #include "util/phmap/phmap_dump.h" #include "util/slice.h" @@ -50,6 +62,7 @@ template struct DistinctAggregateState> { using T = RunTimeCppType; using SumType = RunTimeCppType; +<<<<<<< HEAD size_t update(T key) { auto pair = set.insert(key); @@ -60,6 +73,13 @@ struct DistinctAggregateState> { auto pair = set.emplace_with_hash(hash, key); return pair.second * phmap::item_serialize_size>::value; } +======= + using MyHashSet = HashSetWithAggStateAllocator; + + void update(T key) { set.insert(key); } + + void update_with_hash([[maybe_unused]] MemPool* mempool, T key, size_t hash) { set.emplace_with_hash(hash, key); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void prefetch(T key) { set.prefetch(key); } @@ -77,17 +97,28 @@ struct DistinctAggregateState> { DCHECK(output.length() == set.dump_bound()); } +<<<<<<< HEAD size_t deserialize_and_merge(const uint8_t* src, size_t len) { +======= + void deserialize_and_merge(const uint8_t* src, size_t len) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) phmap::InMemoryInput input(reinterpret_cast(src)); auto old_size = set.size(); if (old_size == 0) { set.load(input); +<<<<<<< HEAD return set.size() * phmap::item_serialize_size>::value; } else { HashSet set_src; set_src.load(input); set.merge(set_src); return (set.size() - old_size) * phmap::item_serialize_size>::value; +======= + } else { + MyHashSet set_src; + set_src.load(input); + set.merge(set_src); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -104,7 +135,11 @@ struct DistinctAggregateState> { return sum; } +<<<<<<< HEAD HashSet set; +======= + MyHashSet set; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template @@ -112,6 +147,7 @@ struct DistinctAggregateState> { DistinctAggregateState() = default; using KeyType = typename SliceHashSet::key_type; +<<<<<<< HEAD size_t update(MemPool* mem_pool, Slice raw_key) { size_t ret = 0; KeyType key(raw_key); @@ -136,6 +172,34 @@ struct DistinctAggregateState> { ret = phmap::item_serialize_size::value; }); return ret; +======= + void update(MemPool* mem_pool, Slice raw_key) { + KeyType key(raw_key); +#if defined(__clang__) && (__clang_major__ >= 16) + set.lazy_emplace(key, [&](const auto& ctor) { +#else + set.template lazy_emplace(key, [&](const auto& ctor) { +#endif + uint8_t* pos = mem_pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); + assert(pos != nullptr); + memcpy(pos, key.data, key.size); + ctor(pos, key.size, key.hash); + }); + } + + void update_with_hash(MemPool* mem_pool, Slice raw_key, size_t hash) { + KeyType key(reinterpret_cast(raw_key.data), raw_key.size, hash); +#if defined(__clang__) && (__clang_major__ >= 16) + set.lazy_emplace_with_hash(key, hash, [&](const auto& ctor) { +#else + set.template lazy_emplace_with_hash(key, hash, [&](const auto& ctor) { +#endif + uint8_t* pos = mem_pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); + assert(pos != nullptr); + memcpy(pos, key.data, key.size); + ctor(pos, key.size, key.hash); + }); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } int64_t disctint_count() const { return set.size(); } @@ -160,8 +224,12 @@ struct DistinctAggregateState> { } } +<<<<<<< HEAD size_t deserialize_and_merge(MemPool* mem_pool, const uint8_t* src, size_t len) { size_t mem_usage = 0; +======= + void deserialize_and_merge(MemPool* mem_pool, const uint8_t* src, size_t len) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const uint8_t* end = src + len; while (src < end) { uint32_t size = 0; @@ -170,20 +238,38 @@ struct DistinctAggregateState> { Slice raw_key(src, size); KeyType key(raw_key); // we only memcpy when the key is new +<<<<<<< HEAD set.template lazy_emplace(key, [&](const auto& ctor) { uint8_t* pos = mem_pool->allocate(key.size); assert(pos != nullptr); memcpy(pos, key.data, key.size); ctor(pos, key.size, key.hash); mem_usage += phmap::item_serialize_size::value; +======= +#if defined(__clang__) && (__clang_major__ >= 16) + set.lazy_emplace(key, [&](const auto& ctor) { +#else + set.template lazy_emplace(key, [&](const auto& ctor) { +#endif + uint8_t* pos = mem_pool->allocate_with_reserve(key.size, SLICE_MEMEQUAL_OVERFLOW_PADDING); + assert(pos != nullptr); + memcpy(pos, key.data, key.size); + ctor(pos, key.size, key.hash); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }); src += size; } DCHECK(src == end); +<<<<<<< HEAD return mem_usage; } SliceHashSet set; +======= + } + + SliceHashSetWithAggStateAllocator set; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; // use a different way to do serialization to gain performance. @@ -194,6 +280,7 @@ template struct DistinctAggregateStateV2> { using T = RunTimeCppType; using SumType = RunTimeCppType; +<<<<<<< HEAD using MyHashSet = HashSet; static constexpr size_t item_size = phmap::item_serialize_size::value; @@ -206,6 +293,13 @@ struct DistinctAggregateStateV2> { auto pair = set.emplace_with_hash(hash, key); return pair.second * item_size; } +======= + using MyHashSet = HashSetWithAggStateAllocator; + + void update(T key) { set.insert(key); } + + void update_with_hash([[maybe_unused]] MemPool* mempool, T key, size_t hash) { set.emplace_with_hash(hash, key); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void prefetch(T key) { set.prefetch(key); } @@ -227,12 +321,19 @@ struct DistinctAggregateStateV2> { } } +<<<<<<< HEAD size_t deserialize_and_merge(const uint8_t* src, size_t len) { +======= + void deserialize_and_merge(const uint8_t* src, size_t len) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t size = 0; memcpy(&size, src, sizeof(size)); set.rehash(set.size() + size); +<<<<<<< HEAD size_t old_size = set.size(); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) src += sizeof(size); for (size_t i = 0; i < size; i++) { T key; @@ -240,8 +341,11 @@ struct DistinctAggregateStateV2> { set.insert(key); src += sizeof(T); } +<<<<<<< HEAD size_t new_size = set.size(); return (new_size - old_size) * item_size; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } SumType sum_distinct() const { @@ -285,6 +389,7 @@ class TDistinctAggregateFunction : public AggregateFunctionBatchHelper< void update(FunctionContext* ctx, const Column** columns, AggDataPtr state, size_t row_num) const override { const auto* column = down_cast(columns[0]); +<<<<<<< HEAD size_t mem_usage; if constexpr (IsSlice) { mem_usage = this->data(state).update(ctx->mem_pool(), column->get_slice(row_num)); @@ -292,6 +397,13 @@ class TDistinctAggregateFunction : public AggregateFunctionBatchHelper< mem_usage = this->data(state).update(column->get_data()[row_num]); } ctx->add_mem_usage(mem_usage); +======= + if constexpr (IsSlice) { + this->data(state).update(ctx->mem_pool(), column->get_slice(row_num)); + } else { + this->data(state).update(column->get_data()[row_num]); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // The following two functions are specialized because of performance issue. @@ -300,7 +412,10 @@ class TDistinctAggregateFunction : public AggregateFunctionBatchHelper< void update_batch_single_state(FunctionContext* ctx, size_t chunk_size, const Column** columns, AggDataPtr __restrict state) const override { const auto* column = down_cast(columns[0]); +<<<<<<< HEAD size_t mem_usage = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto& agg_state = this->data(state); struct CacheEntry { @@ -322,15 +437,23 @@ class TDistinctAggregateFunction : public AggregateFunctionBatchHelper< agg_state.set.prefetch_hash(cache[prefetch_index].hash_value); prefetch_index++; } +<<<<<<< HEAD mem_usage += agg_state.update_with_hash(mem_pool, container_data[i], cache[i].hash_value); } ctx->add_mem_usage(mem_usage); +======= + agg_state.update_with_hash(mem_pool, container_data[i], cache[i].hash_value); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void update_batch(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column** columns, AggDataPtr* states) const override { const auto* column = down_cast(columns[0]); +<<<<<<< HEAD size_t mem_usage = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // We find that agg_states are scatterd in `states`, we can collect them together with hash value, // so there will be good cache locality. We can also collect column data into this `CacheEntry` to @@ -357,24 +480,35 @@ class TDistinctAggregateFunction : public AggregateFunctionBatchHelper< cache[prefetch_index].agg_state->set.prefetch_hash(cache[prefetch_index].hash_value); prefetch_index++; } +<<<<<<< HEAD mem_usage += cache[i].agg_state->update_with_hash(mem_pool, container_data[i], cache[i].hash_value); } ctx->add_mem_usage(mem_usage); +======= + cache[i].agg_state->update_with_hash(mem_pool, container_data[i], cache[i].hash_value); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { DCHECK(column->is_binary()); const auto* input_column = down_cast(column); Slice slice = input_column->get_slice(row_num); +<<<<<<< HEAD size_t mem_usage = 0; if constexpr (IsSlice) { mem_usage += this->data(state).deserialize_and_merge(ctx->mem_pool(), (const uint8_t*)slice.data, slice.size); +======= + if constexpr (IsSlice) { + this->data(state).deserialize_and_merge(ctx->mem_pool(), (const uint8_t*)slice.data, slice.size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { // slice size larger than `MIN_SIZE_OF_HASH_SET_SERIALIZED_DATA`, means which is a hash set // that's said, size of hash set serialization data should be larger than `MIN_SIZE_OF_HASH_SET_SERIALIZED_DATA` // otherwise this slice could be reinterpreted as a single value going be to inserted into hashset. if (slice.size >= MIN_SIZE_OF_HASH_SET_SERIALIZED_DATA) { +<<<<<<< HEAD mem_usage += this->data(state).deserialize_and_merge((const uint8_t*)slice.data, slice.size); } else { T key; @@ -383,6 +517,15 @@ class TDistinctAggregateFunction : public AggregateFunctionBatchHelper< } } ctx->add_mem_usage(mem_usage); +======= + this->data(state).deserialize_and_merge((const uint8_t*)slice.data, slice.size); + } else { + T key; + memcpy(&key, slice.data, sizeof(T)); + this->data(state).update(key); + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void serialize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { @@ -492,7 +635,10 @@ class DictMergeAggregateFunction final void update_batch_single_state(FunctionContext* ctx, size_t chunk_size, const Column** columns, AggDataPtr __restrict state) const override { +<<<<<<< HEAD [[maybe_unused]] size_t mem_usage = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto& agg_state = this->data(state); const auto* column = down_cast(columns[0]); MemPool* mem_pool = ctx->mem_pool(); @@ -510,14 +656,22 @@ class DictMergeAggregateFunction final for (size_t i = 0; i < binary_column.size(); ++i) { if (!null_data[i]) { +<<<<<<< HEAD mem_usage += agg_state.update(mem_pool, binary_column.get_slice(i)); +======= + agg_state.update(mem_pool, binary_column.get_slice(i)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } agg_state.over_limit = agg_state.set.size() > DICT_DECODE_MAX_SIZE; } else { const auto& binary_column = down_cast(elements_column); for (size_t i = 0; i < binary_column.size(); ++i) { +<<<<<<< HEAD mem_usage += agg_state.update(mem_pool, binary_column.get_slice(i)); +======= + agg_state.update(mem_pool, binary_column.get_slice(i)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } agg_state.over_limit = agg_state.set.size() > DICT_DECODE_MAX_SIZE; } @@ -533,9 +687,13 @@ class DictMergeAggregateFunction final const auto* input_column = down_cast(column); Slice slice = input_column->get_slice(row_num); +<<<<<<< HEAD size_t mem_usage = 0; mem_usage += this->data(state).deserialize_and_merge(ctx->mem_pool(), (const uint8_t*)slice.data, slice.size); ctx->add_mem_usage(mem_usage); +======= + this->data(state).deserialize_and_merge(ctx->mem_pool(), (const uint8_t*)slice.data, slice.size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) agg_state.over_limit = agg_state.set.size() > DICT_DECODE_MAX_SIZE; } diff --git a/be/src/exprs/agg/ds_hll_count_distinct.h b/be/src/exprs/agg/ds_hll_count_distinct.h new file mode 100644 index 0000000000000..e83914e0de2cc --- /dev/null +++ b/be/src/exprs/agg/ds_hll_count_distinct.h @@ -0,0 +1,240 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "column/binary_column.h" +#include "column/object_column.h" +#include "column/type_traits.h" +#include "column/vectorized_fwd.h" +#include "exprs/agg/aggregate.h" +#include "gutil/casts.h" +#include "types/hll_sketch.h" + +namespace starrocks { + +struct HLLSketchState { + std::unique_ptr hll_sketch = nullptr; + int64_t memory_usage = 0; +}; + +/** + * RETURN_TYPE: TYPE_BIGINT + * ARGS_TYPE: ALL TYPE + * SERIALIZED_TYPE: TYPE_VARCHAR + */ +template > +class HllSketchAggregateFunction final + : public AggregateFunctionBatchHelper> { +public: + using ColumnType = RunTimeColumnType; + + void reset(FunctionContext* ctx, const Columns& args, AggDataPtr state) const override { + if (this->data(state).hll_sketch != nullptr) { + ctx->add_mem_usage(-this->data(state).hll_sketch->mem_usage()); + this->data(state).hll_sketch->clear(); + } + } + + void update_state(FunctionContext* ctx, AggDataPtr state, uint64_t value) const { + int64_t prev_memory = this->data(state).hll_sketch->mem_usage(); + this->data(state).hll_sketch->update(value); + ctx->add_mem_usage(this->data(state).hll_sketch->mem_usage() - prev_memory); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + // init state if needed + _init_if_needed(ctx, columns, state); + + uint64_t value = 0; + const ColumnType* column = down_cast(columns[0]); + + if constexpr (lt_is_string) { + Slice s = column->get_slice(row_num); + value = HashUtil::murmur_hash64A(s.data, s.size, HashUtil::MURMUR_SEED); + } else { + const auto& v = column->get_data(); + value = HashUtil::murmur_hash64A(&v[row_num], sizeof(v[row_num]), HashUtil::MURMUR_SEED); + } + update_state(ctx, state, value); + } + + void update_batch_single_state_with_frame(FunctionContext* ctx, AggDataPtr __restrict state, const Column** columns, + int64_t peer_group_start, int64_t peer_group_end, int64_t frame_start, + int64_t frame_end) const override { + // init state if needed + _init_if_needed(ctx, columns, state); + const ColumnType* column = down_cast(columns[0]); + if constexpr (lt_is_string) { + uint64_t value = 0; + for (size_t i = frame_start; i < frame_end; ++i) { + Slice s = column->get_slice(i); + value = HashUtil::murmur_hash64A(s.data, s.size, HashUtil::MURMUR_SEED); + + if (value != 0) { + update_state(ctx, state, value); + } + } + } else { + uint64_t value = 0; + const auto& v = column->get_data(); + for (size_t i = frame_start; i < frame_end; ++i) { + value = HashUtil::murmur_hash64A(&v[i], sizeof(v[i]), HashUtil::MURMUR_SEED); + + if (value != 0) { + update_state(ctx, state, value); + } + } + } + } + + void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { + DCHECK(column->is_binary()); + const BinaryColumn* hll_column = down_cast(column); + DataSketchesHll hll(hll_column->get(row_num).get_slice(), &(this->data(state).memory_usage)); + if (UNLIKELY(this->data(state).hll_sketch == nullptr)) { + this->data(state).hll_sketch = std::make_unique( + hll.get_lg_config_k(), hll.get_target_type(), &(this->data(state).memory_usage)); + } + int64_t prev_memory = this->data(state).hll_sketch->mem_usage(); + this->data(state).hll_sketch->merge(hll); + ctx->add_mem_usage(this->data(state).hll_sketch->mem_usage() - prev_memory); + } + + void get_values(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* dst, size_t start, + size_t end) const override { + DCHECK_GT(end, start); + Int64Column* column = down_cast(dst); + int64_t result = 0L; + if (LIKELY(this->data(state).hll_sketch != nullptr)) { + result = this->data(state).hll_sketch->estimate_cardinality(); + } + for (size_t i = start; i < end; ++i) { + column->get_data()[i] = result; + } + } + + void serialize_to_column([[maybe_unused]] FunctionContext* ctx, ConstAggDataPtr __restrict state, + Column* to) const override { + DCHECK(to->is_binary()); + auto* column = down_cast(to); + if (UNLIKELY(this->data(state).hll_sketch == nullptr)) { + column->append_default(); + } else { + size_t size = this->data(state).hll_sketch->serialize_size(); + uint8_t result[size]; + size = this->data(state).hll_sketch->serialize(result); + column->append(Slice(result, size)); + } + } + + void convert_to_serialize_format([[maybe_unused]] FunctionContext* ctx, const Columns& src, size_t chunk_size, + ColumnPtr* dst) const override { + const ColumnType* column = down_cast(src[0].get()); + auto* result = down_cast((*dst).get()); + + Bytes& bytes = result->get_bytes(); + bytes.reserve(chunk_size * 10); + result->get_offset().resize(chunk_size + 1); + + size_t old_size = bytes.size(); + uint64_t value = 0; + uint8_t log_k; + datasketches::target_hll_type tgt_type; + // convert to const Column* + std::vector src_datas; + src_datas.reserve(src.size()); + std::transform(src.begin(), src.end(), std::back_inserter(src_datas), + [](const ColumnPtr& col) { return col.get(); }); + const Column** src_datas_ptr = src_datas.data(); + std::tie(log_k, tgt_type) = _parse_hll_sketch_args(ctx, src_datas_ptr); + for (size_t i = 0; i < chunk_size; ++i) { + int64_t memory_usage = 0; + DataSketchesHll hll{log_k, tgt_type, &memory_usage}; + if constexpr (lt_is_string) { + Slice s = column->get_slice(i); + value = HashUtil::murmur_hash64A(s.data, s.size, HashUtil::MURMUR_SEED); + } else { + auto v = column->get_data()[i]; + value = HashUtil::murmur_hash64A(&v, sizeof(v), HashUtil::MURMUR_SEED); + } + if (value != 0) { + hll.update(value); + } + + size_t new_size = old_size + hll.serialize_size(); + bytes.resize(new_size); + hll.serialize(bytes.data() + old_size); + + result->get_offset()[i + 1] = new_size; + old_size = new_size; + } + } + + void finalize_to_column(FunctionContext* ctx __attribute__((unused)), ConstAggDataPtr __restrict state, + Column* to) const override { + DCHECK(to->is_numeric()); + + auto* column = down_cast(to); + if (UNLIKELY(this->data(state).hll_sketch == nullptr)) { + column->append(0L); + } else { + column->append(this->data(state).hll_sketch->estimate_cardinality()); + } + } + + std::string get_name() const override { return "ds_hll_count_distinct"; } + +private: + // init hll sketch if needed + void _init_if_needed(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state) const { + if (UNLIKELY(this->data(state).hll_sketch == nullptr)) { + uint8_t log_k; + datasketches::target_hll_type tgt_type; + std::tie(log_k, tgt_type) = _parse_hll_sketch_args(ctx, columns); + this->data(state).hll_sketch = _init_hll_sketch(log_k, tgt_type, &(this->data(state).memory_usage)); + } + } + + // parse log_k and target type from args + std::tuple _parse_hll_sketch_args(FunctionContext* ctx, + const Column** columns) const { + uint8_t log_k = DEFAULT_HLL_LOG_K; + datasketches::target_hll_type tgt_type = datasketches::HLL_6; + if (ctx->get_num_args() == 2) { + log_k = (uint8_t)(columns[1]->get(0).get_int32()); + } else if (ctx->get_num_args() == 3) { + log_k = (uint8_t)(columns[1]->get(0).get_int32()); + std::string tgt_type_str = columns[2]->get(0).get_slice().to_string(); + std::transform(tgt_type_str.begin(), tgt_type_str.end(), tgt_type_str.begin(), ::toupper); + if (tgt_type_str == "HLL_4") { + tgt_type = datasketches::HLL_4; + } else if (tgt_type_str == "HLL_8") { + tgt_type = datasketches::HLL_8; + } else { + tgt_type = datasketches::HLL_6; + } + } + return {log_k, tgt_type}; + } + + // init hll sketch with default log_k and target type + std::unique_ptr _init_hll_sketch(uint8_t log_k, datasketches::target_hll_type tgt_type, + int64_t* memory_usage) const { + return std::make_unique(log_k, tgt_type, memory_usage); + } +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/factory/aggregate_factory.cpp b/be/src/exprs/agg/factory/aggregate_factory.cpp index dcc63993f26c7..5b60d7ffd2eb7 100644 --- a/be/src/exprs/agg/factory/aggregate_factory.cpp +++ b/be/src/exprs/agg/factory/aggregate_factory.cpp @@ -15,15 +15,22 @@ #include "exprs/agg/aggregate_factory.h" #include +<<<<<<< HEAD #include #include #include "column/type_traits.h" +======= + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/agg/aggregate.h" #include "exprs/agg/factory/aggregate_factory.hpp" #include "exprs/agg/factory/aggregate_resolver.hpp" #include "types/logical_type.h" +<<<<<<< HEAD #include "types/logical_type_infra.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "udf/java/java_function_fwd.h" namespace starrocks { @@ -40,6 +47,10 @@ AggregateFuncResolver::AggregateFuncResolver() { register_approx(); register_others(); register_retract_functions(); +<<<<<<< HEAD +======= + register_hypothesis_testing(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } AggregateFuncResolver::~AggregateFuncResolver() = default; @@ -168,4 +179,49 @@ const AggregateFunction* get_window_function(const std::string& name, LogicalTyp return nullptr; } +<<<<<<< HEAD +======= +const AggregateFunction* get_aggregate_function(const std::string& agg_func_name, const TypeDescriptor& return_type, + const std::vector& arg_types, bool is_result_nullable, + TFunctionBinaryType::type binary_type, int func_version) { + // get function + if (agg_func_name == "count") { + return get_aggregate_function("count", TYPE_BIGINT, TYPE_BIGINT, is_result_nullable); + } else { + DCHECK_GE(arg_types.size(), 1); + TypeDescriptor arg_type = arg_types[0]; + // Because intersect_count have two input types. + // And intersect_count's first argument's type is alwasy Bitmap, + // so we use its second arguments type as input. + if (agg_func_name == "intersect_count") { + arg_type = arg_types[1]; + } + + // Because max_by and min_by function have two input types, + // so we use its second arguments type as input. + if (agg_func_name == "max_by" || agg_func_name == "min_by" || agg_func_name == "max_by_v2" || + agg_func_name == "min_by_v2") { + arg_type = arg_types[1]; + } + + // Because windowfunnel have more two input types. + // functions registry use 2th args(datetime/date). + if (agg_func_name == "window_funnel") { + arg_type = arg_types[1]; + } + + // hack for accepting various arguments + if (agg_func_name == "exchange_bytes" || agg_func_name == "exchange_speed") { + arg_type = TypeDescriptor(TYPE_BIGINT); + } + + if (agg_func_name == "array_union_agg" || agg_func_name == "array_unique_agg") { + arg_type = arg_type.children[0]; + } + return get_aggregate_function(agg_func_name, arg_type.type, return_type.type, is_result_nullable, binary_type, + func_version); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exprs/agg/factory/aggregate_factory.hpp b/be/src/exprs/agg/factory/aggregate_factory.hpp index 4407e3d4684c5..4c74e28078d91 100644 --- a/be/src/exprs/agg/factory/aggregate_factory.hpp +++ b/be/src/exprs/agg/factory/aggregate_factory.hpp @@ -15,8 +15,11 @@ #pragma once #include +<<<<<<< HEAD #include #include +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/type_traits.h" #include "exprs/agg/aggregate.h" @@ -33,6 +36,10 @@ #include "exprs/agg/count.h" #include "exprs/agg/covariance.h" #include "exprs/agg/distinct.h" +<<<<<<< HEAD +======= +#include "exprs/agg/ds_hll_count_distinct.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/agg/exchange_perf.h" #include "exprs/agg/group_concat.h" #include "exprs/agg/histogram.h" @@ -40,6 +47,11 @@ #include "exprs/agg/hll_union.h" #include "exprs/agg/hll_union_count.h" #include "exprs/agg/intersect_count.h" +<<<<<<< HEAD +======= +#include "exprs/agg/mann_whitney.h" +#include "exprs/agg/map_agg.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/agg/maxmin.h" #include "exprs/agg/maxmin_by.h" #include "exprs/agg/nullable_aggregate.h" @@ -119,6 +131,13 @@ class AggregateFactory { return std::make_shared(); } +<<<<<<< HEAD +======= + static auto MakeMannWhitneyUTestAggregateFunction() { + return std::make_shared(); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template static auto MakeMaxAggregateFunction(); @@ -185,6 +204,12 @@ class AggregateFactory { static AggregateFunctionPtr MakeHllNdvAggregateFunction(); template +<<<<<<< HEAD +======= + static AggregateFunctionPtr MakeHllSketchAggregateFunction(); + + template +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static AggregateFunctionPtr MakeHllRawAggregateFunction(); static AggregateFunctionPtr MakePercentileApproxAggregateFunction(); @@ -197,6 +222,15 @@ class AggregateFactory { template static AggregateFunctionPtr MakePercentileDiscAggregateFunction(); +<<<<<<< HEAD +======= + template + static AggregateFunctionPtr MakeLowCardPercentileBinAggregateFunction(); + + template + static AggregateFunctionPtr MakeLowCardPercentileCntAggregateFunction(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Windows functions: static AggregateFunctionPtr MakeDenseRankWindowFunction(); @@ -382,6 +416,14 @@ AggregateFunctionPtr AggregateFactory::MakeHllNdvAggregateFunction() { } template +<<<<<<< HEAD +======= +AggregateFunctionPtr AggregateFactory::MakeHllSketchAggregateFunction() { + return std::make_shared>(); +} + +template +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) AggregateFunctionPtr AggregateFactory::MakeHllRawAggregateFunction() { return std::make_shared>(); } @@ -396,6 +438,19 @@ AggregateFunctionPtr AggregateFactory::MakePercentileDiscAggregateFunction() { return std::make_shared>(); } +<<<<<<< HEAD +======= +template +AggregateFunctionPtr AggregateFactory::MakeLowCardPercentileBinAggregateFunction() { + return std::make_shared>(); +} + +template +AggregateFunctionPtr AggregateFactory::MakeLowCardPercentileCntAggregateFunction() { + return std::make_shared>(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template AggregateFunctionPtr AggregateFactory::MakeBitmapAggAggregateFunction() { return std::make_shared>(); diff --git a/be/src/exprs/agg/factory/aggregate_resolver.hpp b/be/src/exprs/agg/factory/aggregate_resolver.hpp index a9721c5ec7a07..5320d7973b9e5 100644 --- a/be/src/exprs/agg/factory/aggregate_resolver.hpp +++ b/be/src/exprs/agg/factory/aggregate_resolver.hpp @@ -22,7 +22,10 @@ #include "exprs/agg/aggregate.h" #include "exprs/agg/factory/aggregate_factory.hpp" #include "types/logical_type.h" +<<<<<<< HEAD #include "types/logical_type_infra.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "udf/java/java_function_fwd.h" namespace starrocks { @@ -68,6 +71,10 @@ class AggregateFuncResolver { void register_approx(); void register_others(); void register_retract_functions(); +<<<<<<< HEAD +======= + void register_hypothesis_testing(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& aggregate_types() const { const static std::vector kTypes{ diff --git a/be/src/exprs/agg/factory/aggregate_resolver_approx.cpp b/be/src/exprs/agg/factory/aggregate_resolver_approx.cpp index c13cc051c706f..b6167c65c06e4 100644 --- a/be/src/exprs/agg/factory/aggregate_resolver_approx.cpp +++ b/be/src/exprs/agg/factory/aggregate_resolver_approx.cpp @@ -38,6 +38,12 @@ struct HLLUnionBuilder { resolver->add_aggregate_mapping( "approx_count_distinct", false, AggregateFactory::MakeHllNdvAggregateFunction()); +<<<<<<< HEAD +======= + + resolver->add_aggregate_mapping_variadic( + "ds_hll_count_distinct", false, AggregateFactory::MakeHllSketchAggregateFunction()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } }; diff --git a/be/src/exprs/agg/factory/aggregate_resolver_avg.cpp b/be/src/exprs/agg/factory/aggregate_resolver_avg.cpp index 5bd5ce14db8d9..0e9b7368708c9 100644 --- a/be/src/exprs/agg/factory/aggregate_resolver_avg.cpp +++ b/be/src/exprs/agg/factory/aggregate_resolver_avg.cpp @@ -117,6 +117,34 @@ struct ArrayAggDistinctDispatcher { } }; +<<<<<<< HEAD +======= +struct MapAggDispatcher { + template + void operator()(AggregateFuncResolver* resolver) { + if constexpr (lt_is_aggregate) { + using KeyCppType = RunTimeCppType; + if constexpr (lt_is_largeint) { + using MyHashMap = phmap::flat_hash_map>; + auto func = std::make_shared>(); + resolver->add_aggregate_mapping_notnull("map_agg", false, func); + } else if constexpr (lt_is_fixedlength) { + using MyHashMap = phmap::flat_hash_map>; + auto func = std::make_shared>(); + resolver->add_aggregate_mapping_notnull("map_agg", false, func); + } else if constexpr (lt_is_string) { + using MyHashMap = + phmap::flat_hash_map; + auto func = std::make_shared>(); + resolver->add_aggregate_mapping_notnull("map_agg", false, func); + } else { + throw std::runtime_error("map_agg does not support key type " + type_to_string(kt)); + } + } + } +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void AggregateFuncResolver::register_avg() { for (auto type : aggregate_types()) { type_dispatch_all(type, AvgDispatcher(), this); @@ -124,6 +152,10 @@ void AggregateFuncResolver::register_avg() { type_dispatch_all(type, ArrayAggDistinctDispatcher(), this); type_dispatch_all(type, ArrayUnionAggDispatcher(), this); type_dispatch_all(type, ArrayUniqueAggDispatcher(), this); +<<<<<<< HEAD +======= + type_dispatch_all(type, MapAggDispatcher(), this); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } type_dispatch_all(TYPE_JSON, ArrayAggDispatcher(), this); add_decimal_mapping("decimal_avg"); diff --git a/be/src/exprs/agg/factory/aggregate_resolver_hypothesis_testing.cpp b/be/src/exprs/agg/factory/aggregate_resolver_hypothesis_testing.cpp new file mode 100644 index 0000000000000..66f8881787634 --- /dev/null +++ b/be/src/exprs/agg/factory/aggregate_resolver_hypothesis_testing.cpp @@ -0,0 +1,26 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "exprs/agg/factory/aggregate_factory.hpp" +#include "exprs/agg/factory/aggregate_resolver.hpp" +#include "types/logical_type.h" + +namespace starrocks { + +void AggregateFuncResolver::register_hypothesis_testing() { + add_aggregate_mapping_variadic( + "mann_whitney_u_test", false, AggregateFactory::MakeMannWhitneyUTestAggregateFunction()); +} + +} // namespace starrocks diff --git a/be/src/exprs/agg/factory/aggregate_resolver_minmaxany.cpp b/be/src/exprs/agg/factory/aggregate_resolver_minmaxany.cpp index cbe92cf8acfbc..a310f3d664332 100644 --- a/be/src/exprs/agg/factory/aggregate_resolver_minmaxany.cpp +++ b/be/src/exprs/agg/factory/aggregate_resolver_minmaxany.cpp @@ -62,8 +62,17 @@ struct MinMaxAnyDispatcher { "min", true, AggregateFactory::MakeMinAggregateFunction()); resolver->add_aggregate_mapping>( "max", true, AggregateFactory::MakeMaxAggregateFunction()); +<<<<<<< HEAD resolver->add_aggregate_mapping>( "any_value", true, AggregateFactory::MakeAnyValueAggregateFunction()); +======= + // For json type, use `AnyValueSemiState` state to store the value as other semi structures. + // This is because any_value's agg state may be flat json and cannot extract `JsonValue` from it directly. + if (lt_is_aggregate) { + resolver->add_aggregate_mapping>( + "any_value", true, AggregateFactory::MakeAnyValueAggregateFunction()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } }; diff --git a/be/src/exprs/agg/factory/aggregate_resolver_others.cpp b/be/src/exprs/agg/factory/aggregate_resolver_others.cpp index cf79068b6abf1..62435183ecf7d 100644 --- a/be/src/exprs/agg/factory/aggregate_resolver_others.cpp +++ b/be/src/exprs/agg/factory/aggregate_resolver_others.cpp @@ -34,6 +34,22 @@ struct PercentileDiscDispatcher { } }; +<<<<<<< HEAD +======= +struct LowCardPercentileDispatcher { + template + void operator()(AggregateFuncResolver* resolver) { + if constexpr (lt_is_datetime || lt_is_date || lt_is_arithmetic || + lt_is_decimal_of_any_version) { + resolver->add_aggregate_mapping_variadic>( + "percentile_disc_lc", false, AggregateFactory::MakeLowCardPercentileCntAggregateFunction()); + resolver->add_aggregate_mapping>( + "percentile_build_lc", false, AggregateFactory::MakeLowCardPercentileBinAggregateFunction()); + } + } +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void AggregateFuncResolver::register_others() { add_aggregate_mapping_notnull("percentile_approx", false, AggregateFactory::MakePercentileApproxAggregateFunction()); @@ -53,6 +69,13 @@ void AggregateFuncResolver::register_others() { type_dispatch_all(type, PercentileDiscDispatcher(), this); } +<<<<<<< HEAD +======= + for (auto type : sortable_types()) { + type_dispatch_all(type, LowCardPercentileDispatcher(), this); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_aggregate_mapping_variadic( "group_concat", false, AggregateFactory::MakeGroupConcatAggregateFunction()); add_aggregate_mapping_variadic( diff --git a/be/src/exprs/agg/group_concat.h b/be/src/exprs/agg/group_concat.h index d4a16cb57cdfa..d4ea588a6a3b7 100644 --- a/be/src/exprs/agg/group_concat.h +++ b/be/src/exprs/agg/group_concat.h @@ -544,7 +544,11 @@ class GroupConcatAggregateFunctionV2 // if i-th row is null, set nullable_array[x][i] = null, otherwise, set array[x][i]=src[x][i] std::vector arrays(columns.size()); std::vector array_nulls(columns.size()); +<<<<<<< HEAD std::vector*> array_offsets(columns.size()); +======= + std::vector*> array_offsets(columns.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector nullable_arrays(columns.size()); auto old_size = columns[0]->size(); for (auto j = 0; j < columns.size(); ++j) { diff --git a/be/src/exprs/agg/helpers/serialize_helpers.hpp b/be/src/exprs/agg/helpers/serialize_helpers.hpp new file mode 100644 index 0000000000000..395cc4c6376b7 --- /dev/null +++ b/be/src/exprs/agg/helpers/serialize_helpers.hpp @@ -0,0 +1,258 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace starrocks { + +class SerializeHelpers { +public: + template + static void serialize(const T* data, uint8_t*& buffer, size_t num_elems = 1) { + using T_ = std::remove_cv_t>; + std::copy_n(reinterpret_cast(data), num_elems * sizeof(T), buffer); + buffer += num_elems * sizeof(T); + } + + template + static void deserialize(const uint8_t*& buffer, T* data, size_t num_elems = 1) { + using T_ = std::remove_cv_t>; + std::copy_n(buffer, num_elems * sizeof(T), reinterpret_cast(data)); + buffer += num_elems * sizeof(T); + } + + template + static void serialize(const T& data, uint8_t*& buffer) { + serialize(&data, buffer, 1); + } + + template + static void deserialize(const uint8_t*& buffer, T& data) { + deserialize(buffer, &data, 1); + } + + static void serialize(const std::string& data, uint8_t*& buffer) { + size_t size = data.length(); + serialize(size, buffer); + serialize(data.data(), buffer, size); + } + + static void deserialize(const uint8_t*& buffer, std::string& data) { + size_t size = 0; + deserialize(buffer, size); + data.resize(size); + deserialize(buffer, data.data(), size); + } + + template + static void serialize(std::vector const& data, uint8_t*& buffer) { + size_t size = data.size(); + serialize(size, buffer); + for (auto const& elem : data) { + serialize(elem, buffer); + } + } + + template + static void deserialize(const uint8_t*& buffer, std::vector& data) { + size_t size = 0; + deserialize(buffer, size); + data.resize(size); + for (auto& elem : data) { + deserialize(buffer, elem); + } + } + + template + static typename std::enable_if_t< + std::is_same_v> || + std::is_same_v>, + void> + serialize(MapType const& data, uint8_t*& buffer) { + size_t size = data.size(); + serialize(size, buffer); + for (auto const& [key, value] : data) { + serialize(key, buffer); + serialize(value, buffer); + } + } + + template + static typename std::enable_if_t< + std::is_same_v> || + std::is_same_v>, + void> + deserialize(const uint8_t*& buffer, MapType& data) { + size_t size = 0; + deserialize(buffer, size); + for (size_t i = 0; i < size; ++i) { + typename MapType::key_type key; + typename MapType::mapped_type value; + deserialize(buffer, key); + deserialize(buffer, value); + data[std::move(key)] = std::move(value); + } + } + + template + static typename std::enable_if_t> || + std::is_same_v>, + void> + serialize(SetType const& data, uint8_t*& buffer) { + size_t size = data.size(); + serialize(size, buffer); + for (auto const& key : data) { + serialize(key, buffer); + } + } + + template + static typename std::enable_if_t> || + std::is_same_v>, + void> + deserialize(const uint8_t*& buffer, SetType& data) { + size_t size = 0; + deserialize(buffer, size); + for (size_t i = 0; i < size; ++i) { + typename SetType::key_type key; + deserialize(buffer, key); + data.emplace(std::move(key)); + } + } + + template + static void serialize(std::array const& data, uint8_t*& buffer) { + for (auto const& elem : data) { + serialize(elem, buffer); + } + } + + template + static void deserialize(const uint8_t*& buffer, std::array& data) { + for (auto& elem : data) { + deserialize(buffer, elem); + } + } + + template + static size_t serialized_size(T const&) { + return sizeof(T); + } + + static size_t serialized_size(std::string const& str) { return sizeof(size_t) + sizeof(char) * str.length(); } + + template + static size_t serialized_size(std::vector const& vec) { + size_t size = sizeof(size_t); + for (auto const& elem : vec) { + size += serialized_size(elem); + } + return size; + } + + template + static size_t serialized_size(std::array const& vec) { + size_t size = 0; + for (auto const& elem : vec) { + size += serialized_size(elem); + } + return size; + } + + template + static typename std::enable_if_t< + std::is_same_v> || + std::is_same_v>, + size_t> + serialized_size(MapType const& data) { + size_t size = sizeof(size_t); + for (auto const& [key, value] : data) { + size += serialized_size(key) + serialized_size(value); + } + return size; + } + + template + static typename std::enable_if_t> || + std::is_same_v>, + size_t> + serialized_size(SetType const& data) { + size_t size = sizeof(size_t); + for (auto const& elem : data) { + size += serialized_size(elem); + } + return size; + } + + template + static size_t serialized_size(std::tuple const& tuple) { + size_t size = 0; + std::apply([&size](const auto&... element) { ((size += serialized_size(element)), ...); }, tuple); + return size; + } + + template + static void serialize(std::tuple const& tuple, uint8_t*& buffer) { + std::apply([&buffer](const auto&... element) { (serialize(element, buffer), ...); }, tuple); + } + + template + static void deserialize(const uint8_t*& buffer, std::tuple& tuple) { + std::apply([&buffer](auto&... element) { (deserialize(buffer, element), ...); }, tuple); + } + + template + static size_t serialized_size_all(First&& first, Args&&... rest) { + if constexpr (sizeof...(rest) == 0) { + return serialized_size(first); + } else { + return serialized_size(first) + serialized_size_all(std::forward(rest)...); + } + } + + template + static void serialize_all(uint8_t*& data, First const& first, Args&&... rest) { + serialize(first, data); + if constexpr (sizeof...(rest) != 0) { + serialize_all(data, std::forward(rest)...); + } + } + + template + static void deserialize_all(const uint8_t*& data, First& first, Args&&... rest) { + deserialize(data, first); + if constexpr (sizeof...(rest) != 0) { + deserialize_all(data, std::forward(rest)...); + } + } +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/hll_ndv.h b/be/src/exprs/agg/hll_ndv.h index 79dc182c8ed60..9ed433c4e7adb 100644 --- a/be/src/exprs/agg/hll_ndv.h +++ b/be/src/exprs/agg/hll_ndv.h @@ -18,7 +18,13 @@ #include "column/object_column.h" #include "column/type_traits.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exprs/agg/aggregate.h" +======= +#include "common/compiler_util.h" +#include "exprs/agg/aggregate.h" +#include "exprs/function_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/casts.h" #include "types/hll.h" @@ -36,9 +42,22 @@ class HllNdvAggregateFunction final using ColumnType = RunTimeColumnType; void reset(FunctionContext* ctx, const Columns& args, AggDataPtr state) const override { +<<<<<<< HEAD + this->data(state).clear(); + } + +======= + ctx->add_mem_usage(-this->data(state).mem_usage()); this->data(state).clear(); } + ALWAYS_INLINE void update_state(FunctionContext* ctx, AggDataPtr state, uint64_t value) const { + int64_t prev_memory = this->data(state).mem_usage(); + this->data(state).update(value); + ctx->add_mem_usage(this->data(state).mem_usage() - prev_memory); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, size_t row_num) const override { uint64_t value = 0; @@ -53,7 +72,11 @@ class HllNdvAggregateFunction final } if (value != 0) { +<<<<<<< HEAD this->data(state).update(value); +======= + update_state(ctx, state, value); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -69,7 +92,11 @@ class HllNdvAggregateFunction final value = HashUtil::murmur_hash64A(s.data, s.size, HashUtil::MURMUR_SEED); if (value != 0) { +<<<<<<< HEAD this->data(state).update(value); +======= + update_state(ctx, state, value); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } else { @@ -79,7 +106,11 @@ class HllNdvAggregateFunction final value = HashUtil::murmur_hash64A(&v[i], sizeof(v[i]), HashUtil::MURMUR_SEED); if (value != 0) { +<<<<<<< HEAD this->data(state).update(value); +======= + update_state(ctx, state, value); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } @@ -90,7 +121,13 @@ class HllNdvAggregateFunction final const auto* hll_column = down_cast(column); HyperLogLog hll(hll_column->get(row_num).get_slice()); +<<<<<<< HEAD + this->data(state).merge(hll); +======= + int64_t prev_memory = this->data(state).mem_usage(); this->data(state).merge(hll); + ctx->add_mem_usage(this->data(state).mem_usage() - prev_memory); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void get_values(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* dst, size_t start, diff --git a/be/src/exprs/agg/hll_union.h b/be/src/exprs/agg/hll_union.h index f411355eb8759..dea74f047be46 100644 --- a/be/src/exprs/agg/hll_union.h +++ b/be/src/exprs/agg/hll_union.h @@ -32,10 +32,23 @@ class HllUnionAggregateFunction final : public AggregateFunctionBatchHelperdata(state).clear(); } +<<<<<<< HEAD void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, size_t row_num) const override { const auto* column = down_cast(columns[0]); this->data(state).merge(*(column->get_object(row_num))); +======= + ALWAYS_INLINE void update_state(FunctionContext* ctx, AggDataPtr state, HyperLogLog& hll) const { + int64_t prev_memory = this->data(state).mem_usage(); + this->data(state).merge(hll); + ctx->add_mem_usage(this->data(state).mem_usage() - prev_memory); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + const auto* column = down_cast(columns[0]); + update_state(ctx, state, *(column->get_object(row_num))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void update_batch_single_state_with_frame(FunctionContext* ctx, AggDataPtr __restrict state, const Column** columns, @@ -43,7 +56,11 @@ class HllUnionAggregateFunction final : public AggregateFunctionBatchHelper(columns[0]); for (size_t i = frame_start; i < frame_end; ++i) { +<<<<<<< HEAD this->data(state).merge(*(column->get_object(i))); +======= + update_state(ctx, state, *(column->get_object(i))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -51,7 +68,11 @@ class HllUnionAggregateFunction final : public AggregateFunctionBatchHelperis_object()); const auto* hll_column = down_cast(column); +<<<<<<< HEAD this->data(state).merge(*(hll_column->get_object(row_num))); +======= + update_state(ctx, state, *(hll_column->get_object(row_num))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void get_values(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* dst, size_t start, diff --git a/be/src/exprs/agg/hll_union_count.h b/be/src/exprs/agg/hll_union_count.h index f61449bc11b95..f8c780da28115 100644 --- a/be/src/exprs/agg/hll_union_count.h +++ b/be/src/exprs/agg/hll_union_count.h @@ -17,8 +17,15 @@ #include "column/binary_column.h" #include "column/object_column.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exprs/agg/aggregate.h" #include "gutil/casts.h" +======= +#include "common/compiler_util.h" +#include "exprs/agg/aggregate.h" +#include "gutil/casts.h" +#include "types/hll.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -31,6 +38,7 @@ class HllUnionCountAggregateFunction final : public AggregateFunctionBatchHelper { public: void reset(FunctionContext* ctx, const Columns& args, AggDataPtr state) const override { +<<<<<<< HEAD this->data(state).clear(); } @@ -38,6 +46,22 @@ class HllUnionCountAggregateFunction final size_t row_num) const override { const auto* column = down_cast(columns[0]); this->data(state).merge(*(column->get_object(row_num))); +======= + ctx->add_mem_usage(-this->data(state).mem_usage()); + this->data(state).clear(); + } + + ALWAYS_INLINE void update_state(FunctionContext* ctx, AggDataPtr state, HyperLogLog& hll) const { + int64_t prev_memory = this->data(state).mem_usage(); + this->data(state).merge(hll); + ctx->add_mem_usage(this->data(state).mem_usage() - prev_memory); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + const auto* column = down_cast(columns[0]); + update_state(ctx, state, *(column->get_object(row_num))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void update_batch_single_state_with_frame(FunctionContext* ctx, AggDataPtr __restrict state, const Column** columns, @@ -45,7 +69,11 @@ class HllUnionCountAggregateFunction final int64_t frame_end) const override { const auto* column = down_cast(columns[0]); for (size_t i = frame_start; i < frame_end; ++i) { +<<<<<<< HEAD this->data(state).merge(*(column->get_object(i))); +======= + update_state(ctx, state, *(column->get_object(i))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -53,7 +81,11 @@ class HllUnionCountAggregateFunction final DCHECK(column->is_object()); const auto* hll_column = down_cast(column); +<<<<<<< HEAD this->data(state).merge(*(hll_column->get_object(row_num))); +======= + update_state(ctx, state, *(hll_column->get_object(row_num))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void get_values(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* dst, size_t start, diff --git a/be/src/exprs/agg/hypothesis_testing_common.h b/be/src/exprs/agg/hypothesis_testing_common.h new file mode 100644 index 0000000000000..f371e57bd4f67 --- /dev/null +++ b/be/src/exprs/agg/hypothesis_testing_common.h @@ -0,0 +1,63 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +namespace starrocks { + +class TestingAlternative { +public: + enum Alternative : uint8_t { + // The initial value of TestingAlternative is Unknown, + // which should be considered as an error + // if we encounter a TestingAlternative with a value of Unknown. + Unknown = 0, + TwoSided, + Less, + Greater, + }; + + TestingAlternative(Alternative alternative = Unknown) : _alternative(alternative) {} + TestingAlternative(uint8_t alternative) : _alternative(static_cast(alternative)) {} + + static TestingAlternative from_str(std::string_view alternative_str) { + TestingAlternative alternative; + if (alternative_str == "two-sided") { + alternative._alternative = TwoSided; + } else if (alternative_str == "less") { + alternative._alternative = Less; + } else if (alternative_str == "greater") { + alternative._alternative = Greater; + } else { + alternative._alternative = Unknown; + } + return alternative; + } + + friend bool operator==(TestingAlternative const& lhs, TestingAlternative const& rhs) { + return lhs._alternative == rhs._alternative; + } + + friend bool operator==(TestingAlternative const& lhs, Alternative const& rhs) { return lhs._alternative == rhs; } + + uint8_t value() const { return _alternative; } + +private: + Alternative _alternative{Unknown}; +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/java_udaf_function.h b/be/src/exprs/agg/java_udaf_function.h index 4e7aed41f290e..e812caa51df6b 100644 --- a/be/src/exprs/agg/java_udaf_function.h +++ b/be/src/exprs/agg/java_udaf_function.h @@ -214,7 +214,11 @@ class JavaUDAFAggregateFunction : public AggregateFunction { } void update_batch_selectively(FunctionContext* ctx, size_t batch_size, size_t state_offset, const Column** columns, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto [env, helper] = JVMFunctionHelper::getInstanceWithEnv(); std::vector buffers; std::vector args; @@ -320,7 +324,11 @@ class JavaUDAFAggregateFunction : public AggregateFunction { } void merge_batch_selectively(FunctionContext* ctx, size_t batch_size, size_t state_offset, const Column* column, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // batch merge auto& helper = JVMFunctionHelper::getInstance(); diff --git a/be/src/exprs/agg/mann_whitney.h b/be/src/exprs/agg/mann_whitney.h new file mode 100644 index 0000000000000..11b58663cb316 --- /dev/null +++ b/be/src/exprs/agg/mann_whitney.h @@ -0,0 +1,355 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +#include "boost/math/distributions/normal.hpp" +#include "column/type_traits.h" +#include "column/vectorized_fwd.h" +#include "exprs/agg/aggregate.h" +#include "exprs/agg/helpers/serialize_helpers.hpp" +#include "exprs/agg/hypothesis_testing_common.h" +#include "exprs/function_context.h" +#include "exprs/function_helper.h" +#include "gutil/casts.h" +#include "types/logical_type.h" +#include "util/json.h" + +namespace starrocks { + +class MannWhitneyAggregateState { +public: + MannWhitneyAggregateState() = default; + MannWhitneyAggregateState(const uint8_t*& data) { deserialize(data); } + + void init(TestingAlternative alternative, int64_t continuity_correction) { + _alternative = alternative; + _continuity_correction = continuity_correction; + } + + bool is_uninitialized() const { return _alternative == TestingAlternative::Unknown; } + + void update(double x, bool treatment) { + _stats[treatment].emplace_back(x); + _sorted = false; + } + + void merge(MannWhitneyAggregateState const& other) { + DCHECK(_alternative == other._alternative); + sort_if_not_sorted(); + other.sort_if_not_sorted(); + for (size_t idx = 0; idx < 2; ++idx) { + std::vector tmp; + std::merge(_stats[idx].begin(), _stats[idx].end(), other._stats[idx].begin(), other._stats[idx].end(), + std::back_inserter(tmp)); + _stats[idx] = tmp; + } + } + + void serialize(uint8_t*& data) const { + DCHECK(!is_uninitialized()); + sort_if_not_sorted(); + SerializeHelpers::serialize_all(data, _alternative.value(), _stats, _continuity_correction); + } + + void deserialize(const uint8_t*& data) { + uint8_t tmp; + SerializeHelpers::deserialize_all(data, tmp, _stats, _continuity_correction); + _alternative = TestingAlternative(tmp); + _sorted = true; + } + + size_t serialized_size() const { + return SerializeHelpers::serialized_size_all(_alternative.value(), _stats, _continuity_correction); + } + + void build_result(vpack::Builder& builder) const { + if (_alternative == TestingAlternative::Unknown) { + vpack::ObjectBuilder obj_builder(&builder); + builder.add("Logical Error", vpack::Value("state not initialized.")); + return; + } + // If there's only one state, it's not sorted yet, so sorted it. + sort_if_not_sorted(); + size_t size = _stats[0].size() + _stats[1].size(); + std::vector index(size); + std::iota(index.begin(), index.end(), 0); + auto data = [this](size_t idx) { + if (idx < this->_stats[0].size()) { + return this->_stats[0][idx]; + } + return this->_stats[1][idx - this->_stats[0].size()]; + }; + std::inplace_merge(index.begin(), index.begin() + _stats[0].size(), index.end(), + [data](size_t lhs, size_t rhs) { return data(lhs) < data(rhs); }); + DCHECK(std::is_sorted(index.begin(), index.end(), + [data](size_t lhs, size_t rhs) { return data(lhs) < data(rhs); })); + + const double n1 = _stats[0].size(); + const double n2 = _stats[1].size(); + double r1 = 0; + double tie_correction = 0; + size_t left = 0; + double tie_numenator = 0; + while (left < size) { + size_t right = left; + while (right < size && data(index[left]) == data(index[right])) { + ++right; + } + auto adjusted = (left + right + 1.) / 2.; + auto count_equal = right - left; + + // Scipy implementation throws exception in this case too. + if (count_equal == size) { + vpack::ObjectBuilder obj_builder(&builder); + builder.add("Error", vpack::Value("All numbers in both samples are identical.")); + return; + } + + tie_numenator += std::pow(count_equal, 3) - count_equal; + for (size_t iter = left; iter < right; ++iter) { + if (index[iter] < n1) { + r1 += adjusted; + } + } + left = right; + } + tie_correction = 1 - (tie_numenator / (std::pow(size, 3) - size)); + + const double u1 = n1 * n2 + (n1 * (n1 + 1.)) / 2. - r1; + const double u2 = n1 * n2 - u1; + + /// The distribution of U-statistic under null hypothesis H0 is symmetric with respect to meanrank. + const double meanrank = n1 * n2 / 2. + 0.5 * _continuity_correction; + const double sd = std::sqrt(tie_correction * n1 * n2 * (n1 + n2 + 1) / 12.0); + + if (std::isnan(sd) || std::isinf(sd) || std::abs(sd) < 1e-7) { + vpack::ObjectBuilder obj_builder(&builder); + builder.add("Logical Error", vpack::Value(fmt::format("sd({}) is not a valid value.", sd))); + return; + } + + double u = 0; + if (_alternative == TestingAlternative::TwoSided) { + u = std::max(u1, u2); + } else if (_alternative == TestingAlternative::Less) { + u = u1; + } else if (_alternative == TestingAlternative::Greater) { + u = u2; + } else { + DCHECK(false); + } + + double z = (u - meanrank) / sd; + if (_alternative == TestingAlternative::TwoSided) { + z = std::abs(z); + } + + auto standart_normal_distribution = boost::math::normal_distribution(); + auto cdf = boost::math::cdf(standart_normal_distribution, z); + + double p_value = 0; + if (_alternative == TestingAlternative::TwoSided) { + p_value = 2 - 2 * cdf; + } else { + p_value = 1 - cdf; + } + + vpack::ArrayBuilder array_builder(&builder); + builder.add(vpack::Value(u2)); + builder.add(vpack::Value(p_value)); + } + +private: + TestingAlternative _alternative; + mutable std::array, 2> _stats; + int64_t _continuity_correction{0}; + mutable bool _sorted{true}; + + void sort_if_not_sorted() const { + if (!_sorted) { + for (size_t idx = 0; idx < 2; ++idx) { + std::sort(_stats[idx].begin(), _stats[idx].end()); + } + _sorted = true; + } + for (size_t idx = 0; idx < 2; ++idx) { + DCHECK(std::is_sorted(_stats[idx].begin(), _stats[idx].end())); + } + } +}; + +class MannWhitneyUTestAggregateFunction + : public AggregateFunctionBatchHelper { +public: + using DataColumn = RunTimeColumnType; + using DataCppType = RunTimeCppType; + using IndexColumn = RunTimeColumnType; + using AlternativeColumn = RunTimeColumnType; + using ContinuityCorrectionColumn = RunTimeColumnType; + using ResultColumn = RunTimeColumnType; + + void init_state_if_needed(FunctionContext* ctx, const Column* alternative_col, + const Column* continuity_correction_col, MannWhitneyAggregateState& state) const { + if (!state.is_uninitialized()) { + return; + } + init_state(ctx, alternative_col, continuity_correction_col, state); + } + + void init_state(FunctionContext* ctx, const Column* alternative_col, const Column* continuity_correction_col, + MannWhitneyAggregateState& state) const { + TestingAlternative alternative{TestingAlternative::TwoSided}; + int64_t continuity_correction = 1; + + if (alternative_col != nullptr) { + Slice alternative_slice; + FunctionHelper::get_data_of_column(alternative_col, 0, alternative_slice); + auto alternative_str = boost::to_lower_copy(alternative_slice.to_string()); + TestingAlternative init_alternative = TestingAlternative::from_str(alternative_str); + if (init_alternative == TestingAlternative::Unknown) { + ctx->set_error(fmt::format("Logical Error: invalid alternative `{}`.", alternative_str).c_str()); + return; + } + alternative = init_alternative; + } + + if (continuity_correction_col != nullptr) { + FunctionHelper::get_data_of_column(continuity_correction_col, 0, + continuity_correction); + if (continuity_correction < 0) { + ctx->set_error("Logical Error: continuity_correction must be non-negative."); + return; + } + } + + state.init(alternative, continuity_correction); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + const Column* alternative_col = ctx->get_num_args() >= 3 ? columns[2] : nullptr; + const Column* continuity_correction_col = ctx->get_num_args() >= 4 ? columns[3] : nullptr; + init_state_if_needed(ctx, alternative_col, continuity_correction_col, this->data(state)); + + DataCppType x{}; + const Column* x_col = columns[0]; + FunctionHelper::get_data_of_column(x_col, row_num, x); + + if (std::isnan((double)x) || std::isinf((double)x)) { + return; + } + + bool treatment = false; + const Column* treatment_col = columns[1]; + FunctionHelper::get_data_of_column(treatment_col, row_num, treatment); + + this->data(state).update(x, treatment); + } + + void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { + DCHECK(column->is_binary()); + const uint8_t* serialized_data = reinterpret_cast(column->get(row_num).get_slice().data); + if (this->data(state).is_uninitialized()) { + this->data(state).deserialize(serialized_data); + return; + } + MannWhitneyAggregateState other(serialized_data); + this->data(state).merge(other); + } + + void serialize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + DCHECK(to->is_binary()); + auto* column = down_cast(to); + Bytes& bytes = column->get_bytes(); + size_t old_size = bytes.size(); + size_t new_size = old_size + this->data(state).serialized_size(); + bytes.resize(new_size); + column->get_offset().emplace_back(new_size); + uint8_t* serialized_data = bytes.data() + old_size; + this->data(state).serialize(serialized_data); + } + + void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + if (this->data(state).is_uninitialized()) { + ctx->set_error("Internal Error: state not initialized."); + return; + } + vpack::Builder result_builder; + this->data(state).build_result(result_builder); + JsonValue result_json(result_builder.slice()); + down_cast(to)->append(std::move(result_json)); + } + + void convert_to_serialize_format(FunctionContext* ctx, const Columns& src, size_t chunk_size, + ColumnPtr* dst) const override { + TestingAlternative alternative{TestingAlternative::TwoSided}; + int64_t continuity_correction = 1; + + const Column* alternative_col = ctx->get_num_args() >= 3 ? src[2].get() : nullptr; + const Column* continuity_correction_col = ctx->get_num_args() >= 4 ? src[3].get() : nullptr; + if (alternative_col != nullptr) { + Slice alternative_slice; + FunctionHelper::get_data_of_column(alternative_col, 0, alternative_slice); + auto alternative_str = boost::to_lower_copy(alternative_slice.to_string()); + TestingAlternative init_alternative = TestingAlternative::from_str(alternative_str); + if (init_alternative == TestingAlternative::Unknown) { + ctx->set_error(fmt::format("Logical Error: invalid alternative `{}`.", alternative_str).c_str()); + return; + } + alternative = init_alternative; + } + + if (continuity_correction_col != nullptr) { + FunctionHelper::get_data_of_column(continuity_correction_col, 0, + continuity_correction); + if (continuity_correction < 0) { + ctx->set_error("Logical Error: continuity_correction must be non-negative."); + return; + } + } + + for (size_t idx = 0; idx < chunk_size; ++idx) { + MannWhitneyAggregateState state; + state.init(alternative, continuity_correction); + + DataCppType x{}; + const Column* x_col = src[0].get(); + FunctionHelper::get_data_of_column(x_col, idx, x); + + bool treatment = false; + const Column* treatment_col = src[1].get(); + FunctionHelper::get_data_of_column(treatment_col, idx, treatment); + + if (!(std::isnan((double)x) || std::isinf((double)x))) { + state.update(x, treatment); + } + + serialize_to_column(ctx, reinterpret_cast(&state), dst->get()); + } + } + + std::string get_name() const override { return "mann_whitney_u_test"; } +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/map_agg.h b/be/src/exprs/agg/map_agg.h new file mode 100644 index 0000000000000..d23b3806761a8 --- /dev/null +++ b/be/src/exprs/agg/map_agg.h @@ -0,0 +1,160 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "column/binary_column.h" +#include "column/column.h" +#include "column/column_helper.h" +#include "column/fixed_length_column.h" +#include "column/hash_set.h" +#include "column/map_column.h" +#include "column/type_traits.h" +#include "exprs/agg/aggregate.h" +#include "exprs/function_context.h" +#include "gutil/casts.h" +#include "util/phmap/phmap.h" +#include "util/time.h" + +namespace starrocks { + +template > +struct MapAggAggregateFunctionState : public AggregateFunctionEmptyState { + using KeyColumnType = RunTimeColumnType; + using KeyType = typename SliceHashSet::key_type; + + MyHashMap hash_map; + // Use column to store the values in case that the reference of the Slices disappears. + ColumnPtr value_column; + + void update(MemPool* mem_pool, const KeyColumnType& arg_key_column, const Column& arg_value_column, size_t offset, + size_t count) { + if constexpr (!lt_is_string) { + for (int i = offset; i < offset + count; i++) { + auto key = arg_key_column.get_data()[i]; + if (!hash_map.contains(key)) { + auto value = arg_value_column.get(i); + value_column->append_datum(value); + hash_map.emplace(key, value_column->size() - 1); + } + } + } else { + for (int i = offset; i < offset + count; i++) { + auto raw_key = arg_key_column.get_slice(i); + KeyType key(raw_key); + if (!hash_map.contains(key)) { + uint8_t* pos = mem_pool->allocate(key.size); + memcpy(pos, key.data, key.size); + auto value = arg_value_column.get(i); + value_column->append_datum(value); + hash_map.emplace(Slice(pos, key.size), value_column->size() - 1); + } + } + } + } +}; + +template > +class MapAggAggregateFunction final : public AggregateFunctionBatchHelper, + MapAggAggregateFunction> { +public: + using KeyColumnType = RunTimeColumnType; + + void create(FunctionContext* ctx, AggDataPtr __restrict ptr) const override { + auto* state = new (ptr) MapAggAggregateFunctionState; + state->value_column = ctx->create_column(*ctx->get_arg_type(1), true); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + // Key could not be null. + if ((columns[0]->is_nullable() && columns[0]->is_null(row_num)) || columns[0]->only_null()) { + return; + } + const auto& key_column = down_cast(*ColumnHelper::get_data_column(columns[0])); + this->data(state).update(ctx->mem_pool(), key_column, *columns[1], row_num, 1); + } + + void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { + auto map_column = down_cast(ColumnHelper::get_data_column(column)); + auto& offsets = map_column->offsets().get_data(); + if (offsets[row_num + 1] > offsets[row_num]) { + this->data(state).update( + ctx->mem_pool(), + *down_cast(ColumnHelper::get_data_column(map_column->keys_column().get())), + map_column->values(), offsets[row_num], offsets[row_num + 1] - offsets[row_num]); + } + } + + void serialize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + auto& state_impl = this->data(state); + auto* map_column = down_cast(ColumnHelper::get_data_column(to)); + + auto elem_size = state_impl.hash_map.size(); + auto* key_column = down_cast(ColumnHelper::get_data_column(map_column->keys_column().get())); + if constexpr (lt_is_string) { + for (const auto& entry : state_impl.hash_map) { + key_column->append(Slice(entry.first.data, entry.first.size)); + map_column->values_column()->append_datum(state_impl.value_column->get(entry.second)); + } + } else { + for (const auto& entry : state_impl.hash_map) { + key_column->append(entry.first); + map_column->values_column()->append_datum(state_impl.value_column->get(entry.second)); + } + } + + if (to->is_nullable()) { + down_cast(to)->null_column_data().emplace_back(0); + } + if (map_column->keys_column()->is_nullable()) { + // Key could not be NULL. + auto* nullable_column = down_cast(map_column->keys_column().get()); + nullable_column->null_column_data().resize(nullable_column->null_column_data().size() + elem_size); + } + + auto& offsets = map_column->offsets_column()->get_data(); + offsets.push_back(offsets.back() + elem_size); + } + + void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + serialize_to_column(ctx, state, to); + } + + void convert_to_serialize_format(FunctionContext* ctx, const Columns& src, size_t chunk_size, + ColumnPtr* dst) const override { + auto* column = down_cast(ColumnHelper::get_data_column(dst->get())); + auto key_column = column->keys_column(); + auto value_column = column->values_column(); + auto& offsets = column->offsets_column()->get_data(); + for (size_t i = 0; i < chunk_size; i++) { + if ((src[0]->is_nullable() && src[0]->is_null(i)) || src[0]->only_null()) { + offsets.push_back(offsets.back()); + continue; + } + key_column->append(*src[0], i, 1); + value_column->append(*src[1], i, 1); + offsets.push_back(offsets.back() + 1); + } + if (dst->get()->is_nullable()) { + down_cast(dst->get())->null_column_data().resize(dst->get()->size() + chunk_size); + } + } + + std::string get_name() const override { return "map_agg"; } +}; + +} // namespace starrocks diff --git a/be/src/exprs/agg/nullable_aggregate.h b/be/src/exprs/agg/nullable_aggregate.h index 6cd5da175652b..236b07ebe0ee5 100644 --- a/be/src/exprs/agg/nullable_aggregate.h +++ b/be/src/exprs/agg/nullable_aggregate.h @@ -274,7 +274,11 @@ class NullableAggregateFunctionBase : public AggregateFunctionStateHelper } void merge_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column* column, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < chunk_size; i++) { // TODO: optimize with simd ? if (filter[i] == 0) { @@ -412,7 +416,11 @@ class NullableAggregateFunctionUnary final } void update_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column** columns, +<<<<<<< HEAD AggDataPtr* states, const std::vector& selection) const override { +======= + AggDataPtr* states, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Scalar function compute will return non-nullable column // for nullable column when the real whole chunk data all not-null. if (columns[0]->is_nullable()) { @@ -738,7 +746,11 @@ class NullableAggregateFunctionUnary final } void merge_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column* column, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto fast_call_path = [&](const Column* data_column) { for (size_t i = 0; i < chunk_size; ++i) { if (filter[i] == 0) { @@ -836,7 +848,11 @@ class NullableAggregateFunctionVariadic final } void update_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column** columns, +<<<<<<< HEAD AggDataPtr* states, const std::vector& selection) const override { +======= + AggDataPtr* states, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto column_size = ctx->get_num_args(); for (size_t i = 0; i < column_size; i++) { if (columns[i]->only_null()) { diff --git a/be/src/exprs/agg/percentile_approx.h b/be/src/exprs/agg/percentile_approx.h index 4396efdfdb20b..996a49c54beea 100644 --- a/be/src/exprs/agg/percentile_approx.h +++ b/be/src/exprs/agg/percentile_approx.h @@ -29,6 +29,11 @@ struct PercentileApproxState { PercentileApproxState() : percentile(new PercentileValue()) {} ~PercentileApproxState() = default; +<<<<<<< HEAD +======= + int64_t mem_usage() const { return percentile->mem_usage(); } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::unique_ptr percentile; double targetQuantile = -1.0; bool is_null = true; @@ -55,9 +60,17 @@ class PercentileApproxAggregateFunction final DCHECK(!columns[1]->is_null(0)); +<<<<<<< HEAD + data(state).percentile->add(implicit_cast(column_value)); + data(state).targetQuantile = columns[1]->get(0).get_double(); + data(state).is_null = false; +======= + int64_t prev_memory = data(state).percentile->mem_usage(); data(state).percentile->add(implicit_cast(column_value)); data(state).targetQuantile = columns[1]->get(0).get_double(); data(state).is_null = false; + ctx->add_mem_usage(data(state).percentile->mem_usage() - prev_memory); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { @@ -78,10 +91,18 @@ class PercentileApproxAggregateFunction final PercentileApproxState src_percentile; src_percentile.targetQuantile = quantile; src_percentile.percentile->deserialize((char*)src.data + sizeof(double)); +<<<<<<< HEAD data(state).percentile->merge(src_percentile.percentile.get()); data(state).targetQuantile = quantile; data(state).is_null = false; +======= + int64_t prev_memory = data(state).percentile->mem_usage(); + data(state).percentile->merge(src_percentile.percentile.get()); + data(state).targetQuantile = quantile; + data(state).is_null = false; + ctx->add_mem_usage(data(state).percentile->mem_usage() - prev_memory); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void serialize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { diff --git a/be/src/exprs/agg/percentile_cont.h b/be/src/exprs/agg/percentile_cont.h index cf37a76df6c45..1f298dc4d1826 100644 --- a/be/src/exprs/agg/percentile_cont.h +++ b/be/src/exprs/agg/percentile_cont.h @@ -18,14 +18,31 @@ #include #include +<<<<<<< HEAD #include "column/column_helper.h" #include "column/object_column.h" #include "column/vectorized_fwd.h" #include "exprs/agg/aggregate.h" +======= +#include "column/column_hash.h" +#include "column/column_helper.h" +#include "column/object_column.h" +#include "column/type_traits.h" +#include "column/vectorized_fwd.h" +#include "exprs/agg/aggregate.h" +#include "exprs/agg/aggregate_state_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/function_context.h" #include "gutil/casts.h" #include "runtime/mem_pool.h" #include "util/orlp/pdqsort.h" +<<<<<<< HEAD +======= +#include "util/phmap/phmap.h" +#include "util/phmap/phmap_fwd_decl.h" +#include "util/slice.h" +#include "util/unaligned_access.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -36,21 +53,45 @@ inline constexpr LogicalType PercentileResultLT = LT; template inline constexpr LogicalType PercentileResultLT> = TYPE_DOUBLE; +<<<<<<< HEAD template struct PercentileState { using CppType = RunTimeCppType; void update(CppType item) { items.emplace_back(item); } void update_batch(const std::vector& vec) { +======= +template +struct PercentileStateTypes { + using CppType = RunTimeCppType; + using ItemType = VectorWithAggStateAllocator; + using GridType = VectorWithAggStateAllocator; +}; + +template +struct PercentileState { + using CppType = typename PercentileStateTypes::CppType; + using ItemType = typename PercentileStateTypes::ItemType; + using GridType = typename PercentileStateTypes::GridType; + + void update(CppType item) { items.emplace_back(item); } + void update_batch(const Buffer& vec) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t old_size = items.size(); items.resize(old_size + vec.size()); memcpy(items.data() + old_size, vec.data(), vec.size() * sizeof(CppType)); } +<<<<<<< HEAD std::vector items; std::vector> grid; +======= + ItemType items; + GridType grid; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) double rate = 0.0; }; template +<<<<<<< HEAD void kWayMergeSort(const std::vector>& grid, std::vector& b, std::vector& ls, std::map& mp, size_t goal, int k, CppType& junior_elm, CppType& senior_elm) { CppType minV = RunTimeTypeLimits::min_value(); @@ -58,6 +99,16 @@ void kWayMergeSort(const std::vector>& grid, std::vector::GridType& grid, std::vector& b, + std::vector& ls, std::vector& mp, size_t goal, int k, CppType& junior_elm, + CppType& senior_elm) { + CppType minV = RunTimeTypeLimits::min_value(); + CppType maxV = RunTimeTypeLimits::max_value(); + b.resize(k + 1); + ls.resize(k); + mp.resize(k); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (int i = 0; i < k; ++i) { if constexpr (reverse) { mp[i] = grid[i].size() - 2; @@ -191,9 +242,15 @@ class PercentileContDiscAggregateFunction double rate = *reinterpret_cast(slice.data); size_t items_size = *reinterpret_cast(slice.data + sizeof(double)); auto data_ptr = slice.data + sizeof(double) + sizeof(size_t); +<<<<<<< HEAD std::vector>& grid = this->data(state).grid; std::vector vec; +======= + auto& grid = this->data(state).grid; + + typename PercentileStateTypes::ItemType vec; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) vec.resize(items_size + 2); memcpy(vec.data() + 1, data_ptr, items_size * sizeof(InputCppType)); vec[0] = RunTimeTypeLimits::min_value(); @@ -382,13 +439,21 @@ class PercentileContAggregateFunction final : public PercentileContDiscAggregate using ResultColumnType = RunTimeColumnType; void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { +<<<<<<< HEAD const std::vector>& grid = this->data(state).grid; +======= + const auto& grid = this->data(state).grid; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const double& rate = this->data(state).rate; // for group by if (grid.size() == 0) { ResultColumnType* column = down_cast(to); +<<<<<<< HEAD auto& items = const_cast&>(this->data(state).items); +======= + auto& items = const_cast::ItemType&>(this->data(state).items); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::sort(items.begin(), items.end()); if (items.size() == 0) { @@ -409,7 +474,11 @@ class PercentileContAggregateFunction final : public PercentileContDiscAggregate std::vector b; std::vector ls; +<<<<<<< HEAD std::map mp; +======= + std::vector mp; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t k = grid.size(); size_t rowsNum = 0; @@ -428,8 +497,13 @@ class PercentileContAggregateFunction final : public PercentileContDiscAggregate goal = 0; } +<<<<<<< HEAD InputCppType junior_elm; InputCppType senior_elm; +======= + InputCppType junior_elm{}; + InputCppType senior_elm{}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (reverse) { kWayMergeSort(grid, b, ls, mp, goal, k, junior_elm, senior_elm); @@ -463,7 +537,11 @@ class PercentileDiscAggregateFunction final : public PercentileContDiscAggregate using ResultColumnType = RunTimeColumnType; void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { +<<<<<<< HEAD std::vector new_vector = std::move(this->data(state).items); +======= + typename PercentileStateTypes::ItemType new_vector = std::move(this->data(state).items); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto& innerData : this->data(state).grid) { std::move(innerData.begin() + 1, innerData.end() - 1, std::back_inserter(new_vector)); } @@ -499,4 +577,199 @@ class PercentileDiscAggregateFunction final : public PercentileContDiscAggregate std::string get_name() const override { return "percentile_disc"; } }; -} // namespace starrocks \ No newline at end of file +<<<<<<< HEAD +} // namespace starrocks +======= +template +struct LowCardPercentileState { + using CppType = RunTimeCppType; + constexpr int static ser_header = 0x3355 | LT << 16; + void update(CppType item) { items[item]++; } + + void update_batch(const Buffer& vec) { + for (const auto& item : vec) { + items[item]++; + } + } + + size_t serialize_size() const { + size_t size = 0; + // serialize header + size += sizeof(ser_header); + for (size_t i = 0; i < items.size(); ++i) { + size += sizeof(CppType) + sizeof(size_t); + } + return size; + } + + void serialize(Slice result) const { + char* cur = result.data; + // serialize header + unaligned_store(cur, ser_header); + cur += sizeof(ser_header); + // serialize + for (const auto& [key, value] : items) { + unaligned_store(cur, key); + cur += sizeof(CppType); + unaligned_store(cur, value); + cur += sizeof(size_t); + } + } + + void merge(Slice slice) { + char* cur = slice.data; + char* ed = slice.data + slice.size; + // skip header + if (cur + sizeof(ser_header) >= ed || unaligned_load(cur) != ser_header) { + throw std::runtime_error("Invalid LowCardPercentileState data for " + type_to_string(LT)); + } + cur += sizeof(ser_header); + while (cur < ed) { + CppType key = unaligned_load(cur); + cur += sizeof(CppType); + size_t value = unaligned_load(cur); + cur += sizeof(size_t); + items[key] += value; + } + } + + CppType build_result(double rate) const { + std::vector data; + for (auto [key, _] : items) { + data.push_back(key); + } + pdqsort(data.begin(), data.end()); + + size_t accumulate = 0; + for (auto key : data) { + accumulate += items.at(key); + } + size_t target = accumulate * rate; + + accumulate = 0; + auto res = data[data.size() - 1]; + for (auto key : data) { + accumulate += items.at(key); + if (accumulate > target) { + res = key; + break; + } + } + return res; + } + + using HashFunc = typename HashTypeTraits::HashFunc; + phmap::flat_hash_map items; +}; + +template +class LowCardPercentileBuildAggregateFunction + : public AggregateFunctionBatchHelper, DetailFunction> { +public: + using InputCppType = RunTimeCppType; + using InputColumnType = RunTimeColumnType; + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr __restrict state, + size_t row_num) const override { + const auto& column = down_cast(*columns[0]); + this->data(state).update(column.get_data()[row_num]); + } + + void update_batch_single_state(FunctionContext* ctx, size_t chunk_size, const Column** columns, + AggDataPtr __restrict state) const override { + const auto& column = down_cast(*columns[0]); + this->data(state).update_batch(column.get_data()); + } + + void merge(FunctionContext* ctx, const Column* column, AggDataPtr __restrict state, size_t row_num) const override { + const Slice slice = column->get(row_num).get_slice(); + this->data(state).merge(slice); + } + + void serialize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + size_t serialize_size = this->data(state).serialize_size(); + + auto* column = down_cast(to); + Bytes& bytes = column->get_bytes(); + size_t old_size = bytes.size(); + size_t new_size = old_size + serialize_size; + bytes.resize(new_size); + + this->data(state).serialize(Slice(bytes.data() + old_size, serialize_size)); + + column->get_offset().emplace_back(new_size); + } + + void convert_to_serialize_format(FunctionContext* ctx, const Columns& src, size_t chunk_size, + ColumnPtr* dst) const override { + size_t serialize_row = (sizeof(int) + sizeof(InputCppType) + sizeof(int64_t)); + size_t serialize_size = serialize_row * chunk_size; + + auto* column = down_cast(dst->get()); + Bytes& bytes = column->get_bytes(); + size_t old_size = bytes.size(); + size_t new_size = old_size + serialize_size; + bytes.resize(new_size); + unsigned char* cur = bytes.data() + old_size; + + auto src_column = *down_cast(src[0].get()); + InputCppType* src_data = src_column.get_data().data(); + + size_t cur_size = old_size; + for (size_t i = 0; i < chunk_size; ++i) { + unaligned_store(cur, LowCardPercentileState::ser_header); + cur += sizeof(int); + unaligned_store(cur, src_data[i]); + cur += sizeof(InputCppType); + unaligned_store(cur, 1); + cur += sizeof(size_t); + cur_size += serialize_row; + column->get_offset().emplace_back(cur_size); + } + } +}; + +template +class LowCardPercentileBinAggregateFunction final + : public LowCardPercentileBuildAggregateFunction> { + using Base = LowCardPercentileBuildAggregateFunction>; + +public: + std::string get_name() const override { return "lc_percentile_bin"; } + + // return to binary + void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + Base::serialize_to_column(ctx, state, to); + } +}; + +template +class LowCardPercentileCntAggregateFunction final + : public LowCardPercentileBuildAggregateFunction> { +public: + using InputCppType = RunTimeCppType; + using InputColumnType = RunTimeColumnType; + + std::string get_name() const override { return "lc_percentile_cnt"; } + + // input/output will be the same type + void finalize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { + double rate = 0; + DCHECK_EQ(ctx->get_num_args(), 2); + if (ctx->get_num_args() == 2) { + const auto* rate_column = down_cast(ctx->get_constant_column(1).get()); + rate = rate_column->get(0).get_double(); + } + DCHECK(rate >= 0 && rate <= 1); + auto& result = this->data(state); + if (result.items.empty()) { + to->append_default(); + return; + } + auto res = result.build_result(rate); + down_cast(to)->append(res); + } +}; + +} // namespace starrocks +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/exprs/agg/percentile_union.h b/be/src/exprs/agg/percentile_union.h index 7836a8c877218..a6654c6c3da2a 100644 --- a/be/src/exprs/agg/percentile_union.h +++ b/be/src/exprs/agg/percentile_union.h @@ -16,16 +16,34 @@ #include "column/object_column.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exprs/agg/aggregate.h" +======= +#include "common/compiler_util.h" +#include "exprs/agg/aggregate.h" +#include "exprs/function_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/casts.h" namespace starrocks { class PercentileUnionAggregateFunction final : public AggregateFunctionBatchHelper { public: +<<<<<<< HEAD void update(FunctionContext* ctx, const Column** columns, AggDataPtr state, size_t row_num) const override { const auto* column = down_cast(columns[0]); this->data(state).merge(column->get_object(row_num)); +======= + ALWAYS_INLINE void update_state(FunctionContext* ctx, AggDataPtr state, const PercentileValue* value) const { + int64_t prev_memory = this->data(state).mem_usage(); + this->data(state).merge(value); + ctx->add_mem_usage(this->data(state).mem_usage() - prev_memory); + } + + void update(FunctionContext* ctx, const Column** columns, AggDataPtr state, size_t row_num) const override { + const auto* column = down_cast(columns[0]); + update_state(ctx, state, column->get_object(row_num)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void update_batch_single_state_with_frame(FunctionContext* ctx, AggDataPtr __restrict state, const Column** columns, @@ -33,7 +51,11 @@ class PercentileUnionAggregateFunction final int64_t frame_end) const override { const auto* column = down_cast(columns[0]); for (size_t i = frame_start; i < frame_end; ++i) { +<<<<<<< HEAD this->data(state).merge(column->get_object(i)); +======= + update_state(ctx, state, column->get_object(i)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -41,7 +63,11 @@ class PercentileUnionAggregateFunction final DCHECK(column->is_object()); const auto* percentile_column = down_cast(column); +<<<<<<< HEAD this->data(state).merge(percentile_column->get_object(row_num)); +======= + update_state(ctx, state, percentile_column->get_object(row_num)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void serialize_to_column(FunctionContext* ctx, ConstAggDataPtr __restrict state, Column* to) const override { diff --git a/be/src/exprs/agg/sum.h b/be/src/exprs/agg/sum.h index 2c41ddb0faa71..54f8fe832d667 100644 --- a/be/src/exprs/agg/sum.h +++ b/be/src/exprs/agg/sum.h @@ -158,8 +158,12 @@ class SumAggregateFunction final } void batch_finalize_with_selection(FunctionContext* ctx, size_t chunk_size, const Buffer& agg_states, +<<<<<<< HEAD size_t state_offset, Column* to, const std::vector& selection) const override { +======= + size_t state_offset, Column* to, const Filter& selection) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(to->is_numeric()); ResultType values[chunk_size]; size_t selected_lengh = 0; diff --git a/be/src/exprs/agg/window.h b/be/src/exprs/agg/window.h index 5871f510dc73a..57b3ec2bc1536 100644 --- a/be/src/exprs/agg/window.h +++ b/be/src/exprs/agg/window.h @@ -33,7 +33,11 @@ class WindowFunction : public AggregateFunctionStateHelper { } void merge_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column* column, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(false) << "Shouldn't call this method for window function!"; } @@ -53,7 +57,11 @@ class WindowFunction : public AggregateFunctionStateHelper { } void update_batch_selectively(FunctionContext* ctx, size_t chunk_size, size_t state_offset, const Column** column, +<<<<<<< HEAD AggDataPtr* states, const std::vector& filter) const override { +======= + AggDataPtr* states, const Filter& filter) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(false) << "Shouldn't call this method for window function!"; } diff --git a/be/src/exprs/agg_state_function.h b/be/src/exprs/agg_state_function.h new file mode 100644 index 0000000000000..f7a1bbcf8f705 --- /dev/null +++ b/be/src/exprs/agg_state_function.h @@ -0,0 +1,95 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "column/column.h" +#include "column/column_helper.h" +#include "common/status.h" +#include "exprs/agg/aggregate.h" +#include "exprs/agg/aggregate_state_allocator.h" +#include "exprs/function_context.h" +#include "runtime/agg_state_desc.h" + +namespace starrocks { + +static MemHookAllocator kDefaultAggStateFunctionAllocator = MemHookAllocator{}; + +/** + * @brief compute the immediate result of aggregate function + * DESC: immediate_type {agg_func}_state(arg_types) + * input type : aggregate function's argument types + * return type : aggregate function's immediate type + */ +class AggStateFunction { +public: + AggStateFunction(AggStateDesc agg_state_desc, TypeDescriptor immediate_type, std::vector arg_nullables) + : _agg_state_desc(std::move(agg_state_desc)), + _immediate_type(std::move(immediate_type)), + _arg_nullables(std::move(arg_nullables)) { + _function = AggStateDesc::get_agg_state_func(&_agg_state_desc); + } + + Status prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) { + if (_function == nullptr) { + return Status::InternalError("AggStateFunction is nullptr for " + _agg_state_desc.get_func_name()); + } + return Status::OK(); + } + + Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) { return Status::OK(); } + + StatusOr execute(FunctionContext* context, const Columns& columns) { + if (columns.size() == 0) { + return Status::InternalError("AggStateFunction execute columns is empty"); + } + if (columns.size() != _arg_nullables.size()) { + return Status::InternalError("AggStateFunction execute columns size " + std::to_string(columns.size()) + + " not match with arg_nullables size " + std::to_string(_arg_nullables.size())); + } + + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(&kDefaultAggStateFunctionAllocator); + Columns new_columns; + new_columns.reserve(columns.size()); + for (auto i = 0; i < columns.size(); i++) { + bool arg_nullable = _arg_nullables[i]; + auto& column = columns[i]; + if (!arg_nullable && column->is_nullable()) { + return Status::InternalError( + "AggStateFunction input column is nullable but agg function is not nullable"); + } + if (arg_nullable && !column->is_nullable()) { + new_columns.push_back(ColumnHelper::cast_to_nullable_column(column)); + } else { + new_columns.push_back(column); + } + } + auto result = ColumnHelper::create_column(_immediate_type, _agg_state_desc.is_result_nullable()); + auto chunk_size = columns[0]->size(); + _function->convert_to_serialize_format(context, new_columns, chunk_size, &result); + return result; + } + +private: + AggStateDesc _agg_state_desc; + TypeDescriptor _immediate_type; + std::vector _arg_nullables; + const AggregateFunction* _function; +}; +using AggStateFunctionPtr = std::shared_ptr; + +} // namespace starrocks diff --git a/be/src/exprs/arithmetic_expr.cpp b/be/src/exprs/arithmetic_expr.cpp index bacad39ef5353..e1f9c6845cd08 100644 --- a/be/src/exprs/arithmetic_expr.cpp +++ b/be/src/exprs/arithmetic_expr.cpp @@ -14,9 +14,12 @@ #include "exprs/arithmetic_expr.h" +<<<<<<< HEAD #include #include +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include "column/type_traits.h" @@ -27,12 +30,25 @@ #include "exprs/binary_function.h" #include "exprs/decimal_binary_function.h" #include "exprs/decimal_cast_expr.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/overflow.h" #include "exprs/unary_function.h" #include "runtime/runtime_state.h" #include "types/logical_type.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include +#include + +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { #define DEFINE_CLASS_CONSTRUCTOR(CLASS_NAME) \ @@ -124,6 +140,10 @@ class VectorizedArithmeticExpr final : public Expr { return VectorizedStrictBinaryFunction::template evaluate(l, r); } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::ARITHMETIC) && IRHelper::support_jit(Type); @@ -148,6 +168,10 @@ class VectorizedArithmeticExpr final : public Expr { return ArithmeticOp::template generate_ir(context, jit_ctx->module, jit_ctx->builder, datums); } } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -196,6 +220,11 @@ class VectorizedDivArithmeticExpr final : public Expr { } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::DIV) && Type != TYPE_LARGEINT && IRHelper::support_jit(Type); } @@ -234,6 +263,10 @@ class VectorizedDivArithmeticExpr final : public Expr { return ArithmeticOp::template generate_ir(context, jit_ctx->module, jit_ctx->builder, datums); } } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -290,6 +323,10 @@ class VectorizedModArithmeticExpr final : public Expr { return VectorizedMod::template evaluate(l, r); } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::MOD) && Type != TYPE_LARGEINT && IRHelper::support_jit(Type); @@ -329,6 +366,10 @@ class VectorizedModArithmeticExpr final : public Expr { return ArithmeticOp::template generate_ir(context, jit_ctx->module, jit_ctx->builder, datums); } } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -350,6 +391,10 @@ class VectorizedBitNotArithmeticExpr final : public Expr { using ArithmeticBitNot = ArithmeticUnaryOperator; return VectorizedStrictUnaryFunction::template evaluate(l); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::ARITHMETIC) && IRHelper::support_jit(Type); @@ -381,6 +426,10 @@ class VectorizedBitNotArithmeticExpr final : public Expr { datum.value = ArithmeticBitNot::generate_ir(jit_ctx->builder, datum.value); return datum; } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -404,6 +453,11 @@ class VectorizedBitShiftArithmeticExpr final : public Expr { return VectorizedStrictBinaryFunction::template evaluate(l, r); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::ARITHMETIC) && IRHelper::support_jit(Type); } @@ -439,6 +493,10 @@ class VectorizedBitShiftArithmeticExpr final : public Expr { return ArithmeticOp::template generate_ir, CppType>( context, jit_ctx->module, jit_ctx->builder, datums); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; diff --git a/be/src/exprs/arithmetic_operation.h b/be/src/exprs/arithmetic_operation.h index 426f102bb4d39..9afe7329ac4a5 100644 --- a/be/src/exprs/arithmetic_operation.h +++ b/be/src/exprs/arithmetic_operation.h @@ -14,6 +14,7 @@ #pragma once +<<<<<<< HEAD #include #include @@ -21,10 +22,25 @@ #include "common/status.h" #include "exprs/expr_context.h" #include "exprs/jit/ir_helper.h" +======= +#include "column/type_traits.h" +#include "common/status.h" +#include "exprs/expr_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/decimalv3.h" #include "types/logical_type.h" #include "util/guard.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include +#include + +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { struct AddOp {}; struct SubOp {}; @@ -194,7 +210,11 @@ struct ArithmeticBinaryOperator { static_assert(is_binary_op, "Invalid binary operators"); } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template static StatusOr generate_ir(ExprContext* context, const llvm::Module& module, llvm::IRBuilder<>& b, const std::vector& datums) { @@ -343,6 +363,10 @@ struct ArithmeticBinaryOperator { return result; } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; TYPE_GUARD(DivModOpGuard, is_divmod_op, DivOp, ModOp) @@ -365,7 +389,11 @@ struct ArithmeticBinaryOperator, guard::Gu static_assert(is_divmod_op, "Invalid float operators"); } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template static StatusOr generate_ir(ExprContext* context, const llvm::Module& module, llvm::IRBuilder<>& b, const std::vector& datums) { @@ -378,6 +406,10 @@ struct ArithmeticBinaryOperator, guard::Gu // JIT compile of DecimalV2 type is not supported. return Status::NotSupported("JIT compile of DecimalV2 type is not supported."); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; TYPE_GUARD(DecimalOpGuard, is_decimal_op, AddOp, SubOp, ReverseSubOp, MulOp, DivOp, ModOp, ReverseModOp) @@ -581,12 +613,20 @@ struct ArithmeticBinaryOperator, DecimalLTGuard(l, r, result); } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) llvm::Value* generate_ir(llvm::IRBuilder<>& b, const std::vector& args) const { // TODO(Yueyang): Support JIT compile of DecimalV3 type. LOG(WARNING) << "JIT compile of DecimalV3 type is not supported."; return nullptr; } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template @@ -613,7 +653,11 @@ struct ArithmeticUnaryOperator { static_assert(is_bitnot_op, "Invalid unary operators"); } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static llvm::Value* generate_ir(llvm::IRBuilder<>& b, llvm::Value* l) { if constexpr (is_bitnot_op) { return b.CreateNot(l); @@ -621,6 +665,10 @@ struct ArithmeticUnaryOperator { static_assert(is_bitnot_op, "Invalid unary operators"); } } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; template diff --git a/be/src/exprs/array_element_expr.cpp b/be/src/exprs/array_element_expr.cpp index ca73edf4394ad..bbe29304dc943 100644 --- a/be/src/exprs/array_element_expr.cpp +++ b/be/src/exprs/array_element_expr.cpp @@ -74,7 +74,11 @@ class ArrayElementExpr final : public Expr { } } +<<<<<<< HEAD std::vector null_flags; +======= + NullData null_flags; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) raw::make_room(&null_flags, num_rows); // Construct null flags. diff --git a/be/src/exprs/array_functions.tpp b/be/src/exprs/array_functions.tpp index 78c938ff69a01..7d997391596ca 100644 --- a/be/src/exprs/array_functions.tpp +++ b/be/src/exprs/array_functions.tpp @@ -744,7 +744,11 @@ protected: return; } +<<<<<<< HEAD auto null_first_fn = [src_null_column](size_t i) -> bool { return src_null_column.get_data()[i] == 1; }; +======= + auto null_first_fn = [&src_null_column](size_t i) -> bool { return src_null_column.get_data()[i] == 1; }; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto begin_of_not_null = std::partition(sort_index->begin() + start, sort_index->begin() + start + count, null_first_fn); diff --git a/be/src/exprs/array_map_expr.cpp b/be/src/exprs/array_map_expr.cpp index ae293e859c909..286ea3eed96e2 100644 --- a/be/src/exprs/array_map_expr.cpp +++ b/be/src/exprs/array_map_expr.cpp @@ -29,7 +29,10 @@ #include "column/vectorized_fwd.h" #include "common/constexpr.h" #include "common/statusor.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr_context.h" #include "exprs/function_helper.h" #include "exprs/lambda_function.h" diff --git a/be/src/exprs/arrow_function_call.cpp b/be/src/exprs/arrow_function_call.cpp new file mode 100644 index 0000000000000..64dfc8d36f88f --- /dev/null +++ b/be/src/exprs/arrow_function_call.cpp @@ -0,0 +1,135 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "exprs/arrow_function_call.h" + +#include +#include + +#include "column/chunk.h" +#include "column/column.h" +#include "column/column_helper.h" +#include "column/vectorized_fwd.h" +#include "exprs/function_context.h" +#include "gen_cpp/Types_types.h" +#include "runtime/current_thread.h" +#include "runtime/user_function_cache.h" +#include "udf/python/callstub.h" +#include "util/phmap/phmap.h" + +namespace starrocks { + +using InnerStateMap = phmap::parallel_flat_hash_map, phmap::Hash, + phmap::EqualTo, phmap::Allocator, + NUM_LOCK_SHARD_LOG, std::mutex>; + +struct ArrowCallStubCtx { + InnerStateMap inner_states; + std::mutex inner_states_lock; +}; + +ArrowFunctionCallExpr::ArrowFunctionCallExpr(const TExprNode& node) : Expr(node) {} + +StatusOr ArrowFunctionCallExpr::evaluate_checked(ExprContext* context, Chunk* chunk) { + Columns columns(children().size()); + size_t num_rows = chunk != nullptr ? chunk->num_rows() : 1; + for (int i = 0; i < _children.size(); ++i) { + ASSIGN_OR_RETURN(columns[i], _children[i]->evaluate_checked(context, chunk)); + columns[i] = ColumnHelper::unfold_const_column(_children[i]->type(), num_rows, columns[i]); + } + + // get call stub + int32_t driver_id = CurrentThread::current().get_driver_id(); + FunctionContext* function_context = context->fn_context(_fn_context_index); + UDFCallStub* stub = nullptr; + _call_stub_ctx->inner_states.lazy_emplace_l( + driver_id, [&](auto& value) { stub = value.get(); }, + [&](auto build) { + auto value = _build_stub(driver_id, function_context); + stub = value.get(); + build(driver_id, std::move(value)); + }); + + return stub->evaluate(columns, num_rows); +} + +Status ArrowFunctionCallExpr::prepare(RuntimeState* state, ExprContext* context) { + _runtime_state = state; + // init Expr::prepare + RETURN_IF_ERROR(Expr::prepare(state, context)); + DCHECK(_fn.__isset.fid); + + FunctionContext::TypeDesc return_type = _type; + std::vector args_types; + + for (Expr* child : _children) { + args_types.push_back(child->type()); + } + + _fn_context_index = context->register_func(state, return_type, args_types); + context->fn_context(_fn_context_index)->set_is_udf(true); + + return Status::OK(); +} + +Status ArrowFunctionCallExpr::open(RuntimeState* state, ExprContext* context, + FunctionContext::FunctionStateScope scope) { + RETURN_IF_ERROR(Expr::open(state, context, scope)); + FunctionContext* fn_ctx = context->fn_context(_fn_context_index); + Columns const_columns; + if (scope == FunctionContext::FRAGMENT_LOCAL) { + const_columns.reserve(_children.size()); + for (const auto& child : _children) { + ASSIGN_OR_RETURN(auto&& child_col, child->evaluate_const(context)) + const_columns.emplace_back(std::move(child_col)); + } + fn_ctx->set_constant_columns(std::move(const_columns)); + } + if (scope == FunctionContext::FRAGMENT_LOCAL) { + auto function_cache = UserFunctionCache::instance(); + if (_fn.hdfs_location != "inline") { + RETURN_IF_ERROR(function_cache->get_libpath(_fn.fid, _fn.hdfs_location, _fn.checksum, &_lib_path)); + } else { + _lib_path = "inline"; + } + _call_stub_ctx = std::make_shared(); + } + return Status::OK(); +} + +void ArrowFunctionCallExpr::close(RuntimeState* state, ExprContext* context, + FunctionContext::FunctionStateScope scope) { + Expr::close(state, context, scope); +} + +bool ArrowFunctionCallExpr::is_constant() const { + return false; +} + +std::unique_ptr ArrowFunctionCallExpr::_build_stub(int32_t driver_id, FunctionContext* context) { + auto binary_type = _fn.binary_type; + if (binary_type == TFunctionBinaryType::PYTHON) { + PyFunctionDescriptor py_func_desc; + py_func_desc.symbol = _fn.scalar_fn.symbol; + py_func_desc.location = _lib_path; + py_func_desc.input_type = _fn.input_type; + py_func_desc.input_types = context->get_arg_types(); + py_func_desc.return_type = context->get_return_type(); + py_func_desc.content = _fn.content; + return build_py_call_stub(context, py_func_desc); + } + return create_error_call_stub(Status::NotFound(fmt::format("unsupported function type:{}", binary_type))); +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/exprs/arrow_function_call.h b/be/src/exprs/arrow_function_call.h new file mode 100644 index 0000000000000..adc4ea52edce5 --- /dev/null +++ b/be/src/exprs/arrow_function_call.h @@ -0,0 +1,47 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "common/object_pool.h" +#include "exprs/expr.h" +#include "runtime/runtime_state.h" +#include "udf/udf_call_stub.h" + +namespace starrocks { +struct ArrowCallStubCtx; + +class ArrowFunctionCallExpr final : public Expr { +public: + ArrowFunctionCallExpr(const TExprNode& node); + ~ArrowFunctionCallExpr() override = default; + + Expr* clone(ObjectPool* pool) const override { return pool->add(new ArrowFunctionCallExpr(*this)); } + + StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; + Status prepare(RuntimeState* state, ExprContext* context) override; + Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; + void close(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; + bool is_constant() const override; + +private: + std::unique_ptr _build_stub(int32_t driver_id, FunctionContext* context); + RuntimeState* _runtime_state = nullptr; + + std::string _lib_path; + std::shared_ptr _call_stub_ctx; +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/exprs/binary_predicate.cpp b/be/src/exprs/binary_predicate.cpp index d4b1a0f91929b..6e92f9adeed6b 100644 --- a/be/src/exprs/binary_predicate.cpp +++ b/be/src/exprs/binary_predicate.cpp @@ -14,22 +14,39 @@ #include "exprs/binary_predicate.h" +<<<<<<< HEAD #include #include #include +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/array_column.h" #include "column/column_builder.h" #include "column/column_viewer.h" #include "column/type_traits.h" #include "exprs/binary_function.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/unary_function.h" #include "runtime/runtime_state.h" #include "storage/column_predicate.h" #include "types/logical_type.h" #include "types/logical_type_infra.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include +#include +#include + +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { template @@ -131,6 +148,10 @@ class VectorizedBinaryPredicate final : public Predicate { ASSIGN_OR_RETURN(auto r, _children[1]->evaluate_checked(context, ptr)); return VectorizedStrictBinaryFunction::template evaluate(l, r); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::CMP) && IRHelper::support_jit(Type); @@ -215,6 +236,10 @@ class VectorizedBinaryPredicate final : public Predicate { _children[1]->jit_func_name(state) + "}" + (is_constant() ? "c:" : "") + (is_nullable() ? "n:" : "") + type().debug_string(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -426,6 +451,10 @@ class VectorizedNullSafeEqPredicate final : public Predicate { return builder.build(ColumnHelper::is_all_const(list)); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::CMP) && IRHelper::support_jit(Type); @@ -464,6 +493,10 @@ class VectorizedNullSafeEqPredicate final : public Predicate { return "{" + _children[0]->jit_func_name(state) + "<=>" + _children[1]->jit_func_name(state) + "}" + (is_constant() ? "c:" : "") + (is_nullable() ? "n:" : "") + type().debug_string(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; diff --git a/be/src/exprs/bitmap_functions.cpp b/be/src/exprs/bitmap_functions.cpp index 517efd9c94379..f4b421acabe7b 100644 --- a/be/src/exprs/bitmap_functions.cpp +++ b/be/src/exprs/bitmap_functions.cpp @@ -701,6 +701,7 @@ StatusOr BitmapFunctions::bitmap_to_binary(FunctionContext* context, } ColumnPtr col = builder.build(ColumnHelper::is_all_const(columns)); +<<<<<<< HEAD std::string err_msg; if (col->capacity_limit_reached(&err_msg)) { return Status::InternalError( @@ -708,6 +709,10 @@ StatusOr BitmapFunctions::bitmap_to_binary(FunctionContext* context, } else { return col; } +======= + RETURN_IF_ERROR(col->capacity_limit_reached()); + return col; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr BitmapFunctions::bitmap_from_binary(FunctionContext* context, const Columns& columns) { diff --git a/be/src/exprs/builtin_functions.h b/be/src/exprs/builtin_functions.h index 7cf9881c1998c..c9065a7f84c0c 100644 --- a/be/src/exprs/builtin_functions.h +++ b/be/src/exprs/builtin_functions.h @@ -23,11 +23,17 @@ namespace starrocks { +<<<<<<< HEAD using PrepareFunction = Status (*)(FunctionContext* context, FunctionContext::FunctionStateScope scope); using CloseFunction = Status (*)(FunctionContext* context, FunctionContext::FunctionStateScope scope); using ScalarFunction = StatusOr (*)(FunctionContext* context, const Columns& columns); +======= +using PrepareFunction = std::function; +using CloseFunction = std::function; +using ScalarFunction = std::function(FunctionContext* context, const Columns& columns)>; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct FunctionDescriptor { std::string name; diff --git a/be/src/exprs/case_expr.cpp b/be/src/exprs/case_expr.cpp index 272ad41122083..98240c92462ab 100644 --- a/be/src/exprs/case_expr.cpp +++ b/be/src/exprs/case_expr.cpp @@ -23,13 +23,23 @@ #include "column/type_traits.h" #include "column/vectorized_fwd.h" #include "common/object_pool.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/casts.h" #include "runtime/runtime_state.h" #include "simd/mulselector.h" #include "types/logical_type_infra.h" #include "util/percentile_value.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { /** @@ -71,6 +81,10 @@ class VectorizedCaseExpr final : public Expr { return _children.size() % 2 == 1 ? Status::OK() : Status::InvalidArgument("case when children is error!"); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { if (_has_case_expr) { return state->can_jit_expr(CompilableExprType::CASE) && IRHelper::support_jit(WhenType) && @@ -240,6 +254,10 @@ class VectorizedCaseExpr final : public Expr { out << "}" << (is_constant() ? "c:" : "") << (is_nullable() ? "n:" : "") << type().debug_string(); return out.str(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; diff --git a/be/src/exprs/cast_expr.cpp b/be/src/exprs/cast_expr.cpp index e62b83a82ac34..b8c19f666851b 100644 --- a/be/src/exprs/cast_expr.cpp +++ b/be/src/exprs/cast_expr.cpp @@ -14,10 +14,19 @@ #include "exprs/cast_expr.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include #include +<<<<<<< HEAD +======= +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -38,15 +47,25 @@ #include "exprs/binary_function.h" #include "exprs/column_ref.h" #include "exprs/decimal_cast_expr.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/unary_function.h" #include "gutil/casts.h" #include "gutil/strings/substitute.h" #include "runtime/datetime_value.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" #include "runtime/runtime_state.h" #include "runtime/types.h" #include "types/hll.h" +======= +#include "runtime/runtime_state.h" +#include "runtime/types.h" +#include "types/hll.h" +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type.h" #include "util/date_func.h" #include "util/json.h" @@ -54,6 +73,13 @@ #include "util/mysql_global.h" #include "util/numeric_types.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { #define THROW_RUNTIME_ERROR_WITH_TYPE(TYPE) \ @@ -1118,6 +1144,10 @@ class VectorizedCastExpr final : public Expr { } return result_column; }; +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::CAST) && !AllowThrowException && FromType != TYPE_LARGEINT && @@ -1184,6 +1214,10 @@ class VectorizedCastExpr final : public Expr { return datum; } } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -1588,6 +1622,28 @@ Expr* VectorizedCastExprFactory::create_primitive_cast(ObjectPool* pool, const T } } +<<<<<<< HEAD +======= + if (from_type == TYPE_JSON && to_type == TYPE_STRUCT) { + TypeDescriptor cast_to = TypeDescriptor::from_thrift(node.type); + + std::vector> field_casts(cast_to.children.size()); + for (int i = 0; i < cast_to.children.size(); ++i) { + TypeDescriptor json_type = TypeDescriptor::create_json_type(); + auto ret = create_cast_expr(pool, json_type, cast_to.children[i], allow_throw_exception); + if (!ret.ok()) { + LOG(WARNING) << "Not support cast from type: " << json_type << ", to type: " << cast_to.children[i]; + return nullptr; + } + field_casts[i] = std::move(ret.value()); + auto cast_input = create_slot_ref(json_type); + field_casts[i]->add_child(cast_input.get()); + pool->add(cast_input.release()); + } + return new CastJsonToStruct(node, std::move(field_casts)); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (from_type == TYPE_VARCHAR && to_type == TYPE_OBJECT) { return dispatch_throw_exception(allow_throw_exception, node); } diff --git a/be/src/exprs/cast_expr.h b/be/src/exprs/cast_expr.h index 4965c408f006f..6d85863a64242 100644 --- a/be/src/exprs/cast_expr.h +++ b/be/src/exprs/cast_expr.h @@ -24,8 +24,14 @@ #include "column/vectorized_fwd.h" #include "exprs/column_ref.h" #include "exprs/expr.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" #include "runtime/types.h" +======= +#include "jsonpath.h" +#include "runtime/types.h" +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -63,8 +69,12 @@ class CastStringToArray final : public Expr { ~CastStringToArray() override = default; StatusOr evaluate_checked(ExprContext* context, Chunk* input_chunk) override; Expr* clone(ObjectPool* pool) const override { return pool->add(new CastStringToArray(*this)); } +<<<<<<< HEAD [[nodiscard]] Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; +======= + Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: Slice _unquote(Slice slice) const; @@ -91,6 +101,37 @@ class CastJsonToArray final : public Expr { TypeDescriptor _cast_to_type_desc; }; +<<<<<<< HEAD +======= +// Cast Json to struct +class CastJsonToStruct final : public Expr { +public: + CastJsonToStruct(const TExprNode& node, std::vector> field_casts) + : Expr(node), _field_casts(std::move(field_casts)) { + _json_paths.reserve(_type.field_names.size()); + for (int j = 0; j < _type.field_names.size(); j++) { + std::string path_string = "$." + _type.field_names[j]; + auto res = JsonPath::parse(Slice(path_string)); + if (!res.ok()) { + throw std::runtime_error("Failed to parse JSON path: " + path_string); + } + _json_paths.emplace_back(res.value()); + } + } + + CastJsonToStruct(const CastJsonToStruct& rhs) : Expr(rhs) {} + + ~CastJsonToStruct() override = default; + + StatusOr evaluate_checked(ExprContext* context, Chunk* input_chunk) override; + Expr* clone(ObjectPool* pool) const override { return pool->add(new CastJsonToStruct(*this)); } + +private: + std::vector> _field_casts; + std::vector _json_paths; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // cast one ARRAY to another ARRAY. // For example. // cast ARRAY to ARRAY diff --git a/be/src/exprs/cast_expr_struct.cpp b/be/src/exprs/cast_expr_struct.cpp new file mode 100644 index 0000000000000..36e0426b43800 --- /dev/null +++ b/be/src/exprs/cast_expr_struct.cpp @@ -0,0 +1,133 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "column/array_column.h" +#include "column/column_builder.h" +#include "column/column_helper.h" +#include "column/column_viewer.h" +#include "column/json_column.h" +#include "exprs/cast_expr.h" +#include "exprs/expr_context.h" +#include "gutil/casts.h" +#include "gutil/strings/split.h" +#include "gutil/strings/strip.h" +#include "gutil/strings/substitute.h" +#include "jsonpath.h" +#include "runtime/memory/memory_resource.h" +#include "types/logical_type.h" +#include "util/slice.h" +#include "velocypack/Iterator.h" + +namespace starrocks { + +#define APPEND_NULL(json_columns, null_column) \ + for (auto& json_column : json_columns) { \ + json_column.append_null(); \ + } \ + null_column->append(1); + +StatusOr CastJsonToStruct::evaluate_checked(ExprContext* context, Chunk* input_chunk) { + ASSIGN_OR_RETURN(ColumnPtr column, _children[0]->evaluate_checked(context, input_chunk)); + if (column->only_null()) { + return ColumnHelper::create_const_null_column(column->size()); + } + + ColumnViewer src(column); + NullColumn::Ptr null_column = NullColumn::create(); + + // 1. Cast Json to json columns. + size_t field_size = _type.children.size(); + DCHECK_EQ(field_size, _type.field_names.size()); + vector> json_columns; + for (size_t i = 0; i < field_size; i++) { + ColumnBuilder json_column_builder(src.size()); + json_columns.emplace_back(json_column_builder); + } + for (size_t i = 0; i < src.size(); i++) { + if (src.is_null(i)) { + APPEND_NULL(json_columns, null_column); + continue; + } + const JsonValue* json_value = src.value(i); + if (json_value && json_value->get_type() == JsonType::JSON_ARRAY) { + vpack::Slice json_slice = json_value->to_vslice(); + DCHECK(json_slice.isArray()); + size_t index = 0; + for (const auto& element : vpack::ArrayIterator(json_slice)) { + if (index >= field_size) { + break; + } + JsonValue element_value(element); + json_columns[index].append(std::move(element_value)); + index++; + } + if (index < field_size) { + // Fill the other field with null. + for (; index < field_size; index++) { + json_columns[index].append_null(); + } + } + null_column->append(0); + } else if (json_value && json_value->get_type() == JsonType::JSON_OBJECT) { + // For json object, the names of the struct fields must match the json object keys. + // Otherwise, the value of the field will be NULL. + for (int path_index = 0; path_index < _type.field_names.size(); path_index++) { + vpack::Builder builder; + if (path_index >= _json_paths.size()) { + json_columns[path_index].append_null(); + continue; + } + vpack::Slice json_slice = JsonPath::extract(json_value, _json_paths[path_index], &builder); + if (json_slice.isNone()) { + json_columns[path_index].append_null(); + continue; + } + JsonValue element_value(json_slice); + json_columns[path_index].append(std::move(element_value)); + } + null_column->append(0); + } else { + APPEND_NULL(json_columns, null_column); + } + } + // 2. Cast json column to specified column + Columns casted_fields; + for (size_t i = 0; i < field_size; i++) { + ColumnPtr elements = json_columns[i].build_nullable_column(); + if (_field_casts[i] != nullptr) { + Chunk field_chunk; + field_chunk.append_column(elements, 0); + ASSIGN_OR_RETURN(auto casted_field, _field_casts[i]->evaluate_checked(context, &field_chunk)); + casted_field = NullableColumn::wrap_if_necessary(casted_field); + casted_fields.emplace_back(std::move(casted_field)); + } else { + casted_fields.emplace_back(NullableColumn::wrap_if_necessary(elements->clone_shared())); + } + DCHECK(casted_fields[i]->is_nullable()); + } + + ColumnPtr res = StructColumn::create(std::move(casted_fields), _type.field_names); + RETURN_IF_ERROR(res->unfold_const_children(_type)); + if (column->is_nullable()) { + res = NullableColumn::create(res, null_column); + } + + // Wrap constant column if source column is constant. + if (column->is_constant()) { + res = ConstColumn::create(res, column->size()); + } + return res; +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/exprs/compound_predicate.cpp b/be/src/exprs/compound_predicate.cpp index 5987edd6d0dd9..38b06016a5be8 100644 --- a/be/src/exprs/compound_predicate.cpp +++ b/be/src/exprs/compound_predicate.cpp @@ -16,11 +16,21 @@ #include "common/object_pool.h" #include "exprs/binary_function.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/predicate.h" #include "exprs/unary_function.h" #include "runtime/runtime_state.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { #define DEFINE_COMPOUND_CONSTRUCT(CLASS) \ @@ -60,6 +70,10 @@ class VectorizedAndCompoundPredicate final : public Predicate { return VectorizedLogicPredicateBinaryFunction::template evaluate(l, r); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::LOGICAL); } JitScore compute_jit_score(RuntimeState* state) const override { @@ -94,6 +108,10 @@ class VectorizedAndCompoundPredicate final : public Predicate { return "{" + _children[0]->jit_func_name(state) + " & " + _children[1]->jit_func_name(state) + "}" + (is_constant() ? "c:" : "") + (is_nullable() ? "n:" : "") + type().debug_string(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -137,6 +155,11 @@ class VectorizedOrCompoundPredicate final : public Predicate { return VectorizedLogicPredicateBinaryFunction::template evaluate(l, r); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::LOGICAL); } JitScore compute_jit_score(RuntimeState* state) const override { @@ -171,6 +194,10 @@ class VectorizedOrCompoundPredicate final : public Predicate { return "{" + _children[0]->jit_func_name(state) + " | " + _children[1]->jit_func_name(state) + "}" + (is_constant() ? "c:" : "") + (is_nullable() ? "n:" : "") + type().debug_string(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; @@ -195,6 +222,10 @@ class VectorizedNotCompoundPredicate final : public Predicate { return VectorizedStrictUnaryFunction::template evaluate(l); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override { return state->can_jit_expr(CompilableExprType::LOGICAL); } @@ -226,6 +257,10 @@ class VectorizedNotCompoundPredicate final : public Predicate { return "{!" + _children[0]->jit_func_name(state) + "}" + (is_constant() ? "c:" : "") + (is_nullable() ? "n:" : "") + type().debug_string(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override { std::stringstream out; diff --git a/be/src/exprs/debug_expr.cpp b/be/src/exprs/debug_expr.cpp index b1d0098906f80..8657039b7476d 100644 --- a/be/src/exprs/debug_expr.cpp +++ b/be/src/exprs/debug_expr.cpp @@ -45,12 +45,16 @@ StatusOr DebugFunctions::chunk_check_valid(ExprContext* context, Chun size_t num_rows = ptr->num_rows(); for (const auto& column : ptr->columns()) { // check column size capacity +<<<<<<< HEAD std::string msg; column->capacity_limit_reached(&msg); if (!msg.empty()) { DCHECK(false) << "not expected"; throw std::runtime_error(msg); } +======= + RETURN_IF_ERROR(column->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // check column size matched if (column->size() != num_rows) { DCHECK(false) << "not expected"; diff --git a/be/src/exprs/debug_expr.h b/be/src/exprs/debug_expr.h index 171e46a9bdacb..4856ab029d4e7 100644 --- a/be/src/exprs/debug_expr.h +++ b/be/src/exprs/debug_expr.h @@ -14,7 +14,11 @@ class DebugExpr final : public Expr { Expr* clone(ObjectPool* pool) const override { return pool->add(new DebugExpr(*this)); } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state, ExprContext* context) override; +======= + Status prepare(RuntimeState* state, ExprContext* context) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; diff --git a/be/src/exprs/decimal_binary_function.h b/be/src/exprs/decimal_binary_function.h index 699bc74a858f2..69778805a6f0a 100644 --- a/be/src/exprs/decimal_binary_function.h +++ b/be/src/exprs/decimal_binary_function.h @@ -205,6 +205,10 @@ struct DecimalBinaryFunction { } } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template static llvm::Value* generate_ir(llvm::IRBuilder<>& b, llvm::Module& module, llvm::Value* l, llvm::Value* r, int l_scale, int r_scale) { @@ -217,6 +221,10 @@ struct DecimalBinaryFunction { return nullptr; } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template static inline ColumnPtr const_const(const ColumnPtr& lhs, const ColumnPtr& rhs) { diff --git a/be/src/exprs/expr.cpp b/be/src/exprs/expr.cpp index 39eb545a6266f..a207ba5fbb5c7 100644 --- a/be/src/exprs/expr.cpp +++ b/be/src/exprs/expr.cpp @@ -34,7 +34,10 @@ #include "exprs/expr.h" +<<<<<<< HEAD #include +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -45,11 +48,18 @@ #include "common/object_pool.h" #include "common/status.h" #include "common/statusor.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/arithmetic_expr.h" #include "exprs/array_element_expr.h" #include "exprs/array_expr.h" #include "exprs/array_map_expr.h" +<<<<<<< HEAD +======= +#include "exprs/arrow_function_call.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/binary_predicate.h" #include "exprs/case_expr.h" #include "exprs/cast_expr.h" @@ -65,9 +75,12 @@ #include "exprs/info_func.h" #include "exprs/is_null_predicate.h" #include "exprs/java_function_call_expr.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" #include "exprs/jit/jit_engine.h" #include "exprs/jit/jit_expr.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/lambda_function.h" #include "exprs/literal.h" #include "exprs/map_apply_expr.h" @@ -82,6 +95,17 @@ #include "types/logical_type.h" #include "util/failpoint/fail_point.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include + +#include "exprs/jit/ir_helper.h" +#include "exprs/jit/jit_engine.h" +#include "exprs/jit/jit_expr.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" using std::vector; @@ -94,6 +118,10 @@ Expr::Expr(const Expr& expr) _opcode(expr._opcode), _is_slotref(expr._is_slotref), _is_nullable(expr._is_nullable), +<<<<<<< HEAD +======= + _is_monotonic(expr._is_monotonic), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _type(expr._type), _output_scale(expr._output_scale), _fn(expr._fn), @@ -230,6 +258,10 @@ Status Expr::create_expr_tree(ObjectPool* pool, const TExpr& texpr, ExprContext* return status; } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status Expr::prepare_jit_expr(RuntimeState* state, ExprContext* context) { if (this->node_type() == TExprNodeType::JIT_EXPR) { RETURN_IF_ERROR(((JITExpr*)this)->prepare_impl(state, context)); @@ -239,6 +271,10 @@ Status Expr::prepare_jit_expr(RuntimeState* state, ExprContext* context) { } return Status::OK(); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status Expr::create_expr_trees(ObjectPool* pool, const std::vector& texprs, std::vector* ctxs, RuntimeState* state, bool can_jit) { @@ -259,6 +295,10 @@ Status Expr::create_tree_from_thrift_with_jit(ObjectPool* pool, const std::vecto return status; } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool replaced = false; status = (*root_expr)->replace_compilable_exprs(root_expr, pool, state, replaced); if (!status.ok()) { @@ -271,6 +311,10 @@ Status Expr::create_tree_from_thrift_with_jit(ObjectPool* pool, const std::vecto // The node was replaced, so we need to update the context. *ctx = pool->add(new ExprContext(*root_expr)); } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return status; } @@ -378,6 +422,11 @@ Status Expr::create_vectorized_expr(starrocks::ObjectPool* pool, const starrocks case TExprNodeType::FUNCTION_CALL: { if (texpr_node.fn.binary_type == TFunctionBinaryType::SRJAR) { *expr = pool->add(new JavaFunctionCallExpr(texpr_node)); +<<<<<<< HEAD +======= + } else if (texpr_node.fn.binary_type == TFunctionBinaryType::PYTHON) { + *expr = pool->add(new ArrowFunctionCallExpr(texpr_node)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else if (texpr_node.fn.name.function_name == "if") { *expr = pool->add(VectorizedConditionExprFactory::create_if_expr(texpr_node)); } else if (texpr_node.fn.name.function_name == "nullif") { @@ -726,6 +775,10 @@ ColumnRef* Expr::get_column_ref() { return nullptr; } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr Expr::generate_ir(ExprContext* context, JITContext* jit_ctx) { if (this->is_compilable(context->_runtime_state)) { return this->generate_ir_impl(context, jit_ctx); @@ -846,6 +899,10 @@ bool Expr::should_compile(RuntimeState* state) const { } return true; } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool Expr::support_ngram_bloom_filter(ExprContext* context) const { bool support = false; diff --git a/be/src/exprs/expr.h b/be/src/exprs/expr.h index e0d5a74bd1f43..83f337935ec32 100644 --- a/be/src/exprs/expr.h +++ b/be/src/exprs/expr.h @@ -173,8 +173,13 @@ class Expr { /// root_expr: out: root of constructed expr tree /// ctx: out: context of constructed expr tree /// return +<<<<<<< HEAD /// [[nodiscard]] Status.ok() if successful /// ![[nodiscard]] Status.ok() if tree is inconsistent or corrupt +======= + /// Status.ok() if successful + /// !Status.ok() if tree is inconsistent or corrupt +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static Status create_tree_from_thrift(ObjectPool* pool, const std::vector& nodes, Expr* parent, int* node_idx, Expr** root_expr, ExprContext** ctx, RuntimeState* state); @@ -183,18 +188,30 @@ class Expr { RuntimeState* state); /// Convenience function for preparing multiple expr trees. +<<<<<<< HEAD [[nodiscard]] static Status prepare(const std::vector& ctxs, RuntimeState* state); /// Convenience function for opening multiple expr trees. [[nodiscard]] static Status open(const std::vector& ctxs, RuntimeState* state); +======= + static Status prepare(const std::vector& ctxs, RuntimeState* state); + + /// Convenience function for opening multiple expr trees. + static Status open(const std::vector& ctxs, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Clones each ExprContext for multiple expr trees. 'new_ctxs' must be non-NULL. /// Idempotent: if '*new_ctxs' is empty, a clone of each context in 'ctxs' will be added /// to it, and if non-empty, it is assumed CloneIfNotExists() was already called and the /// call is a no-op. The new ExprContexts are created in provided object pool. +<<<<<<< HEAD [[nodiscard]] static Status clone_if_not_exists(RuntimeState* state, ObjectPool* pool, const std::vector& ctxs, std::vector* new_ctxs); +======= + static Status clone_if_not_exists(RuntimeState* state, ObjectPool* pool, const std::vector& ctxs, + std::vector* new_ctxs); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Convenience function for closing multiple expr trees. static void close(const std::vector& ctxs, RuntimeState* state); @@ -210,11 +227,19 @@ class Expr { static Expr* copy(ObjectPool* pool, Expr* old_expr); // for vector query engine +<<<<<<< HEAD [[nodiscard]] virtual StatusOr evaluate_const(ExprContext* context); // TODO: check error in expression and return error [[nodiscard]] Status, instead of return null column [[nodiscard]] virtual StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) = 0; [[nodiscard]] virtual StatusOr evaluate_with_filter(ExprContext* context, Chunk* ptr, uint8_t* filter); +======= + virtual StatusOr evaluate_const(ExprContext* context); + + // TODO: check error in expression and return error Status, instead of return null column + virtual StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) = 0; + virtual StatusOr evaluate_with_filter(ExprContext* context, Chunk* ptr, uint8_t* filter); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // TODO:(murphy) remove this unchecked evaluate ColumnPtr evaluate(ExprContext* context, Chunk* ptr) { return evaluate_checked(context, ptr).value(); } @@ -222,6 +247,10 @@ class Expr { // Get the first column ref in expr. ColumnRef* get_column_ref(); +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr generate_ir(ExprContext* context, JITContext* jit_ctx); virtual StatusOr generate_ir_impl(ExprContext* context, JITContext* jit_ctx); @@ -253,6 +282,10 @@ class Expr { // The valuable expressions get 1 score per expression, others get 0 score per expression, including // comparison expr, logical expr, branch expr, div and mod. virtual JitScore compute_jit_score(RuntimeState* state) const; +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Return true if this expr or any of its children support ngram bloom filter, otherwise return flase virtual bool support_ngram_bloom_filter(ExprContext* context) const; @@ -291,7 +324,11 @@ class Expr { /// /// Subclasses overriding this function should call Expr::Prepare() to recursively call /// Prepare() on the expr tree. +<<<<<<< HEAD [[nodiscard]] virtual Status prepare(RuntimeState* state, ExprContext* context); +======= + virtual Status prepare(RuntimeState* state, ExprContext* context); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Initializes 'context' for execution. If scope if FRAGMENT_LOCAL, both fragment- and /// thread-local state should be initialized. Otherwise, if scope is THREAD_LOCAL, only @@ -299,12 +336,20 @@ class Expr { // /// Subclasses overriding this function should call Expr::Open() to recursively call /// Open() on the expr tree. +<<<<<<< HEAD [[nodiscard]] Status open(RuntimeState* state, ExprContext* context) { return open(state, context, FunctionContext::FRAGMENT_LOCAL); } [[nodiscard]] virtual Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope); +======= + Status open(RuntimeState* state, ExprContext* context) { + return open(state, context, FunctionContext::FRAGMENT_LOCAL); + } + + virtual Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Subclasses overriding this function should call Expr::Close(). // @@ -318,6 +363,14 @@ class Expr { /// Releases cache entries to LibCache in all nodes of the Expr tree. virtual void close(); +<<<<<<< HEAD +======= + // ------------------------------------------------------------------------------------ + // Data Members: + // **NOTE** that when adding a new data member, please check whether it need to be added into `Expr::Expr(const Expr&)`. + // ------------------------------------------------------------------------------------ + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Cache entry for the library implementing this function. std::shared_ptr _cache_entry = nullptr; @@ -363,6 +416,7 @@ class Expr { out << expr_name << "(" << Expr::debug_string() << ")"; return out.str(); } +<<<<<<< HEAD Status prepare_jit_expr(RuntimeState* state, ExprContext* context); @@ -370,6 +424,16 @@ class Expr { // Create a new vectorized expr [[nodiscard]] static Status create_vectorized_expr(ObjectPool* pool, const TExprNode& texpr_node, Expr** expr, RuntimeState* state); +======= +#ifdef STARROCKS_JIT_ENABLE + Status prepare_jit_expr(RuntimeState* state, ExprContext* context); +#endif + +private: + // Create a new vectorized expr + static Status create_vectorized_expr(ObjectPool* pool, const TExprNode& texpr_node, Expr** expr, + RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exprs/expr_context.cpp b/be/src/exprs/expr_context.cpp index bc0a0784ff3ce..c5b3d11e2b753 100644 --- a/be/src/exprs/expr_context.cpp +++ b/be/src/exprs/expr_context.cpp @@ -219,6 +219,10 @@ Status ExprContext::rewrite_jit_expr(ObjectPool* pool) { if (_runtime_state == nullptr || !_runtime_state->is_jit_enabled()) { return Status::OK(); } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool replaced = false; auto st = _root->replace_compilable_exprs(&_root, pool, _runtime_state, replaced); if (!st.ok()) { @@ -229,6 +233,11 @@ Status ExprContext::rewrite_jit_expr(ObjectPool* pool) { if (replaced) { // only prepare jit_expr WARN_IF_ERROR(_root->prepare_jit_expr(_runtime_state, this), "prepare rewritten expr failed"); } +<<<<<<< HEAD +======= +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } diff --git a/be/src/exprs/expr_context.h b/be/src/exprs/expr_context.h index 378dadffa05af..90d5c0d03b219 100644 --- a/be/src/exprs/expr_context.h +++ b/be/src/exprs/expr_context.h @@ -69,14 +69,24 @@ class ExprContext { /// Prepare expr tree for evaluation. /// Allocations from this context will be counted against 'tracker'. +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state); +======= + Status prepare(RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Must be called after calling Prepare(). Does not need to be called on clones. /// Idempotent (this allows exprs to be opened multiple times in subplans without /// reinitializing function state). +<<<<<<< HEAD [[nodiscard]] Status open(RuntimeState* state); [[nodiscard]] static Status open(std::vector input_evals, RuntimeState* state); +======= + Status open(RuntimeState* state); + + static Status open(std::vector input_evals, RuntimeState* state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Creates a copy of this ExprContext. Open() must be called first. The copy contains /// clones of each FunctionContext, which share the fragment-local state of the @@ -84,7 +94,11 @@ class ExprContext { /// to create an ExprContext for each execution thread that needs to evaluate /// 'root'. Note that clones are already opened. '*new_context' must be initialized by /// the caller to NULL. +<<<<<<< HEAD [[nodiscard]] Status clone(RuntimeState* state, ObjectPool* pool, ExprContext** new_context); +======= + Status clone(RuntimeState* state, ObjectPool* pool, ExprContext** new_context); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /// Closes all FunctionContexts. Must be called on every ExprContext, including clones. void close(RuntimeState* state); @@ -110,12 +124,21 @@ class ExprContext { bool opened() { return _opened; } +<<<<<<< HEAD [[nodiscard]] Status get_udf_error(); std::string get_error_msg() const; [[nodiscard]] StatusOr evaluate(Chunk* chunk, uint8_t* filter = nullptr); [[nodiscard]] StatusOr evaluate(Expr* expr, Chunk* chunk, uint8_t* filter = nullptr); +======= + Status get_udf_error(); + + std::string get_error_msg() const; + + StatusOr evaluate(Chunk* chunk, uint8_t* filter = nullptr); + StatusOr evaluate(Expr* expr, Chunk* chunk, uint8_t* filter = nullptr); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool ngram_bloom_filter(const BloomFilter* bf, const NgramBloomFilterReaderOptions& reader_options); bool support_ngram_bloom_filter(); bool is_index_only_filter() const; diff --git a/be/src/exprs/function_call_expr.cpp b/be/src/exprs/function_call_expr.cpp index 988c05d4896cc..2fa66a4f46e3e 100644 --- a/be/src/exprs/function_call_expr.cpp +++ b/be/src/exprs/function_call_expr.cpp @@ -20,7 +20,10 @@ #include "column/column_helper.h" #include "column/const_column.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/builtin_functions.h" #include "exprs/expr_context.h" #include "gutil/strings/substitute.h" @@ -40,6 +43,7 @@ DEFINE_FAIL_POINT(expr_prepare_fragment_thread_local_call_failed); VectorizedFunctionCallExpr::VectorizedFunctionCallExpr(const TExprNode& node) : Expr(node) {} +<<<<<<< HEAD Status VectorizedFunctionCallExpr::prepare(starrocks::RuntimeState* state, starrocks::ExprContext* context) { RETURN_IF_ERROR(Expr::prepare(state, context)); @@ -61,6 +65,63 @@ Status VectorizedFunctionCallExpr::prepare(starrocks::RuntimeState* state, starr _fn_desc = BuiltinFunctions::find_builtin_function(fid); +======= +const FunctionDescriptor* VectorizedFunctionCallExpr::_get_function_by_fid(const TFunction& fn) { + // branch-3.0 is 150102~150104, branch-3.1 is 150103~150105 + // refs: https://github.com/StarRocks/starrocks/pull/17803 + // @todo: remove this code when branch-3.0 is deprecated + int64_t fid = fn.fid; + if (fn.fid == 150102 && _type.type == TYPE_ARRAY && _type.children[0].type == TYPE_DECIMAL32) { + fid = 150103; + } else if (fn.fid == 150103 && _type.type == TYPE_ARRAY && _type.children[0].type == TYPE_DECIMAL64) { + fid = 150104; + } else if (fn.fid == 150104 && _type.type == TYPE_ARRAY && _type.children[0].type == TYPE_DECIMAL128) { + fid = 150105; + } + return BuiltinFunctions::find_builtin_function(fid); +} + +const FunctionDescriptor* VectorizedFunctionCallExpr::_get_function(const TFunction& fn, + const std::vector& arg_types, + const TypeDescriptor& return_type, + std::vector arg_nullables) { + if (fn.__isset.agg_state_desc) { + // For _state combinator function, it's created according to the agg_state_desc rather than fid. + auto agg_state_desc = AggStateDesc::from_thrift(fn.agg_state_desc); + _agg_state_func = std::make_shared(agg_state_desc, return_type, std::move(arg_nullables)); + auto execute_func = std::bind(&AggStateFunction::execute, _agg_state_func.get(), std::placeholders::_1, + std::placeholders::_2); + auto prepare_func = std::bind(&AggStateFunction::prepare, _agg_state_func.get(), std::placeholders::_1, + std::placeholders::_2); + auto close_func = std::bind(&AggStateFunction::close, _agg_state_func.get(), std::placeholders::_1, + std::placeholders::_2); + _agg_func_desc = std::make_shared(fn.name.function_name, arg_types.size(), execute_func, + prepare_func, close_func, true, false); + return _agg_func_desc.get(); + } else { + return _get_function_by_fid(fn); + } +} + +Status VectorizedFunctionCallExpr::prepare(starrocks::RuntimeState* state, starrocks::ExprContext* context) { + RETURN_IF_ERROR(Expr::prepare(state, context)); + + // parpare result type and arg types + FunctionContext::TypeDesc return_type = _type; + if (!_fn.__isset.fid && !_fn.__isset.agg_state_desc) { + return Status::InternalError("Vectorized engine doesn't implement agg state function " + + _fn.name.function_name); + } + std::vector args_types; + std::vector arg_nullblaes; + for (Expr* child : _children) { + args_types.push_back(child->type()); + arg_nullblaes.emplace_back(child->is_nullable()); + } + + // initialize function descriptor + _fn_desc = _get_function(_fn, args_types, return_type, arg_nullblaes); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_fn_desc == nullptr || _fn_desc->scalar_function == nullptr) { return Status::InternalError("Vectorized engine doesn't implement function " + _fn.name.function_name); } @@ -74,6 +135,7 @@ Status VectorizedFunctionCallExpr::prepare(starrocks::RuntimeState* state, starr FAIL_POINT_TRIGGER_RETURN_ERROR(random_error); FAIL_POINT_TRIGGER_RETURN_ERROR(expr_prepare_failed); +<<<<<<< HEAD FunctionContext::TypeDesc return_type = AnyValUtil::column_type_to_type_desc(_type); std::vector args_types; @@ -81,6 +143,8 @@ Status VectorizedFunctionCallExpr::prepare(starrocks::RuntimeState* state, starr args_types.push_back(AnyValUtil::column_type_to_type_desc(child->type())); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // todo: varargs use for allocate slice memory, need compute buffer size // for varargs in vectorized engine? _fn_context_index = context->register_func(state, return_type, args_types); @@ -192,11 +256,15 @@ StatusOr VectorizedFunctionCallExpr::evaluate_checked(starrocks::Expr } RETURN_IF_ERROR(result); if (_fn_desc->check_overflow) { +<<<<<<< HEAD std::string err_msg; if (UNLIKELY(result.value()->capacity_limit_reached(&err_msg))) { return Status::InternalError( fmt::format("Result column of function {} exceed limit: {}", _fn_desc->name, err_msg)); } +======= + RETURN_IF_ERROR(result.value()->capacity_limit_reached()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // For no args function call (pi, e) diff --git a/be/src/exprs/function_call_expr.h b/be/src/exprs/function_call_expr.h index 98dee447ab0c8..b02dd7095373a 100644 --- a/be/src/exprs/function_call_expr.h +++ b/be/src/exprs/function_call_expr.h @@ -15,6 +15,10 @@ #pragma once #include "common/object_pool.h" +<<<<<<< HEAD +======= +#include "exprs/agg_state_function.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/builtin_functions.h" #include "exprs/expr.h" @@ -43,21 +47,45 @@ class VectorizedFunctionCallExpr final : public Expr { std::vector& ngram_set); protected: +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state, ExprContext* context) override; [[nodiscard]] Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; +======= + Status prepare(RuntimeState* state, ExprContext* context) override; + + Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; bool is_constant() const override; +<<<<<<< HEAD [[nodiscard]] StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; private: const FunctionDescriptor* _fn_desc{nullptr}; bool _is_returning_random_value = false; +======= + StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; + +private: + const FunctionDescriptor* _get_function_by_fid(const TFunction& fn); + const FunctionDescriptor* _get_function(const TFunction& fn, const std::vector& arg_types, + const TypeDescriptor& result_type, std::vector arg_nullables); + + const FunctionDescriptor* _fn_desc{nullptr}; + + bool _is_returning_random_value = false; + + // only set when it's a agg state combinator function to track its lifecycle be with the expr + std::shared_ptr _agg_state_func = nullptr; + // only set when it's a agg state combinator function to track its lifecycle be with the expr + std::shared_ptr _agg_func_desc = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exprs/function_context.cpp b/be/src/exprs/function_context.cpp index e9112328a9c04..06a36dd8b0aca 100644 --- a/be/src/exprs/function_context.cpp +++ b/be/src/exprs/function_context.cpp @@ -196,12 +196,17 @@ bool FunctionContext::add_warning(const char* warning_msg) { std::stringstream ss; ss << "UDF WARNING: " << warning_msg; +<<<<<<< HEAD if (_state != nullptr) { return _state->log_error(ss.str()); } else { std::cerr << ss.str() << std::endl; return true; } +======= + std::cerr << ss.str() << std::endl; + return true; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } const FunctionContext::TypeDesc* FunctionContext::get_arg_type(int arg_idx) const { diff --git a/be/src/exprs/function_context.h b/be/src/exprs/function_context.h index 82e5388cd8d9f..771a56c3f847d 100644 --- a/be/src/exprs/function_context.h +++ b/be/src/exprs/function_context.h @@ -22,6 +22,11 @@ #include #include +<<<<<<< HEAD +======= +#include "common/status.h" +#include "runtime/types.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type.h" namespace starrocks { @@ -37,6 +42,7 @@ using ColumnPtr = std::shared_ptr; class FunctionContext { public: +<<<<<<< HEAD struct TypeDesc { ::starrocks::LogicalType type = ::starrocks::TYPE_NULL; @@ -54,6 +60,9 @@ class FunctionContext { std::vector children; std::vector field_names; }; +======= + using TypeDesc = TypeDescriptor; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) enum FunctionStateScope { /// Indicates that the function state for this FunctionContext's UDF is shared across @@ -135,6 +144,11 @@ class FunctionContext { // the FunctionContext* argument). Returns NULL if arg_idx is invalid. const TypeDesc* get_arg_type(int arg_idx) const; +<<<<<<< HEAD +======= + const std::vector& get_arg_types() const { return _arg_types; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_constant_column(int arg_idx) const; // Return true if it's constant and not null @@ -160,8 +174,22 @@ class FunctionContext { void set_constant_columns(std::vector columns) { _constant_columns = std::move(columns); } MemPool* mem_pool() { return _mem_pool; } +<<<<<<< HEAD size_t mem_usage() { return _mem_usage; } void add_mem_usage(size_t size) { _mem_usage += size; } +======= + + void set_mem_usage_counter(int64_t* mem_usage_counter) { _mem_usage_counter = mem_usage_counter; } + + int64_t mem_usage() const { + DCHECK(_mem_usage_counter); + return *_mem_usage_counter; + } + void add_mem_usage(int64_t delta) { + DCHECK(_mem_usage_counter); + *_mem_usage_counter += delta; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeState* state() { return _state; } bool has_error() const; @@ -213,8 +241,17 @@ class FunctionContext { // Indicates whether this context has been closed. Used for verification/debugging. bool _is_udf = false; +<<<<<<< HEAD // this is used for count memory usage of aggregate state size_t _mem_usage = 0; +======= + int64_t _mem_usage = 0; + // This is used to count the memory usage of the agg state. + // In Aggregator, multiple FunctionContexts can share the same counter. + // If it is not explicitly set externally (e.g. AggFuncBasedValueAggregator), + // it will point to the internal _mem_usage + int64_t* _mem_usage_counter = &_mem_usage; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // UDAF Context std::unique_ptr _jvm_udaf_ctxs; diff --git a/be/src/exprs/function_helper.cpp b/be/src/exprs/function_helper.cpp index bd20dcd2ccba4..b2afb06d2341d 100644 --- a/be/src/exprs/function_helper.cpp +++ b/be/src/exprs/function_helper.cpp @@ -14,12 +14,19 @@ #include "function_helper.h" +<<<<<<< HEAD #ifdef __x86_64__ #include #endif #include +======= +#include + +#include "simd/multi_version.h" + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { NullColumnPtr FunctionHelper::union_nullable_column(const ColumnPtr& v1, const ColumnPtr& v2) { @@ -82,6 +89,56 @@ void FunctionHelper::union_produce_nullable_column(const ColumnPtr& v1, NullColu } } +<<<<<<< HEAD +======= +MFV_AVX512(void union_null_column_impl(uint8_t* dest, const uint8_t* v1, const uint8_t* v2, const size_t bytes) { + constexpr auto SIMD_SIZE = sizeof(__m512i); + const auto null1_end = v1 + bytes; + const auto null1_simd_end = v1 + (bytes & ~(SIMD_SIZE - 1)); + + for (; v1 < null1_simd_end; v1 += SIMD_SIZE, v2 += SIMD_SIZE, dest += SIMD_SIZE) { + _mm512_storeu_si512((__m512i*)dest, + _mm512_or_si512(_mm512_loadu_si512((__m512i*)v1), _mm512_loadu_si512((__m512i*)v2))); + } + for (; v1 < null1_end; ++v1, ++v2, ++dest) { + *dest = *v1 | *v2; + } +}) + +MFV_AVX2(void union_null_column_impl(uint8_t* dest, const uint8_t* v1, const uint8_t* v2, const size_t bytes) { + constexpr auto SIMD_SIZE = sizeof(__m256i); + const auto null1_end = v1 + bytes; + const auto null1_simd_end = v1 + (bytes & ~(SIMD_SIZE - 1)); + + for (; v1 < null1_simd_end; v1 += SIMD_SIZE, v2 += SIMD_SIZE, dest += SIMD_SIZE) { + _mm256_storeu_si256((__m256i*)dest, + _mm256_or_si256(_mm256_loadu_si256((__m256i*)v1), _mm256_loadu_si256((__m256i*)v2))); + } + for (; v1 < null1_end; ++v1, ++v2, ++dest) { + *dest = *v1 | *v2; + } +}) + +MFV_SSE42(void union_null_column_impl(uint8_t* dest, const uint8_t* v1, const uint8_t* v2, const size_t bytes) { + constexpr auto SIMD_SIZE = sizeof(__m128i); + const auto null1_end = v1 + bytes; + const auto null1_simd_end = v1 + (bytes & ~(SIMD_SIZE - 1)); + + for (; v1 < null1_simd_end; v1 += SIMD_SIZE, v2 += SIMD_SIZE, dest += SIMD_SIZE) { + _mm_storeu_si128((__m128i*)dest, _mm_or_si128(_mm_loadu_si128((__m128i*)v1), _mm_loadu_si128((__m128i*)v2))); + } + for (; v1 < null1_end; ++v1, ++v2, ++dest) { + *dest = *v1 | *v2; + } +}) + +MFV_DEFAULT(void union_null_column_impl(uint8_t* dest, const uint8_t* v1, const uint8_t* v2, const size_t bytes) { + for (const auto null1_end = v1 + bytes; v1 < null1_end; ++v1, ++v2, ++dest) { + *dest = *v1 | *v2; + } +}) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) NullColumnPtr FunctionHelper::union_null_column(const NullColumnPtr& v1, const NullColumnPtr& v2) { // union null column auto null1_begin = (uint8_t*)v1->get_data().data(); @@ -94,6 +151,7 @@ NullColumnPtr FunctionHelper::union_null_column(const NullColumnPtr& v1, const N raw::make_room(&result_data, row_num); auto result_begin = (uint8_t*)result_data.data(); const size_t bytes_size = sizeof(NullColumn::ValueType) * row_num; +<<<<<<< HEAD const auto null1_end = null1_begin + bytes_size; auto null1_curr = null1_begin; @@ -117,6 +175,10 @@ NullColumnPtr FunctionHelper::union_null_column(const NullColumnPtr& v1, const N for (; null1_curr < null1_end; ++null1_curr, ++null2_curr, ++result_curr) { *result_curr = *null1_curr | *null2_curr; } +======= + + union_null_column_impl(result_begin, null1_begin, null2_begin, bytes_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return null_result; } diff --git a/be/src/exprs/function_helper.h b/be/src/exprs/function_helper.h index 8b7c04a84f9f8..6f76e42c5a4e9 100644 --- a/be/src/exprs/function_helper.h +++ b/be/src/exprs/function_helper.h @@ -17,6 +17,10 @@ #include "column/column_helper.h" #include "column/const_column.h" #include "column/type_traits.h" +<<<<<<< HEAD +======= +#include "gutil/casts.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { class FunctionContext; @@ -38,6 +42,24 @@ class FunctionHelper { } /** +<<<<<<< HEAD +======= + * get data of column. + * @param col, row_num, data + */ + template + static void get_data_of_column(const Column* col, size_t row_num, CppType& data) { + if (col->is_constant()) { + auto const_col = down_cast(col); + col = const_col->data_column().get(); + row_num = 0; + } + const auto* column = down_cast(col); + data = column->get_data()[row_num]; + } + + /** +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) * if ptr is ConstColumn, return data column * else return ptr * @param ptr diff --git a/be/src/exprs/in_const_predicate.hpp b/be/src/exprs/in_const_predicate.hpp index bc55775ce378b..5c60b2b88361e 100644 --- a/be/src/exprs/in_const_predicate.hpp +++ b/be/src/exprs/in_const_predicate.hpp @@ -85,7 +85,11 @@ class VectorizedInConstPredicate final : public Predicate { Type == TYPE_BIGINT; } +<<<<<<< HEAD [[nodiscard]] Status prepare([[maybe_unused]] RuntimeState* state) { +======= + Status prepare([[maybe_unused]] RuntimeState* state) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_is_prepare) { return Status::OK(); } @@ -95,7 +99,11 @@ class VectorizedInConstPredicate final : public Predicate { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status merge(Predicate* predicate) override { +======= + Status merge(Predicate* predicate) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (auto* that = dynamic_cast(predicate)) { const auto& hash_set = that->hash_set(); _hash_set.insert(hash_set.begin(), hash_set.end()); @@ -107,7 +115,11 @@ class VectorizedInConstPredicate final : public Predicate { } } +<<<<<<< HEAD [[nodiscard]] Status prepare(RuntimeState* state, ExprContext* context) override { +======= + Status prepare(RuntimeState* state, ExprContext* context) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(Expr::prepare(state, context)); if (_is_prepare) { @@ -128,8 +140,12 @@ class VectorizedInConstPredicate final : public Predicate { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override { +======= + Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(Expr::open(state, context, scope)); if (scope == FunctionContext::FRAGMENT_LOCAL) { if (Type != _children[0]->type().type) { @@ -436,8 +452,12 @@ class VectorizedInConstPredicateGeneric final : public Predicate { Expr* clone(ObjectPool* pool) const override { return pool->add(new VectorizedInConstPredicateGeneric(*this)); } +<<<<<<< HEAD [[nodiscard]] Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override { +======= + Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(Expr::open(state, context, scope)); if (scope == FunctionContext::FRAGMENT_LOCAL) { _const_input.resize(_children.size()); @@ -548,7 +568,11 @@ class VectorizedInConstPredicateBuilder { VectorizedInConstPredicateBuilder(RuntimeState* state, ObjectPool* pool, Expr* expr) : _state(state), _pool(pool), _expr(expr) {} +<<<<<<< HEAD [[nodiscard]] Status create(); +======= + Status create(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void add_values(const ColumnPtr& column, size_t column_offset); void use_array_set(size_t array_size) { _array_size = array_size; } void use_as_join_runtime_filter() { _is_join_runtime_filter = true; } diff --git a/be/src/exprs/inet_aton.cpp b/be/src/exprs/inet_aton.cpp new file mode 100644 index 0000000000000..352207b11cc63 --- /dev/null +++ b/be/src/exprs/inet_aton.cpp @@ -0,0 +1,48 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "common/format_ip.h" +#include "exprs/string_functions.h" + +namespace starrocks { + +static inline bool try_parse_ipv4(const char* pos, size_t str_len, int64& result_value) { + return parse_ipv4(pos, str_len, result_value); +} + +StatusOr StringFunctions::inet_aton(FunctionContext* context, const Columns& columns) { + RETURN_IF_COLUMNS_ONLY_NULL(columns); + + auto str_viewer = ColumnViewer(columns[0]); + auto size = columns[0]->size(); + + ColumnBuilder result(size); + for (int row = 0; row < size; row++) { + if (str_viewer.is_null(row)) { + result.append_null(); + continue; + } + + auto str_value = str_viewer.value(row); + int64_t parsed_result; + if (try_parse_ipv4(str_value.get_data(), str_value.get_size(), parsed_result)) { + result.append(parsed_result); + } else { + result.append_null(); + } + } + return result.build(ColumnHelper::is_all_const(columns)); +} + +} // namespace starrocks diff --git a/be/src/exprs/java_function_call_expr.cpp b/be/src/exprs/java_function_call_expr.cpp index 0d783f5943590..bf5e4500594b5 100644 --- a/be/src/exprs/java_function_call_expr.cpp +++ b/be/src/exprs/java_function_call_expr.cpp @@ -27,7 +27,10 @@ #include "column/vectorized_fwd.h" #include "common/status.h" #include "common/statusor.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/function_context.h" #include "gutil/casts.h" #include "jni.h" @@ -133,11 +136,19 @@ Status JavaFunctionCallExpr::prepare(RuntimeState* state, ExprContext* context) return Status::InternalError("Not Found function id for " + _fn.name.function_name); } +<<<<<<< HEAD FunctionContext::TypeDesc return_type = AnyValUtil::column_type_to_type_desc(_type); std::vector args_types; for (Expr* child : _children) { args_types.push_back(AnyValUtil::column_type_to_type_desc(child->type())); +======= + FunctionContext::TypeDesc return_type = _type; + std::vector args_types; + + for (Expr* child : _children) { + args_types.push_back(child->type()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // todo: varargs use for allocate slice memory, need compute buffer size diff --git a/be/src/exprs/java_function_call_expr.h b/be/src/exprs/java_function_call_expr.h index 200e238b9d36c..09221e37094cb 100644 --- a/be/src/exprs/java_function_call_expr.h +++ b/be/src/exprs/java_function_call_expr.h @@ -29,10 +29,16 @@ class JavaFunctionCallExpr final : public Expr { ~JavaFunctionCallExpr() override; Expr* clone(ObjectPool* pool) const override { return pool->add(new JavaFunctionCallExpr(*this)); } +<<<<<<< HEAD [[nodiscard]] StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; [[nodiscard]] Status prepare(RuntimeState* state, ExprContext* context) override; [[nodiscard]] Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; +======= + StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; + Status prepare(RuntimeState* state, ExprContext* context) override; + Status open(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close(RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) override; bool is_constant() const override; diff --git a/be/src/exprs/jit/jit_expr.cpp b/be/src/exprs/jit/jit_expr.cpp index efd73a54b175f..9acdbc9db6465 100644 --- a/be/src/exprs/jit/jit_expr.cpp +++ b/be/src/exprs/jit/jit_expr.cpp @@ -24,7 +24,10 @@ #include "common/compiler_util.h" #include "common/status.h" #include "exec/pipeline/fragment_context.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr.h" #include "exprs/function_context.h" #include "exprs/jit/jit_engine.h" diff --git a/be/src/exprs/json_functions.h b/be/src/exprs/json_functions.h index fae58cb77bbd5..e8567a8a3ff98 100644 --- a/be/src/exprs/json_functions.h +++ b/be/src/exprs/json_functions.h @@ -65,8 +65,13 @@ struct SimpleJsonPath { class JsonFunctions { public: +<<<<<<< HEAD [[nodiscard]] static Status json_path_prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope); [[nodiscard]] static Status json_path_close(FunctionContext* context, FunctionContext::FunctionStateScope scope); +======= + static Status json_path_prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope); + static Status json_path_close(FunctionContext* context, FunctionContext::FunctionStateScope scope); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /** * @param: [json_string, tagged_value] @@ -161,6 +166,7 @@ class JsonFunctions { */ DEFINE_VECTORIZED_FN(to_json); +<<<<<<< HEAD [[nodiscard]] static Status native_json_path_prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope); [[nodiscard]] static Status native_json_path_close(FunctionContext* context, @@ -174,6 +180,17 @@ class JsonFunctions { [[nodiscard]] static Status parse_json_paths(const std::string& path_strings, std::vector* parsed_paths); +======= + static Status native_json_path_prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope); + static Status native_json_path_close(FunctionContext* context, FunctionContext::FunctionStateScope scope); + + // extract_from_object extracts value from object according to the json path. + // Now, we do not support complete functions of json path. + static Status extract_from_object(simdjson::ondemand::object& obj, const std::vector& jsonpath, + simdjson::ondemand::value* value) noexcept; + + static Status parse_json_paths(const std::string& path_strings, std::vector* parsed_paths); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // jsonpaths_to_string serializes json patsh to std::string. Setting sub_index to serializes paritially json paths. static std::string jsonpaths_to_string(const std::vector& jsonpaths, size_t sub_index = -1); @@ -189,7 +206,11 @@ class JsonFunctions { private: template +<<<<<<< HEAD [[nodiscard]] static StatusOr _json_query_impl(FunctionContext* context, const Columns& columns); +======= + static StatusOr _json_query_impl(FunctionContext* context, const Columns& columns); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template DEFINE_VECTORIZED_FN(_flat_json_query_impl); @@ -229,8 +250,13 @@ class JsonFunctions { * @return: JsonColumn */ +<<<<<<< HEAD [[nodiscard]] static Status _get_parsed_paths(const std::vector& path_exprs, std::vector* parsed_paths); +======= + static Status _get_parsed_paths(const std::vector& path_exprs, + std::vector* parsed_paths); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exprs/like_predicate.cpp b/be/src/exprs/like_predicate.cpp index 8ac13609ad0ba..bedb4cf15dcd1 100644 --- a/be/src/exprs/like_predicate.cpp +++ b/be/src/exprs/like_predicate.cpp @@ -351,7 +351,11 @@ StatusOr LikePredicate::constant_substring_fn(FunctionContext* contex size_t type_size = res->type_size(); memset(res->mutable_raw_data(), 1, res->size() * type_size); } else { +<<<<<<< HEAD const std::vector& offsets = haystack->get_offset(); +======= + const Buffer& offsets = haystack->get_offset(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) res->resize(haystack->size()); const char* begin = haystack->get_slice(0).data; diff --git a/be/src/exprs/literal.cpp b/be/src/exprs/literal.cpp index af9027e3bf5f3..600b95e921d99 100644 --- a/be/src/exprs/literal.cpp +++ b/be/src/exprs/literal.cpp @@ -19,11 +19,21 @@ #include "column/const_column.h" #include "column/vectorized_fwd.h" #include "common/statusor.h" +<<<<<<< HEAD #include "exprs/jit/ir_helper.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/port.h" #include "gutil/strings/fastmem.h" #include "types/constexpr.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include "exprs/jit/ir_helper.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { #define CASE_TYPE_COLUMN(NODE_TYPE, CHECK_TYPE, LITERAL_VALUE) \ @@ -165,6 +175,11 @@ StatusOr VectorizedLiteral::evaluate_checked(ExprContext* context, Ch return column; } +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool VectorizedLiteral::is_compilable(RuntimeState* state) const { return IRHelper::support_jit(_type.type); } @@ -187,6 +202,10 @@ StatusOr VectorizedLiteral::generate_ir_impl(ExprContext* context, JI } return datum; } +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string VectorizedLiteral::debug_string() const { std::stringstream out; diff --git a/be/src/exprs/literal.h b/be/src/exprs/literal.h index 7c34dc497750a..0cdc46a466d9e 100644 --- a/be/src/exprs/literal.h +++ b/be/src/exprs/literal.h @@ -30,6 +30,10 @@ class VectorizedLiteral final : public Expr { StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override; +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_compilable(RuntimeState* state) const override; JitScore compute_jit_score(RuntimeState* state) const override; @@ -37,7 +41,11 @@ class VectorizedLiteral final : public Expr { std::string jit_func_name_impl(RuntimeState* state) const override; StatusOr generate_ir_impl(ExprContext* context, JITContext* jit_ctx) override; +<<<<<<< HEAD +======= +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_literal() const override { return true; } std::string debug_string() const override; diff --git a/be/src/exprs/locate.cpp b/be/src/exprs/locate.cpp index 7d7b6f6766ad1..4ddcb6bea4ac7 100644 --- a/be/src/exprs/locate.cpp +++ b/be/src/exprs/locate.cpp @@ -79,7 +79,11 @@ ColumnPtr haystack_vector_and_needle_const(const ColumnPtr& haystack_ptr, const start_pos = ColumnHelper::as_raw_column>(start_pos_expansion); } +<<<<<<< HEAD const std::vector& offsets = haystack->get_offset(); +======= + const Buffer& offsets = haystack->get_offset(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Slice needle = ColumnHelper::get_const_value(needle_ptr); auto res = RunTimeColumnType::create(); res->resize(haystack->size()); diff --git a/be/src/exprs/map_apply_expr.cpp b/be/src/exprs/map_apply_expr.cpp index d2ebcc7c74b15..933286d99ff68 100644 --- a/be/src/exprs/map_apply_expr.cpp +++ b/be/src/exprs/map_apply_expr.cpp @@ -22,7 +22,10 @@ #include "column/fixed_length_column.h" #include "column/map_column.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exprs/anyval_util.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr_context.h" #include "exprs/function_helper.h" #include "exprs/lambda_function.h" diff --git a/be/src/exprs/map_functions.cpp b/be/src/exprs/map_functions.cpp index 6f62be18fb799..a1422cad15b19 100644 --- a/be/src/exprs/map_functions.cpp +++ b/be/src/exprs/map_functions.cpp @@ -254,7 +254,11 @@ void MapFunctions::_filter_map_items(const MapColumn* src_column, const ColumnPt } else { filter = down_cast(raw_filter.get()); } +<<<<<<< HEAD std::vector indexes; +======= + Buffer indexes; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // only keep the elements whose filter is not null and not 0. for (size_t i = 0; i < src_column->size(); ++i) { if (dest_null_map == nullptr || !dest_null_map->get_data()[i]) { // dest_null_map[i] is not null diff --git a/be/src/exprs/math_functions.cpp b/be/src/exprs/math_functions.cpp index 361036d8f6243..e28f915d21a38 100644 --- a/be/src/exprs/math_functions.cpp +++ b/be/src/exprs/math_functions.cpp @@ -886,7 +886,10 @@ StatusOr MathFunctions::cosine_similarity(FunctionContext* context, c target_sum += target_data[j] * target_data[j]; } } +<<<<<<< HEAD +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if constexpr (!isNorm) { result_value = sum / (std::sqrt(base_sum) * std::sqrt(target_sum)); } else { @@ -899,10 +902,120 @@ StatusOr MathFunctions::cosine_similarity(FunctionContext* context, c return result; } +<<<<<<< HEAD // explicitly instaniate template function. +======= +// explicitly instantiate template function. +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template StatusOr MathFunctions::cosine_similarity(FunctionContext* context, const Columns& columns); template StatusOr MathFunctions::cosine_similarity(FunctionContext* context, const Columns& columns); +<<<<<<< HEAD +======= +template +StatusOr MathFunctions::l2_distance(FunctionContext* context, const Columns& columns) { + DCHECK_EQ(columns.size(), 2); + + const Column* base = columns[0].get(); + const Column* target = columns[1].get(); + size_t target_size = target->size(); + if (base->size() != target_size) { + return Status::InvalidArgument(fmt::format( + "l2_distance requires equal length arrays. base array size is {} and target array size is {}.", + base->size(), target->size())); + } + if (base->has_null() || target->has_null()) { + return Status::InvalidArgument(fmt::format("l2_distance does not support null values. {} array has null value.", + base->has_null() ? "base" : "target")); + } + if (base->is_constant()) { + auto* const_column = down_cast(base); + const_column->data_column()->assign(base->size(), 0); + base = const_column->data_column().get(); + } + if (target->is_constant()) { + auto* const_column = down_cast(target); + const_column->data_column()->assign(target->size(), 0); + target = const_column->data_column().get(); + } + if (base->is_nullable()) { + base = down_cast(base)->data_column().get(); + } + if (target->is_nullable()) { + target = down_cast(target)->data_column().get(); + } + + // check dimension equality. + const Column* base_flat = down_cast(base)->elements_column().get(); + const uint32_t* base_offset = down_cast(base)->offsets().get_data().data(); + size_t base_flat_size = base_flat->size(); + + const Column* target_flat = down_cast(target)->elements_column().get(); + size_t target_flat_size = target_flat->size(); + const uint32_t* target_offset = down_cast(target)->offsets().get_data().data(); + + if (base_flat_size != target_flat_size) { + return Status::InvalidArgument("l2_distance requires equal length arrays"); + } + + if (base_flat->has_null() || target_flat->has_null()) { + return Status::InvalidArgument("l2_distance does not support null values"); + } + if (base_flat->is_nullable()) { + base_flat = down_cast(base_flat)->data_column().get(); + } + if (target_flat->is_nullable()) { + target_flat = down_cast(target_flat)->data_column().get(); + } + + using CppType = RunTimeCppType; + using ColumnType = RunTimeColumnType; + + const CppType* base_data_head = down_cast(base_flat)->get_data().data(); + const CppType* target_data_head = down_cast(target_flat)->get_data().data(); + + // prepare result with nullable value. + ColumnPtr result = ColumnHelper::create_column(TypeDescriptor{TYPE}, false, false, target_size); + ColumnType* data_result = down_cast(result.get()); + CppType* result_data = data_result->get_data().data(); + + for (size_t i = 0; i < target_size; i++) { + size_t t_dim_size = target_offset[i + 1] - target_offset[i]; + size_t b_dim_size = base_offset[i + 1] - base_offset[i]; + if (t_dim_size != b_dim_size) { + return Status::InvalidArgument( + fmt::format("l2_distance requires equal length arrays in each row. base array dimension size " + "is {}, target array dimension size is {}.", + b_dim_size, t_dim_size)); + } + if (t_dim_size == 0) { + return Status::InvalidArgument("l2_distance requires non-empty arrays in each row"); + } + } + + const CppType* target_data = target_data_head; + const CppType* base_data = base_data_head; + + for (size_t i = 0; i < target_size; i++) { + CppType sum = 0; + size_t dim_size = target_offset[i + 1] - target_offset[i]; + for (size_t j = 0; j < dim_size; j++) { + CppType distance; + distance = (base_data[j] - target_data[j]) * (base_data[j] - target_data[j]); + sum += distance; + } + result_data[i] = sum; + target_data += dim_size; + base_data += dim_size; + } + + return result; +} + +// explicitly instantiate template function. +template StatusOr MathFunctions::l2_distance(FunctionContext* context, const Columns& columns); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exprs/math_functions.h b/be/src/exprs/math_functions.h index 6a5b3abc850aa..bba1d4073d8dc 100644 --- a/be/src/exprs/math_functions.h +++ b/be/src/exprs/math_functions.h @@ -167,6 +167,18 @@ class MathFunctions { template DEFINE_VECTORIZED_FN(cosine_similarity); +<<<<<<< HEAD +======= + template + DEFINE_VECTORIZED_FN(cosine_similarity2); + + template + DEFINE_VECTORIZED_FN(l2_distance); + + template + DEFINE_VECTORIZED_FN(l2_distance2); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /** * @param columns: [DoubleColumn] * @return BigIntColumn diff --git a/be/src/exprs/min_max_predicate.h b/be/src/exprs/min_max_predicate.h new file mode 100644 index 0000000000000..c7015acc46085 --- /dev/null +++ b/be/src/exprs/min_max_predicate.h @@ -0,0 +1,150 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "column/chunk.h" +#include "column/column_helper.h" +#include "column/type_traits.h" +#include "exprs/expr.h" +#include "exprs/runtime_filter.h" +#include "types/large_int_value.h" + +namespace starrocks { +template +class MinMaxPredicate : public Expr { +public: + using CppType = RunTimeCppType; + MinMaxPredicate(SlotId slot_id, const CppType& min_value, const CppType& max_value, bool has_null) + : Expr(TypeDescriptor(Type), false), + _slot_id(slot_id), + _min_value(min_value), + _max_value(max_value), + _has_null(has_null) { + _node_type = TExprNodeType::RUNTIME_FILTER_MIN_MAX_EXPR; + } + ~MinMaxPredicate() override = default; + Expr* clone(ObjectPool* pool) const override { + return pool->add(new MinMaxPredicate(_slot_id, _min_value, _max_value, _has_null)); + } + + bool is_constant() const override { return false; } + bool is_bound(const std::vector& tuple_ids) const override { return false; } + bool has_null() const { return _has_null; } + + StatusOr evaluate_with_filter(ExprContext* context, Chunk* ptr, uint8_t* filter) override { + const ColumnPtr col = ptr->get_column_by_slot_id(_slot_id); + size_t size = col->size(); + + std::shared_ptr result(new BooleanColumn(size, 1)); + uint8_t* res = result->get_data().data(); + + if (col->only_null()) { + if (!_has_null) { + memset(res, 0x0, size); + } + return result; + } + + if (col->is_constant()) { + CppType value = ColumnHelper::get_const_value(col); + if (!(value >= _min_value && value <= _max_value)) { + memset(res, 0x0, size); + } + return result; + } + + // NOTE(yan): make sure following code can be compiled into SIMD instructions: + // in original version, we use + // 1. memcpy filter -> res + // 2. res[i] = res[i] && (null_data[i] || (data[i] >= _min_value && data[i] <= _max_value)); + // but they can not be compiled into SIMD instructions. + if (col->is_nullable() && col->has_null()) { + auto tmp = ColumnHelper::as_raw_column(col); + uint8_t* __restrict__ null_data = tmp->null_column_data().data(); + CppType* __restrict__ data = ColumnHelper::cast_to_raw(tmp->data_column())->get_data().data(); + for (int i = 0; i < size; i++) { + res[i] = (data[i] >= _min_value && data[i] <= _max_value); + } + + if (_has_null) { + for (int i = 0; i < size; i++) { + res[i] = res[i] | null_data[i]; + } + } else { + for (int i = 0; i < size; i++) { + res[i] = res[i] & !null_data[i]; + } + } + } else { + const CppType* __restrict__ data = + ColumnHelper::get_data_column_by_type(col.get())->get_data().data(); + for (int i = 0; i < size; i++) { + res[i] = (data[i] >= _min_value && data[i] <= _max_value); + } + } + + // NOTE(yan): filter can be used optionally. + // if (filter != nullptr) { + // for (int i = 0; i < size; i++) { + // res[i] = res[i] & filter[i]; + // } + // } + + return result; + } + + StatusOr evaluate_checked(ExprContext* context, Chunk* ptr) override { + return evaluate_with_filter(context, ptr, nullptr); + } + + int get_slot_ids(std::vector* slot_ids) const override { + slot_ids->emplace_back(_slot_id); + return 1; + } + + std::string debug_string() const override { + std::stringstream out; + auto expr_debug_string = Expr::debug_string(); + out << "MinMaxPredicate (type=" << Type << ", slot_id=" << _slot_id << ", has_null=" << _has_null + << ", min=" << _min_value << ", max=" << _max_value << ", expr(" << expr_debug_string << "))"; + return out.str(); + } + +private: + SlotId _slot_id; + const CppType _min_value; + const CppType _max_value; + bool _has_null = false; +}; + +class MinMaxPredicateBuilder { +public: + MinMaxPredicateBuilder(ObjectPool* pool, SlotId slot_id, const JoinRuntimeFilter* filter) + : _pool(pool), _slot_id(slot_id), _filter(filter) {} + + template + Expr* operator()() { + auto* bloom_filter = (RuntimeBloomFilter*)(_filter); + return _pool->add(new MinMaxPredicate(_slot_id, bloom_filter->min_value(), bloom_filter->max_value(), + bloom_filter->has_null())); + } + +private: + ObjectPool* _pool; + SlotId _slot_id; + const JoinRuntimeFilter* _filter; +}; + +} // namespace starrocks diff --git a/be/src/exprs/percentile_functions.cpp b/be/src/exprs/percentile_functions.cpp index 326547d82fc57..c571f581e8326 100644 --- a/be/src/exprs/percentile_functions.cpp +++ b/be/src/exprs/percentile_functions.cpp @@ -17,7 +17,14 @@ #include "column/column_builder.h" #include "column/column_helper.h" #include "column/column_viewer.h" +<<<<<<< HEAD #include "gutil/strings/substitute.h" +======= +#include "column/vectorized_fwd.h" +#include "exprs/agg/percentile_cont.h" +#include "gutil/strings/substitute.h" +#include "types/logical_type.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/percentile_value.h" #include "util/string_parser.hpp" @@ -64,4 +71,36 @@ StatusOr PercentileFunctions::percentile_approx_raw(FunctionContext* return builder.build(columns[0]->is_constant()); } +<<<<<<< HEAD +======= +struct LCPercentileExtracter { + template + ColumnPtr operator()(const FunctionContext::TypeDesc& type_desc, const ColumnPtr& lc_percentile, double rate) { + if constexpr (lt_is_decimal || lt_is_float || lt_is_integer || lt_is_date_or_datetime) { + ColumnBuilder builder(lc_percentile->size(), type_desc.precision, type_desc.scale); + ColumnViewer viewer(lc_percentile); + for (size_t i = 0; i < viewer.size(); ++i) { + // process null + if (viewer.is_null(i)) { + builder.append_null(); + continue; + } + LowCardPercentileState state; + state.merge(viewer.value(i)); + if (state.items.empty()) { + builder.append_null(); + continue; + } + auto res = state.build_result(rate); + builder.append(res); + } + return builder.build(lc_percentile->is_constant()); + } else { + throw std::runtime_error(fmt::format("Unsupported column type {}", Type)); + } + return nullptr; + } +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exprs/regexp_split.cpp b/be/src/exprs/regexp_split.cpp new file mode 100644 index 0000000000000..53c053d648847 --- /dev/null +++ b/be/src/exprs/regexp_split.cpp @@ -0,0 +1,115 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "exprs/regexp_split.h" + +#include + +using namespace starrocks; + +namespace starrocks { + +unsigned RegexpSplit::match(const char* subject, size_t subject_size, std::vector& matches, + unsigned limit) const { + matches.clear(); + + if (limit == 0) { + return 0; + } + + limit = std::min(limit, _number_of_subpatterns + 1); + + re2::StringPiece pieces[limit]; + + if (!_re2->Match({subject, subject_size}, 0, subject_size, re2::RE2::UNANCHORED, pieces, limit)) { + return 0; + } else { + matches.resize(limit); + for (size_t i = 0; i < limit; ++i) { + if (pieces[i].empty()) { + matches[i].offset = std::string::npos; + matches[i].length = 0; + } else { + matches[i].offset = pieces[i].data() - subject; + matches[i].length = pieces[i].length(); + } + } + return limit; + } +} + +void RegexpSplit::init(re2::RE2* re2, int32_t max_splits) { + _max_splits = max_splits; + _re2 = re2; + if (_re2) { + _number_of_subpatterns = _re2->NumberOfCapturingGroups(); + } +} + +// Called for each next string. +void RegexpSplit::set(const char* pos, const char* end) { + _pos = pos; + _end = end; + _splits = 0; +} + +// Get the next token, if any, or return false. +bool RegexpSplit::get(const char*& token_begin, const char*& token_end) { + if (!_re2) { + if (_pos == _end) { + return false; + } + + token_begin = _pos; + + if (_max_splits != -1) { + if (_splits == _max_splits - 1) { + token_end = _end; + _pos = nullptr; + return true; + } + } + + _pos += 1; + token_end = _pos; + ++_splits; + } else { + if (!_pos || _pos > _end) { + return false; + } + + token_begin = _pos; + + if (_max_splits != -1) { + if (_splits == _max_splits - 1) { + token_end = _end; + _pos = nullptr; + return true; + } + } + + if (!match(_pos, _end - _pos, _matches, _number_of_subpatterns + 1) || !_matches[0].length) { + token_end = _end; + _pos = _end + 1; + } else { + token_end = _pos + _matches[0].offset; + _pos = token_end + _matches[0].length; + ++_splits; + } + } + + return true; +} + +} // namespace starrocks diff --git a/be/src/exprs/regexp_split.h b/be/src/exprs/regexp_split.h new file mode 100644 index 0000000000000..41e479dc90915 --- /dev/null +++ b/be/src/exprs/regexp_split.h @@ -0,0 +1,44 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +namespace starrocks { + +struct Match { + std::string::size_type offset; + std::string::size_type length; +}; + +class RegexpSplit { +public: + void init(re2::RE2* re2, int32_t max_splits); + void set(const char* pos, const char* end); + bool get(const char*& token_begin, const char*& token_end); + +private: + const char* _pos; + const char* _end; + + std::int32_t _max_splits; + std::vector _matches; + int32_t _splits; + re2::RE2* _re2 = nullptr; + unsigned _number_of_subpatterns; + + unsigned match(const char* subject, size_t subject_size, std::vector& matches, + unsigned limit) const; +}; + +} // namespace starrocks diff --git a/be/src/exprs/runtime_filter_bank.cpp b/be/src/exprs/runtime_filter_bank.cpp index 8d3bf6e938e32..18841d03ac06c 100644 --- a/be/src/exprs/runtime_filter_bank.cpp +++ b/be/src/exprs/runtime_filter_bank.cpp @@ -22,6 +22,10 @@ #include "exprs/dictmapping_expr.h" #include "exprs/in_const_predicate.hpp" #include "exprs/literal.h" +<<<<<<< HEAD +======= +#include "exprs/min_max_predicate.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/runtime_filter.h" #include "exprs/runtime_filter_layout.h" #include "gen_cpp/RuntimeFilter_types.h" @@ -155,6 +159,23 @@ Status RuntimeFilterHelper::fill_runtime_bloom_filter(const ColumnPtr& column, L return Status::OK(); } +<<<<<<< HEAD +======= +Status RuntimeFilterHelper::fill_runtime_bloom_filter(const std::vector& columns, LogicalType type, + JoinRuntimeFilter* filter, size_t column_offset, bool eq_null) { + for (const auto& column : columns) { + RETURN_IF_ERROR(fill_runtime_bloom_filter(column, type, filter, column_offset, eq_null)); + } + return Status::OK(); +} + +Status RuntimeFilterHelper::fill_runtime_bloom_filter(const starrocks::pipeline::RuntimeBloomFilterBuildParam& param, + LogicalType type, JoinRuntimeFilter* filter, + size_t column_offset) { + return fill_runtime_bloom_filter(param.columns, type, filter, column_offset, param.eq_null); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr RuntimeFilterHelper::rewrite_runtime_filter_in_cross_join_node(ObjectPool* pool, ExprContext* conjunct, Chunk* chunk) { @@ -764,6 +785,7 @@ void RuntimeFilterProbeDescriptor::set_shared_runtime_filter(const std::shared_p } } +<<<<<<< HEAD // ======================================================== template class MinMaxPredicate : public Expr { @@ -871,6 +893,12 @@ void RuntimeFilterHelper::create_min_max_value_predicate(ObjectPool* pool, SlotI const JoinRuntimeFilter* filter, Expr** min_max_predicate) { *min_max_predicate = nullptr; if (filter == nullptr || filter->has_null()) return; +======= +void RuntimeFilterHelper::create_min_max_value_predicate(ObjectPool* pool, SlotId slot_id, LogicalType slot_type, + const JoinRuntimeFilter* filter, Expr** min_max_predicate) { + *min_max_predicate = nullptr; + if (filter == nullptr) return; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (slot_type == TYPE_CHAR || slot_type == TYPE_VARCHAR) return; auto res = type_dispatch_filter(slot_type, (Expr*)nullptr, MinMaxPredicateBuilder(pool, slot_id, filter)); *min_max_predicate = res; diff --git a/be/src/exprs/runtime_filter_bank.h b/be/src/exprs/runtime_filter_bank.h index c954fbe85347e..1f107c33434f7 100644 --- a/be/src/exprs/runtime_filter_bank.h +++ b/be/src/exprs/runtime_filter_bank.h @@ -35,6 +35,13 @@ #include "types/logical_type.h" #include "util/blocking_queue.hpp" +<<<<<<< HEAD +======= +namespace starrocks::pipeline { +class RuntimeBloomFilterBuildParam; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { class RowDescriptor; class MemTracker; @@ -57,7 +64,14 @@ class RuntimeFilterHelper { static JoinRuntimeFilter* create_runtime_bloom_filter(ObjectPool* pool, LogicalType type); static Status fill_runtime_bloom_filter(const ColumnPtr& column, LogicalType type, JoinRuntimeFilter* filter, size_t column_offset, bool eq_null); +<<<<<<< HEAD +======= + static Status fill_runtime_bloom_filter(const std::vector& column, LogicalType type, + JoinRuntimeFilter* filter, size_t column_offset, bool eq_null); + static Status fill_runtime_bloom_filter(const starrocks::pipeline::RuntimeBloomFilterBuildParam& param, + LogicalType type, JoinRuntimeFilter* filter, size_t column_offset); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static StatusOr rewrite_runtime_filter_in_cross_join_node(ObjectPool* pool, ExprContext* conjunct, Chunk* chunk); diff --git a/be/src/exprs/split.cpp b/be/src/exprs/split.cpp index a4872a25e2647..309b5b7b2c542 100644 --- a/be/src/exprs/split.cpp +++ b/be/src/exprs/split.cpp @@ -148,7 +148,11 @@ StatusOr StringFunctions::split(FunctionContext* context, const starr } array_offsets->append(offset); +<<<<<<< HEAD array_binary_column->append_continuous_strings(v); +======= + array_binary_column->append_continuous_strings(v.data(), v.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { //row_nums * 5 is an estimated value, because the true value cannot be obtained for the time being here array_binary_column->reserve(row_nums * 5, haystack_columns->get_bytes().size()); diff --git a/be/src/exprs/string_functions.cpp b/be/src/exprs/string_functions.cpp index 4cc10b3595c82..fc56d5b69ec0f 100644 --- a/be/src/exprs/string_functions.cpp +++ b/be/src/exprs/string_functions.cpp @@ -38,13 +38,23 @@ #include "common/status.h" #include "exprs/binary_function.h" #include "exprs/math_functions.h" +<<<<<<< HEAD +======= +#include "exprs/regexp_split.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/unary_function.h" #include "gutil/strings/fastmem.h" #include "gutil/strings/strip.h" #include "gutil/strings/substitute.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" #include "runtime/runtime_state.h" #include "storage/olap_define.h" +======= +#include "runtime/runtime_state.h" +#include "storage/olap_define.h" +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/raw_container.h" #include "util/sm3.h" #include "util/utf8.h" @@ -55,7 +65,11 @@ namespace starrocks { static const RE2 SUBSTRING_RE(R"((?:\.\*)*([^\.\^\{\[\(\|\)\]\}\+\*\?\$\\]+)(?:\.\*)*)", re2::RE2::Quiet); #define THROW_RUNTIME_ERROR_IF_EXCEED_LIMIT(col, func_name) \ +<<<<<<< HEAD if (UNLIKELY(col->capacity_limit_reached())) { \ +======= + if (UNLIKELY(!col->capacity_limit_reached().ok())) { \ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) col->reset_column(); \ throw std::runtime_error("binary column exceed 4G in function " #func_name); \ } @@ -436,10 +450,15 @@ ColumnPtr substr_const_not_null(const Columns& columns, BinaryColumn* src, Subst bytes.reserve(reserved); } +<<<<<<< HEAD raw::RawVector raw_offsets; raw_offsets.resize(size + 1); raw_offsets[0] = 0; offsets.swap(reinterpret_cast(raw_offsets)); +======= + raw::make_room(&offsets, size + 1); + offsets[0] = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto& src_bytes = src->get_bytes(); auto is_ascii = validate_ascii_fast((const char*)src_bytes.data(), src_bytes.size()); @@ -486,10 +505,15 @@ ColumnPtr right_const_not_null(const Columns& columns, BinaryColumn* src, Substr } bytes.reserve(reserved); +<<<<<<< HEAD raw::RawVector raw_offsets; raw_offsets.resize(size + 1); raw_offsets[0] = 0; offsets.swap(reinterpret_cast(raw_offsets)); +======= + raw::make_room(&offsets, size + 1); + offsets[0] = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto is_ascii = validate_ascii_fast((const char*)src_bytes.data(), src_bytes_size); if (is_ascii) { // off_is_negative=true, off=-len @@ -2632,7 +2656,12 @@ StatusOr StringFunctions::ascii(FunctionContext* context, const Colum } DEFINE_UNARY_FN_WITH_IMPL(get_charImpl, value) { +<<<<<<< HEAD return std::string((char*)&value, 1); +======= + char* p = (char*)&value; + return std::string(p, 1); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } StatusOr StringFunctions::get_char(FunctionContext* context, const Columns& columns) { @@ -3732,6 +3761,207 @@ StatusOr StringFunctions::regexp_replace(FunctionContext* context, co return regexp_replace_general(context, options, columns); } +<<<<<<< HEAD +======= +static StatusOr regexp_split_const(re2::RE2* const_re, const Columns& columns, int32_t max_split = -1) { + auto content_viewer = ColumnViewer(columns[0]); + + auto size = ColumnHelper::is_all_const(columns) ? 1 : columns[0]->size(); + + auto str_col = BinaryColumn::create(); + auto offset_col = UInt32Column::create(); + offset_col->append(0); + + NullColumnPtr nl_col; + if (columns[0]->is_nullable()) { + auto x = down_cast(columns[0].get())->null_column(); + nl_col = ColumnHelper::as_column(x->clone_shared()); + } else { + nl_col = NullColumn::create(size, 0); + } + + const char* token_begin = nullptr; + const char* token_end = nullptr; + + uint32_t index = 0; + + RegexpSplit regexpSplit; + for (int row = 0; row < size; ++row) { + if (content_viewer.is_null(row)) { + offset_col->append(index); + continue; + } + + auto str_value = content_viewer.value(row); + + regexpSplit.init(const_re, max_split); + regexpSplit.set(str_value.get_data(), str_value.get_data() + str_value.get_size()); + + while (regexpSplit.get(token_begin, token_end)) { + size_t token_size = token_end - token_begin; + str_col->append(Slice(token_begin, token_size)); + index += 1; + } + offset_col->append(index); + } + + auto array = + ArrayColumn::create(NullableColumn::create(str_col, NullColumn::create(str_col->size(), 0)), offset_col); + + if (ColumnHelper::is_all_const(columns)) { + return ConstColumn::create(array, columns[0]->size()); + } + return NullableColumn::create(array, nl_col); +} + +static StatusOr regexp_split_const_pattern(re2::RE2* const_re, const Columns& columns) { + auto content_viewer = ColumnViewer(columns[0]); + ColumnPtr max_split_column; + if (columns.size() > 2) { + max_split_column = columns[2]; + } else { + max_split_column = ColumnHelper::create_const_column(-1, columns[0]->size()); + } + ColumnViewer max_split_viewer(max_split_column); + + auto size = ColumnHelper::is_all_const(columns) ? 1 : columns[0]->size(); + + auto str_col = BinaryColumn::create(); + auto offset_col = UInt32Column::create(); + offset_col->append(0); + + NullColumnPtr nl_col; + if (columns[0]->is_nullable()) { + auto x = down_cast(columns[0].get())->null_column(); + nl_col = ColumnHelper::as_column(x->clone_shared()); + } else { + nl_col = NullColumn::create(size, 0); + } + + const char* token_begin = nullptr; + const char* token_end = nullptr; + + uint32_t index = 0; + + RegexpSplit RegexpSplit; + + for (int row = 0; row < size; ++row) { + if (content_viewer.is_null(row)) { + offset_col->append(index); + continue; + } + + auto max_split = max_split_viewer.value(row); + auto str_value = content_viewer.value(row); + + RegexpSplit.init(const_re, max_split); + RegexpSplit.set(str_value.get_data(), str_value.get_data() + str_value.get_size()); + + while (RegexpSplit.get(token_begin, token_end)) { + size_t token_size = token_end - token_begin; + str_col->append(Slice(token_begin, token_size)); + index += 1; + } + offset_col->append(index); + } + + auto array = + ArrayColumn::create(NullableColumn::create(str_col, NullColumn::create(str_col->size(), 0)), offset_col); + + if (ColumnHelper::is_all_const(columns)) { + return ConstColumn::create(array, columns[0]->size()); + } + return NullableColumn::create(array, nl_col); +} + +static StatusOr regexp_split_general(FunctionContext* context, re2::RE2::Options* options, + const Columns& columns) { + auto content_viewer = ColumnViewer(columns[0]); + auto ptn_viewer = ColumnViewer(columns[1]); + ColumnPtr max_split_column; + if (columns.size() > 2) { + max_split_column = columns[2]; + } else { + max_split_column = ColumnHelper::create_const_column(-1, columns[0]->size()); + } + ColumnViewer max_split_viewer(max_split_column); + auto size = columns[0]->size(); + + auto str_col = BinaryColumn::create(); + auto offset_col = UInt32Column::create(); + auto nl_col = NullColumn::create(); + offset_col->append(0); + uint32_t index = 0; + + const char* token_begin = nullptr; + const char* token_end = nullptr; + + RegexpSplit regexpSplit; + + for (int row = 0; row < size; ++row) { + if (content_viewer.is_null(row) || ptn_viewer.is_null(row)) { + offset_col->append(index); + nl_col->append(1); + continue; + } + + std::string ptn_value = ptn_viewer.value(row).to_string(); + std::unique_ptr local_re; + + if (ptn_value.size()) { + local_re = std::make_unique(ptn_value, *options); + if (!local_re.get()->ok()) { + context->set_error(strings::Substitute("Invalid regex: $0", ptn_value).c_str()); + offset_col->append(index); + nl_col->append(1); + continue; + } + } + + nl_col->append(0); + auto max_split = max_split_viewer.value(row); + auto str_value = content_viewer.value(row); + + regexpSplit.init(local_re.get(), max_split); + regexpSplit.set(str_value.get_data(), str_value.get_data() + str_value.get_size()); + + while (regexpSplit.get(token_begin, token_end)) { + size_t token_size = token_end - token_begin; + str_col->append(Slice(token_begin, token_size)); + index += 1; + } + offset_col->append(index); + } + + auto array = + ArrayColumn::create(NullableColumn::create(str_col, NullColumn::create(str_col->size(), 0)), offset_col); + return NullableColumn::create(array, nl_col); +} + +StatusOr StringFunctions::regexp_split(FunctionContext* context, const Columns& columns) { + RETURN_IF_COLUMNS_ONLY_NULL(columns); + auto state = reinterpret_cast(context->get_function_state(FunctionContext::THREAD_LOCAL)); + if (state->const_pattern) { + re2::RE2* const_re = nullptr; + if (!state->pattern.empty()) { + const_re = state->regex.get(); + } + if (columns.size() > 2) { + if (columns[2]->is_constant()) { + return regexp_split_const(const_re, columns, ColumnHelper::get_const_value(columns[2])); + } else { + return regexp_split_const_pattern(const_re, columns); + } + } else { + return regexp_split_const(const_re, columns); + } + } + + re2::RE2::Options* options = state->options.get(); + return regexp_split_general(context, options, columns); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct ReplaceState { bool only_null{false}; diff --git a/be/src/exprs/string_functions.h b/be/src/exprs/string_functions.h index 85ad050dfe9e5..2707a114561c3 100644 --- a/be/src/exprs/string_functions.h +++ b/be/src/exprs/string_functions.h @@ -29,6 +29,10 @@ #include "util/url_parser.h" namespace starrocks { +<<<<<<< HEAD +======= +class RegexpSplit; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct PadState { bool is_const; @@ -275,6 +279,16 @@ class StringFunctions { DEFINE_VECTORIZED_FN(get_char); /** +<<<<<<< HEAD +======= + * @param: [string_value] + * @paramType: [BinaryColumn] + * @return: BigIntColumn + */ + DEFINE_VECTORIZED_FN(inet_aton); + + /** +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) * Return the index of the first occurrence of substring * * @param: [string_value, sub_string_value] @@ -404,6 +418,16 @@ class StringFunctions { static StatusOr regexp_replace_use_hyperscan_vec(StringFunctionsState* state, const Columns& columns); /** +<<<<<<< HEAD +======= + * @param: [string_value, pattern, max_split] + * @paramType: [BinaryColumn, BinaryColumn, IntColumn] + * @return: Array + */ + DEFINE_VECTORIZED_FN(regexp_split); + + /** +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) * @param: [string_value, pattern_value, replace_value] * @paramType: [BinaryColumn, BinaryColumn, BinaryColumn] * @return: BinaryColumn diff --git a/be/src/exprs/table_function/generate_series.h b/be/src/exprs/table_function/generate_series.h index b5d78b9e2860e..777a664cda484 100644 --- a/be/src/exprs/table_function/generate_series.h +++ b/be/src/exprs/table_function/generate_series.h @@ -35,11 +35,16 @@ class GenerateSeries final : public TableFunction { public: ~GenerateSeries() override = default; +<<<<<<< HEAD [[nodiscard]] Status init(const TFunction& fn, TableFunctionState** state) const override { +======= + Status init(const TFunction& fn, TableFunctionState** state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) *state = new MyState(); return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status prepare(TableFunctionState* /*state*/) const override { return Status::OK(); } [[nodiscard]] Status open(RuntimeState* /*runtime_state*/, TableFunctionState* /*state*/) const override { @@ -47,6 +52,13 @@ class GenerateSeries final : public TableFunction { } [[nodiscard]] Status close(RuntimeState* /*runtime_state*/, TableFunctionState* state) const override { +======= + Status prepare(TableFunctionState* /*state*/) const override { return Status::OK(); } + + Status open(RuntimeState* /*runtime_state*/, TableFunctionState* /*state*/) const override { return Status::OK(); } + + Status close(RuntimeState* /*runtime_state*/, TableFunctionState* state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) delete state; return Status::OK(); } diff --git a/be/src/exprs/table_function/java_udtf_function.h b/be/src/exprs/table_function/java_udtf_function.h index 938ba8f72490a..379df382b59f6 100644 --- a/be/src/exprs/table_function/java_udtf_function.h +++ b/be/src/exprs/table_function/java_udtf_function.h @@ -25,11 +25,20 @@ class JavaUDTFFunction final : public TableFunction { JavaUDTFFunction() = default; ~JavaUDTFFunction() override = default; +<<<<<<< HEAD [[nodiscard]] Status init(const TFunction& fn, TableFunctionState** state) const override; [[nodiscard]] Status prepare(TableFunctionState* state) const override; [[nodiscard]] Status open(RuntimeState* runtime_state, TableFunctionState* state) const override; std::pair process(RuntimeState* runtime_state, TableFunctionState* state) const override; [[nodiscard]] Status close(RuntimeState* _runtime_state, TableFunctionState* state) const override; +======= + Status init(const TFunction& fn, TableFunctionState** state) const override; + Status prepare(TableFunctionState* state) const override; + Status open(RuntimeState* runtime_state, TableFunctionState* state) const override; + std::pair process(RuntimeState* runtime_state, + TableFunctionState* state) const override; + Status close(RuntimeState* _runtime_state, TableFunctionState* state) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/exprs/table_function/json_each.h b/be/src/exprs/table_function/json_each.h index eff27c2156aea..47fef848897df 100644 --- a/be/src/exprs/table_function/json_each.h +++ b/be/src/exprs/table_function/json_each.h @@ -30,11 +30,16 @@ class JsonEach final : public TableFunction { std::pair process(RuntimeState* runtime_state, TableFunctionState* state) const override; +<<<<<<< HEAD [[nodiscard]] Status init(const TFunction& fn, TableFunctionState** state) const override { +======= + Status init(const TFunction& fn, TableFunctionState** state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) *state = new TableFunctionState(); return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status prepare(TableFunctionState* state) const override { return Status::OK(); } [[nodiscard]] Status open(RuntimeState* runtime_state, TableFunctionState* state) const override { @@ -42,6 +47,13 @@ class JsonEach final : public TableFunction { }; [[nodiscard]] Status close(RuntimeState* runtime_state, TableFunctionState* state) const override { +======= + Status prepare(TableFunctionState* state) const override { return Status::OK(); } + + Status open(RuntimeState* runtime_state, TableFunctionState* state) const override { return Status::OK(); }; + + Status close(RuntimeState* runtime_state, TableFunctionState* state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) delete state; return Status::OK(); } diff --git a/be/src/exprs/table_function/list_rowsets.cpp b/be/src/exprs/table_function/list_rowsets.cpp index 083e5e1df6bc6..c258741fe1a66 100644 --- a/be/src/exprs/table_function/list_rowsets.cpp +++ b/be/src/exprs/table_function/list_rowsets.cpp @@ -74,7 +74,11 @@ static void fill_rowset_row(Columns& columns, const RowsetMetadataPB& rowset) { opts.pretty_json = false; std::string json; (void)json2pb::ProtoMessageToJson(rowset.delete_predicate(), &json, opts); +<<<<<<< HEAD (void)columns[5]->append_strings({json}); +======= + (void)columns[5]->append_strings(std::vector{Slice{json}}); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } diff --git a/be/src/exprs/table_function/list_rowsets.h b/be/src/exprs/table_function/list_rowsets.h index 5b79a9e2f5c85..2aba382e4614b 100644 --- a/be/src/exprs/table_function/list_rowsets.h +++ b/be/src/exprs/table_function/list_rowsets.h @@ -32,11 +32,16 @@ class ListRowsets final : public TableFunction { }; public: +<<<<<<< HEAD [[nodiscard]] Status init(const TFunction& fn, TableFunctionState** state) const override { +======= + Status init(const TFunction& fn, TableFunctionState** state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) *state = new MyState(); return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status prepare(TableFunctionState* /*state*/) const override { return Status::OK(); } [[nodiscard]] Status open(RuntimeState* /*runtime_state*/, TableFunctionState* /*state*/) const override { @@ -44,6 +49,13 @@ class ListRowsets final : public TableFunction { } [[nodiscard]] Status close(RuntimeState* /*runtime_state*/, TableFunctionState* state) const override { +======= + Status prepare(TableFunctionState* /*state*/) const override { return Status::OK(); } + + Status open(RuntimeState* /*runtime_state*/, TableFunctionState* /*state*/) const override { return Status::OK(); } + + Status close(RuntimeState* /*runtime_state*/, TableFunctionState* state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) delete state; return Status::OK(); } diff --git a/be/src/exprs/table_function/multi_unnest.h b/be/src/exprs/table_function/multi_unnest.h index 7d12eb934a93f..e219684913bd0 100644 --- a/be/src/exprs/table_function/multi_unnest.h +++ b/be/src/exprs/table_function/multi_unnest.h @@ -116,7 +116,11 @@ class MultiUnnest final : public TableFunction { */ }; +<<<<<<< HEAD [[nodiscard]] Status init(const TFunction& fn, TableFunctionState** state) const override { +======= + Status init(const TFunction& fn, TableFunctionState** state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) *state = new UnnestState(); const auto& table_fn = fn.table_fn; if (table_fn.__isset.is_left_join) { @@ -125,6 +129,7 @@ class MultiUnnest final : public TableFunction { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status prepare(TableFunctionState* state) const override { return Status::OK(); } [[nodiscard]] Status open(RuntimeState* runtime_state, TableFunctionState* state) const override { @@ -132,6 +137,13 @@ class MultiUnnest final : public TableFunction { }; [[nodiscard]] Status close(RuntimeState* runtime_state, TableFunctionState* state) const override { +======= + Status prepare(TableFunctionState* state) const override { return Status::OK(); } + + Status open(RuntimeState* runtime_state, TableFunctionState* state) const override { return Status::OK(); }; + + Status close(RuntimeState* runtime_state, TableFunctionState* state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) delete state; return Status::OK(); } diff --git a/be/src/exprs/table_function/subdivide_bitmap.h b/be/src/exprs/table_function/subdivide_bitmap.h index b55f63422c40c..ddf0ee61afa49 100644 --- a/be/src/exprs/table_function/subdivide_bitmap.h +++ b/be/src/exprs/table_function/subdivide_bitmap.h @@ -45,7 +45,11 @@ class SubdivideBitmap final : public TableFunction { return Status::OK(); } +<<<<<<< HEAD void process_row(const std::vector& src_bitmap_col, SrcSizeCppType batch_size, size_t row, +======= + void process_row(const Buffer& src_bitmap_col, SrcSizeCppType batch_size, size_t row, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Column* dst_bitmap_col, UInt32Column* dst_offset_col, uint32_t* compact_offset) const { auto* bitmap = src_bitmap_col[row]; @@ -105,6 +109,7 @@ class SubdivideBitmap final : public TableFunction { &compact_offset); } } +<<<<<<< HEAD std::string err_msg; auto ret = dst_bitmap_col->capacity_limit_reached(&err_msg); if (ret) { @@ -116,6 +121,18 @@ class SubdivideBitmap final : public TableFunction { if (ret) { state->set_status(Status::InternalError( fmt::format("Offset column generate by subdivide_bitmap reach limit, {}", err_msg))); +======= + Status st = dst_bitmap_col->capacity_limit_reached(); + if (!st.ok()) { + state->set_status(Status::InternalError( + fmt::format("Bitmap column generate by subdivide_bitmap reach limit, {}", st.message()))); + return {}; + } + st = dst_offset_col->capacity_limit_reached(); + if (!st.ok()) { + state->set_status(Status::InternalError( + fmt::format("Offset column generate by subdivide_bitmap reach limit, {}", st.message()))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return {}; } dst_columns.emplace_back(std::move(dst_bitmap_col)); diff --git a/be/src/exprs/table_function/table_function.h b/be/src/exprs/table_function/table_function.h index dc3fe16936008..253b209871f1a 100644 --- a/be/src/exprs/table_function/table_function.h +++ b/be/src/exprs/table_function/table_function.h @@ -86,19 +86,32 @@ class TableFunction { virtual ~TableFunction() = default; //Initialize TableFunctionState +<<<<<<< HEAD [[nodiscard]] virtual Status init(const TFunction& fn, TableFunctionState** state) const = 0; //Some preparations are made in prepare, such as establishing a connection or initializing initial values [[nodiscard]] virtual Status prepare(TableFunctionState* state) const = 0; [[nodiscard]] virtual Status open(RuntimeState* runtime_state, TableFunctionState* state) const = 0; +======= + virtual Status init(const TFunction& fn, TableFunctionState** state) const = 0; + + //Some preparations are made in prepare, such as establishing a connection or initializing initial values + virtual Status prepare(TableFunctionState* state) const = 0; + + virtual Status open(RuntimeState* runtime_state, TableFunctionState* state) const = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) //Table function processing logic virtual std::pair process(RuntimeState* runtime_state, TableFunctionState* state) const = 0; //Release the resources constructed in init and prepare +<<<<<<< HEAD [[nodiscard]] virtual Status close(RuntimeState* runtime_state, TableFunctionState* context) const = 0; +======= + virtual Status close(RuntimeState* runtime_state, TableFunctionState* context) const = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; using TableFunctionPtr = std::shared_ptr; diff --git a/be/src/exprs/table_function/unnest.h b/be/src/exprs/table_function/unnest.h index eaa8b0779eb08..c187207863f7b 100644 --- a/be/src/exprs/table_function/unnest.h +++ b/be/src/exprs/table_function/unnest.h @@ -86,7 +86,11 @@ class Unnest final : public TableFunction { */ }; +<<<<<<< HEAD [[nodiscard]] Status init(const TFunction& fn, TableFunctionState** state) const override { +======= + Status init(const TFunction& fn, TableFunctionState** state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) *state = new UnnestState(); const auto& table_fn = fn.table_fn; if (table_fn.__isset.is_left_join) { @@ -95,6 +99,7 @@ class Unnest final : public TableFunction { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status prepare(TableFunctionState* state) const override { return Status::OK(); } [[nodiscard]] Status open(RuntimeState* runtime_state, TableFunctionState* state) const override { @@ -102,6 +107,13 @@ class Unnest final : public TableFunction { }; [[nodiscard]] Status close(RuntimeState* runtime_state, TableFunctionState* state) const override { +======= + Status prepare(TableFunctionState* state) const override { return Status::OK(); } + + Status open(RuntimeState* runtime_state, TableFunctionState* state) const override { return Status::OK(); }; + + Status close(RuntimeState* runtime_state, TableFunctionState* state) const override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) delete state; return Status::OK(); } diff --git a/be/src/exprs/unary_function.h b/be/src/exprs/unary_function.h index 4ff6f5c664d90..f2ea00433c064 100644 --- a/be/src/exprs/unary_function.h +++ b/be/src/exprs/unary_function.h @@ -136,7 +136,10 @@ struct StringUnaryFunction { int size = v1->size(); for (int i = 0; i < size; ++i) { std::string ret = OP::template apply, std::string>(r1[i], std::forward(args)...); +<<<<<<< HEAD bytes.reserve(ret.size()); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bytes.insert(bytes.end(), (uint8_t*)ret.data(), (uint8_t*)ret.data() + ret.size()); offset.emplace_back(bytes.size()); } diff --git a/be/src/exprs/utility_functions.cpp b/be/src/exprs/utility_functions.cpp index b6ffe5df6ae39..de9e5325a37f1 100644 --- a/be/src/exprs/utility_functions.cpp +++ b/be/src/exprs/utility_functions.cpp @@ -304,4 +304,73 @@ StatusOr UtilityFunctions::get_query_profile(FunctionContext* context return builder.build(false); } +<<<<<<< HEAD +======= +StatusOr UtilityFunctions::bar(FunctionContext* context, const Columns& columns) { + static std::u8string kBar = u8"\u2593"; + RETURN_IF(columns.size() != 4, Status::InvalidArgument("expect 4 arguments")); + RETURN_IF(!columns[1]->is_constant(), Status::InvalidArgument("argument[min] must be constant")); + RETURN_IF(!columns[2]->is_constant(), Status::InvalidArgument("argument[max] must be constant")); + RETURN_IF(!columns[3]->is_constant(), Status::InvalidArgument("argument[width] must be constant")); + + ColumnViewer viewer_size(columns[0]); + ColumnViewer viewer_min(columns[1]); + ColumnViewer viewer_max(columns[2]); + ColumnViewer viewer_width(columns[3]); + size_t rows = columns[0]->size(); + ColumnBuilder builder(rows); + + size_t min = viewer_min.value(0); + size_t max = viewer_max.value(0); + size_t width = viewer_width.value(0); + RETURN_IF(min >= max, Status::InvalidArgument("requirement: min < max")); + RETURN_IF(width <= 0, Status::InvalidArgument("requirement: width > 0")); + + for (size_t i = 0; i < rows; i++) { + size_t size = viewer_size.value(i); + RETURN_IF(size < min, Status::InvalidArgument("requirement: size >= min")); + RETURN_IF(size > max, Status::InvalidArgument("requirement: size <= max")); + + double ratio = std::min(1.0, 1.0 * (size - min) / (max - min)); + size_t result_width = ratio * width; + std::string bar; + for (size_t j = 0; j < result_width; j++) { + bar.append(reinterpret_cast(kBar.c_str())); + } + builder.append(bar); + } + return builder.build(false); +} + +StatusOr UtilityFunctions::equiwidth_bucket(FunctionContext* context, const Columns& columns) { + RETURN_IF(columns.size() != 4, Status::InvalidArgument("expect 4 arguments")); + RETURN_IF(!columns[1]->is_constant(), Status::InvalidArgument("argument[min] must be constant")); + RETURN_IF(!columns[2]->is_constant(), Status::InvalidArgument("argument[max] must be constant")); + RETURN_IF(!columns[3]->is_constant(), Status::InvalidArgument("argument[bucket] must be constant")); + + ColumnViewer viewer_size(columns[0]); + ColumnViewer viewer_min(columns[1]); + ColumnViewer viewer_max(columns[2]); + ColumnViewer viewer_buckets(columns[3]); + size_t rows = columns[0]->size(); + ColumnBuilder builder(rows); + + size_t min = viewer_min.value(0); + size_t max = viewer_max.value(0); + size_t buckets = viewer_buckets.value(0); + RETURN_IF(min >= max, Status::InvalidArgument("requirement: min < max")); + RETURN_IF(buckets <= 0, Status::InvalidArgument("requirement: buckets > 0")); + + for (size_t i = 0; i < rows; i++) { + size_t size = viewer_size.value(i); + RETURN_IF(size < min, Status::InvalidArgument("requirement: size >= min")); + RETURN_IF(size > max, Status::InvalidArgument("requirement: size <= max")); + + size_t bucket = (size - min) / std::max(1, ((max - min) / buckets)); + builder.append(bucket); + } + return builder.build(false); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/exprs/utility_functions.h b/be/src/exprs/utility_functions.h index d5258757601b3..547919b528822 100644 --- a/be/src/exprs/utility_functions.h +++ b/be/src/exprs/utility_functions.h @@ -61,6 +61,15 @@ class UtilityFunctions { DEFINE_VECTORIZED_FN(host_name); DEFINE_VECTORIZED_FN(get_query_profile); +<<<<<<< HEAD +======= + + // Draw a bar graph + DEFINE_VECTORIZED_FN(bar); + + // Build a equi-width histogram + DEFINE_VECTORIZED_FN(equiwidth_bucket); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/formats/CMakeLists.txt b/be/src/formats/CMakeLists.txt index fc763b1922f10..55bd9411f3bed 100644 --- a/be/src/formats/CMakeLists.txt +++ b/be/src/formats/CMakeLists.txt @@ -56,6 +56,12 @@ add_library(Formats STATIC parquet/column_chunk_reader.cpp parquet/column_converter.cpp parquet/column_reader.cpp +<<<<<<< HEAD +======= + parquet/column_reader_factory.cpp + parquet/scalar_column_reader.cpp + parquet/complex_column_reader.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) parquet/encoding.cpp parquet/level_codec.cpp parquet/page_reader.cpp @@ -75,6 +81,10 @@ add_library(Formats STATIC parquet/column_chunk_writer.cpp parquet/column_read_order_ctx.cpp parquet/statistics_helper.cpp +<<<<<<< HEAD +======= + parquet/zone_map_filter_evaluator.h +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) disk_range.hpp ) diff --git a/be/src/formats/csv/json_converter.h b/be/src/formats/csv/json_converter.h index 5548a95ffae5b..3994285b9ee33 100644 --- a/be/src/formats/csv/json_converter.h +++ b/be/src/formats/csv/json_converter.h @@ -20,10 +20,16 @@ namespace starrocks::csv { class JsonConverter final : public Converter { public: +<<<<<<< HEAD [[nodiscard]] Status write_string(OutputStream* os, const Column& column, size_t row_num, const Options& options) const override; [[nodiscard]] Status write_quoted_string(OutputStream* os, const Column& column, size_t row_num, const Options& options) const override; +======= + Status write_string(OutputStream* os, const Column& column, size_t row_num, const Options& options) const override; + Status write_quoted_string(OutputStream* os, const Column& column, size_t row_num, + const Options& options) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool read_string(Column* column, const Slice& s, const Options& options) const override; bool read_quoted_string(Column* column, const Slice& s, const Options& options) const override; }; diff --git a/be/src/formats/orc/apache-orc/c++/include/orc/Common.hh b/be/src/formats/orc/apache-orc/c++/include/orc/Common.hh index bbc9fd09bd3de..0bde03983303b 100644 --- a/be/src/formats/orc/apache-orc/c++/include/orc/Common.hh +++ b/be/src/formats/orc/apache-orc/c++/include/orc/Common.hh @@ -18,11 +18,20 @@ #pragma once +<<<<<<< HEAD +======= +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include "orc/Exceptions.hh" #include "orc/Type.hh" #include "orc/Vector.hh" +<<<<<<< HEAD +======= +#include "runtime/integer_overflow_arithmetics.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace orc { @@ -218,6 +227,7 @@ inline bool compare(T val1, T val2) { // Specialization for Decimal template <> inline bool compare(Decimal val1, Decimal val2) { +<<<<<<< HEAD // compare integral parts Int128 integral1 = scaleDownInt128ByPowerOfTen(val1.value, val1.scale); Int128 integral2 = scaleDownInt128ByPowerOfTen(val2.value, val2.scale); @@ -252,6 +262,41 @@ inline bool compare(Decimal val1, Decimal val2) { return true; } return false; +======= + if (val1.scale == val2.scale) { + return val1.value < val2.value; + } + + // three-way comparison + // requires val1.scale < val2.scale + // returns negative iff x < y + // returns zero iff x = y + // returns positive iff x > y + auto cmp = [](Decimal& val1, Decimal& val2) -> int128_t { + DCHECK(val1.scale < val2.scale); + int128_t value1 = (static_cast(val1.value.getHighBits()) << 64) + val1.value.getLowBits(); + int128_t value2 = (static_cast(val2.value.getHighBits()) << 64) + val2.value.getLowBits(); + int32_t delta = val2.scale - val1.scale; + int128_t scaled_value1; + bool overflow; + overflow = starrocks::mul_overflow(value1, starrocks::exp10_int128(delta), &scaled_value1); + if (overflow) { + return value1; + } + int128_t diff; + overflow = starrocks::sub_overflow(scaled_value1, value2, &diff); + if (overflow) { + return value1; + } + return diff; + }; + + if (val1.scale < val2.scale) { + return cmp(val1, val2) < 0; + } else { + return cmp(val2, val1) > 0; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } enum BloomFilterVersion { diff --git a/be/src/formats/orc/apache-orc/c++/src/Int128.cc b/be/src/formats/orc/apache-orc/c++/src/Int128.cc index 52547127193b8..b7624f2e8c214 100644 --- a/be/src/formats/orc/apache-orc/c++/src/Int128.cc +++ b/be/src/formats/orc/apache-orc/c++/src/Int128.cc @@ -26,7 +26,11 @@ namespace orc { Int128 Int128::maximumValue() { +<<<<<<< HEAD return {0x7fffffffffffffff, 0xfffffffffffffff}; +======= + return {0x7fffffffffffffff, 0xffffffffffffffff}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Int128 Int128::minimumValue() { diff --git a/be/src/formats/orc/apache-orc/c++/src/Statistics.hh b/be/src/formats/orc/apache-orc/c++/src/Statistics.hh index 204fbb1f5d055..c31aeae676a39 100644 --- a/be/src/formats/orc/apache-orc/c++/src/Statistics.hh +++ b/be/src/formats/orc/apache-orc/c++/src/Statistics.hh @@ -572,7 +572,12 @@ public: void reset() override { _stats.reset(); +<<<<<<< HEAD setSum(Decimal()); +======= + // Note(letian-jiang): Do not compute the sum of decimal column since it is time-consuming and hard to exploit. + _stats.setHasSum(false); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void toProtoBuf(proto::ColumnStatistics& pbStats) const override { diff --git a/be/src/formats/orc/orc_chunk_reader.cpp b/be/src/formats/orc/orc_chunk_reader.cpp index 54cf97cfb528e..c4c24938459eb 100644 --- a/be/src/formats/orc/orc_chunk_reader.cpp +++ b/be/src/formats/orc/orc_chunk_reader.cpp @@ -35,7 +35,11 @@ #include "orc_schema_builder.h" #include "simd/simd.h" #include "types/logical_type.h" +<<<<<<< HEAD #include "util/stack_util.cpp" +======= +#include "util/stack_util.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/timezone_utils.h" namespace starrocks { @@ -190,6 +194,12 @@ Status OrcChunkReader::init(std::unique_ptr reader, const OrcPredic return Status::InternalError(s); } +<<<<<<< HEAD +======= + // _batch can't be reused because the schema between files may be different + _batch.reset(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // TODO(SmithCruise) delete _init_position_in_orc() when develop subfield lazy load. RETURN_IF_ERROR(_init_position_in_orc()); RETURN_IF_ERROR(_init_cast_exprs()); diff --git a/be/src/formats/parquet/chunk_writer.cpp b/be/src/formats/parquet/chunk_writer.cpp index 70f6d6dd6ffac..7e31481f498ba 100644 --- a/be/src/formats/parquet/chunk_writer.cpp +++ b/be/src/formats/parquet/chunk_writer.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/chunk_writer.h" +<<<<<<< HEAD #include #include @@ -28,6 +29,20 @@ #include "formats/parquet/column_chunk_writer.h" #include "formats/parquet/level_builder.h" #include "util/defer_op.h" +======= +#include +#include + +#include +#include +#include + +#include "column/chunk.h" +#include "common/statusor.h" +#include "exprs/function_context.h" +#include "formats/parquet/column_chunk_writer.h" +#include "formats/parquet/level_builder.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { diff --git a/be/src/formats/parquet/chunk_writer.h b/be/src/formats/parquet/chunk_writer.h index 47744387a624a..b99bcc42b070e 100644 --- a/be/src/formats/parquet/chunk_writer.h +++ b/be/src/formats/parquet/chunk_writer.h @@ -26,6 +26,7 @@ #include #include #include +<<<<<<< HEAD #include @@ -35,6 +36,38 @@ #include "runtime/runtime_state.h" #include "util/priority_thread_pool.hpp" +======= +#include +#include + +#include +#include +#include +#include + +#include "column/chunk.h" +#include "column/nullable_column.h" +#include "column/vectorized_fwd.h" +#include "common/status.h" +#include "fs/fs.h" +#include "runtime/runtime_state.h" +#include "runtime/types.h" +#include "util/priority_thread_pool.hpp" + +namespace parquet { +class RowGroupWriter; + +namespace schema { +class GroupNode; +} // namespace schema +} // namespace parquet +namespace starrocks { +class Chunk; +template +class StatusOr; +} // namespace starrocks + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { // Wraps parquet::RowGroupWriter. diff --git a/be/src/formats/parquet/column_chunk_reader.cpp b/be/src/formats/parquet/column_chunk_reader.cpp index 19bdb2e46ce0d..7724e993f97bf 100644 --- a/be/src/formats/parquet/column_chunk_reader.cpp +++ b/be/src/formats/parquet/column_chunk_reader.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/column_chunk_reader.h" +<<<<<<< HEAD #include #include "common/status.h" @@ -22,6 +23,26 @@ #include "formats/parquet/utils.h" #include "gutil/strings/substitute.h" #include "runtime/current_thread.h" +======= +#include + +#include +#include +#include +#include + +#include "common/compiler_util.h" +#include "common/status.h" +#include "common/statusor.h" +#include "formats/parquet/encoding.h" +#include "formats/parquet/types.h" +#include "formats/parquet/utils.h" +#include "fs/fs.h" +#include "gutil/strings/substitute.h" +#include "runtime/current_thread.h" +#include "runtime/mem_tracker.h" +#include "util/compression/block_compression.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { @@ -33,7 +54,16 @@ ColumnChunkReader::ColumnChunkReader(level_t max_def_level, level_t max_rep_leve _chunk_metadata(column_chunk), _opts(opts), _def_level_decoder(&opts.stats->level_decode_ns), +<<<<<<< HEAD _rep_level_decoder(&opts.stats->level_decode_ns) {} +======= + _rep_level_decoder(&opts.stats->level_decode_ns) { + if (_chunk_metadata->meta_data.__isset.statistics && _chunk_metadata->meta_data.statistics.__isset.null_count && + _chunk_metadata->meta_data.statistics.null_count == 0) { + _current_row_group_no_null = true; + } +} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ColumnChunkReader::~ColumnChunkReader() = default; @@ -52,7 +82,11 @@ Status ColumnChunkReader::init(int chunk_size) { // seek to the first page RETURN_IF_ERROR(_page_reader->seek_to_offset(start_offset)); +<<<<<<< HEAD auto compress_type = convert_compression_codec(metadata().codec); +======= + auto compress_type = ParquetUtils::convert_compression_codec(metadata().codec); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(get_block_compression_codec(compress_type, &_compress_codec)); _chunk_size = chunk_size; @@ -120,6 +154,14 @@ Status ColumnChunkReader::_parse_page_header() { _opts.stats->has_page_statistics |= (header.data_page_header.__isset.statistics && (header.data_page_header.statistics.__isset.min_value || header.data_page_header.statistics.__isset.min)); +<<<<<<< HEAD +======= + _current_page_no_null = + (header.data_page_header.__isset.statistics && header.data_page_header.statistics.__isset.null_count && + header.data_page_header.statistics.null_count == 0) + ? true + : false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); diff --git a/be/src/formats/parquet/column_chunk_reader.h b/be/src/formats/parquet/column_chunk_reader.h index dcb6cc64b6eff..639ac664d0ce1 100644 --- a/be/src/formats/parquet/column_chunk_reader.h +++ b/be/src/formats/parquet/column_chunk_reader.h @@ -14,6 +14,11 @@ #pragma once +<<<<<<< HEAD +======= +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -26,13 +31,31 @@ #include "formats/parquet/encoding.h" #include "formats/parquet/level_codec.h" #include "formats/parquet/page_reader.h" +<<<<<<< HEAD +======= +#include "formats/parquet/types.h" +#include "formats/parquet/utils.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fs/fs.h" #include "gen_cpp/parquet_types.h" #include "util/compression/block_compression.h" #include "util/runtime_profile.h" +<<<<<<< HEAD + +namespace starrocks { +class BlockCompressionCodec; +======= +#include "util/slice.h" +#include "util/stopwatch.hpp" namespace starrocks { class BlockCompressionCodec; +class NullableColumn; + +namespace io { +class SeekableInputStream; +} // namespace io +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks namespace starrocks::parquet { @@ -73,6 +96,12 @@ class ColumnChunkReader { Status decode_values(size_t n, const uint16_t* is_nulls, ColumnContentType content_type, Column* dst) { SCOPED_RAW_TIMER(&_opts.stats->value_decode_ns); +<<<<<<< HEAD +======= + if (_current_row_group_no_null || _current_page_no_null) { + return _cur_decoder->next_batch(n, content_type, dst); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t idx = 0; while (idx < n) { bool is_null = is_nulls[idx++]; @@ -102,7 +131,11 @@ class ColumnChunkReader { return _cur_decoder->get_dict_values(column); } +<<<<<<< HEAD Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) { +======= + Status get_dict_values(const Buffer& dict_codes, const NullableColumn& nulls, Column* column) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(_try_load_dictionary()); return _cur_decoder->get_dict_values(dict_codes, nulls, column); } @@ -141,6 +174,11 @@ class ColumnChunkReader { level_t _max_def_level = 0; level_t _max_rep_level = 0; +<<<<<<< HEAD +======= + bool _current_row_group_no_null = false; + bool _current_page_no_null = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int32_t _type_length = 0; const tparquet::ColumnChunk* _chunk_metadata = nullptr; const ColumnReaderOptions& _opts; diff --git a/be/src/formats/parquet/column_chunk_writer.cpp b/be/src/formats/parquet/column_chunk_writer.cpp index 21c6ee455aecf..e248877600b69 100644 --- a/be/src/formats/parquet/column_chunk_writer.cpp +++ b/be/src/formats/parquet/column_chunk_writer.cpp @@ -14,9 +14,15 @@ #include "formats/parquet/column_chunk_writer.h" +<<<<<<< HEAD #include #include "formats/parquet/chunk_writer.h" +======= +#include +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/level_builder.h" #include "gutil/casts.h" diff --git a/be/src/formats/parquet/column_chunk_writer.h b/be/src/formats/parquet/column_chunk_writer.h index f615a05134232..a7a75f756502a 100644 --- a/be/src/formats/parquet/column_chunk_writer.h +++ b/be/src/formats/parquet/column_chunk_writer.h @@ -26,6 +26,10 @@ #include #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include @@ -35,6 +39,13 @@ #include "runtime/runtime_state.h" #include "util/priority_thread_pool.hpp" +<<<<<<< HEAD +======= +namespace parquet { +class ColumnWriter; +} // namespace parquet + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { class LevelBuilderResult; diff --git a/be/src/formats/parquet/column_converter.cpp b/be/src/formats/parquet/column_converter.cpp index bca1f47a317ca..00edd50915ecd 100644 --- a/be/src/formats/parquet/column_converter.cpp +++ b/be/src/formats/parquet/column_converter.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/column_converter.h" +<<<<<<< HEAD #include #include @@ -31,6 +32,40 @@ #include "util/bit_util.h" #include "util/logging.h" #include "util/runtime_profile.h" +======= +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "column/binary_column.h" +#include "column/column.h" +#include "column/column_helper.h" +#include "column/fixed_length_column.h" +#include "column/nullable_column.h" +#include "column/type_traits.h" +#include "column/vectorized_fwd.h" +#include "formats/parquet/schema.h" +#include "formats/parquet/types.h" +#include "gutil/casts.h" +#include "gutil/integral_types.h" +#include "gutil/strings/substitute.h" +#include "runtime/time_types.h" +#include "runtime/types.h" +#include "storage/olap_common.h" +#include "types/date_value.h" +#include "types/logical_type.h" +#include "types/timestamp_value.h" +#include "util/bit_util.h" +#include "util/decimal_types.h" +#include "util/int96.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/timezone_utils.h" namespace starrocks::parquet { diff --git a/be/src/formats/parquet/column_converter.h b/be/src/formats/parquet/column_converter.h index 9b48eecb6fef8..cfa4a7e9c3e43 100644 --- a/be/src/formats/parquet/column_converter.h +++ b/be/src/formats/parquet/column_converter.h @@ -14,9 +14,19 @@ #pragma once +<<<<<<< HEAD #include "column/column_helper.h" #include "column/type_traits.h" #include "common/status.h" +======= +#include +#include + +#include "column/column_helper.h" +#include "column/type_traits.h" +#include "common/status.h" +#include "exprs/function_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/types.h" #include "formats/parquet/utils.h" #include "gen_cpp/parquet_types.h" @@ -25,6 +35,10 @@ namespace starrocks { class Column; +<<<<<<< HEAD +======= +struct TypeDescriptor; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks namespace starrocks::parquet { diff --git a/be/src/formats/parquet/column_read_order_ctx.cpp b/be/src/formats/parquet/column_read_order_ctx.cpp index 83b7df2d3b5cd..fae0d6ebf90d5 100644 --- a/be/src/formats/parquet/column_read_order_ctx.cpp +++ b/be/src/formats/parquet/column_read_order_ctx.cpp @@ -31,11 +31,21 @@ const std::vector& ColumnReadOrderCtx::get_column_read_order() { } } +<<<<<<< HEAD void ColumnReadOrderCtx::update_ctx(size_t round_cost) { +======= +void ColumnReadOrderCtx::update_ctx(size_t round_cost, double first_selectivity) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_rand_round_order_index > 0) { if (round_cost < _min_round_cost) { _column_indices = _trying_column_indices; _min_round_cost = round_cost; +<<<<<<< HEAD +======= + } else if (round_cost == _min_round_cost && first_selectivity > 0 && first_selectivity < _first_selectivity) { + _column_indices = _trying_column_indices; + _first_selectivity = first_selectivity; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _trying_column_indices.clear(); _rand_round_order_index--; diff --git a/be/src/formats/parquet/column_read_order_ctx.h b/be/src/formats/parquet/column_read_order_ctx.h index bbfb20bf5fbb4..b66b91ac72e8e 100644 --- a/be/src/formats/parquet/column_read_order_ctx.h +++ b/be/src/formats/parquet/column_read_order_ctx.h @@ -32,7 +32,11 @@ class ColumnReadOrderCtx { int get_column_cost(int col_idx) const { return _column_cost_map.at(col_idx); } +<<<<<<< HEAD void update_ctx(size_t round_cost); +======= + void update_ctx(size_t round_cost, double first_selectivity); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t get_min_round_cost() const { return _min_round_cost; } @@ -43,6 +47,11 @@ class ColumnReadOrderCtx { std::vector _trying_column_indices; // cost size_t _min_round_cost = 0; +<<<<<<< HEAD +======= + // first selective + size_t _first_selectivity = 1; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // rand round order index, select the min round_cost from 10 random order size_t _rand_round_order_index = 10; // column cost map index -> cost diff --git a/be/src/formats/parquet/column_reader.cpp b/be/src/formats/parquet/column_reader.cpp index c8b585cc930c5..dcd240920722f 100644 --- a/be/src/formats/parquet/column_reader.cpp +++ b/be/src/formats/parquet/column_reader.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/column_reader.h" +<<<<<<< HEAD #include #include "column/array_column.h" @@ -389,6 +390,30 @@ void ScalarColumnReader::select_offset_index(const SparseRange& range, _reader = std::make_unique(std::move(_reader), _offset_index_ctx.get(), has_dict_page); } +======= +#include + +#include +#include +#include +#include + +#include "column/chunk.h" +#include "column/column_helper.h" +#include "column/nullable_column.h" +#include "common/compiler_util.h" +#include "exec/exec_node.h" +#include "exec/hdfs_scanner.h" +#include "formats/parquet/scalar_column_reader.h" +#include "formats/utils.h" +#include "gen_cpp/parquet_types.h" +#include "simd/batch_run_counter.h" +#include "storage/column_or_predicate.h" +#include "storage/column_predicate.h" + +namespace starrocks::parquet { + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status ColumnDictFilterContext::rewrite_conjunct_ctxs_to_predicate(StoredColumnReader* reader, bool* is_group_filtered) { // create dict value chunk for evaluation. @@ -457,12 +482,17 @@ Status ColumnDictFilterContext::rewrite_conjunct_ctxs_to_predicate(StoredColumnR predicate = obj_pool.add( new_column_eq_predicate(get_type_info(kDictCodeFieldType), slot_id, std::to_string(dict_codes[0]))); } else { +<<<<<<< HEAD std::vector str_codes; str_codes.reserve(dict_codes.size()); for (int code : dict_codes) { str_codes.emplace_back(std::to_string(code)); } predicate = obj_pool.add(new_column_in_predicate(get_type_info(kDictCodeFieldType), slot_id, str_codes)); +======= + predicate = obj_pool.add(new_dictionary_code_in_predicate(get_type_info(kDictCodeFieldType), slot_id, + dict_codes, dict_value_column->size())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // deal with if NULL works or not. @@ -486,6 +516,7 @@ Status ColumnDictFilterContext::rewrite_conjunct_ctxs_to_predicate(StoredColumnR return Status::OK(); } +<<<<<<< HEAD class ListColumnReader : public ColumnReader { public: explicit ListColumnReader(const ColumnReaderOptions& opts) {} @@ -1228,4 +1259,6 @@ Status ColumnReader::create(const ColumnReaderOptions& opts, const ParquetField* return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::parquet diff --git a/be/src/formats/parquet/column_reader.h b/be/src/formats/parquet/column_reader.h index 40693dbef990a..83ce684e488fc 100644 --- a/be/src/formats/parquet/column_reader.h +++ b/be/src/formats/parquet/column_reader.h @@ -14,6 +14,7 @@ #pragma once +<<<<<<< HEAD #include "common/status.h" #include "formats/parquet/column_converter.h" #include "formats/parquet/utils.h" @@ -21,10 +22,50 @@ #include "io/shared_buffered_input_stream.h" #include "storage/column_predicate.h" #include "storage/range.h" +======= +#include +#include + +#include +#include +#include + +#include "column/column.h" +#include "column/vectorized_fwd.h" +#include "common/object_pool.h" +#include "common/status.h" +#include "common/statusor.h" +#include "formats/parquet/metadata.h" +#include "formats/parquet/types.h" +#include "formats/parquet/utils.h" +#include "io/shared_buffered_input_stream.h" +#include "storage/column_predicate.h" +#include "storage/predicate_tree/predicate_tree_fwd.h" +#include "storage/range.h" +#include "types/logical_type.h" + +namespace tparquet { +class ColumnChunk; +class OffsetIndex; +class RowGroup; +} // namespace tparquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { class RandomAccessFile; struct HdfsScanStats; +<<<<<<< HEAD +======= +class ColumnPredicate; +class ExprContext; +class NullableColumn; +class TIcebergSchemaField; +struct TypeDescriptor; + +namespace parquet { +struct ParquetField; +} // namespace parquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks namespace starrocks::parquet { @@ -37,6 +78,10 @@ struct ColumnReaderOptions { RandomAccessFile* file = nullptr; const tparquet::RowGroup* row_group_meta = nullptr; uint64_t first_row_index = 0; +<<<<<<< HEAD +======= + const FileMetaData* file_meta_data = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class StoredColumnReader; @@ -60,6 +105,7 @@ struct ColumnDictFilterContext { class ColumnReader { public: +<<<<<<< HEAD // TODO(zc): review this, // create a column reader static Status create(const ColumnReaderOptions& opts, const ParquetField* field, const TypeDescriptor& col_type, @@ -82,16 +128,26 @@ class ColumnReader { virtual ~ColumnReader() = default; virtual Status read_range(const Range& range, const Filter* filter, Column* dst) = 0; +======= + explicit ColumnReader(const ParquetField* parquet_field) : _parquet_field(parquet_field) {} + virtual ~ColumnReader() = default; + virtual Status prepare() = 0; + + virtual Status read_range(const Range& range, const Filter* filter, ColumnPtr& dst) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void get_levels(level_t** def_levels, level_t** rep_levels, size_t* num_levels) = 0; virtual void set_need_parse_levels(bool need_parse_levels) = 0; +<<<<<<< HEAD virtual Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) { return Status::NotSupported("get_dict_values is not supported"); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual bool try_to_use_dict_filter(ExprContext* ctx, bool is_decode_needed, const SlotId slotId, const std::vector& sub_field_path, const size_t& layer) { return false; @@ -103,15 +159,23 @@ class ColumnReader { return Status::OK(); } +<<<<<<< HEAD virtual void init_dict_column(ColumnPtr& column, const std::vector& sub_field_path, const size_t& layer) {} +======= + virtual void set_can_lazy_decode(bool can_lazy_decode) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual Status filter_dict_column(const ColumnPtr& column, Filter* filter, const std::vector& sub_field_path, const size_t& layer) { return Status::OK(); } +<<<<<<< HEAD virtual Status fill_dst_column(ColumnPtr& dst, const ColumnPtr& src) { +======= + virtual Status fill_dst_column(ColumnPtr& dst, ColumnPtr& src) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) dst->swap_column(*src); return Status::OK(); } @@ -119,9 +183,33 @@ class ColumnReader { virtual void collect_column_io_range(std::vector* ranges, int64_t* end_offset, ColumnIOType type, bool active) = 0; +<<<<<<< HEAD virtual const tparquet::ColumnChunk* get_chunk_metadata() { return nullptr; } virtual const ParquetField* get_column_parquet_field() { return nullptr; } +======= + // For field which type is complex, the filed physical_column_index in file meta is not same with the column index + // in row_group's column metas + // For example: + // table schema : + // -- col_tinyint tinyint + // -- col_struct struct + // ----- name string + // ----- age int + // file metadata schema : + // -- ParquetField(name=col_tinyint, physical_column_index=0) + // -- ParquetField(name=col_struct,physical_column_index=0, + // children=[ParquetField(name=name, physical_column_index=1), + // ParquetField(name=age, physical_column_index=2)]) + // row group column metas: + // -- ColumnMetaData(path_in_schema=[col_tinyint]) + // -- ColumnMetaData(path_in_schema=[col_struct, name]) + // -- ColumnMetaData(path_in_schema=[col_struct, age]) + // So for complex type, there isn't exist ColumnChunkMetaData + virtual const tparquet::ColumnChunk* get_chunk_metadata() const { return nullptr; } + + const ParquetField* get_column_parquet_field() const { return _parquet_field; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual StatusOr get_offset_index(const uint64_t rg_first_row) { return Status::NotSupported("get_offset_index is not supported"); @@ -129,6 +217,7 @@ class ColumnReader { virtual void select_offset_index(const SparseRange& range, const uint64_t rg_first_row) = 0; +<<<<<<< HEAD std::unique_ptr converter; private: @@ -136,4 +225,30 @@ class ColumnReader { const std::map>& children_readers); }; +======= + // Return true means selected, return false means not selected + virtual StatusOr row_group_zone_map_filter(const std::vector& predicates, + CompoundNodeType pred_relation, const uint64_t rg_first_row, + const uint64_t rg_num_rows) const { + // not implemented, select the whole row group by default + return true; + } + + // return true means page index filter happened + // return false means no page index filter happened + virtual StatusOr page_index_zone_map_filter(const std::vector& predicates, + SparseRange* row_ranges, CompoundNodeType pred_relation, + const uint64_t rg_first_row, const uint64_t rg_num_rows) { + DCHECK(row_ranges->empty()); + return false; + } + +private: + // _parquet_field is generated by parquet format, so ParquetField's children order may different from ColumnReader's children. + const ParquetField* _parquet_field = nullptr; +}; + +using ColumnReaderPtr = std::unique_ptr; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::parquet diff --git a/be/src/formats/parquet/column_reader_factory.cpp b/be/src/formats/parquet/column_reader_factory.cpp new file mode 100644 index 0000000000000..1f5be92d6c157 --- /dev/null +++ b/be/src/formats/parquet/column_reader_factory.cpp @@ -0,0 +1,266 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "formats/parquet/column_reader_factory.h" + +#include "formats/parquet/complex_column_reader.h" +#include "formats/parquet/scalar_column_reader.h" +#include "formats/parquet/schema.h" +#include "formats/utils.h" + +namespace starrocks::parquet { + +StatusOr ColumnReaderFactory::create(const ColumnReaderOptions& opts, const ParquetField* field, + const TypeDescriptor& col_type) { + // We will only set a complex type in ParquetField + if ((field->is_complex_type() || col_type.is_complex_type()) && !field->has_same_complex_type(col_type)) { + return Status::InternalError( + strings::Substitute("ParquetField '$0' file's type $1 is different from table's type $2", field->name, + column_type_to_string(field->type), logical_type_to_string(col_type.type))); + } + if (field->type == ColumnType::ARRAY) { + ASSIGN_OR_RETURN(ColumnReaderPtr child_reader, + ColumnReaderFactory::create(opts, &field->children[0], col_type.children[0])); + if (child_reader != nullptr) { + return std::make_unique(field, std::move(child_reader)); + } else { + return nullptr; + } + } else if (field->type == ColumnType::MAP) { + std::unique_ptr key_reader = nullptr; + std::unique_ptr value_reader = nullptr; + + if (!col_type.children[0].is_unknown_type()) { + ASSIGN_OR_RETURN(key_reader, + ColumnReaderFactory::create(opts, &(field->children[0]), col_type.children[0])); + } + if (!col_type.children[1].is_unknown_type()) { + ASSIGN_OR_RETURN(value_reader, + ColumnReaderFactory::create(opts, &field->children[1], col_type.children[1])); + } + + if (key_reader != nullptr || value_reader != nullptr) { + return std::make_unique(field, std::move(key_reader), std::move(value_reader)); + } else { + return nullptr; + } + } else if (field->type == ColumnType::STRUCT) { + std::vector subfield_pos(col_type.children.size()); + get_subfield_pos_with_pruned_type(*field, col_type, opts.case_sensitive, subfield_pos); + + std::map children_readers; + for (size_t i = 0; i < col_type.children.size(); i++) { + if (subfield_pos[i] == -1) { + // -1 means subfield not existed; we need to emplace nullptr + children_readers.emplace(col_type.field_names[i], nullptr); + continue; + } + ASSIGN_OR_RETURN( + ColumnReaderPtr child_reader, + ColumnReaderFactory::create(opts, &field->children[subfield_pos[i]], col_type.children[i])); + children_readers.emplace(col_type.field_names[i], std::move(child_reader)); + } + + // maybe struct subfield ColumnReader is null + if (_has_valid_subfield_column_reader(children_readers)) { + return std::make_unique(field, std::move(children_readers)); + } else { + return nullptr; + } + } else { + return std::make_unique(field, &opts.row_group_meta->columns[field->physical_column_index], + &col_type, opts); + } +} + +StatusOr ColumnReaderFactory::create(const ColumnReaderOptions& opts, const ParquetField* field, + const TypeDescriptor& col_type, + const TIcebergSchemaField* iceberg_schema_field) { + // We will only set a complex type in ParquetField + if ((field->is_complex_type() || col_type.is_complex_type()) && !field->has_same_complex_type(col_type)) { + return Status::InternalError( + strings::Substitute("ParquetField '$0' file's type $1 is different from table's type $2", field->name, + column_type_to_string(field->type), logical_type_to_string(col_type.type))); + } + DCHECK(iceberg_schema_field != nullptr); + if (field->type == ColumnType::ARRAY) { + const TIcebergSchemaField* element_schema = &iceberg_schema_field->children[0]; + ASSIGN_OR_RETURN(ColumnReaderPtr child_reader, + ColumnReaderFactory::create(opts, &field->children[0], col_type.children[0], element_schema)); + if (child_reader != nullptr) { + return std::make_unique(field, std::move(child_reader)); + } else { + return nullptr; + } + } else if (field->type == ColumnType::MAP) { + std::unique_ptr key_reader = nullptr; + std::unique_ptr value_reader = nullptr; + + const TIcebergSchemaField* key_iceberg_schema = &iceberg_schema_field->children[0]; + const TIcebergSchemaField* value_iceberg_schema = &iceberg_schema_field->children[1]; + + if (!col_type.children[0].is_unknown_type()) { + ASSIGN_OR_RETURN(key_reader, ColumnReaderFactory::create(opts, &(field->children[0]), col_type.children[0], + key_iceberg_schema)); + } + if (!col_type.children[1].is_unknown_type()) { + ASSIGN_OR_RETURN(value_reader, ColumnReaderFactory::create(opts, &(field->children[1]), + col_type.children[1], value_iceberg_schema)); + } + + if (key_reader != nullptr || value_reader != nullptr) { + return std::make_unique(field, std::move(key_reader), std::move(value_reader)); + } else { + return nullptr; + } + } else if (field->type == ColumnType::STRUCT) { + std::vector subfield_pos(col_type.children.size()); + std::vector iceberg_schema_subfield(col_type.children.size()); + get_subfield_pos_with_pruned_type(*field, col_type, opts.case_sensitive, iceberg_schema_field, subfield_pos, + iceberg_schema_subfield); + + std::map> children_readers; + for (size_t i = 0; i < col_type.children.size(); i++) { + if (subfield_pos[i] == -1) { + // -1 means subfield not existed; we need to emplace nullptr + children_readers.emplace(col_type.field_names[i], nullptr); + continue; + } + + ASSIGN_OR_RETURN(ColumnReaderPtr child_reader, + ColumnReaderFactory::create(opts, &field->children[subfield_pos[i]], col_type.children[i], + iceberg_schema_subfield[i])); + children_readers.emplace(col_type.field_names[i], std::move(child_reader)); + } + + // maybe struct subfield ColumnReader is null + if (_has_valid_subfield_column_reader(children_readers)) { + return std::make_unique(field, std::move(children_readers)); + } else { + return nullptr; + } + } else { + return std::make_unique(field, &opts.row_group_meta->columns[field->physical_column_index], + &col_type, opts); + } +} + +void ColumnReaderFactory::get_subfield_pos_with_pruned_type(const ParquetField& field, const TypeDescriptor& col_type, + bool case_sensitive, std::vector& pos) { + DCHECK(field.type == ColumnType::STRUCT); + if (!col_type.field_ids.empty()) { + std::unordered_map field_id_2_pos; + for (size_t i = 0; i < field.children.size(); i++) { + field_id_2_pos.emplace(field.children[i].field_id, i); + } + + for (size_t i = 0; i < col_type.children.size(); i++) { + auto it = field_id_2_pos.find(col_type.field_ids[i]); + if (it == field_id_2_pos.end()) { + pos[i] = -1; + continue; + } + pos[i] = it->second; + } + } else { + std::unordered_map field_name_2_pos; + for (size_t i = 0; i < field.children.size(); i++) { + const std::string& format_field_name = Utils::format_name(field.children[i].name, case_sensitive); + field_name_2_pos.emplace(format_field_name, i); + } + + if (!col_type.field_physical_names.empty()) { + for (size_t i = 0; i < col_type.children.size(); i++) { + const std::string& formatted_physical_name = + Utils::format_name(col_type.field_physical_names[i], case_sensitive); + + auto it = field_name_2_pos.find(formatted_physical_name); + if (it == field_name_2_pos.end()) { + pos[i] = -1; + continue; + } + pos[i] = it->second; + } + } else { + for (size_t i = 0; i < col_type.children.size(); i++) { + const std::string formatted_subfield_name = Utils::format_name(col_type.field_names[i], case_sensitive); + + auto it = field_name_2_pos.find(formatted_subfield_name); + if (it == field_name_2_pos.end()) { + pos[i] = -1; + continue; + } + pos[i] = it->second; + } + } + } +} + +void ColumnReaderFactory::get_subfield_pos_with_pruned_type( + const ParquetField& field, const TypeDescriptor& col_type, bool case_sensitive, + const TIcebergSchemaField* iceberg_schema_field, std::vector& pos, + std::vector& iceberg_schema_subfield) { + // For Struct type with schema change, we need to consider a subfield not existed situation. + // When Iceberg adds a new struct subfield, the original parquet file does not contain the newly added subfield. + std::unordered_map subfield_name_2_field_schema{}; + for (const auto& each : iceberg_schema_field->children) { + std::string format_subfield_name = case_sensitive ? each.name : boost::algorithm::to_lower_copy(each.name); + subfield_name_2_field_schema.emplace(format_subfield_name, &each); + } + + std::unordered_map field_id_2_pos{}; + for (size_t i = 0; i < field.children.size(); i++) { + field_id_2_pos.emplace(field.children[i].field_id, i); + } + for (size_t i = 0; i < col_type.children.size(); i++) { + const auto& format_subfield_name = + case_sensitive ? col_type.field_names[i] : boost::algorithm::to_lower_copy(col_type.field_names[i]); + + auto iceberg_it = subfield_name_2_field_schema.find(format_subfield_name); + if (iceberg_it == subfield_name_2_field_schema.end()) { + // This situation should not be happened, means table's struct subfield not existed in iceberg schema + // Below code is defensive + DCHECK(false) << "Struct subfield name: " + format_subfield_name + " not found in iceberg schema."; + pos[i] = -1; + iceberg_schema_subfield[i] = nullptr; + continue; + } + + int32_t field_id = iceberg_it->second->field_id; + + auto parquet_field_it = field_id_2_pos.find(field_id); + if (parquet_field_it == field_id_2_pos.end()) { + // Means newly added struct subfield not existed in an original parquet file, we put nullptr + // column reader in children_reader, we will append the default value for this subfield later. + pos[i] = -1; + iceberg_schema_subfield[i] = nullptr; + continue; + } + + pos[i] = parquet_field_it->second; + iceberg_schema_subfield[i] = iceberg_it->second; + } +} + +bool ColumnReaderFactory::_has_valid_subfield_column_reader( + const std::map>& children_readers) { + for (const auto& pair : children_readers) { + if (pair.second != nullptr) { + return true; + } + } + return false; +} + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/column_reader_factory.h b/be/src/formats/parquet/column_reader_factory.h new file mode 100644 index 0000000000000..376cad971f578 --- /dev/null +++ b/be/src/formats/parquet/column_reader_factory.h @@ -0,0 +1,46 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "formats/parquet/column_reader.h" + +namespace starrocks::parquet { + +class ColumnReaderFactory { +public: + // create a column reader + static StatusOr create(const ColumnReaderOptions& opts, const ParquetField* field, + const TypeDescriptor& col_type); + + // Create a column reader with iceberg schema + static StatusOr create(const ColumnReaderOptions& opts, const ParquetField* field, + const TypeDescriptor& col_type, + const TIcebergSchemaField* iceberg_schema_field); + +private: + // for struct type without schema change + static void get_subfield_pos_with_pruned_type(const ParquetField& field, const TypeDescriptor& col_type, + bool case_sensitive, std::vector& pos); + + // for schema changed + static void get_subfield_pos_with_pruned_type(const ParquetField& field, const TypeDescriptor& col_type, + bool case_sensitive, const TIcebergSchemaField* iceberg_schema_field, + std::vector& pos, + std::vector& iceberg_schema_subfield); + + static bool _has_valid_subfield_column_reader( + const std::map>& children_readers); +}; + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/complex_column_reader.cpp b/be/src/formats/parquet/complex_column_reader.cpp new file mode 100644 index 0000000000000..6bbcb66c0a6b4 --- /dev/null +++ b/be/src/formats/parquet/complex_column_reader.cpp @@ -0,0 +1,354 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "formats/parquet/complex_column_reader.h" + +#include "column/array_column.h" +#include "column/map_column.h" +#include "column/struct_column.h" +#include "formats/parquet/schema.h" +#include "gutil/casts.h" +#include "gutil/strings/substitute.h" + +namespace starrocks::parquet { + +template +static void def_rep_to_offset(const LevelInfo& level_info, const level_t* def_levels, const level_t* rep_levels, + size_t num_levels, TOffset* offsets, TIsNull* is_nulls, size_t* num_offsets, + bool* has_null) { + size_t offset_pos = 0; + for (int i = 0; i < num_levels; ++i) { + // when def_level is less than immediate_repeated_ancestor_def_level, it means that level + // will affect its ancestor. + // when rep_level is greater than max_rep_level, this means that level affects its + // descendants. + // So we can skip this levels + if (def_levels[i] < level_info.immediate_repeated_ancestor_def_level || + rep_levels[i] > level_info.max_rep_level) { + continue; + } + if (rep_levels[i] == level_info.max_rep_level) { + offsets[offset_pos]++; + continue; + } + + // Start for a new row + offset_pos++; + offsets[offset_pos] = offsets[offset_pos - 1]; + if (def_levels[i] >= level_info.max_def_level) { + offsets[offset_pos]++; + } + + // when def_level equals with max_def_level, this is a non null element or a required element + // when def_level equals with (max_def_level - 1), this indicates an empty array + // when def_level less than (max_def_level - 1) it means this array is null + if (def_levels[i] >= level_info.max_def_level - 1) { + is_nulls[offset_pos - 1] = 0; + } else { + is_nulls[offset_pos - 1] = 1; + *has_null = true; + } + } + *num_offsets = offset_pos; +} + +Status ListColumnReader::read_range(const Range& range, const Filter* filter, ColumnPtr& dst) { + NullableColumn* nullable_column = nullptr; + ArrayColumn* array_column = nullptr; + if (dst->is_nullable()) { + nullable_column = down_cast(dst.get()); + DCHECK(nullable_column->mutable_data_column()->is_array()); + array_column = down_cast(nullable_column->mutable_data_column()); + } else { + DCHECK(dst->is_array()); + DCHECK(!get_column_parquet_field()->is_nullable); + array_column = down_cast(dst.get()); + } + auto& child_column = array_column->elements_column(); + RETURN_IF_ERROR(_element_reader->read_range(range, filter, child_column)); + + level_t* def_levels = nullptr; + level_t* rep_levels = nullptr; + size_t num_levels = 0; + _element_reader->get_levels(&def_levels, &rep_levels, &num_levels); + + auto& offsets = array_column->offsets_column()->get_data(); + offsets.resize(num_levels + 1); + NullColumn null_column(num_levels); + auto& is_nulls = null_column.get_data(); + size_t num_offsets = 0; + bool has_null = false; + def_rep_to_offset(get_column_parquet_field()->level_info, def_levels, rep_levels, num_levels, &offsets[0], + &is_nulls[0], &num_offsets, &has_null); + offsets.resize(num_offsets + 1); + is_nulls.resize(num_offsets); + + if (dst->is_nullable()) { + DCHECK(nullable_column != nullptr); + nullable_column->mutable_null_column()->swap_column(null_column); + nullable_column->set_has_null(has_null); + } + + return Status::OK(); +} + +Status MapColumnReader::read_range(const Range& range, const Filter* filter, ColumnPtr& dst) { + NullableColumn* nullable_column = nullptr; + MapColumn* map_column = nullptr; + if (dst->is_nullable()) { + nullable_column = down_cast(dst.get()); + DCHECK(nullable_column->mutable_data_column()->is_map()); + map_column = down_cast(nullable_column->mutable_data_column()); + } else { + DCHECK(dst->is_map()); + DCHECK(!get_column_parquet_field()->is_nullable); + map_column = down_cast(dst.get()); + } + auto& key_column = map_column->keys_column(); + auto& value_column = map_column->values_column(); + if (_key_reader != nullptr) { + RETURN_IF_ERROR(_key_reader->read_range(range, filter, key_column)); + } + + if (_value_reader != nullptr) { + RETURN_IF_ERROR(_value_reader->read_range(range, filter, value_column)); + } + + // if neither key_reader not value_reader is nullptr , check the value_column size is the same with key_column + DCHECK((_key_reader == nullptr) || (_value_reader == nullptr) || (value_column->size() == key_column->size())); + + level_t* def_levels = nullptr; + level_t* rep_levels = nullptr; + size_t num_levels = 0; + + if (_key_reader != nullptr) { + _key_reader->get_levels(&def_levels, &rep_levels, &num_levels); + } else if (_value_reader != nullptr) { + _value_reader->get_levels(&def_levels, &rep_levels, &num_levels); + } else { + DCHECK(false) << "Unreachable!"; + } + + auto& offsets = map_column->offsets_column()->get_data(); + offsets.resize(num_levels + 1); + NullColumn null_column(num_levels); + auto& is_nulls = null_column.get_data(); + size_t num_offsets = 0; + bool has_null = false; + + // ParquetFiled Map -> Map> + def_rep_to_offset(get_column_parquet_field()->level_info, def_levels, rep_levels, num_levels, &offsets[0], + &is_nulls[0], &num_offsets, &has_null); + offsets.resize(num_offsets + 1); + is_nulls.resize(num_offsets); + + // fill with default + if (_key_reader == nullptr) { + key_column->append_default(offsets.back()); + } + if (_value_reader == nullptr) { + value_column->append_default(offsets.back()); + } + + if (dst->is_nullable()) { + DCHECK(nullable_column != nullptr); + nullable_column->mutable_null_column()->swap_column(null_column); + nullable_column->set_has_null(has_null); + } + + return Status::OK(); +} + +Status StructColumnReader::read_range(const Range& range, const Filter* filter, ColumnPtr& dst) { + NullableColumn* nullable_column = nullptr; + StructColumn* struct_column = nullptr; + if (dst->is_nullable()) { + nullable_column = down_cast(dst.get()); + DCHECK(nullable_column->mutable_data_column()->is_struct()); + struct_column = down_cast(nullable_column->mutable_data_column()); + } else { + DCHECK(dst->is_struct()); + DCHECK(!get_column_parquet_field()->is_nullable); + struct_column = down_cast(dst.get()); + } + + const auto& field_names = struct_column->field_names(); + + DCHECK_EQ(field_names.size(), _child_readers.size()); + + // Fill data for subfield column reader + size_t real_read = 0; + bool first_read = true; + for (size_t i = 0; i < field_names.size(); i++) { + const auto& field_name = field_names[i]; + if (LIKELY(_child_readers.find(field_name) != _child_readers.end())) { + if (_child_readers[field_name] != nullptr) { + auto& child_column = struct_column->field_column(field_name); + RETURN_IF_ERROR(_child_readers[field_name]->read_range(range, filter, child_column)); + real_read = child_column->size(); + first_read = false; + } + } else { + return Status::InternalError(strings::Substitute("there is no match subfield reader for $1", field_name)); + } + } + + if (UNLIKELY(first_read)) { + return Status::InternalError(strings::Substitute("All used subfield of struct type $1 is not exist", + get_column_parquet_field()->name)); + } + + for (size_t i = 0; i < field_names.size(); i++) { + const auto& field_name = field_names[i]; + if (_child_readers[field_name] == nullptr) { + Column* child_column = struct_column->field_column(field_name).get(); + child_column->append_default(real_read); + } + } + + if (dst->is_nullable()) { + DCHECK(nullable_column != nullptr); + size_t row_nums = struct_column->fields_column()[0]->size(); + NullColumn null_column(row_nums, 0); + auto& is_nulls = null_column.get_data(); + bool has_null = false; + _handle_null_rows(is_nulls.data(), &has_null, row_nums); + + nullable_column->mutable_null_column()->swap_column(null_column); + nullable_column->set_has_null(has_null); + } + return Status::OK(); +} + +bool StructColumnReader::try_to_use_dict_filter(ExprContext* ctx, bool is_decode_needed, const SlotId slotId, + const std::vector& sub_field_path, const size_t& layer) { + if (sub_field_path.size() <= layer) { + return false; + } + const std::string& sub_field = sub_field_path[layer]; + if (_child_readers.find(sub_field) == _child_readers.end()) { + return false; + } + + if (_child_readers[sub_field] == nullptr) { + return false; + } + return _child_readers[sub_field]->try_to_use_dict_filter(ctx, is_decode_needed, slotId, sub_field_path, layer + 1); +} + +Status StructColumnReader::filter_dict_column(const ColumnPtr& column, Filter* filter, + const std::vector& sub_field_path, const size_t& layer) { + const std::string& sub_field = sub_field_path[layer]; + StructColumn* struct_column = nullptr; + if (column->is_nullable()) { + NullableColumn* nullable_column = down_cast(column.get()); + DCHECK(nullable_column->mutable_data_column()->is_struct()); + struct_column = down_cast(nullable_column->mutable_data_column()); + } else { + DCHECK(column->is_struct()); + DCHECK(!get_column_parquet_field()->is_nullable); + struct_column = down_cast(column.get()); + } + return _child_readers[sub_field]->filter_dict_column(struct_column->field_column(sub_field), filter, sub_field_path, + layer + 1); +} + +Status StructColumnReader::fill_dst_column(ColumnPtr& dst, ColumnPtr& src) { + StructColumn* struct_column_src = nullptr; + StructColumn* struct_column_dst = nullptr; + if (src->is_nullable()) { + NullableColumn* nullable_column_src = down_cast(src.get()); + DCHECK(nullable_column_src->mutable_data_column()->is_struct()); + struct_column_src = down_cast(nullable_column_src->mutable_data_column()); + NullColumn* null_column_src = nullable_column_src->mutable_null_column(); + NullableColumn* nullable_column_dst = down_cast(dst.get()); + DCHECK(nullable_column_dst->mutable_data_column()->is_struct()); + struct_column_dst = down_cast(nullable_column_dst->mutable_data_column()); + NullColumn* null_column_dst = nullable_column_dst->mutable_null_column(); + null_column_dst->swap_column(*null_column_src); + nullable_column_src->update_has_null(); + nullable_column_dst->update_has_null(); + } else { + DCHECK(src->is_struct()); + DCHECK(dst->is_struct()); + DCHECK(!get_column_parquet_field()->is_nullable); + struct_column_src = down_cast(src.get()); + struct_column_dst = down_cast(dst.get()); + } + const auto& field_names = struct_column_dst->field_names(); + for (size_t i = 0; i < field_names.size(); i++) { + const auto& field_name = field_names[i]; + if (LIKELY(_child_readers.find(field_name) != _child_readers.end())) { + if (_child_readers[field_name] == nullptr) { + struct_column_dst->field_column(field_name) + ->swap_column(*(struct_column_src->field_column(field_name))); + } else { + RETURN_IF_ERROR(_child_readers[field_name]->fill_dst_column( + struct_column_dst->field_column(field_name), struct_column_src->field_column(field_name))); + } + } else { + return Status::InternalError(strings::Substitute("there is no match subfield reader for $1", field_name)); + } + } + return Status::OK(); +} + +void StructColumnReader::_handle_null_rows(uint8_t* is_nulls, bool* has_null, size_t num_rows) { + level_t* def_levels = nullptr; + level_t* rep_levels = nullptr; + size_t num_levels = 0; + (*_def_rep_level_child_reader)->get_levels(&def_levels, &rep_levels, &num_levels); + + if (def_levels == nullptr) { + // If subfields are required, def_levels is nullptr + *has_null = false; + return; + } + + LevelInfo level_info = get_column_parquet_field()->level_info; + + if (rep_levels != nullptr) { + // It's a RepeatedStoredColumnReader + size_t rows = 0; + for (size_t i = 0; i < num_levels; i++) { + if (def_levels[i] < level_info.immediate_repeated_ancestor_def_level || + rep_levels[i] > level_info.max_rep_level) { + continue; + } + + // Start for a new row + if (def_levels[i] >= level_info.max_def_level) { + is_nulls[rows] = 0; + } else { + is_nulls[rows] = 1; + *has_null = true; + } + rows++; + } + DCHECK_EQ(num_rows, rows); + } else { + // For OptionalStoredColumnReader, num_levels is equal to num_rows + DCHECK(num_rows == num_levels); + for (size_t i = 0; i < num_levels; i++) { + if (def_levels[i] >= level_info.max_def_level) { + is_nulls[i] = 0; + } else { + is_nulls[i] = 1; + *has_null = true; + } + } + } +} + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/complex_column_reader.h b/be/src/formats/parquet/complex_column_reader.h new file mode 100644 index 0000000000000..3a1b8e094bf0d --- /dev/null +++ b/be/src/formats/parquet/complex_column_reader.h @@ -0,0 +1,222 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "formats/parquet/column_reader.h" + +namespace starrocks::parquet { + +class ListColumnReader final : public ColumnReader { +public: + explicit ListColumnReader(const ParquetField* parquet_field, std::unique_ptr&& element_reader) + : ColumnReader(parquet_field), _element_reader(std::move(element_reader)) {} + ~ListColumnReader() override = default; + + Status prepare() override { return _element_reader->prepare(); } + + Status read_range(const Range& range, const Filter* filter, ColumnPtr& dst) override; + + void get_levels(level_t** def_levels, level_t** rep_levels, size_t* num_levels) override { + _element_reader->get_levels(def_levels, rep_levels, num_levels); + } + + void set_need_parse_levels(bool need_parse_levels) override { + _element_reader->set_need_parse_levels(need_parse_levels); + } + + void collect_column_io_range(std::vector* ranges, int64_t* end_offset, + ColumnIOType type, bool active) override { + _element_reader->collect_column_io_range(ranges, end_offset, type, active); + } + + void select_offset_index(const SparseRange& range, const uint64_t rg_first_row) override { + _element_reader->select_offset_index(range, rg_first_row); + } + +private: + std::unique_ptr _element_reader; +}; + +class MapColumnReader final : public ColumnReader { +public: + explicit MapColumnReader(const ParquetField* parquet_field, std::unique_ptr&& key_reader, + std::unique_ptr&& value_reader) + : ColumnReader(parquet_field), _key_reader(std::move(key_reader)), _value_reader(std::move(value_reader)) {} + ~MapColumnReader() override = default; + + Status prepare() override { + // Check must has one valid column reader + if (_key_reader == nullptr && _value_reader == nullptr) { + return Status::InternalError("No available subfield column reader in MapColumnReader"); + } + + if (_key_reader != nullptr) { + RETURN_IF_ERROR(_key_reader->prepare()); + } + if (_value_reader != nullptr) { + RETURN_IF_ERROR(_value_reader->prepare()); + } + + return Status::OK(); + } + + Status read_range(const Range& range, const Filter* filter, ColumnPtr& dst) override; + + void get_levels(level_t** def_levels, level_t** rep_levels, size_t* num_levels) override { + // check _value_reader + if (_key_reader != nullptr) { + _key_reader->get_levels(def_levels, rep_levels, num_levels); + } else if (_value_reader != nullptr) { + _value_reader->get_levels(def_levels, rep_levels, num_levels); + } else { + DCHECK(false) << "Unreachable!"; + } + } + + void set_need_parse_levels(bool need_parse_levels) override { + if (_key_reader != nullptr) { + _key_reader->set_need_parse_levels(need_parse_levels); + } + + if (_value_reader != nullptr) { + _value_reader->set_need_parse_levels(need_parse_levels); + } + } + + void collect_column_io_range(std::vector* ranges, int64_t* end_offset, + ColumnIOType type, bool active) override { + if (_key_reader != nullptr) { + _key_reader->collect_column_io_range(ranges, end_offset, type, active); + } + if (_value_reader != nullptr) { + _value_reader->collect_column_io_range(ranges, end_offset, type, active); + } + } + + void select_offset_index(const SparseRange& range, const uint64_t rg_first_row) override { + if (_key_reader != nullptr) { + _key_reader->select_offset_index(range, rg_first_row); + } + if (_value_reader != nullptr) { + _value_reader->select_offset_index(range, rg_first_row); + } + } + +private: + std::unique_ptr _key_reader; + std::unique_ptr _value_reader; +}; + +class StructColumnReader final : public ColumnReader { +public: + explicit StructColumnReader(const ParquetField* parquet_field, + std::map>&& child_readers) + : ColumnReader(parquet_field), _child_readers(std::move(child_readers)) {} + ~StructColumnReader() override = default; + + Status prepare() override { + if (_child_readers.empty()) { + return Status::InternalError("No avaliable parquet subfield column reader in StructColumn"); + } + + for (const auto& child : _child_readers) { + if (child.second != nullptr) { + RETURN_IF_ERROR(child.second->prepare()); + } + } + + for (const auto& pair : _child_readers) { + if (pair.second != nullptr) { + _def_rep_level_child_reader = &(pair.second); + return Status::OK(); + } + } + + return Status::InternalError("No existed parquet subfield column reader in StructColumn"); + } + + Status read_range(const Range& range, const Filter* filter, ColumnPtr& dst) override; + + void set_can_lazy_decode(bool can_lazy_decode) override { + for (const auto& kv : _child_readers) { + if (kv.second == nullptr) continue; + kv.second->set_can_lazy_decode(can_lazy_decode); + } + } + + // get_levels functions only called by complex type + // If parent is a struct type, only def_levels has value. + // If parent is list or map type, def_levels & rep_levels both have value. + void get_levels(level_t** def_levels, level_t** rep_levels, size_t* num_levels) override { + for (const auto& pair : _child_readers) { + // Considering not existed subfield, we will not create its ColumnReader + // So we should pick up the first existed subfield column reader + if (pair.second != nullptr) { + pair.second->get_levels(def_levels, rep_levels, num_levels); + return; + } + } + } + + void set_need_parse_levels(bool need_parse_levels) override { + for (const auto& pair : _child_readers) { + if (pair.second != nullptr) { + pair.second->set_need_parse_levels(need_parse_levels); + } + } + } + + bool try_to_use_dict_filter(ExprContext* ctx, bool is_decode_needed, const SlotId slotId, + const std::vector& sub_field_path, const size_t& layer) override; + + Status rewrite_conjunct_ctxs_to_predicate(bool* is_group_filtered, const std::vector& sub_field_path, + const size_t& layer) override { + const std::string& sub_field = sub_field_path[layer]; + return _child_readers[sub_field]->rewrite_conjunct_ctxs_to_predicate(is_group_filtered, sub_field_path, + layer + 1); + } + + Status filter_dict_column(const ColumnPtr& column, Filter* filter, const std::vector& sub_field_path, + const size_t& layer) override; + + Status fill_dst_column(ColumnPtr& dst, ColumnPtr& src) override; + + void collect_column_io_range(std::vector* ranges, int64_t* end_offset, + ColumnIOType type, bool active) override { + for (const auto& pair : _child_readers) { + if (pair.second != nullptr) { + pair.second->collect_column_io_range(ranges, end_offset, type, active); + } + } + } + + void select_offset_index(const SparseRange& range, const uint64_t rg_first_row) override { + for (const auto& pair : _child_readers) { + if (pair.second != nullptr) { + pair.second->select_offset_index(range, rg_first_row); + } + } + } + +private: + void _handle_null_rows(uint8_t* is_nulls, bool* has_null, size_t num_rows); + + // _children_readers order is the same as TypeDescriptor children order. + std::map _child_readers; + // First non-nullptr child ColumnReader, used to get def & rep levels + const std::unique_ptr* _def_rep_level_child_reader = nullptr; +}; + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/encoding.cpp b/be/src/formats/parquet/encoding.cpp index 30fdaf9dbc3f0..5a1aaef313678 100644 --- a/be/src/formats/parquet/encoding.cpp +++ b/be/src/formats/parquet/encoding.cpp @@ -14,7 +14,15 @@ #include "formats/parquet/encoding.h" +<<<<<<< HEAD #include +======= +#include +#include +#include +#include +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/encoding_dict.h" #include "formats/parquet/encoding_plain.h" diff --git a/be/src/formats/parquet/encoding.h b/be/src/formats/parquet/encoding.h index 84febeaec39c8..08de22fd96752 100644 --- a/be/src/formats/parquet/encoding.h +++ b/be/src/formats/parquet/encoding.h @@ -14,9 +14,20 @@ #pragma once +<<<<<<< HEAD #include #include +======= +#include +#include + +#include +#include +#include + +#include "column/vectorized_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/status.h" #include "gen_cpp/parquet_types.h" #include "utils.h" @@ -56,8 +67,12 @@ class Decoder { virtual Status get_dict_values(Column* column) { return Status::NotSupported("get_dict_values is not supported"); } +<<<<<<< HEAD virtual Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) { +======= + virtual Status get_dict_values(const Buffer& dict_codes, const NullableColumn& nulls, Column* column) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::NotSupported("get_dict_values is not supported"); } diff --git a/be/src/formats/parquet/encoding_dict.h b/be/src/formats/parquet/encoding_dict.h index 95f8f561eefe9..fc3510d90753e 100644 --- a/be/src/formats/parquet/encoding_dict.h +++ b/be/src/formats/parquet/encoding_dict.h @@ -19,6 +19,10 @@ #include "column/column.h" #include "column/column_helper.h" +<<<<<<< HEAD +======= +#include "column/nullable_column.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/status.h" #include "formats/parquet/encoding.h" #include "simd/simd.h" @@ -107,9 +111,16 @@ class DictDecoder final : public Decoder { } Status skip(size_t values_to_skip) override { +<<<<<<< HEAD //TODO(Smith) still heavy work load _indexes.reserve(values_to_skip); _rle_batch_reader.GetBatch(&_indexes[0], values_to_skip); +======= + auto ret = _rle_batch_reader.SkipBatch(values_to_skip); + if (UNLIKELY(ret != values_to_skip)) { + return Status::InternalError("rle skip error, not enough values"); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -186,9 +197,14 @@ class DictDecoder final : public Decoder { return Status::OK(); } +<<<<<<< HEAD Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) override { const std::vector& null_data = nulls.immutable_null_column_data(); +======= + Status get_dict_values(const Buffer& dict_codes, const NullableColumn& nulls, Column* column) override { + const NullData& null_data = nulls.immutable_null_column_data(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool has_null = nulls.has_null(); bool all_null = false; @@ -243,9 +259,16 @@ class DictDecoder final : public Decoder { } Status skip(size_t values_to_skip) override { +<<<<<<< HEAD //TODO(Smith) still heavy work load _indexes.reserve(values_to_skip); _rle_batch_reader.GetBatch(&_indexes[0], values_to_skip); +======= + auto ret = _rle_batch_reader.SkipBatch(values_to_skip); + if (UNLIKELY(ret != values_to_skip)) { + return Status::InternalError("rle skip error, not enough values"); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -293,7 +316,10 @@ class DictDecoder final : public Decoder { std::vector _dict; std::vector _indexes; std::vector _slices; +<<<<<<< HEAD +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t _max_value_length = 0; }; diff --git a/be/src/formats/parquet/file_reader.cpp b/be/src/formats/parquet/file_reader.cpp index b1684c84d5eb3..f9a198690c1f9 100644 --- a/be/src/formats/parquet/file_reader.cpp +++ b/be/src/formats/parquet/file_reader.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/file_reader.h" +<<<<<<< HEAD #include "column/column_helper.h" #include "column/vectorized_fwd.h" #include "common/config.h" @@ -35,10 +36,58 @@ #include "util/coding.h" #include "util/defer_op.h" #include "util/memcmp.h" +======= +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "block_cache/kv_cache.h" +#include "column/chunk.h" +#include "column/column.h" +#include "column/column_helper.h" +#include "column/const_column.h" +#include "column/datum.h" +#include "column/vectorized_fwd.h" +#include "common/compiler_util.h" +#include "common/config.h" +#include "common/global_types.h" +#include "common/logging.h" +#include "common/status.h" +#include "exec/hdfs_scanner.h" +#include "exprs/expr_context.h" +#include "exprs/runtime_filter.h" +#include "exprs/runtime_filter_bank.h" +#include "formats/parquet/column_converter.h" +#include "formats/parquet/metadata.h" +#include "formats/parquet/scalar_column_reader.h" +#include "formats/parquet/schema.h" +#include "formats/parquet/statistics_helper.h" +#include "formats/parquet/utils.h" +#include "formats/parquet/zone_map_filter_evaluator.h" +#include "fs/fs.h" +#include "gen_cpp/PlanNodes_types.h" +#include "gen_cpp/parquet_types.h" +#include "gutil/casts.h" +#include "gutil/strings/substitute.h" +#include "io/shared_buffered_input_stream.h" +#include "runtime/descriptors.h" +#include "runtime/types.h" +#include "storage/chunk_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/thrift_util.h" namespace starrocks::parquet { +<<<<<<< HEAD struct SplitContext : public HdfsSplitContext { FileMetaDataPtr file_metadata; @@ -80,6 +129,8 @@ static int64_t _get_row_group_end_offset(const tparquet::RowGroup& row_group) { return _get_column_start_offset(last_column) + last_column.total_compressed_size; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) FileReader::FileReader(int chunk_size, RandomAccessFile* file, size_t file_size, const DataCacheOptions& datacache_options, io::SharedBufferedInputStream* sb_stream, const std::set* _need_skip_rowids) @@ -92,6 +143,7 @@ FileReader::FileReader(int chunk_size, RandomAccessFile* file, size_t file_size, FileReader::~FileReader() = default; +<<<<<<< HEAD std::string FileReader::_build_metacache_key() { auto& filename = _file->filename(); std::string metacache_key; @@ -115,6 +167,8 @@ std::string FileReader::_build_metacache_key() { return metacache_key; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status FileReader::init(HdfsScannerContext* ctx) { _scanner_ctx = ctx; #ifdef WITH_STARCACHE @@ -123,7 +177,13 @@ Status FileReader::init(HdfsScannerContext* ctx) { _cache = BlockCache::instance(); } #endif +<<<<<<< HEAD RETURN_IF_ERROR(_get_footer()); +======= + // parse FileMetadata + FileMetaDataParser file_metadata_parser{_file, ctx, _cache, &_datacache_options, _file_size}; + ASSIGN_OR_RETURN(_file_metadata, file_metadata_parser.get_file_metadata()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // set existed SlotDescriptor in this parquet file std::unordered_set existed_column_names; @@ -171,6 +231,7 @@ Status FileReader::collect_scan_io_ranges(std::vector footer_buffer; ASSIGN_OR_RETURN(uint32_t footer_read_size, _get_footer_read_size()); @@ -268,6 +329,8 @@ Status FileReader::_get_footer() { return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status FileReader::_build_split_tasks() { // dont do split in following cases: // 1. this feature is not enabled @@ -279,6 +342,7 @@ Status FileReader::_build_split_tasks() { size_t row_group_size = _file_metadata->t_metadata().row_groups.size(); for (size_t i = 0; i < row_group_size; i++) { const tparquet::RowGroup& row_group = _file_metadata->t_metadata().row_groups[i]; +<<<<<<< HEAD bool selected = _select_row_group(row_group); if (!selected) continue; if (_filter_group(row_group)) { @@ -287,6 +351,11 @@ Status FileReader::_build_split_tasks() { } int64_t start_offset = _get_row_group_start_offset(row_group); int64_t end_offset = _get_row_group_end_offset(row_group); +======= + if (!_select_row_group(row_group)) continue; + int64_t start_offset = ParquetUtils::get_row_group_start_offset(row_group); + int64_t end_offset = ParquetUtils::get_row_group_end_offset(row_group); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (start_offset >= end_offset) { LOG(INFO) << "row group " << i << " is empty. start = " << start_offset << ", end = " << end_offset; continue; @@ -299,7 +368,11 @@ Status FileReader::_build_split_tasks() { // so as long as `end_offset > start_offset && end_offset <= start_offset(next_group)`, it's ok if ((i + 1) < row_group_size) { const tparquet::RowGroup& next_row_group = _file_metadata->t_metadata().row_groups[i + 1]; +<<<<<<< HEAD DCHECK(end_offset <= _get_row_group_start_offset(next_row_group)); +======= + DCHECK(end_offset <= ParquetUtils::get_row_group_start_offset(next_row_group)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } #endif auto split_ctx = std::make_unique(); @@ -325,6 +398,7 @@ Status FileReader::_build_split_tasks() { return Status::OK(); } +<<<<<<< HEAD StatusOr FileReader::_get_footer_read_size() const { if (_file_size == 0) { return Status::Corruption("Parquet file size is 0 bytes"); @@ -356,13 +430,20 @@ StatusOr FileReader::_parse_metadata_length(const std::vector& f } bool FileReader::_filter_group_with_min_max_conjuncts(const tparquet::RowGroup& row_group) { +======= +bool FileReader::_filter_group_with_min_max_conjuncts(const GroupReaderPtr& group_reader) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // filter by min/max conjunct ctxs. if (!_scanner_ctx->min_max_conjunct_ctxs.empty()) { const TupleDescriptor& tuple_desc = *(_scanner_ctx->min_max_tuple_desc); ChunkPtr min_chunk = ChunkHelper::new_chunk(tuple_desc, 0); ChunkPtr max_chunk = ChunkHelper::new_chunk(tuple_desc, 0); +<<<<<<< HEAD auto st = _read_min_max_chunk(row_group, tuple_desc.slots(), &min_chunk, &max_chunk); +======= + auto st = _read_min_max_chunk(group_reader, tuple_desc.slots(), &min_chunk, &max_chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!st.ok()) { // if there are some error when dealing statistics, shouldn't return the error status, // just read data ignore the statistics. @@ -376,8 +457,13 @@ bool FileReader::_filter_group_with_min_max_conjuncts(const tparquet::RowGroup& // maybe one of the conjuncts encounter error when dealing statistics, just ignore it and continue continue; } +<<<<<<< HEAD auto min_column = res_min.value(); auto max_column = res_max.value(); +======= + const auto& min_column = res_min.value(); + const auto& max_column = res_max.value(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto f = [&](Column* c) { // is_null(0) only when something unexpected happens if (c->is_null(0)) return (int8_t)0; @@ -393,20 +479,32 @@ bool FileReader::_filter_group_with_min_max_conjuncts(const tparquet::RowGroup& return false; } +<<<<<<< HEAD bool FileReader::_filter_group_with_bloom_filter_min_max_conjuncts(const tparquet::RowGroup& row_group) { +======= +bool FileReader::_filter_group_with_bloom_filter_min_max_conjuncts(const GroupReaderPtr& group_reader) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // filter by min/max in runtime filter. if (_scanner_ctx->runtime_filter_collector) { std::vector min_max_slots(1); +<<<<<<< HEAD const TupleDescriptor& tuple_desc = *(_scanner_ctx->tuple_desc); const std::vector& slots = tuple_desc.slots(); +======= + const std::vector& slots = _scanner_ctx->slot_descs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto& it : _scanner_ctx->runtime_filter_collector->descriptors()) { RuntimeFilterProbeDescriptor* rf_desc = it.second; // external node won't have colocate runtime filter const JoinRuntimeFilter* filter = rf_desc->runtime_filter(-1); SlotId probe_slot_id; +<<<<<<< HEAD if (filter == nullptr || filter->has_null() || !rf_desc->is_probe_slot_ref(&probe_slot_id)) continue; +======= + if (filter == nullptr || !rf_desc->is_probe_slot_ref(&probe_slot_id)) continue; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // !!linear search slot by slot_id. SlotDescriptor* slot = nullptr; for (SlotDescriptor* s : slots) { @@ -417,6 +515,7 @@ bool FileReader::_filter_group_with_bloom_filter_min_max_conjuncts(const tparque } if (!slot) continue; min_max_slots[0] = slot; +<<<<<<< HEAD ChunkPtr min_chunk = ChunkHelper::new_chunk(min_max_slots, 0); ChunkPtr max_chunk = ChunkHelper::new_chunk(min_max_slots, 0); @@ -426,12 +525,37 @@ bool FileReader::_filter_group_with_bloom_filter_min_max_conjuncts(const tparque slot->type().type, filter, min_chunk->columns()[0].get(), max_chunk->columns()[0].get()); if (discard) { return true; +======= + + if (filter->has_null()) { + std::vector has_nulls; + auto st = _read_has_nulls(group_reader, min_max_slots, &has_nulls); + if (!st.ok()) continue; + + if (has_nulls[0]) { + continue; + } + } + + { + ChunkPtr min_chunk = ChunkHelper::new_chunk(min_max_slots, 0); + ChunkPtr max_chunk = ChunkHelper::new_chunk(min_max_slots, 0); + + auto st = _read_min_max_chunk(group_reader, min_max_slots, &min_chunk, &max_chunk); + if (!st.ok()) continue; + bool discard = RuntimeFilterHelper::filter_zonemap_with_min_max( + slot->type().type, filter, min_chunk->columns()[0].get(), max_chunk->columns()[0].get()); + if (discard) { + return true; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } return false; } +<<<<<<< HEAD bool FileReader::_filter_group_with_more_filter(const tparquet::RowGroup& row_group) { // runtime_in_filter, the sql-original in_filter and is_null/not_null filter will be in // _scanner_ctx->conjunct_ctxs_by_slot @@ -441,17 +565,41 @@ bool FileReader::_filter_group_with_more_filter(const tparquet::RowGroup& row_gr if (StatisticsHelper::can_be_used_for_statistics_filter(ctx, filter_type)) { const TupleDescriptor& tuple_desc = *(_scanner_ctx->tuple_desc); SlotDescriptor* slot = tuple_desc.get_slot_by_id(kv.first); +======= +bool FileReader::_filter_group_with_more_filter(const GroupReaderPtr& group_reader) { + // runtime_in_filter, the sql-original in_filter and is_null/not_null filter will be in + // _scanner_ctx->conjunct_ctxs_by_slot + for (const auto& kv : _scanner_ctx->conjunct_ctxs_by_slot) { + StatisticsHelper::StatSupportedFilter filter_type; + for (auto ctx : kv.second) { + if (StatisticsHelper::can_be_used_for_statistics_filter(ctx, filter_type)) { + SlotDescriptor* slot = nullptr; + for (auto s : _scanner_ctx->slot_descs) { + if (s->id() == kv.first) { + slot = s; + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (UNLIKELY(slot == nullptr)) { // it shouldn't be here, just some defensive code DCHECK(false) << "couldn't find slot id " << kv.first << " in tuple desc"; LOG(WARNING) << "couldn't find slot id " << kv.first << " in tuple desc"; continue; } +<<<<<<< HEAD std::unordered_map column_name_2_pos_in_meta{}; std::vector slot_v{slot}; _meta_helper->build_column_name_2_pos_in_meta(column_name_2_pos_in_meta, slot_v); const tparquet::ColumnMetaData* column_meta = _meta_helper->get_column_meta(column_name_2_pos_in_meta, row_group, slot->col_name()); +======= + const tparquet::ColumnMetaData* column_meta = nullptr; + const tparquet::ColumnChunk* column_chunk = group_reader->get_chunk_metadata(slot->id()); + if (column_chunk && column_chunk->__isset.meta_data) { + column_meta = &column_chunk->meta_data; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (column_meta == nullptr || !column_meta->__isset.statistics) continue; if (filter_type == StatisticsHelper::StatSupportedFilter::IS_NULL) { if (!column_meta->statistics.__isset.null_count) continue; @@ -460,19 +608,32 @@ bool FileReader::_filter_group_with_more_filter(const tparquet::RowGroup& row_gr } } else if (filter_type == StatisticsHelper::StatSupportedFilter::IS_NOT_NULL) { if (!column_meta->statistics.__isset.null_count) continue; +<<<<<<< HEAD if (column_meta->statistics.null_count == row_group.num_rows) { +======= + if (column_meta->statistics.null_count == group_reader->get_row_group_metadata()->num_rows) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return true; } } else if (filter_type == StatisticsHelper::StatSupportedFilter::FILTER_IN) { std::vector min_values; std::vector max_values; +<<<<<<< HEAD const ParquetField* field = _meta_helper->get_parquet_field(slot); +======= + const ParquetField* field = group_reader->get_column_parquet_field(slot->id()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (field == nullptr) { LOG(WARNING) << "Can't get " + slot->col_name() + "'s ParquetField in _read_min_max_chunk."; continue; } +<<<<<<< HEAD auto st = _get_min_max_value(slot, column_meta, field, min_values, max_values); +======= + auto st = StatisticsHelper::get_min_max_value(_file_metadata.get(), slot->type(), column_meta, + field, min_values, max_values); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!st.ok()) continue; Filter selected(min_values.size(), 1); st = StatisticsHelper::in_filter_on_min_max_stat(min_values, max_values, ctx, field, @@ -490,6 +651,7 @@ bool FileReader::_filter_group_with_more_filter(const tparquet::RowGroup& row_gr // when doing row group filter, there maybe some error, but we'd better just ignore it instead of returning the error // status and lead to the query failed. +<<<<<<< HEAD bool FileReader::_filter_group(const tparquet::RowGroup& row_group) { if (_filter_group_with_min_max_conjuncts(row_group)) { return true; @@ -519,6 +681,91 @@ Status FileReader::_read_min_max_chunk(const tparquet::RowGroup& row_group, cons const SlotDescriptor* slot = slots[i]; const tparquet::ColumnMetaData* column_meta = _meta_helper->get_column_meta(column_name_2_pos_in_meta, row_group, slot->col_name()); +======= +bool FileReader::_filter_group(const GroupReaderPtr& group_reader) { + if (config::parquet_advance_zonemap_filter) { + auto res = _scanner_ctx->predicate_tree.visit( + ZoneMapEvaluator{_scanner_ctx->predicate_tree, group_reader.get()}); + if (!res.ok()) { + LOG(WARNING) << "filter row group failed: " << res.status().message(); + return false; + } + if (res.value().has_value() && res.value()->span_size() == 0) { + // no rows selected, the whole row group can be filtered + return true; + } + return false; + } else { + if (_filter_group_with_min_max_conjuncts(group_reader)) { + return true; + } + + if (_filter_group_with_bloom_filter_min_max_conjuncts(group_reader)) { + return true; + } + + if (config::parquet_statistics_process_more_filter_enable && _filter_group_with_more_filter(group_reader)) { + return true; + } + + return false; + } +} + +Status FileReader::_read_has_nulls(const GroupReaderPtr& group_reader, const std::vector& slots, + std::vector* has_nulls) { + const HdfsScannerContext& ctx = *_scanner_ctx; + + for (size_t i = 0; i < slots.size(); i++) { + const SlotDescriptor* slot = slots[i]; + const tparquet::ColumnMetaData* column_meta = nullptr; + const tparquet::ColumnChunk* column_chunk = group_reader->get_chunk_metadata(slot->id()); + if (column_chunk && column_chunk->__isset.meta_data) { + column_meta = &column_chunk->meta_data; + } + if (column_meta == nullptr) { + int col_idx = _get_partition_column_idx(slot->col_name()); + if (col_idx < 0) { + // column not exist in parquet file + (*has_nulls).emplace_back(true); + } else { + // is partition column + auto* const_column = ColumnHelper::as_raw_column(ctx.partition_values[col_idx]); + ColumnPtr data_column = const_column->data_column(); + if (data_column->is_nullable()) { + (*has_nulls).emplace_back(true); + } else { + (*has_nulls).emplace_back(false); + } + } + } else if (!column_meta->__isset.statistics) { + // statistics not exist in parquet file + return Status::Aborted("No exist statistics"); + } else { + const ParquetField* field = group_reader->get_column_parquet_field(slot->id()); + if (field == nullptr) { + LOG(WARNING) << "Can't get " + slot->col_name() + "'s ParquetField in _read_has_nulls."; + return Status::InternalError(strings::Substitute("Can't get $0 field", slot->col_name())); + } + RETURN_IF_ERROR(StatisticsHelper::get_has_nulls(column_meta, *has_nulls)); + } + } + + return Status::OK(); +} + +Status FileReader::_read_min_max_chunk(const GroupReaderPtr& group_reader, const std::vector& slots, + ChunkPtr* min_chunk, ChunkPtr* max_chunk) const { + const HdfsScannerContext& ctx = *_scanner_ctx; + + for (size_t i = 0; i < slots.size(); i++) { + const SlotDescriptor* slot = slots[i]; + const tparquet::ColumnMetaData* column_meta = nullptr; + const tparquet::ColumnChunk* column_chunk = group_reader->get_chunk_metadata(slot->id()); + if (column_chunk && column_chunk->__isset.meta_data) { + column_meta = &column_chunk->meta_data; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (column_meta == nullptr) { int col_idx = _get_partition_column_idx(slot->col_name()); if (col_idx < 0) { @@ -544,13 +791,22 @@ Status FileReader::_read_min_max_chunk(const tparquet::RowGroup& row_group, cons std::vector min_values; std::vector max_values; +<<<<<<< HEAD const ParquetField* field = _meta_helper->get_parquet_field(slot); +======= + const ParquetField* field = group_reader->get_column_parquet_field(slot->id()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (field == nullptr) { LOG(WARNING) << "Can't get " + slot->col_name() + "'s ParquetField in _read_min_max_chunk."; return Status::InternalError(strings::Substitute("Can't get $0 field", slot->col_name())); } +<<<<<<< HEAD RETURN_IF_ERROR(_get_min_max_value(slot, column_meta, field, min_values, max_values)); +======= + RETURN_IF_ERROR(StatisticsHelper::get_min_max_value(_file_metadata.get(), slot->type(), column_meta, field, + min_values, max_values)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(StatisticsHelper::decode_value_into_column((*min_chunk)->columns()[i], min_values, slot->type(), field, ctx.timezone)); RETURN_IF_ERROR(StatisticsHelper::decode_value_into_column((*max_chunk)->columns()[i], max_values, @@ -570,6 +826,7 @@ int32_t FileReader::_get_partition_column_idx(const std::string& col_name) const return -1; } +<<<<<<< HEAD Status FileReader::_get_min_max_value(const SlotDescriptor* slot, const tparquet::ColumnMetaData* column_meta, const ParquetField* field, std::vector& min_values, std::vector& max_values) const { @@ -604,6 +861,8 @@ bool FileReader::_has_correct_min_max_stats(const tparquet::ColumnMetaData& colu return _file_metadata->writer_version().HasCorrectStatistics(column_meta, sort_order); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void FileReader::_prepare_read_columns(std::unordered_set& existed_column_names) { _meta_helper->prepare_read_columns(_scanner_ctx->materialized_columns, _group_reader_param.read_cols, existed_column_names); @@ -611,7 +870,11 @@ void FileReader::_prepare_read_columns(std::unordered_set& existed_ } bool FileReader::_select_row_group(const tparquet::RowGroup& row_group) { +<<<<<<< HEAD size_t row_group_start = _get_row_group_start_offset(row_group); +======= + size_t row_group_start = ParquetUtils::get_row_group_start_offset(row_group); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const auto* scan_range = _scanner_ctx->scan_range; size_t scan_start = scan_range->offset; size_t scan_end = scan_range->length + scan_start; @@ -625,7 +888,10 @@ Status FileReader::_init_group_readers() { const HdfsScannerContext& fd_scanner_ctx = *_scanner_ctx; // _group_reader_param is used by all group readers +<<<<<<< HEAD _group_reader_param.tuple_desc = fd_scanner_ctx.tuple_desc; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _group_reader_param.conjunct_ctxs_by_slot = fd_scanner_ctx.conjunct_ctxs_by_slot; _group_reader_param.timezone = fd_scanner_ctx.timezone; _group_reader_param.stats = fd_scanner_ctx.stats; @@ -635,12 +901,22 @@ Status FileReader::_init_group_readers() { _group_reader_param.file_metadata = _file_metadata.get(); _group_reader_param.case_sensitive = fd_scanner_ctx.case_sensitive; _group_reader_param.lazy_column_coalesce_counter = fd_scanner_ctx.lazy_column_coalesce_counter; +<<<<<<< HEAD // for pageIndex _group_reader_param.min_max_conjunct_ctxs = fd_scanner_ctx.min_max_conjunct_ctxs; +======= + _group_reader_param.partition_columns = &fd_scanner_ctx.partition_columns; + _group_reader_param.partition_values = &fd_scanner_ctx.partition_values; + _group_reader_param.not_existed_slots = &fd_scanner_ctx.not_existed_slots; + // for pageIndex + _group_reader_param.min_max_conjunct_ctxs = fd_scanner_ctx.min_max_conjunct_ctxs; + _group_reader_param.predicate_tree = &fd_scanner_ctx.predicate_tree; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t row_group_first_row = 0; // select and create row group readers. for (size_t i = 0; i < _file_metadata->t_metadata().row_groups.size(); i++) { +<<<<<<< HEAD bool selected = _select_row_group(_file_metadata->t_metadata().row_groups[i]); if (i > 0) { @@ -676,6 +952,41 @@ Status FileReader::_init_group_readers() { RETURN_IF_ERROR(r->init()); } +======= + if (i > 0) { + row_group_first_row += _file_metadata->t_metadata().row_groups[i - 1].num_rows; + } + + if (!_select_row_group(_file_metadata->t_metadata().row_groups[i])) { + continue; + } + + auto row_group_reader = + std::make_shared(_group_reader_param, i, _need_skip_rowids, row_group_first_row); + RETURN_IF_ERROR(row_group_reader->init()); + + _group_reader_param.stats->parquet_total_row_groups += 1; + + // You should call row_group_reader->init() before _filter_group() + if (_filter_group(row_group_reader)) { + DLOG(INFO) << "row group " << i << " of file has been filtered by min/max conjunct"; + _group_reader_param.stats->parquet_filtered_row_groups += 1; + continue; + } + + _row_group_readers.emplace_back(row_group_reader); + int64_t num_rows = _file_metadata->t_metadata().row_groups[i].num_rows; + // for iceberg v2 pos delete + if (_need_skip_rowids != nullptr && !_need_skip_rowids->empty()) { + auto start_iter = _need_skip_rowids->lower_bound(row_group_first_row); + auto end_iter = _need_skip_rowids->upper_bound(row_group_first_row + num_rows - 1); + num_rows -= std::distance(start_iter, end_iter); + } + _total_row_count += num_rows; + } + _row_group_size = _row_group_readers.size(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // collect pageIndex io ranges. if (config::parquet_coalesce_read_enable && _sb_stream != nullptr && config::parquet_page_index_enable) { std::vector ranges; @@ -710,10 +1021,19 @@ Status FileReader::get_next(ChunkPtr* chunk) { if (row_count > 0) { RETURN_IF_ERROR(_scanner_ctx->append_or_update_not_existed_columns_to_chunk(chunk, row_count)); _scanner_ctx->append_or_update_partition_column_to_chunk(chunk, row_count); +<<<<<<< HEAD _scan_row_count += (*chunk)->num_rows(); } if (status.is_end_of_file()) { _row_group_readers[_cur_row_group_idx]->close(); +======= + _scanner_ctx->append_or_update_extended_column_to_chunk(chunk, row_count); + _scan_row_count += (*chunk)->num_rows(); + } + if (status.is_end_of_file()) { + // release previous RowGroupReader + _row_group_readers[_cur_row_group_idx] = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _cur_row_group_idx++; if (_cur_row_group_idx < _row_group_size) { // prepare new group @@ -742,10 +1062,18 @@ Status FileReader::_exec_no_materialized_column_scan(ChunkPtr* chunk) { read_size = _total_row_count - _scan_row_count; _scanner_ctx->append_or_update_count_column_to_chunk(chunk, read_size); _scanner_ctx->append_or_update_partition_column_to_chunk(chunk, 1); +<<<<<<< HEAD +======= + _scanner_ctx->append_or_update_extended_column_to_chunk(chunk, 1); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { read_size = std::min(static_cast(_chunk_size), _total_row_count - _scan_row_count); RETURN_IF_ERROR(_scanner_ctx->append_or_update_not_existed_columns_to_chunk(chunk, read_size)); _scanner_ctx->append_or_update_partition_column_to_chunk(chunk, read_size); +<<<<<<< HEAD +======= + _scanner_ctx->append_or_update_extended_column_to_chunk(chunk, read_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _scan_row_count += read_size; return Status::OK(); diff --git a/be/src/formats/parquet/file_reader.h b/be/src/formats/parquet/file_reader.h index 04b08b37b356f..bddd23f070bd6 100644 --- a/be/src/formats/parquet/file_reader.h +++ b/be/src/formats/parquet/file_reader.h @@ -16,25 +16,62 @@ #include #include +<<<<<<< HEAD #include "block_cache/block_cache.h" #include "column/chunk.h" #include "common/status.h" #include "formats/parquet/group_reader.h" #include "formats/parquet/meta_helper.h" +======= +#include +#include +#include + +#include "block_cache/block_cache.h" +#include "column/vectorized_fwd.h" +#include "common/status.h" +#include "common/statusor.h" +#include "formats/parquet/group_reader.h" +#include "formats/parquet/meta_helper.h" +#include "formats/parquet/metadata.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/parquet_types.h" #include "io/shared_buffered_input_stream.h" #include "runtime/runtime_state.h" +<<<<<<< HEAD namespace starrocks { class RandomAccessFile; struct HdfsScannerContext; +======= +namespace tparquet { +class ColumnMetaData; +class ColumnOrder; +class RowGroup; +} // namespace tparquet + +namespace starrocks { +class RandomAccessFile; +struct HdfsScannerContext; +class BlockCache; +class SlotDescriptor; + +namespace io { +class SharedBufferedInputStream; +} // namespace io +namespace parquet { +struct ParquetField; +} // namespace parquet +struct TypeDescriptor; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks namespace starrocks::parquet { +<<<<<<< HEAD // contains magic number (4 bytes) and footer length (4 bytes) constexpr static const uint32_t PARQUET_FOOTER_SIZE = 8; constexpr static const uint64_t DEFAULT_FOOTER_BUFFER_SIZE = 48 * 1024; @@ -42,6 +79,17 @@ constexpr static const char* PARQUET_MAGIC_NUMBER = "PAR1"; constexpr static const char* PARQUET_EMAIC_NUMBER = "PARE"; using FileMetaDataPtr = std::shared_ptr; +======= +struct SplitContext : public HdfsSplitContext { + FileMetaDataPtr file_metadata; + + HdfsSplitContextPtr clone() override { + auto ctx = std::make_unique(); + ctx->file_metadata = file_metadata; + return ctx; + } +}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class FileReader { public: @@ -59,6 +107,7 @@ class FileReader { Status collect_scan_io_ranges(std::vector* io_ranges); +<<<<<<< HEAD private: int _chunk_size; @@ -71,11 +120,21 @@ class FileReader { Status _parse_footer(FileMetaDataPtr* file_metadata, int64_t* file_metadata_size); +======= + size_t row_group_size() const { return _row_group_size; } + +private: + int _chunk_size; + + std::shared_ptr _build_meta_helper(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _prepare_read_columns(std::unordered_set& existed_column_names); Status _init_group_readers(); // filter row group by conjuncts +<<<<<<< HEAD bool _filter_group(const tparquet::RowGroup& row_group); bool _filter_group_with_min_max_conjuncts(const tparquet::RowGroup& row_group); @@ -83,6 +142,15 @@ class FileReader { bool _filter_group_with_bloom_filter_min_max_conjuncts(const tparquet::RowGroup& row_group); bool _filter_group_with_more_filter(const tparquet::RowGroup& row_group); +======= + bool _filter_group(const GroupReaderPtr& group_reader); + + bool _filter_group_with_min_max_conjuncts(const GroupReaderPtr& group_reader); + + bool _filter_group_with_bloom_filter_min_max_conjuncts(const GroupReaderPtr& group_reader); + + bool _filter_group_with_more_filter(const GroupReaderPtr& group_reader); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // get row group to read // if scan range conatain the first byte in the row group, will be read @@ -91,8 +159,15 @@ class FileReader { // make min/max chunk from stats of row group meta // exist=true: group meta contain statistics info +<<<<<<< HEAD Status _read_min_max_chunk(const tparquet::RowGroup& row_group, const std::vector& slots, ChunkPtr* min_chunk, ChunkPtr* max_chunk) const; +======= + Status _read_min_max_chunk(const GroupReaderPtr& group_reader, const std::vector& slots, + ChunkPtr* min_chunk, ChunkPtr* max_chunk) const; + Status _read_has_nulls(const GroupReaderPtr& group_reader, const std::vector& slots, + std::vector* has_nulls); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // only scan partition column + not exist column Status _exec_no_materialized_column_scan(ChunkPtr* chunk); @@ -100,6 +175,7 @@ class FileReader { // get partition column idx in param.partition_columns int32_t _get_partition_column_idx(const std::string& col_name) const; +<<<<<<< HEAD // Get parquet footer size StatusOr _get_footer_read_size() const; @@ -113,6 +189,8 @@ class FileReader { bool _has_correct_min_max_stats(const tparquet::ColumnMetaData& column_meta, const SortOrder& sort_order) const; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status _build_split_tasks(); RandomAccessFile* _file = nullptr; diff --git a/be/src/formats/parquet/file_writer.cpp b/be/src/formats/parquet/file_writer.cpp index fb75d99ae38d6..893c7ed68d05d 100644 --- a/be/src/formats/parquet/file_writer.cpp +++ b/be/src/formats/parquet/file_writer.cpp @@ -16,6 +16,7 @@ #include "formats/parquet/file_writer.h" #include +<<<<<<< HEAD #include #include #include @@ -33,12 +34,34 @@ #include "exprs/expr_context.h" #include "formats/parquet/utils.h" #include "runtime/exec_env.h" +======= +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "column/chunk.h" +#include "column/vectorized_fwd.h" +#include "exprs/expr.h" +#include "exprs/expr_context.h" +#include "formats/parquet/utils.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/runtime_state.h" #include "types/logical_type.h" #include "util/defer_op.h" #include "util/priority_thread_pool.hpp" #include "util/runtime_profile.h" #include "util/slice.h" +<<<<<<< HEAD +======= +#include "util/stopwatch.hpp" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { @@ -315,8 +338,13 @@ arrow::Result<::parquet::schema::NodePtr> ParquetBuildHelper::_make_schema_node( case TYPE_DECIMAL128: { return ::parquet::schema::PrimitiveNode::Make( name, rep_type, ::parquet::LogicalType::Decimal(type_desc.precision, type_desc.scale), +<<<<<<< HEAD ::parquet::Type::FIXED_LEN_BYTE_ARRAY, decimal_precision_to_byte_count(type_desc.precision), file_column_id.field_id); +======= + ::parquet::Type::FIXED_LEN_BYTE_ARRAY, + ParquetUtils::decimal_precision_to_byte_count(type_desc.precision), file_column_id.field_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } case TYPE_STRUCT: { DCHECK(type_desc.children.size() == type_desc.field_names.size()); diff --git a/be/src/formats/parquet/file_writer.h b/be/src/formats/parquet/file_writer.h index dc05a20de0114..7fb4414b63ce3 100644 --- a/be/src/formats/parquet/file_writer.h +++ b/be/src/formats/parquet/file_writer.h @@ -20,23 +20,69 @@ #include #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include #include #include #include +<<<<<<< HEAD #include #include "column/chunk.h" #include "column/nullable_column.h" +======= +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "column/chunk.h" +#include "column/nullable_column.h" +#include "column/vectorized_fwd.h" +#include "common/status.h" +#include "common/statusor.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/chunk_writer.h" #include "fs/fs.h" #include "gen_cpp/Types_types.h" #include "io/async_flush_output_stream.h" #include "runtime/runtime_state.h" +<<<<<<< HEAD +#include "util/priority_thread_pool.hpp" +======= +#include "runtime/types.h" #include "util/priority_thread_pool.hpp" +#include "util/runtime_profile.h" + +namespace parquet { +class FileMetaData; +} // namespace parquet +namespace starrocks { +class Chunk; +class ExprContext; +class PriorityThreadPool; +class RuntimeState; +} // namespace starrocks +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { diff --git a/be/src/formats/parquet/group_reader.cpp b/be/src/formats/parquet/group_reader.cpp index 525cbfff993fc..4c22b97356489 100644 --- a/be/src/formats/parquet/group_reader.cpp +++ b/be/src/formats/parquet/group_reader.cpp @@ -14,22 +14,46 @@ #include "formats/parquet/group_reader.h" +<<<<<<< HEAD #include #include #include "column/column_helper.h" +======= +#include + +#include +#include +#include + +#include "column/chunk.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/config.h" #include "common/status.h" #include "exec/exec_node.h" #include "exec/hdfs_scanner.h" #include "exprs/expr.h" #include "exprs/expr_context.h" +<<<<<<< HEAD +#include "formats/parquet/page_index_reader.h" +======= +#include "formats/parquet/column_reader_factory.h" +#include "formats/parquet/metadata.h" #include "formats/parquet/page_index_reader.h" +#include "formats/parquet/scalar_column_reader.h" +#include "formats/parquet/schema.h" +#include "formats/parquet/zone_map_filter_evaluator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/strings/substitute.h" #include "runtime/types.h" #include "simd/simd.h" #include "storage/chunk_helper.h" #include "util/defer_op.h" +<<<<<<< HEAD +======= +#include "util/runtime_profile.h" +#include "util/stopwatch.hpp" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "utils.h" namespace starrocks::parquet { @@ -40,12 +64,38 @@ GroupReader::GroupReader(GroupReaderParam& param, int row_group_number, const st _row_group_metadata = &_param.file_metadata->t_metadata().row_groups[row_group_number]; } +<<<<<<< HEAD Status GroupReader::init() { // the calling order matters, do not change unless you know why. RETURN_IF_ERROR(_init_column_readers()); _process_columns_and_conjunct_ctxs(); _range = SparseRange(_row_group_first_row, _row_group_first_row + _row_group_metadata->num_rows); +======= +GroupReader::~GroupReader() { + if (_param.sb_stream) { + _param.sb_stream->release_to_offset(_end_offset); + } + // If GroupReader is filtered by statistics, it's _has_prepared = false + if (_has_prepared) { + if (_lazy_column_needed) { + _param.lazy_column_coalesce_counter->fetch_add(1, std::memory_order_relaxed); + } else { + _param.lazy_column_coalesce_counter->fetch_sub(1, std::memory_order_relaxed); + } + _param.stats->group_min_round_cost = _param.stats->group_min_round_cost == 0 + ? _column_read_order_ctx->get_min_round_cost() + : std::min(_param.stats->group_min_round_cost, + int64_t(_column_read_order_ctx->get_min_round_cost())); + } +} + +Status GroupReader::init() { + // Create column readers and bind ParquetField & ColumnChunkMetaData(except complex type) to each ColumnReader + RETURN_IF_ERROR(_create_column_readers()); + _process_columns_and_conjunct_ctxs(); + _range = SparseRange(_row_group_first_row, _row_group_first_row + _row_group_metadata->num_rows); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -53,12 +103,38 @@ Status GroupReader::_deal_with_pageindex() { if (config::parquet_page_index_enable) { SCOPED_RAW_TIMER(&_param.stats->page_index_ns); _param.stats->rows_before_page_index += _row_group_metadata->num_rows; +<<<<<<< HEAD auto page_index_reader = std::make_unique(this, _param.file, _column_readers, _row_group_metadata, _param.min_max_conjunct_ctxs, _param.conjunct_ctxs_by_slot); ASSIGN_OR_RETURN(bool flag, page_index_reader->generate_read_range(_range)); if (flag && !_is_group_filtered) { page_index_reader->select_column_offset_index(); +======= + if (config::parquet_advance_zonemap_filter) { + ASSIGN_OR_RETURN(auto sparse_range, _param.predicate_tree->visit(ZoneMapEvaluator{ + *_param.predicate_tree, this})); + if (sparse_range.has_value()) { + if (sparse_range.value().empty()) { + // the whole row group has been filtered + _is_group_filtered = true; + } else if (sparse_range->span_size() < _row_group_metadata->num_rows) { + // some pages have been filtered + _range = sparse_range.value(); + for (const auto& pair : _column_readers) { + pair.second->select_offset_index(_range, _row_group_first_row); + } + } + } + } else { + auto page_index_reader = + std::make_unique(this, _param.file, _column_readers, _row_group_metadata, + _param.min_max_conjunct_ctxs, _param.conjunct_ctxs_by_slot); + ASSIGN_OR_RETURN(bool flag, page_index_reader->generate_read_range(_range)); + if (flag && !_is_group_filtered) { + page_index_reader->select_column_offset_index(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -66,6 +142,10 @@ Status GroupReader::_deal_with_pageindex() { } Status GroupReader::prepare() { +<<<<<<< HEAD +======= + RETURN_IF_ERROR(_prepare_column_readers()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // we need deal with page index first, so that it can work on collect_io_range, // and pageindex's io has been collected in FileReader RETURN_IF_ERROR(_deal_with_pageindex()); @@ -94,9 +174,45 @@ Status GroupReader::prepare() { if (!_is_group_filtered) { _range_iter = _range.new_iterator(); } +<<<<<<< HEAD return Status::OK(); } +======= + + _has_prepared = true; + return Status::OK(); +} + +const tparquet::ColumnChunk* GroupReader::get_chunk_metadata(SlotId slot_id) { + const auto& it = _column_readers.find(slot_id); + if (it == _column_readers.end()) { + return nullptr; + } + return it->second->get_chunk_metadata(); +} + +ColumnReader* GroupReader::get_column_reader(SlotId slot_id) { + const auto& it = _column_readers.find(slot_id); + if (it == _column_readers.end()) { + return nullptr; + } + return it->second.get(); +} + +const ParquetField* GroupReader::get_column_parquet_field(SlotId slot_id) { + const auto& it = _column_readers.find(slot_id); + if (it == _column_readers.end()) { + return nullptr; + } + return it->second->get_column_parquet_field(); +} + +const tparquet::RowGroup* GroupReader::get_row_group_metadata() const { + return _row_group_metadata; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status GroupReader::get_next(ChunkPtr* chunk, size_t* row_count) { SCOPED_RAW_TIMER(&_param.stats->group_chunk_read_ns); if (_is_group_filtered) { @@ -163,8 +279,18 @@ Status GroupReader::get_next(ChunkPtr* chunk, size_t* row_count) { ChunkPtr lazy_chunk = _create_read_chunk(_lazy_column_indices); if (has_filter) { +<<<<<<< HEAD RETURN_IF_ERROR(_read_range(_lazy_column_indices, r, &chunk_filter, &lazy_chunk)); lazy_chunk->filter_range(chunk_filter, 0, count); +======= + Range lazy_read_range = r.filter(&chunk_filter); + // if all data is filtered, we have skipped early. + DCHECK(lazy_read_range.span_size() > 0); + Filter lazy_filter = {chunk_filter.begin() + lazy_read_range.begin() - r.begin(), + chunk_filter.begin() + lazy_read_range.end() - r.begin()}; + RETURN_IF_ERROR(_read_range(_lazy_column_indices, lazy_read_range, &lazy_filter, &lazy_chunk)); + lazy_chunk->filter_range(lazy_filter, 0, lazy_read_range.span_size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { RETURN_IF_ERROR(_read_range(_lazy_column_indices, r, nullptr, &lazy_chunk)); } @@ -176,12 +302,20 @@ Status GroupReader::get_next(ChunkPtr* chunk, size_t* row_count) { active_chunk->merge(std::move(*lazy_chunk)); } +<<<<<<< HEAD _read_chunk->swap_chunk(*active_chunk); *row_count = _read_chunk->num_rows(); SCOPED_RAW_TIMER(&_param.stats->group_dict_decode_ns); // convert from _read_chunk to chunk. RETURN_IF_ERROR(_fill_dst_chunk(_read_chunk, chunk)); +======= + *row_count = active_chunk->num_rows(); + + SCOPED_RAW_TIMER(&_param.stats->group_dict_decode_ns); + // convert from _read_chunk to chunk. + RETURN_IF_ERROR(_fill_dst_chunk(active_chunk, chunk)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) break; } @@ -197,8 +331,12 @@ Status GroupReader::_read_range(const std::vector& read_columns, const Rang for (int col_idx : read_columns) { auto& column = _param.read_cols[col_idx]; SlotId slot_id = column.slot_id(); +<<<<<<< HEAD RETURN_IF_ERROR( _column_readers[slot_id]->read_range(range, filter, (*chunk)->get_column_by_slot_id(slot_id).get())); +======= + RETURN_IF_ERROR(_column_readers[slot_id]->read_range(range, filter, (*chunk)->get_column_by_slot_id(slot_id))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); @@ -208,14 +346,23 @@ StatusOr GroupReader::_read_range_round_by_round(const Range& ChunkPtr* chunk) { const std::vector& read_order = _column_read_order_ctx->get_column_read_order(); size_t round_cost = 0; +<<<<<<< HEAD DeferOp defer([&]() { _column_read_order_ctx->update_ctx(round_cost); }); +======= + double first_selectivity = -1; + DeferOp defer([&]() { _column_read_order_ctx->update_ctx(round_cost, first_selectivity); }); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t hit_count = 0; for (int col_idx : read_order) { auto& column = _param.read_cols[col_idx]; round_cost += _column_read_order_ctx->get_column_cost(col_idx); SlotId slot_id = column.slot_id(); +<<<<<<< HEAD RETURN_IF_ERROR( _column_readers[slot_id]->read_range(range, filter, (*chunk)->get_column_by_slot_id(slot_id).get())); +======= + RETURN_IF_ERROR(_column_readers[slot_id]->read_range(range, filter, (*chunk)->get_column_by_slot_id(slot_id))); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (std::find(_dict_column_indices.begin(), _dict_column_indices.end(), col_idx) != _dict_column_indices.end()) { @@ -243,11 +390,16 @@ StatusOr GroupReader::_read_range_round_by_round(const Range& break; } } +<<<<<<< HEAD +======= + first_selectivity = first_selectivity < 0 ? hit_count * 1.0 / filter->size() : first_selectivity; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return hit_count; } +<<<<<<< HEAD void GroupReader::close() { if (_param.sb_stream) { _param.sb_stream->release_to_offset(_end_offset); @@ -267,6 +419,13 @@ void GroupReader::close() { Status GroupReader::_init_column_readers() { // ColumnReaderOptions is used by all column readers in one row group ColumnReaderOptions& opts = _column_reader_opts; +======= +Status GroupReader::_create_column_readers() { + SCOPED_RAW_TIMER(&_param.stats->column_reader_init_ns); + // ColumnReaderOptions is used by all column readers in one row group + ColumnReaderOptions& opts = _column_reader_opts; + opts.file_meta_data = _param.file_metadata; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) opts.timezone = _param.timezone; opts.case_sensitive = _param.case_sensitive; opts.chunk_size = _param.chunk_size; @@ -275,11 +434,35 @@ Status GroupReader::_init_column_readers() { opts.row_group_meta = _row_group_metadata; opts.first_row_index = _row_group_first_row; for (const auto& column : _param.read_cols) { +<<<<<<< HEAD RETURN_IF_ERROR(_create_column_reader(column)); +======= + ASSIGN_OR_RETURN(ColumnReaderPtr column_reader, _create_column_reader(column)); + _column_readers[column.slot_id()] = std::move(column_reader); + } + + // create for partition values + if (_param.partition_columns != nullptr && _param.partition_values != nullptr) { + for (size_t i = 0; i < _param.partition_columns->size(); i++) { + const auto& column = (*_param.partition_columns)[i]; + const auto* slot_desc = column.slot_desc; + const auto value = (*_param.partition_values)[i]; + _column_readers.emplace(slot_desc->id(), std::make_unique(value->get(0))); + } + } + + // create for not existed column + if (_param.not_existed_slots != nullptr) { + for (size_t i = 0; i < _param.not_existed_slots->size(); i++) { + const auto* slot = (*_param.not_existed_slots)[i]; + _column_readers.emplace(slot->id(), std::make_unique(kNullDatum)); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return Status::OK(); } +<<<<<<< HEAD Status GroupReader::_create_column_reader(const GroupReaderParam::Column& column) { std::unique_ptr column_reader = nullptr; const auto* schema_node = _param.file_metadata->schema().get_stored_column_by_field_idx(column.idx_in_parquet); @@ -290,20 +473,49 @@ Status GroupReader::_create_column_reader(const GroupReaderParam::Column& column } else { RETURN_IF_ERROR(ColumnReader::create(_column_reader_opts, schema_node, column.slot_type(), column.t_iceberg_schema_field, &column_reader)); +======= +StatusOr GroupReader::_create_column_reader(const GroupReaderParam::Column& column) { + std::unique_ptr column_reader = nullptr; + const auto* schema_node = _param.file_metadata->schema().get_stored_column_by_field_idx(column.idx_in_parquet); + { + if (column.t_iceberg_schema_field == nullptr) { + ASSIGN_OR_RETURN(column_reader, + ColumnReaderFactory::create(_column_reader_opts, schema_node, column.slot_type())); + } else { + ASSIGN_OR_RETURN(column_reader, + ColumnReaderFactory::create(_column_reader_opts, schema_node, column.slot_type(), + column.t_iceberg_schema_field)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if (column_reader == nullptr) { // this shouldn't happen but guard return Status::InternalError("No valid column reader."); } +<<<<<<< HEAD if (column.slot_type().is_complex_type()) { +======= + } + return column_reader; +} + +Status GroupReader::_prepare_column_readers() const { + SCOPED_RAW_TIMER(&_param.stats->column_reader_init_ns); + for (const auto& [slot_id, column_reader] : _column_readers) { + RETURN_IF_ERROR(column_reader->prepare()); + if (column_reader->get_column_parquet_field() != nullptr && + column_reader->get_column_parquet_field()->is_complex_type()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // For complex type columns, we need parse def & rep levels. // For OptionalColumnReader, by default, we will not parse it's def level for performance. But if // column is a complex type, we have to parse def level to calculate nullability. column_reader->set_need_parse_levels(true); } } +<<<<<<< HEAD _column_readers[column.slot_id()] = std::move(column_reader); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -336,6 +548,10 @@ void GroupReader::_process_columns_and_conjunct_ctxs() { } else { _active_column_indices.emplace_back(read_col_idx); } +<<<<<<< HEAD +======= + _column_readers[slot_id]->set_can_lazy_decode(true); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } ++read_col_idx; } @@ -416,7 +632,10 @@ void GroupReader::_init_read_chunk() { } size_t chunk_size = _param.chunk_size; _read_chunk = ChunkHelper::new_chunk(read_slots, chunk_size); +<<<<<<< HEAD _init_chunk_dict_column(&_read_chunk); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void GroupReader::_use_as_dict_filter_column(int col_idx, SlotId slot_id, std::vector& sub_field_path) { @@ -444,6 +663,7 @@ Status GroupReader::_rewrite_conjunct_ctxs_to_predicates(bool* is_group_filtered return Status::OK(); } +<<<<<<< HEAD void GroupReader::_init_chunk_dict_column(ChunkPtr* chunk) { // replace dict filter column for (int col_idx : _dict_column_indices) { @@ -455,6 +675,8 @@ void GroupReader::_init_chunk_dict_column(ChunkPtr* chunk) { } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr GroupReader::_filter_chunk_with_dict_filter(ChunkPtr* chunk, Filter* filter) { if (_dict_column_indices.size() == 0) { return false; @@ -470,7 +692,11 @@ StatusOr GroupReader::_filter_chunk_with_dict_filter(ChunkPtr* chunk, Filt return true; } +<<<<<<< HEAD Status GroupReader::_fill_dst_chunk(const ChunkPtr& read_chunk, ChunkPtr* chunk) { +======= +Status GroupReader::_fill_dst_chunk(ChunkPtr& read_chunk, ChunkPtr* chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) read_chunk->check_or_die(); for (const auto& column : _param.read_cols) { SlotId slot_id = column.slot_id(); diff --git a/be/src/formats/parquet/group_reader.h b/be/src/formats/parquet/group_reader.h index a391120f1b530..624f8947e951b 100644 --- a/be/src/formats/parquet/group_reader.h +++ b/be/src/formats/parquet/group_reader.h @@ -14,11 +14,26 @@ #pragma once +<<<<<<< HEAD #include #include "column/chunk.h" #include "column/vectorized_fwd.h" #include "common/config.h" +======= +#include +#include +#include +#include +#include +#include + +#include "column/vectorized_fwd.h" +#include "common/global_types.h" +#include "common/object_pool.h" +#include "common/status.h" +#include "common/statusor.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exprs/expr_context.h" #include "formats/parquet/column_read_order_ctx.h" #include "formats/parquet/column_reader.h" @@ -28,11 +43,26 @@ #include "io/shared_buffered_input_stream.h" #include "runtime/descriptors.h" #include "runtime/runtime_state.h" +<<<<<<< HEAD #include "util/runtime_profile.h" namespace starrocks { class RandomAccessFile; struct HdfsScanStats; +======= +#include "storage/range.h" + +namespace starrocks { +class RandomAccessFile; +struct HdfsScanStats; +class ExprContext; +class TIcebergSchemaField; + +namespace parquet { +class FileMetaData; +} // namespace parquet +struct TypeDescriptor; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks namespace starrocks::parquet { @@ -55,7 +85,10 @@ struct GroupReaderParam { const SlotId slot_id() const { return slot_desc->id(); } }; +<<<<<<< HEAD const TupleDescriptor* tuple_desc = nullptr; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // conjunct_ctxs that column is materialized in group reader std::unordered_map> conjunct_ctxs_by_slot; @@ -81,6 +114,17 @@ struct GroupReaderParam { // used for pageIndex std::vector min_max_conjunct_ctxs; +<<<<<<< HEAD +======= + const PredicateTree* predicate_tree = nullptr; + + // partition column + const std::vector* partition_columns = nullptr; + // partition column value which read from hdfs file path + const std::vector* partition_values = nullptr; + // not existed column + const std::vector* not_existed_slots = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class PageIndexReader; @@ -91,14 +135,27 @@ class GroupReader { public: GroupReader(GroupReaderParam& param, int row_group_number, const std::set* need_skip_rowids, int64_t row_group_first_row); +<<<<<<< HEAD ~GroupReader() = default; +======= + ~GroupReader(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // init used to init column reader, and devide active/lazy // then we can use inited column collect io range. Status init(); Status prepare(); +<<<<<<< HEAD Status get_next(ChunkPtr* chunk, size_t* row_count); void close(); +======= + const tparquet::ColumnChunk* get_chunk_metadata(SlotId slot_id); + const ParquetField* get_column_parquet_field(SlotId slot_id); + ColumnReader* get_column_reader(SlotId slot_id); + uint64_t get_row_group_first_row() const { return _row_group_first_row; } + const tparquet::RowGroup* get_row_group_metadata() const; + Status get_next(ChunkPtr* chunk, size_t* row_count); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void collect_io_ranges(std::vector* ranges, int64_t* end_offset, ColumnIOType type = ColumnIOType::PAGES); @@ -113,12 +170,21 @@ class GroupReader { void _use_as_dict_filter_column(int col_idx, SlotId slot_id, std::vector& sub_field_path); Status _rewrite_conjunct_ctxs_to_predicates(bool* is_group_filtered); +<<<<<<< HEAD void _init_chunk_dict_column(ChunkPtr* chunk); StatusOr _filter_chunk_with_dict_filter(ChunkPtr* chunk, Filter* filter); Status _fill_dst_chunk(const ChunkPtr& read_chunk, ChunkPtr* chunk); Status _init_column_readers(); Status _create_column_reader(const GroupReaderParam::Column& column); +======= + StatusOr _filter_chunk_with_dict_filter(ChunkPtr* chunk, Filter* filter); + Status _fill_dst_chunk(ChunkPtr& read_chunk, ChunkPtr* chunk); + + Status _create_column_readers(); + StatusOr _create_column_reader(const GroupReaderParam::Column& column); + Status _prepare_column_readers() const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkPtr _create_read_chunk(const std::vector& column_indices); // Extract dict filter columns and conjuncts void _process_columns_and_conjunct_ctxs(); @@ -176,6 +242,16 @@ class GroupReader { // round by round ctx std::unique_ptr _column_read_order_ctx; +<<<<<<< HEAD }; +======= + + // a flag to reflect prepare() is called + bool _has_prepared = false; +}; + +using GroupReaderPtr = std::shared_ptr; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::parquet diff --git a/be/src/formats/parquet/level_builder.cpp b/be/src/formats/parquet/level_builder.cpp index adf1282f3effd..d970b8792ec01 100644 --- a/be/src/formats/parquet/level_builder.cpp +++ b/be/src/formats/parquet/level_builder.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/level_builder.h" +<<<<<<< HEAD #include #include @@ -28,6 +29,24 @@ #include "exprs/expr.h" #include "gutil/casts.h" #include "gutil/endian.h" +======= +#include + +#include +#include + +#include "column/array_column.h" +#include "column/column.h" +#include "column/column_helper.h" +#include "column/fixed_length_column.h" +#include "column/map_column.h" +#include "column/nullable_column.h" +#include "column/struct_column.h" +#include "column/type_traits.h" +#include "common/compiler_util.h" +#include "gutil/casts.h" +#include "types/date_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/defer_op.h" #include "utils.h" @@ -263,7 +282,11 @@ Status LevelBuilder::_write_decimal_to_flba_column_chunk(const LevelBuilderConte auto flba_values = new ::parquet::FixedLenByteArray[col->size()]; DeferOp flba_defer([&] { delete[] flba_values; }); +<<<<<<< HEAD size_t padding = sizeof(cpp_type) - decimal_precision_to_byte_count(type_desc.precision); +======= + size_t padding = sizeof(cpp_type) - ParquetUtils::decimal_precision_to_byte_count(type_desc.precision); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < col->size(); i++) { flba_values[i].ptr = reinterpret_cast(values + i) + padding; } diff --git a/be/src/formats/parquet/level_builder.h b/be/src/formats/parquet/level_builder.h index cebdcad9f282e..c772094c11d6e 100644 --- a/be/src/formats/parquet/level_builder.h +++ b/be/src/formats/parquet/level_builder.h @@ -21,11 +21,16 @@ #include #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include #include #include +<<<<<<< HEAD #include #include @@ -35,6 +40,27 @@ #include "formats/parquet/chunk_writer.h" #include "fs/fs.h" #include "runtime/runtime_state.h" +======= +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "column/chunk.h" +#include "column/nullable_column.h" +#include "column/vectorized_fwd.h" +#include "common/status.h" +#include "formats/parquet/chunk_writer.h" +#include "fs/fs.h" +#include "runtime/runtime_state.h" +#include "runtime/types.h" +#include "types/logical_type.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/priority_thread_pool.hpp" namespace starrocks::parquet { diff --git a/be/src/formats/parquet/level_codec.cpp b/be/src/formats/parquet/level_codec.cpp index 2530dbf70fb60..af5a4906a2a33 100644 --- a/be/src/formats/parquet/level_codec.cpp +++ b/be/src/formats/parquet/level_codec.cpp @@ -14,8 +14,15 @@ #include "formats/parquet/level_codec.h" +<<<<<<< HEAD #include "util/bit_util.h" #include "util/coding.h" +======= +#include "util/bit_stream_utils.inline.h" +#include "util/bit_util.h" +#include "util/coding.h" +#include "util/slice.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { diff --git a/be/src/formats/parquet/level_codec.h b/be/src/formats/parquet/level_codec.h index 13dbd2b1f17e1..e3a96f210f25b 100644 --- a/be/src/formats/parquet/level_codec.h +++ b/be/src/formats/parquet/level_codec.h @@ -14,7 +14,16 @@ #pragma once +<<<<<<< HEAD #include +======= +#include +#include + +#include +#include +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/status.h" #include "formats/parquet/types.h" @@ -22,6 +31,10 @@ #include "util/bit_stream_utils.h" #include "util/rle_encoding.h" #include "util/runtime_profile.h" +<<<<<<< HEAD +======= +#include "util/stopwatch.hpp" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { class Slice; diff --git a/be/src/formats/parquet/meta_helper.cpp b/be/src/formats/parquet/meta_helper.cpp index 17cc734b8d2b4..460f7d074d613 100644 --- a/be/src/formats/parquet/meta_helper.cpp +++ b/be/src/formats/parquet/meta_helper.cpp @@ -14,6 +14,7 @@ #include "meta_helper.h" +<<<<<<< HEAD #include #include "formats/utils.h" @@ -62,11 +63,25 @@ void ParquetMetaHelper::build_column_name_2_pos_in_meta( } } +======= +#include "formats/parquet/metadata.h" +#include "formats/parquet/schema.h" +#include "formats/utils.h" +#include "gen_cpp/Descriptors_types.h" +#include "runtime/descriptors.h" + +namespace starrocks::parquet { + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void ParquetMetaHelper::prepare_read_columns(const std::vector& materialized_columns, std::vector& read_cols, std::unordered_set& existed_column_names) const { for (auto& materialized_column : materialized_columns) { +<<<<<<< HEAD SlotDescriptor* slotDesc = materialized_column.slot_desc; +======= + const SlotDescriptor* slotDesc = materialized_column.slot_desc; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int32_t field_idx = -1; if (slotDesc->col_unique_id() != -1) { @@ -170,6 +185,7 @@ bool ParquetMetaHelper::_is_valid_type(const ParquetField* parquet_field, const return has_valid_child; } +<<<<<<< HEAD const ParquetField* ParquetMetaHelper::get_parquet_field(const SlotDescriptor* slot_desc) const { if (slot_desc->col_unique_id() != -1) { return _file_metadata->schema().get_stored_column_by_field_id(slot_desc->col_unique_id()); @@ -180,6 +196,8 @@ const ParquetField* ParquetMetaHelper::get_parquet_field(const SlotDescriptor* s } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void IcebergMetaHelper::_init_field_mapping() { for (const auto& each : _t_iceberg_schema->fields) { _field_name_2_iceberg_field.emplace(Utils::format_name(each.name, _case_sensitive), &each); @@ -244,6 +262,7 @@ bool IcebergMetaHelper::_is_valid_type(const ParquetField* parquet_field, const return has_valid_child; } +<<<<<<< HEAD void IcebergMetaHelper::build_column_name_2_pos_in_meta( std::unordered_map& column_name_2_pos_in_meta, const std::vector& slots) const { @@ -263,6 +282,8 @@ void IcebergMetaHelper::build_column_name_2_pos_in_meta( } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void IcebergMetaHelper::prepare_read_columns(const std::vector& materialized_columns, std::vector& read_cols, std::unordered_set& existed_column_names) const { @@ -293,6 +314,7 @@ void IcebergMetaHelper::prepare_read_columns(const std::vectorcol_name(), _case_sensitive)); if (it == _field_name_2_iceberg_field.end()) { @@ -302,4 +324,6 @@ const ParquetField* IcebergMetaHelper::get_parquet_field(const SlotDescriptor* s return _file_metadata->schema().get_stored_column_by_field_id(field_id); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/meta_helper.h b/be/src/formats/parquet/meta_helper.h index 31023ac7ef826..5d15e0e01a59d 100644 --- a/be/src/formats/parquet/meta_helper.h +++ b/be/src/formats/parquet/meta_helper.h @@ -14,7 +14,15 @@ #pragma once +<<<<<<< HEAD #include +======= +#include + +#include +#include +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -22,8 +30,25 @@ #include "formats/parquet/group_reader.h" #include "formats/parquet/metadata.h" #include "gen_cpp/Descriptors_types.h" +<<<<<<< HEAD #include "runtime/descriptors.h" +======= +#include "gen_cpp/parquet_types.h" +#include "runtime/descriptors.h" + +namespace starrocks { +class SlotDescriptor; +class TIcebergSchema; +class TIcebergSchemaField; + +namespace parquet { +class FileMetaData; +struct ParquetField; +} // namespace parquet +} // namespace starrocks + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { class MetaHelper { @@ -32,13 +57,17 @@ class MetaHelper { : _file_metadata(file_metadata), _case_sensitive(case_sensitive) {} virtual ~MetaHelper() = default; +<<<<<<< HEAD virtual void build_column_name_2_pos_in_meta(std::unordered_map& column_name_2_pos_in_meta, const std::vector& slots) const = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void prepare_read_columns(const std::vector& materialized_columns, std::vector& read_cols, std::unordered_set& existed_column_names) const = 0; +<<<<<<< HEAD virtual const ParquetField* get_parquet_field(const SlotDescriptor* slot_desc) const = 0; const tparquet::ColumnMetaData* get_column_meta( @@ -60,6 +89,8 @@ class MetaHelper { return &row_group.columns[it->second].meta_data; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: GroupReaderParam::Column _build_column(int32_t idx_in_parquet, const tparquet::Type::type& type_in_parquet, SlotDescriptor* slot_desc, bool decode_needed, @@ -82,14 +113,20 @@ class ParquetMetaHelper : public MetaHelper { ParquetMetaHelper(FileMetaData* file_metadata, bool case_sensitive) : MetaHelper(file_metadata, case_sensitive) {} ~ParquetMetaHelper() override = default; +<<<<<<< HEAD void build_column_name_2_pos_in_meta(std::unordered_map& column_name_2_pos_in_meta, const std::vector& slots) const override; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void prepare_read_columns(const std::vector& materialized_columns, std::vector& read_cols, std::unordered_set& existed_column_names) const override; +<<<<<<< HEAD const ParquetField* get_parquet_field(const SlotDescriptor* slot_desc) const override; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: bool _is_valid_type(const ParquetField* parquet_field, const TypeDescriptor* type_descriptor) const; }; @@ -105,12 +142,18 @@ class IcebergMetaHelper : public MetaHelper { ~IcebergMetaHelper() override = default; +<<<<<<< HEAD void build_column_name_2_pos_in_meta(std::unordered_map& column_name_2_pos_in_meta, const std::vector& slots) const override; void prepare_read_columns(const std::vector& materialized_columns, std::vector& read_cols, std::unordered_set& existed_column_names) const override; const ParquetField* get_parquet_field(const SlotDescriptor* slot_desc) const override; +======= + void prepare_read_columns(const std::vector& materialized_columns, + std::vector& read_cols, + std::unordered_set& existed_column_names) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: void _init_field_mapping(); diff --git a/be/src/formats/parquet/metadata.cpp b/be/src/formats/parquet/metadata.cpp index 87ef641d79546..b829d898ad4c3 100644 --- a/be/src/formats/parquet/metadata.cpp +++ b/be/src/formats/parquet/metadata.cpp @@ -14,9 +14,22 @@ #include "formats/parquet/metadata.h" +<<<<<<< HEAD #include #include "formats/parquet/schema.h" +======= +#include + +#include +#include +#include +#include + +#include "formats/parquet/file_reader.h" +#include "formats/parquet/schema.h" +#include "util/thrift_util.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { @@ -425,6 +438,162 @@ bool ApplicationVersion::HasCorrectStatistics(const tparquet::ColumnMetaData& co return true; } +<<<<<<< HEAD +======= +StatusOr FileMetaDataParser::get_file_metadata() { + // return from split_context directly + if (_scanner_ctx->split_context != nullptr) { + auto split_ctx = down_cast(_scanner_ctx->split_context); + return split_ctx->file_metadata; + } + + // parse FileMetadata from remote + if (!_cache) { + int64_t file_metadata_size = 0; + FileMetaDataPtr file_metadata_ptr = nullptr; + RETURN_IF_ERROR(_parse_footer(&file_metadata_ptr, &file_metadata_size)); + return file_metadata_ptr; + } + + DataCacheHandle cache_handle; + std::string metacache_key = + _build_metacache_key(_file->filename(), _datacache_options->modification_time, _file_size); + { + SCOPED_RAW_TIMER(&_scanner_ctx->stats->footer_cache_read_ns); + Status st = _cache->read_object(metacache_key, &cache_handle); + if (st.ok()) { + _scanner_ctx->stats->footer_cache_read_count += 1; + return *(static_cast(cache_handle.ptr())); + } + } + + FileMetaDataPtr file_metadata = nullptr; + int64_t file_metadata_size = 0; + RETURN_IF_ERROR(_parse_footer(&file_metadata, &file_metadata_size)); + if (file_metadata_size > 0) { + // cache does not understand shared ptr at all. + // so we have to new a object to hold this shared ptr. + FileMetaDataPtr* capture = new FileMetaDataPtr(file_metadata); + Status st = Status::InternalError("write footer cache failed"); + DeferOp op([&st, this, capture, file_metadata_size]() { + if (st.ok()) { + _scanner_ctx->stats->footer_cache_write_bytes += file_metadata_size; + _scanner_ctx->stats->footer_cache_write_count += 1; + } else { + _scanner_ctx->stats->footer_cache_write_fail_count += 1; + delete capture; + } + }); + auto deleter = [capture]() { delete capture; }; + WriteCacheOptions options; + options.evict_probability = _datacache_options->datacache_evict_probability; + st = _cache->write_object(metacache_key, capture, file_metadata_size, deleter, &cache_handle, &options); + } else { + LOG(ERROR) << "Parsing unexpected parquet file metadata size"; + } + return file_metadata; +} + +Status FileMetaDataParser::_parse_footer(FileMetaDataPtr* file_metadata_ptr, int64_t* file_metadata_size) { + std::vector footer_buffer; + ASSIGN_OR_RETURN(uint32_t footer_read_size, _get_footer_read_size()); + footer_buffer.resize(footer_read_size); + + { + SCOPED_RAW_TIMER(&_scanner_ctx->stats->footer_read_ns); + RETURN_IF_ERROR(_file->read_at_fully(_file_size - footer_read_size, footer_buffer.data(), footer_read_size)); + } + + ASSIGN_OR_RETURN(uint32_t metadata_length, _parse_metadata_length(footer_buffer)); + + _scanner_ctx->stats->request_bytes_read += metadata_length + PARQUET_FOOTER_SIZE; + _scanner_ctx->stats->request_bytes_read_uncompressed += metadata_length + PARQUET_FOOTER_SIZE; + + if (footer_read_size < (metadata_length + PARQUET_FOOTER_SIZE)) { + // footer_buffer's size is not enough to read the whole metadata, we need to re-read for larger size + size_t re_read_size = metadata_length + PARQUET_FOOTER_SIZE; + footer_buffer.resize(re_read_size); + { + SCOPED_RAW_TIMER(&_scanner_ctx->stats->footer_read_ns); + RETURN_IF_ERROR(_file->read_at_fully(_file_size - re_read_size, footer_buffer.data(), re_read_size)); + } + } + + // NOTICE: When you need to modify the logic within this scope (including the subfuctions), you should be + // particularly careful to ensure that it does not affect the correctness of the footer's memory statistics. + { + int64_t before_bytes = CurrentThread::current().get_consumed_bytes(); + tparquet::FileMetaData t_metadata; + // deserialize footer + RETURN_IF_ERROR(deserialize_thrift_msg(reinterpret_cast(footer_buffer.data()) + + footer_buffer.size() - PARQUET_FOOTER_SIZE - metadata_length, + &metadata_length, TProtocolType::COMPACT, &t_metadata)); + + *file_metadata_ptr = std::make_shared(); + FileMetaData* file_metadata = file_metadata_ptr->get(); + RETURN_IF_ERROR(file_metadata->init(t_metadata, _scanner_ctx->case_sensitive)); + *file_metadata_size = CurrentThread::current().get_consumed_bytes() - before_bytes; + } +#ifdef BE_TEST + *file_metadata_size = sizeof(FileMetaData); +#endif + return Status::OK(); +} + +StatusOr FileMetaDataParser::_get_footer_read_size() const { + if (_file_size == 0) { + return Status::Corruption("Parquet file size is 0 bytes"); + } else if (_file_size < PARQUET_FOOTER_SIZE) { + return Status::Corruption(strings::Substitute( + "Parquet file size is $0 bytes, smaller than the minimum parquet file footer ($1 bytes)", _file_size, + PARQUET_FOOTER_SIZE)); + } + return std::min(_file_size, DEFAULT_FOOTER_BUFFER_SIZE); +} + +StatusOr FileMetaDataParser::_parse_metadata_length(const std::vector& footer_buff) const { + size_t size = footer_buff.size(); + if (memequal(footer_buff.data() + size - 4, 4, PARQUET_EMAIC_NUMBER, 4)) { + return Status::NotSupported("StarRocks parquet reader not support encrypted parquet file yet"); + } + + if (!memequal(footer_buff.data() + size - 4, 4, PARQUET_MAGIC_NUMBER, 4)) { + return Status::Corruption("Parquet file magic not matched"); + } + + uint32_t metadata_length = decode_fixed32_le(reinterpret_cast(footer_buff.data()) + size - 8); + if (metadata_length > _file_size - PARQUET_FOOTER_SIZE) { + return Status::Corruption(strings::Substitute( + "Parquet file size is $0 bytes, smaller than the size reported by footer's ($1 bytes)", _file_size, + metadata_length)); + } + return metadata_length; +} + +std::string FileMetaDataParser::_build_metacache_key(const std::string& filename, int64_t modification_time, + uint64_t file_size) { + std::string metacache_key; + metacache_key.resize(14); + char* data = metacache_key.data(); + const std::string footer_suffix = "ft"; + uint64_t hash_value = HashUtil::hash64(filename.data(), filename.size(), 0); + memcpy(data, &hash_value, sizeof(hash_value)); + memcpy(data + 8, footer_suffix.data(), footer_suffix.length()); + // The modification time is more appropriate to indicate the different file versions. + // While some data source, such as Hudi, have no modification time because their files + // cannot be overwritten. So, if the modification time is unsupported, we use file size instead. + // Also, to reduce memory usage, we only use the high four bytes to represent the second timestamp. + if (modification_time > 0) { + uint32_t mtime_s = (modification_time >> 9) & 0x00000000FFFFFFFF; + memcpy(data + 10, &mtime_s, sizeof(mtime_s)); + } else { + uint32_t size = file_size; + memcpy(data + 10, &size, sizeof(size)); + } + return metacache_key; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // reference both be/src/formats/parquet/column_converter.cpp // and https://github.com/apache/parquet-format/blob/master/LogicalTypes.md SortOrder sort_order_of_logical_type(LogicalType type) { diff --git a/be/src/formats/parquet/metadata.h b/be/src/formats/parquet/metadata.h index 3d2561662911e..6349812783df2 100644 --- a/be/src/formats/parquet/metadata.h +++ b/be/src/formats/parquet/metadata.h @@ -14,9 +14,20 @@ #pragma once +<<<<<<< HEAD #include "common/status.h" #include "formats/parquet/schema.h" #include "gen_cpp/parquet_types.h" +======= +#include + +#include "common/status.h" +#include "exec/hdfs_scanner.h" +#include "formats/parquet/schema.h" +#include "fs/fs.h" +#include "gen_cpp/parquet_types.h" +#include "types/logical_type.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { @@ -94,6 +105,43 @@ class FileMetaData { ApplicationVersion _writer_version; }; +<<<<<<< HEAD +======= +using FileMetaDataPtr = std::shared_ptr; + +// FileMetaDataParser parse FileMetaData through below way: +// 1. try to reuse SplitContext's FileMetaData +// 2. if DataCache is enabled, retrieve FileMetaData from DataCache. Otherwise, parse FileMetaData normally +class FileMetaDataParser { +public: + FileMetaDataParser(RandomAccessFile* file, const HdfsScannerContext* scanner_context, BlockCache* cache, + const DataCacheOptions* datacache_options, uint64_t file_size) + : _file(file), + _scanner_ctx(scanner_context), + _cache(cache), + _datacache_options(datacache_options), + _file_size(file_size) {} + StatusOr get_file_metadata(); + +private: + Status _parse_footer(FileMetaDataPtr* file_metadata_ptr, int64_t* file_metadata_size); + StatusOr _get_footer_read_size() const; + StatusOr _parse_metadata_length(const std::vector& footer_buff) const; + static std::string _build_metacache_key(const std::string& filename, int64_t modification_time, uint64_t file_size); + RandomAccessFile* _file = nullptr; + const HdfsScannerContext* _scanner_ctx = nullptr; + BlockCache* _cache = nullptr; + const DataCacheOptions* _datacache_options = nullptr; + uint64_t _file_size = 0; + + // contains magic number (4 bytes) and footer length (4 bytes) + constexpr static const uint32_t PARQUET_FOOTER_SIZE = 8; + constexpr static const uint64_t DEFAULT_FOOTER_BUFFER_SIZE = 48 * 1024; + constexpr static const char* PARQUET_MAGIC_NUMBER = "PAR1"; + constexpr static const char* PARQUET_EMAIC_NUMBER = "PARE"; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SortOrder sort_order_of_logical_type(LogicalType type); } // namespace starrocks::parquet diff --git a/be/src/formats/parquet/page_index_reader.cpp b/be/src/formats/parquet/page_index_reader.cpp index 242a3b3844d08..0cdc46fa534d4 100644 --- a/be/src/formats/parquet/page_index_reader.cpp +++ b/be/src/formats/parquet/page_index_reader.cpp @@ -14,8 +14,17 @@ #include "formats/parquet/page_index_reader.h" +<<<<<<< HEAD #include +======= +#include +#include +#include + +#include "column/chunk.h" +#include "column/column.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/column_helper.h" #include "column/vectorized_fwd.h" #include "common/compiler_util.h" @@ -23,13 +32,25 @@ #include "common/status.h" #include "exprs/expr.h" #include "exprs/expr_context.h" +<<<<<<< HEAD +======= +#include "formats/parquet/column_converter.h" +#include "formats/parquet/column_reader.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/encoding_plain.h" #include "formats/parquet/group_reader.h" #include "formats/parquet/schema.h" #include "formats/parquet/statistics_helper.h" #include "fs/fs.h" #include "gen_cpp/parquet_types.h" +<<<<<<< HEAD +#include "simd/simd.h" +======= +#include "gutil/stringprintf.h" +#include "runtime/types.h" #include "simd/simd.h" +#include "util/slice.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/thrift_util.h" namespace starrocks::parquet { diff --git a/be/src/formats/parquet/page_index_reader.h b/be/src/formats/parquet/page_index_reader.h index 8b7bdbbe84634..c8d9ee9a88061 100644 --- a/be/src/formats/parquet/page_index_reader.h +++ b/be/src/formats/parquet/page_index_reader.h @@ -14,6 +14,7 @@ #pragma once +<<<<<<< HEAD #include #include @@ -24,6 +25,39 @@ #include "runtime/types.h" #include "storage/range.h" +======= +#include + +#include +#include +#include +#include + +#include "common/global_types.h" +#include "common/status.h" +#include "common/statusor.h" +#include "exprs/expr_context.h" +#include "exprs/function_context.h" +#include "formats/parquet/column_reader.h" +#include "formats/parquet/group_reader.h" +#include "formats/parquet/schema.h" +#include "gen_cpp/parquet_types.h" +#include "io/shared_buffered_input_stream.h" +#include "runtime/types.h" +#include "storage/range.h" + +namespace starrocks { +class RandomAccessFile; + +namespace parquet { +class ColumnReader; +class GroupReader; +struct ParquetField; +} // namespace parquet +struct TypeDescriptor; +} // namespace starrocks + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { struct ColumnOffsetIndexCtx { diff --git a/be/src/formats/parquet/page_reader.cpp b/be/src/formats/parquet/page_reader.cpp index d6f83ebe2c25b..ab2c87b94b123 100644 --- a/be/src/formats/parquet/page_reader.cpp +++ b/be/src/formats/parquet/page_reader.cpp @@ -14,9 +14,20 @@ #include "formats/parquet/page_reader.h" +<<<<<<< HEAD #include "common/config.h" #include "exec/hdfs_scanner.h" #include "formats/parquet/column_reader.h" +======= +#include + +#include +#include +#include + +#include "common/compiler_util.h" +#include "exec/hdfs_scanner.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/strings/substitute.h" #include "util/thrift_util.h" diff --git a/be/src/formats/parquet/page_reader.h b/be/src/formats/parquet/page_reader.h index 4272da5513004..a6403986afd9a 100644 --- a/be/src/formats/parquet/page_reader.h +++ b/be/src/formats/parquet/page_reader.h @@ -14,9 +14,19 @@ #pragma once +<<<<<<< HEAD #include #include "common/status.h" +======= +#include + +#include +#include + +#include "common/status.h" +#include "common/statusor.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/parquet_types.h" #include "io/seekable_input_stream.h" diff --git a/be/src/formats/parquet/parquet_file_writer.cpp b/be/src/formats/parquet/parquet_file_writer.cpp index 2b4a92f663104..4194eeff8af0b 100644 --- a/be/src/formats/parquet/parquet_file_writer.cpp +++ b/be/src/formats/parquet/parquet_file_writer.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/parquet_file_writer.h" +<<<<<<< HEAD #include #include #include @@ -29,18 +30,46 @@ #include "column/vectorized_fwd.h" #include "common/logging.h" #include "exprs/expr.h" +======= +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/file_writer.h" #include "formats/parquet/arrow_memory_pool.h" #include "formats/parquet/chunk_writer.h" #include "formats/parquet/file_writer.h" #include "formats/parquet/utils.h" #include "formats/utils.h" +<<<<<<< HEAD #include "runtime/exec_env.h" #include "util/debug_util.h" #include "util/defer_op.h" #include "util/priority_thread_pool.hpp" #include "util/runtime_profile.h" #include "util/slice.h" +======= +#include "fs/fs.h" +#include "runtime/runtime_state.h" +#include "types/logical_type.h" +#include "util/debug_util.h" +#include "util/priority_thread_pool.hpp" + +namespace starrocks { +class Chunk; +} // namespace starrocks +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::formats { @@ -265,7 +294,11 @@ StatusOr<::parquet::Compression::type> ParquetFileWriter::_convert_compression_t } arrow::Result> ParquetFileWriter::_make_schema( +<<<<<<< HEAD const vector& column_names, const vector& type_descs, +======= + const std::vector& column_names, const std::vector& type_descs, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& file_column_ids) { ::parquet::schema::NodeVector fields; for (int i = 0; i < type_descs.size(); i++) { @@ -358,8 +391,13 @@ arrow::Result<::parquet::schema::NodePtr> ParquetFileWriter::_make_schema_node(c } return ::parquet::schema::PrimitiveNode::Make( name, rep_type, ::parquet::LogicalType::Decimal(type_desc.precision, type_desc.scale), +<<<<<<< HEAD ::parquet::Type::FIXED_LEN_BYTE_ARRAY, parquet::decimal_precision_to_byte_count(type_desc.precision), file_column_id.field_id); +======= + ::parquet::Type::FIXED_LEN_BYTE_ARRAY, + parquet::ParquetUtils::decimal_precision_to_byte_count(type_desc.precision), file_column_id.field_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } case TYPE_STRUCT: { DCHECK(type_desc.children.size() == type_desc.field_names.size()); diff --git a/be/src/formats/parquet/parquet_file_writer.h b/be/src/formats/parquet/parquet_file_writer.h index 291e7e32e4707..a5c131b41a588 100644 --- a/be/src/formats/parquet/parquet_file_writer.h +++ b/be/src/formats/parquet/parquet_file_writer.h @@ -19,18 +19,48 @@ #include #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include #include #include #include +<<<<<<< HEAD #include +======= +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "arrow_memory_pool.h" #include "column/chunk.h" #include "column/nullable_column.h" +<<<<<<< HEAD +======= +#include "column/vectorized_fwd.h" +#include "common/status.h" +#include "common/statusor.h" +#include "exprs/function_context.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/column_evaluator.h" #include "formats/file_writer.h" #include "formats/parquet/arrow_memory_pool.h" @@ -38,9 +68,34 @@ #include "formats/parquet/file_writer.h" #include "formats/utils.h" #include "fs/fs.h" +<<<<<<< HEAD +#include "runtime/runtime_state.h" +#include "util/priority_thread_pool.hpp" + +======= +#include "gen_cpp/Types_types.h" #include "runtime/runtime_state.h" +#include "runtime/types.h" #include "util/priority_thread_pool.hpp" +namespace parquet { +class FileMetaData; +class ParquetFileWriter; +class WriterProperties; +} // namespace parquet +namespace starrocks { +class Chunk; +class FileSystem; +class PriorityThreadPool; +class RuntimeState; + +namespace parquet { +class ChunkWriter; +class ParquetOutputStream; +} // namespace parquet +} // namespace starrocks + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::formats { struct FileColumnId { diff --git a/be/src/formats/parquet/scalar_column_reader.cpp b/be/src/formats/parquet/scalar_column_reader.cpp new file mode 100644 index 0000000000000..e41a88bb670a3 --- /dev/null +++ b/be/src/formats/parquet/scalar_column_reader.cpp @@ -0,0 +1,420 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "formats/parquet/scalar_column_reader.h" + +#include "formats/parquet/stored_column_reader_with_index.h" +#include "formats/parquet/utils.h" +#include "formats/parquet/zone_map_filter_evaluator.h" +#include "gutil/casts.h" +#include "io/shared_buffered_input_stream.h" +#include "simd/simd.h" +#include "statistics_helper.h" + +namespace starrocks::parquet { + +StatusOr FixedValueColumnReader::row_group_zone_map_filter(const std::vector& predicates, + CompoundNodeType pred_relation, + const uint64_t rg_first_row, + const uint64_t rg_num_rows) const { + ZoneMapDetail zone_map{_fixed_value, _fixed_value, _fixed_value.is_null()}; + return ZoneMapEvaluatorUtils::is_satisfy(predicates, zone_map, pred_relation); +} + +StatusOr FixedValueColumnReader::page_index_zone_map_filter(const std::vector& predicates, + SparseRange* row_ranges, + CompoundNodeType pred_relation, + const uint64_t rg_first_row, + const uint64_t rg_num_rows) { + DCHECK(row_ranges->empty()); + ZoneMapDetail zone_map{_fixed_value, _fixed_value, _fixed_value.is_null()}; + + // is_satisfy = true means no filter happened, return false + // is_satisfy = false means entire row group can be filtered, filter happened, return true + return !ZoneMapEvaluatorUtils::is_satisfy(predicates, zone_map, pred_relation); +} + +Status ScalarColumnReader::read_range(const Range& range, const Filter* filter, ColumnPtr& dst) { + DCHECK(get_column_parquet_field()->is_nullable ? dst->is_nullable() : true); + _need_lazy_decode = + _dict_filter_ctx != nullptr || (_can_lazy_decode && filter != nullptr && + SIMD::count_nonzero(*filter) * 1.0 / filter->size() < FILTER_RATIO); + ColumnContentType content_type = !_need_lazy_decode ? ColumnContentType::VALUE : ColumnContentType::DICT_CODE; + if (_need_lazy_decode) { + if (_dict_code == nullptr) { + _dict_code = ColumnHelper::create_column( + TypeDescriptor::from_logical_type(ColumnDictFilterContext::kDictCodePrimitiveType), true); + } + _ori_column = dst; + dst = _dict_code; + dst->reserve(range.span_size()); + } + if (!_converter->need_convert) { + SCOPED_RAW_TIMER(&_opts.stats->column_read_ns); + return _reader->read_range(range, filter, content_type, dst.get()); + } else { + auto column = _converter->create_src_column(); + { + SCOPED_RAW_TIMER(&_opts.stats->column_read_ns); + RETURN_IF_ERROR(_reader->read_range(range, filter, content_type, column.get())); + } + SCOPED_RAW_TIMER(&_opts.stats->column_convert_ns); + return _converter->convert(column, dst.get()); + } +} + +bool ScalarColumnReader::try_to_use_dict_filter(ExprContext* ctx, bool is_decode_needed, const SlotId slotId, + const std::vector& sub_field_path, const size_t& layer) { + if (sub_field_path.size() != layer) { + return false; + } + + if (!_col_type->is_string_type()) { + return false; + } + + if (_column_all_pages_dict_encoded()) { + if (_dict_filter_ctx == nullptr) { + _dict_filter_ctx = std::make_unique(); + _dict_filter_ctx->is_decode_needed = is_decode_needed; + _dict_filter_ctx->sub_field_path = sub_field_path; + _dict_filter_ctx->slot_id = slotId; + } + _dict_filter_ctx->conjunct_ctxs.push_back(ctx); + return true; + } else { + return false; + } +} + +Status ScalarColumnReader::fill_dst_column(ColumnPtr& dst, ColumnPtr& src) { + if (!_need_lazy_decode) { + dst->swap_column(*src); + } else { + if (_dict_filter_ctx == nullptr || _dict_filter_ctx->is_decode_needed) { + ColumnPtr& dict_values = dst; + dict_values->reserve(src->size()); + + // decode dict code to dict values. + // note that in dict code, there could be null value. + const ColumnPtr& dict_codes = src; + auto* codes_nullable_column = ColumnHelper::as_raw_column(dict_codes); + auto* codes_column = + ColumnHelper::as_raw_column>(codes_nullable_column->data_column()); + RETURN_IF_ERROR( + _reader->get_dict_values(codes_column->get_data(), *codes_nullable_column, dict_values.get())); + DCHECK_EQ(dict_codes->size(), dict_values->size()); + if (dict_values->is_nullable()) { + auto* nullable_codes = down_cast(dict_codes.get()); + auto* nullable_values = down_cast(dict_values.get()); + nullable_values->null_column_data().swap(nullable_codes->null_column_data()); + nullable_values->set_has_null(nullable_codes->has_null()); + } + } else { + dst->append_default(src->size()); + } + + src->reset_column(); + src = _ori_column; + } + return Status::OK(); +} + +bool ScalarColumnReader::_column_all_pages_dict_encoded() { + // The Parquet spec allows for column chunks to have mixed encodings + // where some data pages are dictionary-encoded and others are plain + // encoded. For example, a Parquet file writer might start writing + // a column chunk as dictionary encoded, but it will switch to plain + // encoding if the dictionary grows too large. + // + // In order for dictionary filters to skip the entire row group, + // the conjuncts must be evaluated on column chunks that are entirely + // encoded with the dictionary encoding. There are two checks + // available to verify this: + // 1. The encoding_stats field on the column chunk metadata provides + // information about the number of data pages written in each + // format. This allows for a specific check of whether all the + // data pages are dictionary encoded. + // 2. The encodings field on the column chunk metadata lists the + // encodings used. If this list contains the dictionary encoding + // and does not include unexpected encodings (i.e. encodings not + // associated with definition/repetition levels), then it is entirely + // dictionary encoded. + const tparquet::ColumnMetaData& column_metadata = get_chunk_metadata()->meta_data; + if (column_metadata.__isset.encoding_stats) { + // Condition #1 above + for (const tparquet::PageEncodingStats& enc_stat : column_metadata.encoding_stats) { + if (enc_stat.page_type == tparquet::PageType::DATA_PAGE && + (enc_stat.encoding != tparquet::Encoding::PLAIN_DICTIONARY && + enc_stat.encoding != tparquet::Encoding::RLE_DICTIONARY) && + enc_stat.count > 0) { + return false; + } + } + } else { + // Condition #2 above + bool has_dict_encoding = false; + bool has_nondict_encoding = false; + for (const tparquet::Encoding::type& encoding : column_metadata.encodings) { + if (encoding == tparquet::Encoding::PLAIN_DICTIONARY || encoding == tparquet::Encoding::RLE_DICTIONARY) { + has_dict_encoding = true; + } + + // RLE and BIT_PACKED are used for repetition/definition levels + if (encoding != tparquet::Encoding::PLAIN_DICTIONARY && encoding != tparquet::Encoding::RLE_DICTIONARY && + encoding != tparquet::Encoding::RLE && encoding != tparquet::Encoding::BIT_PACKED) { + has_nondict_encoding = true; + break; + } + } + // Not entirely dictionary encoded if: + // 1. No dictionary encoding listed + // OR + // 2. Some non-dictionary encoding is listed + if (!has_dict_encoding || has_nondict_encoding) { + return false; + } + } + + return true; +} + +void ScalarColumnReader::collect_column_io_range(std::vector* ranges, + int64_t* end_offset, ColumnIOType type, bool active) { + const auto& column = *get_chunk_metadata(); + if (type == ColumnIOType::PAGES) { + const tparquet::ColumnMetaData& column_metadata = column.meta_data; + if (_offset_index_ctx != nullptr && !_offset_index_ctx->page_selected.empty()) { + // add dict page + if (column_metadata.__isset.dictionary_page_offset) { + auto r = io::SharedBufferedInputStream::IORange( + column_metadata.dictionary_page_offset, + column_metadata.data_page_offset - column_metadata.dictionary_page_offset, active); + ranges->emplace_back(r); + *end_offset = std::max(*end_offset, r.offset + r.size); + } + _offset_index_ctx->collect_io_range(ranges, end_offset, active); + } else { + int64_t offset = 0; + if (column_metadata.__isset.dictionary_page_offset) { + offset = column_metadata.dictionary_page_offset; + } else { + offset = column_metadata.data_page_offset; + } + int64_t size = column_metadata.total_compressed_size; + auto r = io::SharedBufferedInputStream::IORange(offset, size, active); + ranges->emplace_back(r); + *end_offset = std::max(*end_offset, offset + size); + } + } else if (type == ColumnIOType::PAGE_INDEX) { + // only active column need column index + if (column.__isset.column_index_offset && active) { + auto r = io::SharedBufferedInputStream::IORange(column.column_index_offset, column.column_index_length); + ranges->emplace_back(r); + } + // all column need offset index + if (column.__isset.offset_index_offset) { + auto r = io::SharedBufferedInputStream::IORange(column.offset_index_offset, column.offset_index_length); + ranges->emplace_back(r); + } + } +} + +void ScalarColumnReader::select_offset_index(const SparseRange& range, const uint64_t rg_first_row) { + if (_offset_index_ctx == nullptr) { + if (!get_chunk_metadata()->__isset.offset_index_offset) { + return; + } + auto st = get_offset_index(rg_first_row); + if (!st.ok()) { + return; + } + } + size_t page_num = _offset_index_ctx->offset_index.page_locations.size(); + size_t range_size = range.size(); + + size_t range_idx = 0; + Range r = range[range_idx++]; + + for (size_t i = 0; i < page_num; i++) { + int64_t first_row = _offset_index_ctx->offset_index.page_locations[i].first_row_index + rg_first_row; + int64_t end_row = first_row; + if (i != page_num - 1) { + end_row = _offset_index_ctx->offset_index.page_locations[i + 1].first_row_index + rg_first_row; + } else { + // a little trick, we don't care about the real rows of the last page. + if (range.end() < first_row) { + _offset_index_ctx->page_selected.emplace_back(false); + continue; + } else { + end_row = range.end(); + } + } + if (end_row <= r.begin()) { + _offset_index_ctx->page_selected.emplace_back(false); + continue; + } + while (first_row >= r.end() && range_idx < range_size) { + r = range[range_idx++]; + } + _offset_index_ctx->page_selected.emplace_back(first_row < r.end() && end_row > r.begin()); + } + const tparquet::ColumnMetaData& column_metadata = get_chunk_metadata()->meta_data; + bool has_dict_page = column_metadata.__isset.dictionary_page_offset; + // be compatible with PARQUET-1850 + has_dict_page |= _offset_index_ctx->check_dictionary_page(column_metadata.data_page_offset); + _reader = std::make_unique(std::move(_reader), _offset_index_ctx.get(), has_dict_page); +} + +StatusOr ScalarColumnReader::row_group_zone_map_filter(const std::vector& predicates, + CompoundNodeType pred_relation, + const uint64_t rg_first_row, + const uint64_t rg_num_rows) const { + if (!get_chunk_metadata()->meta_data.__isset.statistics || get_column_parquet_field() == nullptr) { + // statistics is not existed, select all + return true; + } + + bool has_null = true; + bool is_all_null = false; + + if (get_chunk_metadata()->meta_data.statistics.__isset.null_count) { + has_null = get_chunk_metadata()->meta_data.statistics.null_count > 0; + is_all_null = get_chunk_metadata()->meta_data.statistics.null_count == rg_num_rows; + } + + std::optional zone_map_detail = std::nullopt; + + // used to hold min/max slice values + const ColumnPtr min_column = ColumnHelper::create_column(*_col_type, true); + const ColumnPtr max_column = ColumnHelper::create_column(*_col_type, true); + if (is_all_null) { + // if the entire column's value is null, the min/max value not existed + zone_map_detail = ZoneMapDetail{Datum{}, Datum{}, true}; + zone_map_detail->set_num_rows(rg_num_rows); + } else { + std::vector min_values; + std::vector max_values; + Status st = + StatisticsHelper::get_min_max_value(_opts.file_meta_data, *_col_type, &get_chunk_metadata()->meta_data, + get_column_parquet_field(), min_values, max_values); + if (st.ok()) { + RETURN_IF_ERROR(StatisticsHelper::decode_value_into_column(min_column, min_values, *_col_type, + get_column_parquet_field(), _opts.timezone)); + RETURN_IF_ERROR(StatisticsHelper::decode_value_into_column(max_column, max_values, *_col_type, + get_column_parquet_field(), _opts.timezone)); + + zone_map_detail = ZoneMapDetail{min_column->get(0), max_column->get(0), has_null}; + zone_map_detail->set_num_rows(rg_num_rows); + } + } + + if (!zone_map_detail.has_value()) { + // ZoneMapDetail not set, means select all + return true; + } + + return ZoneMapEvaluatorUtils::is_satisfy(predicates, zone_map_detail.value(), pred_relation); +} + +StatusOr ScalarColumnReader::page_index_zone_map_filter(const std::vector& predicates, + SparseRange* row_ranges, + CompoundNodeType pred_relation, + const uint64_t rg_first_row, const uint64_t rg_num_rows) { + DCHECK(row_ranges->empty()); + const tparquet::ColumnChunk* chunk_meta = get_chunk_metadata(); + if (!chunk_meta->__isset.column_index_offset || !chunk_meta->__isset.offset_index_offset || + !chunk_meta->__isset.meta_data) { + // no page index, dont filter + return false; + } + + // get column index + int64_t column_index_offset = chunk_meta->column_index_offset; + uint32_t column_index_length = chunk_meta->column_index_length; + + std::vector page_index_data; + page_index_data.reserve(column_index_length); + RETURN_IF_ERROR(_opts.file->read_at_fully(column_index_offset, page_index_data.data(), column_index_length)); + + tparquet::ColumnIndex column_index; + RETURN_IF_ERROR(deserialize_thrift_msg(page_index_data.data(), &column_index_length, TProtocolType::COMPACT, + &column_index)); + + ASSIGN_OR_RETURN(const tparquet::OffsetIndex* offset_index, get_offset_index(rg_first_row)); + + const size_t page_num = column_index.min_values.size(); + + ColumnPtr min_column = ColumnHelper::create_column(*_col_type, true); + ColumnPtr max_column = ColumnHelper::create_column(*_col_type, true); + // deal with min_values + auto st = StatisticsHelper::decode_value_into_column(min_column, column_index.min_values, *_col_type, + get_column_parquet_field(), _opts.timezone); + if (!st.ok()) { + // swallow error status + LOG(INFO) << "Error when decode min/max statistics, type " << _col_type->debug_string(); + return false; + } + // deal with max_values + st = StatisticsHelper::decode_value_into_column(max_column, column_index.max_values, *_col_type, + get_column_parquet_field(), _opts.timezone); + if (!st.ok()) { + // swallow error status + LOG(INFO) << "Error when decode min/max statistics, type " << _col_type->debug_string(); + return false; + } + + DCHECK_EQ(page_num, min_column->size()); + DCHECK_EQ(page_num, max_column->size()); + + // fill ZoneMapDetail + const std::vector null_pages = column_index.null_pages; + std::vector zone_map_details{}; + for (size_t i = 0; i < page_num; i++) { + if (null_pages[i]) { + // all null + zone_map_details.emplace_back(Datum{}, Datum{}, true); + } else { + bool has_null = column_index.null_counts[i] > 0; + zone_map_details.emplace_back(min_column->get(i), max_column->get(i), has_null); + } + } + + // select all pages by default + Filter page_filter(page_num, 1); + for (size_t i = 0; i < page_num; i++) { + page_filter[i] = ZoneMapEvaluatorUtils::is_satisfy(predicates, zone_map_details[i], pred_relation); + } + + if (!SIMD::contain_zero(page_filter)) { + // no page has been filtered + return false; + } + + for (int i = 0; i < page_num; i++) { + if (page_filter[i]) { + int64_t first_row = offset_index->page_locations[i].first_row_index + rg_first_row; + int64_t end_row = first_row; + if (i != page_num - 1) { + end_row = offset_index->page_locations[i + 1].first_row_index + rg_first_row; + } else { + end_row = rg_first_row + rg_num_rows; + } + row_ranges->add(Range(first_row, end_row)); + } + } + return true; +} + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/scalar_column_reader.h b/be/src/formats/parquet/scalar_column_reader.h new file mode 100644 index 0000000000000..063a0036cd60a --- /dev/null +++ b/be/src/formats/parquet/scalar_column_reader.h @@ -0,0 +1,157 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "formats/parquet/column_converter.h" +#include "formats/parquet/column_reader.h" +#include "formats/parquet/page_index_reader.h" +#include "formats/parquet/stored_column_reader.h" +#include "util/thrift_util.h" + +namespace starrocks::parquet { + +class FixedValueColumnReader final : public ColumnReader { +public: + explicit FixedValueColumnReader(Datum fixed_value) : ColumnReader(nullptr), _fixed_value(std::move(fixed_value)) {} + + ~FixedValueColumnReader() override = default; + + Status prepare() override { return Status::OK(); } + + void get_levels(level_t** def_levels, level_t** rep_levels, size_t* num_levels) override {} + + void set_need_parse_levels(bool need_parse_levels) override {} + + void collect_column_io_range(std::vector* ranges, int64_t* end_offset, + ColumnIOType type, bool active) override {} + + void select_offset_index(const SparseRange& range, const uint64_t rg_first_row) override {} + + Status read_range(const Range& range, const Filter* filter, ColumnPtr& dst) override { + return Status::NotSupported("Not implemented"); + } + + StatusOr row_group_zone_map_filter(const std::vector& predicates, + CompoundNodeType pred_relation, const uint64_t rg_first_row, + const uint64_t rg_num_rows) const override; + + StatusOr page_index_zone_map_filter(const std::vector& predicates, + SparseRange* row_ranges, CompoundNodeType pred_relation, + const uint64_t rg_first_row, const uint64_t rg_num_rows) override; + +private: + const Datum _fixed_value; +}; + +class ScalarColumnReader final : public ColumnReader { +public: + explicit ScalarColumnReader(const ParquetField* parquet_field, const tparquet::ColumnChunk* column_chunk_metadata, + const TypeDescriptor* col_type, const ColumnReaderOptions& opts) + : ColumnReader(parquet_field), _opts(opts), _col_type(col_type), _chunk_metadata(column_chunk_metadata) {} + ~ScalarColumnReader() override = default; + + Status prepare() override { + RETURN_IF_ERROR(ColumnConverterFactory::create_converter(*get_column_parquet_field(), *_col_type, + _opts.timezone, &_converter)); + return StoredColumnReader::create(_opts, get_column_parquet_field(), get_chunk_metadata(), &_reader); + } + + Status read_range(const Range& range, const Filter* filter, ColumnPtr& dst) override; + + void get_levels(level_t** def_levels, level_t** rep_levels, size_t* num_levels) override { + _reader->get_levels(def_levels, rep_levels, num_levels); + } + + void set_need_parse_levels(bool need_parse_levels) override { _reader->set_need_parse_levels(need_parse_levels); } + + bool try_to_use_dict_filter(ExprContext* ctx, bool is_decode_needed, const SlotId slotId, + const std::vector& sub_field_path, const size_t& layer) override; + + Status rewrite_conjunct_ctxs_to_predicate(bool* is_group_filtered, const std::vector& sub_field_path, + const size_t& layer) override { + DCHECK_EQ(sub_field_path.size(), layer); + return _dict_filter_ctx->rewrite_conjunct_ctxs_to_predicate(_reader.get(), is_group_filtered); + } + + void set_can_lazy_decode(bool can_lazy_decode) override { + _can_lazy_decode = can_lazy_decode && _col_type->is_string_type() && _column_all_pages_dict_encoded(); + } + + Status filter_dict_column(const ColumnPtr& column, Filter* filter, const std::vector& sub_field_path, + const size_t& layer) override { + DCHECK_EQ(sub_field_path.size(), layer); + return _dict_filter_ctx->predicate->evaluate_and(column.get(), filter->data()); + } + + Status fill_dst_column(ColumnPtr& dst, ColumnPtr& src) override; + + void collect_column_io_range(std::vector* ranges, int64_t* end_offset, + ColumnIOType type, bool active) override; + + const tparquet::ColumnChunk* get_chunk_metadata() const override { return _chunk_metadata; } + + StatusOr get_offset_index(const uint64_t rg_first_row) override { + if (_offset_index_ctx == nullptr) { + _offset_index_ctx = std::make_unique(); + _offset_index_ctx->rg_first_row = rg_first_row; + int64_t offset_index_offset = get_chunk_metadata()->offset_index_offset; + uint32_t offset_index_length = get_chunk_metadata()->offset_index_length; + std::vector offset_index_data; + offset_index_data.reserve(offset_index_length); + RETURN_IF_ERROR( + _opts.file->read_at_fully(offset_index_offset, offset_index_data.data(), offset_index_length)); + + RETURN_IF_ERROR(deserialize_thrift_msg(offset_index_data.data(), &offset_index_length, + TProtocolType::COMPACT, &_offset_index_ctx->offset_index)); + } + return &_offset_index_ctx->offset_index; + } + + void select_offset_index(const SparseRange& range, const uint64_t rg_first_row) override; + + StatusOr row_group_zone_map_filter(const std::vector& predicates, + CompoundNodeType pred_relation, uint64_t rg_first_row, + uint64_t rg_num_rows) const override; + + StatusOr page_index_zone_map_filter(const std::vector& predicates, + SparseRange* row_ranges, CompoundNodeType pred_relation, + const uint64_t rg_first_row, const uint64_t rg_num_rows) override; + +private: + // Returns true if all of the data pages in the column chunk are dict encoded + bool _column_all_pages_dict_encoded(); + + const ColumnReaderOptions& _opts; + + std::unique_ptr _reader; + + std::unique_ptr _converter; + + std::unique_ptr _dict_filter_ctx; + const TypeDescriptor* _col_type = nullptr; + const tparquet::ColumnChunk* _chunk_metadata = nullptr; + std::unique_ptr _offset_index_ctx; + + // _can_lazy_decode means string type and all page dict code + bool _can_lazy_decode = false; + // we use lazy decode adaptively because of RLE && decoder may be better than filter && decoder + static constexpr double FILTER_RATIO = 0.2; + bool _need_lazy_decode = false; + // dict code + ColumnPtr _dict_code = nullptr; + ColumnPtr _ori_column = nullptr; +}; + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/formats/parquet/schema.cpp b/be/src/formats/parquet/schema.cpp index 5e59c0e609202..d115b72b09b7c 100644 --- a/be/src/formats/parquet/schema.cpp +++ b/be/src/formats/parquet/schema.cpp @@ -14,10 +14,20 @@ #include "formats/parquet/schema.h" +<<<<<<< HEAD #include #include "gutil/casts.h" #include "gutil/strings/substitute.h" +======= +#include +#include +#include +#include + +#include "gutil/strings/substitute.h" +#include "types/logical_type.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/slice.h" namespace starrocks::parquet { diff --git a/be/src/formats/parquet/schema.h b/be/src/formats/parquet/schema.h index abbd19b35549c..d2e091f95ff6f 100644 --- a/be/src/formats/parquet/schema.h +++ b/be/src/formats/parquet/schema.h @@ -14,7 +14,15 @@ #pragma once +<<<<<<< HEAD #include +======= +#include +#include + +#include +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include diff --git a/be/src/formats/parquet/statistics_helper.cpp b/be/src/formats/parquet/statistics_helper.cpp index cb5cd942c4895..6d9dbf3449c6e 100644 --- a/be/src/formats/parquet/statistics_helper.cpp +++ b/be/src/formats/parquet/statistics_helper.cpp @@ -17,7 +17,10 @@ #include #include "column/column_helper.h" +<<<<<<< HEAD #include "column/datum.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/type_traits.h" #include "column/vectorized_fwd.h" #include "common/object_pool.h" @@ -27,18 +30,29 @@ #include "formats/parquet/encoding_plain.h" #include "formats/parquet/schema.h" #include "gutil/casts.h" +<<<<<<< HEAD #include "runtime/large_int_value.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/types.h" #include "simd/simd.h" #include "storage/column_predicate.h" #include "storage/types.h" #include "storage/uint24.h" #include "types/date_value.h" +<<<<<<< HEAD +======= +#include "types/large_int_value.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "types/logical_type.h" namespace starrocks::parquet { +<<<<<<< HEAD Status StatisticsHelper::decode_value_into_column(ColumnPtr column, const std::vector& values, +======= +Status StatisticsHelper::decode_value_into_column(const ColumnPtr& column, const std::vector& values, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TypeDescriptor& type, const ParquetField* field, const std::string& timezone) { std::unique_ptr converter; @@ -162,7 +176,11 @@ bool StatisticsHelper::can_be_used_for_statistics_filter(ExprContext* ctx, } } +<<<<<<< HEAD void translate_to_string_value(ColumnPtr col, size_t i, std::string& value) { +======= +void translate_to_string_value(const ColumnPtr& col, size_t i, std::string& value) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (col->is_date()) { value = col->get(i).get_date().to_string(); return; @@ -274,4 +292,51 @@ Status StatisticsHelper::in_filter_on_min_max_stat(const std::vector& min_values, std::vector& max_values) { + // When statistics is empty, column_meta->__isset.statistics is still true, + // but statistics.__isset.xxx may be false, so judgment is required here. + bool is_set_min_max = (column_meta->statistics.__isset.max && column_meta->statistics.__isset.min) || + (column_meta->statistics.__isset.max_value && column_meta->statistics.__isset.min_value); + if (!is_set_min_max) { + return Status::Aborted("No exist min/max"); + } + + DCHECK_EQ(field->physical_type, column_meta->type); + auto sort_order = sort_order_of_logical_type(type.type); + + if (!has_correct_min_max_stats(file_metadata, *column_meta, sort_order)) { + return Status::Aborted("The file has incorrect order"); + } + + if (column_meta->statistics.__isset.min_value) { + min_values.emplace_back(column_meta->statistics.min_value); + max_values.emplace_back(column_meta->statistics.max_value); + } else { + min_values.emplace_back(column_meta->statistics.min); + max_values.emplace_back(column_meta->statistics.max); + } + + return Status::OK(); +} + +Status StatisticsHelper::get_has_nulls(const tparquet::ColumnMetaData* column_meta, std::vector& has_nulls) { + if (!column_meta->statistics.__isset.null_count) { + return Status::Aborted("No null_count in column statistics"); + } + has_nulls.emplace_back(column_meta->statistics.null_count > 0); + return Status::OK(); +} + +bool StatisticsHelper::has_correct_min_max_stats(const FileMetaData* file_metadata, + const tparquet::ColumnMetaData& column_meta, + const SortOrder& sort_order) { + return file_metadata->writer_version().HasCorrectStatistics(column_meta, sort_order); +} + +} // namespace starrocks::parquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/formats/parquet/statistics_helper.h b/be/src/formats/parquet/statistics_helper.h index 126d51d7d89f1..12cbec625e001 100644 --- a/be/src/formats/parquet/statistics_helper.h +++ b/be/src/formats/parquet/statistics_helper.h @@ -16,8 +16,13 @@ #include "column/vectorized_fwd.h" #include "common/status.h" +<<<<<<< HEAD #include "exprs/expr_context.h" #include "exprs/in_const_predicate.hpp" +======= +#include "exprs/in_const_predicate.hpp" +#include "formats/parquet/metadata.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/schema.h" #include "runtime/types.h" @@ -27,7 +32,11 @@ class StatisticsHelper { public: enum StatSupportedFilter { FILTER_IN, IS_NULL, IS_NOT_NULL }; +<<<<<<< HEAD static Status decode_value_into_column(ColumnPtr column, const std::vector& values, +======= + static Status decode_value_into_column(const ColumnPtr& column, const std::vector& values, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const TypeDescriptor& type, const ParquetField* field, const std::string& timezone); @@ -36,6 +45,22 @@ class StatisticsHelper { static Status in_filter_on_min_max_stat(const std::vector& min_values, const std::vector& max_values, ExprContext* ctx, const ParquetField* field, const std::string& timezone, Filter& selected); +<<<<<<< HEAD +}; + +} // namespace starrocks::parquet +======= + + // get min/max value from row group stats + static Status get_min_max_value(const FileMetaData* file_meta_data, const TypeDescriptor& type, + const tparquet::ColumnMetaData* column_meta, const ParquetField* field, + std::vector& min_values, std::vector& max_values); + + static Status get_has_nulls(const tparquet::ColumnMetaData* column_meta, std::vector& has_nulls); + + static bool has_correct_min_max_stats(const FileMetaData* file_metadata, + const tparquet::ColumnMetaData& column_meta, const SortOrder& sort_order); }; -} // namespace starrocks::parquet \ No newline at end of file +} // namespace starrocks::parquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/formats/parquet/stored_column_reader.cpp b/be/src/formats/parquet/stored_column_reader.cpp index 501e66031d3f4..635d0ae27ecbf 100644 --- a/be/src/formats/parquet/stored_column_reader.cpp +++ b/be/src/formats/parquet/stored_column_reader.cpp @@ -14,6 +14,7 @@ #include "formats/parquet/stored_column_reader.h" +<<<<<<< HEAD #include "column/column.h" #include "column_reader.h" #include "common/status.h" @@ -22,6 +23,30 @@ #include "formats/parquet/utils.h" #include "simd/simd.h" #include "util/runtime_profile.h" +======= +#include +#include + +#include +#include +#include +#include + +#include "column/column.h" +#include "column_reader.h" +#include "common/compiler_util.h" +#include "common/logging.h" +#include "common/status.h" +#include "formats/parquet/level_codec.h" +#include "formats/parquet/schema.h" +#include "formats/parquet/types.h" +#include "formats/parquet/utils.h" +#include "simd/simd.h" + +namespace tparquet { +class ColumnChunk; +} // namespace tparquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { diff --git a/be/src/formats/parquet/stored_column_reader.h b/be/src/formats/parquet/stored_column_reader.h index a635f4291081e..03a694a8d1658 100644 --- a/be/src/formats/parquet/stored_column_reader.h +++ b/be/src/formats/parquet/stored_column_reader.h @@ -17,18 +17,42 @@ #include #include #include +<<<<<<< HEAD #include "column_reader.h" #include "common/status.h" +======= +#include + +#include "column/vectorized_fwd.h" +#include "column_reader.h" +#include "common/status.h" +#include "common/statusor.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "formats/parquet/column_chunk_reader.h" #include "formats/parquet/schema.h" #include "formats/parquet/types.h" #include "formats/parquet/utils.h" #include "gen_cpp/parquet_types.h" +<<<<<<< HEAD +======= +#include "storage/range.h" + +namespace tparquet { +class ColumnChunk; +} // namespace tparquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { class Column; class NullableColumn; +<<<<<<< HEAD +======= + +namespace parquet { +struct ParquetField; +} // namespace parquet +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks namespace starrocks::parquet { @@ -58,8 +82,12 @@ class StoredColumnReader { virtual Status get_dict_values(Column* column) = 0; +<<<<<<< HEAD virtual Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) = 0; +======= + virtual Status get_dict_values(const Buffer& dict_codes, const NullableColumn& nulls, Column* column) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual Status load_dictionary_page() { return Status::InternalError("Not supported load_dictionary_page"); } @@ -84,10 +112,16 @@ class StoredColumnReaderImpl : public StoredColumnReader { Status read_range(const Range& range, const Filter* filter, ColumnContentType content_type, Column* dst) override; +<<<<<<< HEAD virtual Status get_dict_values(Column* column) override { return _reader->get_dict_values(column); } virtual Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) override { +======= + Status get_dict_values(Column* column) override { return _reader->get_dict_values(column); } + + Status get_dict_values(const Buffer& dict_codes, const NullableColumn& nulls, Column* column) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return _reader->get_dict_values(dict_codes, nulls, column); } diff --git a/be/src/formats/parquet/stored_column_reader_with_index.cpp b/be/src/formats/parquet/stored_column_reader_with_index.cpp index aebfc35b904ee..f49f1c640dc79 100644 --- a/be/src/formats/parquet/stored_column_reader_with_index.cpp +++ b/be/src/formats/parquet/stored_column_reader_with_index.cpp @@ -14,8 +14,20 @@ #include "formats/parquet/stored_column_reader_with_index.h" +<<<<<<< HEAD #include "util/defer_op.h" +======= +#include + +#include "gen_cpp/parquet_types.h" +#include "util/defer_op.h" + +namespace starrocks { +class Column; +} // namespace starrocks + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { Status StoredColumnReaderWithIndex::read_range(const Range& range, const Filter* filter, diff --git a/be/src/formats/parquet/stored_column_reader_with_index.h b/be/src/formats/parquet/stored_column_reader_with_index.h index a0f4e4a11a687..4157d24ce2ef7 100644 --- a/be/src/formats/parquet/stored_column_reader_with_index.h +++ b/be/src/formats/parquet/stored_column_reader_with_index.h @@ -14,8 +14,30 @@ #pragma once +<<<<<<< HEAD #include "formats/parquet/page_index_reader.h" #include "formats/parquet/stored_column_reader.h" +======= +#include +#include + +#include +#include +#include + +#include "column/vectorized_fwd.h" +#include "common/status.h" +#include "formats/parquet/page_index_reader.h" +#include "formats/parquet/stored_column_reader.h" +#include "formats/parquet/types.h" +#include "formats/parquet/utils.h" +#include "storage/range.h" + +namespace starrocks { +class Column; +class NullableColumn; +} // namespace starrocks +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks::parquet { @@ -44,8 +66,12 @@ class StoredColumnReaderWithIndex : public StoredColumnReader { Status get_dict_values(Column* column) override { return _inner_reader->get_dict_values(column); } +<<<<<<< HEAD Status get_dict_values(const std::vector& dict_codes, const NullableColumn& nulls, Column* column) override { +======= + Status get_dict_values(const Buffer& dict_codes, const NullableColumn& nulls, Column* column) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return _inner_reader->get_dict_values(dict_codes, nulls, column); } diff --git a/be/src/formats/parquet/utils.cpp b/be/src/formats/parquet/utils.cpp index 95c5617a946ac..bae62d6e9f8fc 100644 --- a/be/src/formats/parquet/utils.cpp +++ b/be/src/formats/parquet/utils.cpp @@ -16,9 +16,17 @@ #include +<<<<<<< HEAD namespace starrocks::parquet { CompressionTypePB convert_compression_codec(tparquet::CompressionCodec::type codec) { +======= +#include "util/hash_util.hpp" + +namespace starrocks::parquet { + +CompressionTypePB ParquetUtils::convert_compression_codec(tparquet::CompressionCodec::type codec) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) switch (codec) { case tparquet::CompressionCodec::UNCOMPRESSED: return NO_COMPRESSION; @@ -46,7 +54,11 @@ int decimal_precision_to_byte_count_inner(int precision) { return std::ceil((std::log(std::pow(10, precision) - 1) / std::log(2) + 1) / 8); } +<<<<<<< HEAD int decimal_precision_to_byte_count(int precision) { +======= +int ParquetUtils::decimal_precision_to_byte_count(int precision) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(precision > 0 && precision <= 38); static std::array table = { 0, @@ -93,4 +105,38 @@ int decimal_precision_to_byte_count(int precision) { return table[precision]; } +<<<<<<< HEAD +======= +int64_t ParquetUtils::get_column_start_offset(const tparquet::ColumnMetaData& column) { + int64_t offset = column.data_page_offset; + if (column.__isset.index_page_offset) { + offset = std::min(offset, column.index_page_offset); + } + if (column.__isset.dictionary_page_offset) { + offset = std::min(offset, column.dictionary_page_offset); + } + return offset; +} + +int64_t ParquetUtils::get_row_group_start_offset(const tparquet::RowGroup& row_group) { + const tparquet::ColumnMetaData& first_column = row_group.columns[0].meta_data; + int64_t offset = get_column_start_offset(first_column); + + if (row_group.__isset.file_offset) { + offset = std::min(offset, row_group.file_offset); + } + return offset; +} + +int64_t ParquetUtils::get_row_group_end_offset(const tparquet::RowGroup& row_group) { + // following computation is not correct. `total_compressed_size` means compressed size of all columns + // but between columns there could be holes, which means end offset inaccurate. + // if (row_group.__isset.file_offset && row_group.__isset.total_compressed_size) { + // return row_group.file_offset + row_group.total_compressed_size; + // } + const tparquet::ColumnMetaData& last_column = row_group.columns.back().meta_data; + return get_column_start_offset(last_column) + last_column.total_compressed_size; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::parquet diff --git a/be/src/formats/parquet/utils.h b/be/src/formats/parquet/utils.h index 287b2d2845481..eca4445fb4f83 100644 --- a/be/src/formats/parquet/utils.h +++ b/be/src/formats/parquet/utils.h @@ -19,12 +19,30 @@ namespace starrocks::parquet { +<<<<<<< HEAD CompressionTypePB convert_compression_codec(tparquet::CompressionCodec::type parquet_codec); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) enum ColumnContentType { VALUE, DICT_CODE }; enum ColumnIOType { PAGE_INDEX, PAGES }; +<<<<<<< HEAD int decimal_precision_to_byte_count(int precision); +======= +class ParquetUtils { +public: + static CompressionTypePB convert_compression_codec(tparquet::CompressionCodec::type parquet_codec); + + static int decimal_precision_to_byte_count(int precision); + + static int64_t get_column_start_offset(const tparquet::ColumnMetaData& column); + + static int64_t get_row_group_start_offset(const tparquet::RowGroup& row_group); + + static int64_t get_row_group_end_offset(const tparquet::RowGroup& row_group); +}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks::parquet diff --git a/be/src/formats/parquet/zone_map_filter_evaluator.h b/be/src/formats/parquet/zone_map_filter_evaluator.h new file mode 100644 index 0000000000000..519c5ee1c55aa --- /dev/null +++ b/be/src/formats/parquet/zone_map_filter_evaluator.h @@ -0,0 +1,102 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "formats/parquet/group_reader.h" +#include "storage/predicate_tree/predicate_tree.h" + +namespace starrocks::parquet { + +enum class FilterLevel { ROW_GROUP = 0, PAGE_INDEX }; + +class ZoneMapEvaluatorUtils { +public: + static bool is_satisfy(const std::vector& predicates, const ZoneMapDetail& detail, + const CompoundNodeType pred_relation) { + if (pred_relation == CompoundNodeType::AND) { + return std::ranges::all_of(predicates, [&](const auto* pred) { return pred->zone_map_filter(detail); }); + } else { + return predicates.empty() || + std::ranges::any_of(predicates, [&](const auto* pred) { return pred->zone_map_filter(detail); }); + } + } +}; + +template +struct ZoneMapEvaluator { + template + StatusOr>> operator()(const PredicateCompoundNode& node) { + std::optional> row_ranges = std::nullopt; + const uint64_t rg_first_row = group_reader->get_row_group_first_row(); + const uint64_t rg_num_rows = group_reader->get_row_group_metadata()->num_rows; + + const auto& ctx = pred_tree.compound_node_context(node.id()); + const auto& cid_to_col_preds = ctx.cid_to_col_preds(node); + + for (const auto& [cid, col_preds] : cid_to_col_preds) { + SparseRange cur_row_ranges; + + auto* column_reader = group_reader->get_column_reader(cid); + + if (column_reader == nullptr) { + // ColumnReader not found, select all by default + cur_row_ranges.add({rg_first_row, rg_first_row + rg_num_rows}); + } else if (level == FilterLevel::ROW_GROUP) { + ASSIGN_OR_RETURN(bool is_selected, + column_reader->row_group_zone_map_filter(col_preds, Type, rg_first_row, rg_num_rows)); + if (is_selected) { + cur_row_ranges.add({rg_first_row, rg_first_row + rg_num_rows}); + } + } else { + ASSIGN_OR_RETURN(bool has_filtered, + column_reader->page_index_zone_map_filter( + col_preds, &cur_row_ranges, Type, group_reader->get_row_group_first_row(), + group_reader->get_row_group_metadata()->num_rows)); + if (!has_filtered) { + // no filter happened, select the whole row group by default + cur_row_ranges.add({rg_first_row, rg_first_row + rg_num_rows}); + } + } + + merge_row_ranges(row_ranges, cur_row_ranges); + } + + for (const auto& child : node.compound_children()) { + ASSIGN_OR_RETURN(auto cur_row_ranges_opt, child.visit(*this)); + if (cur_row_ranges_opt.has_value()) { + merge_row_ranges(row_ranges, cur_row_ranges_opt.value()); + } + } + return row_ranges; + } + + template + static void merge_row_ranges(std::optional>& dest, SparseRange& source) { + if (!dest.has_value()) { + dest = std::move(source); + } else { + if constexpr (Type == CompoundNodeType::AND) { + dest.value() &= source; + } else { + dest.value() |= source; + } + } + } + + const PredicateTree& pred_tree; + GroupReader* group_reader; +}; + +} // namespace starrocks::parquet \ No newline at end of file diff --git a/be/src/fs/CMakeLists.txt b/be/src/fs/CMakeLists.txt index b4d22f640fba9..81df298dc9311 100644 --- a/be/src/fs/CMakeLists.txt +++ b/be/src/fs/CMakeLists.txt @@ -28,10 +28,23 @@ set(EXEC_FILES fs_s3.cpp hdfs/fs_hdfs.cpp hdfs/hdfs_fs_cache.cpp +<<<<<<< HEAD fs_util.cpp fs_starlet.cpp ) +======= + s3/poco_http_client_factory.cpp + s3/poco_http_client.cpp + s3/poco_common.cpp + fs_util.cpp + ) + +if (NOT BUILD_FORMAT_LIB) + list(APPEND EXEC_FILES fs_starlet.cpp) +endif() + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_library(FileSystem STATIC ${EXEC_FILES} ) diff --git a/be/src/fs/fs.cpp b/be/src/fs/fs.cpp index cebd0e1718a76..2d97d1c8eae3a 100644 --- a/be/src/fs/fs.cpp +++ b/be/src/fs/fs.cpp @@ -22,7 +22,11 @@ #include "fs/fs_util.h" #include "fs/hdfs/fs_hdfs.h" #include "runtime/file_result_writer.h" +<<<<<<< HEAD #ifdef USE_STAROS +======= +#if defined(USE_STAROS) && !defined(BUILD_FORMAT_LIB) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fs/fs_starlet.h" #endif @@ -52,7 +56,11 @@ std::unique_ptr RandomAccessFile::from(std::unique_ptr tls_fs_posix; static thread_local std::shared_ptr tls_fs_s3; static thread_local std::shared_ptr tls_fs_hdfs; +<<<<<<< HEAD #ifdef USE_STAROS +======= +#if defined(USE_STAROS) && !defined(BUILD_FORMAT_LIB) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static thread_local std::shared_ptr tls_fs_starlet; #endif @@ -77,7 +85,11 @@ inline std::shared_ptr get_tls_fs_s3() { return tls_fs_s3; } +<<<<<<< HEAD #ifdef USE_STAROS +======= +#if defined(USE_STAROS) && !defined(BUILD_FORMAT_LIB) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) inline std::shared_ptr get_tls_fs_starlet() { if (tls_fs_starlet == nullptr) { tls_fs_starlet.reset(new_fs_starlet().release()); @@ -86,7 +98,20 @@ inline std::shared_ptr get_tls_fs_starlet() { } #endif +<<<<<<< HEAD StatusOr> FileSystem::CreateUniqueFromString(std::string_view uri, FSOptions options) { +======= +StatusOr> FileSystem::Create(std::string_view uri, const FSOptions& options) { + if (!options._fs_options.empty()) { + return FileSystem::CreateUniqueFromString(uri, options); + } else { + return FileSystem::CreateSharedFromString(uri); + } +} + +StatusOr> FileSystem::CreateUniqueFromString(std::string_view uri, + const FSOptions& options) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (fs::is_fallback_to_hadoop_fs(uri)) { return new_fs_hdfs(options); } @@ -101,7 +126,11 @@ StatusOr> FileSystem::CreateUniqueFromString(std::st // Now Azure storage and Google Cloud Storage both are using LibHdfs, we can use cpp sdk instead in the future. return new_fs_hdfs(options); } +<<<<<<< HEAD #ifdef USE_STAROS +======= +#if defined(USE_STAROS) && !defined(BUILD_FORMAT_LIB) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (is_starlet_uri(uri)) { return new_fs_starlet(); } @@ -121,7 +150,11 @@ StatusOr> FileSystem::CreateSharedFromString(std::st if (fs::is_s3_uri(uri)) { return get_tls_fs_s3(); } +<<<<<<< HEAD #ifdef USE_STAROS +======= +#if defined(USE_STAROS) && !defined(BUILD_FORMAT_LIB) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (is_starlet_uri(uri)) { return get_tls_fs_starlet(); } diff --git a/be/src/fs/fs.h b/be/src/fs/fs.h index 8a2656b3d21d8..136f64e7bb8b6 100644 --- a/be/src/fs/fs.h +++ b/be/src/fs/fs.h @@ -33,6 +33,10 @@ struct ResultFileOptions; class TUploadReq; class TDownloadReq; struct WritableFileOptions; +<<<<<<< HEAD +======= +class FileSystem; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) struct SpaceInfo { // Total size of the filesystem, in bytes @@ -47,13 +51,23 @@ struct FSOptions { private: FSOptions(const TBrokerScanRangeParams* scan_range_params, const TExportSink* export_sink, const ResultFileOptions* result_file_options, const TUploadReq* upload, const TDownloadReq* download, +<<<<<<< HEAD const TCloudConfiguration* cloud_configuration) +======= + const TCloudConfiguration* cloud_configuration, + const std::unordered_map& fs_options = {}) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : scan_range_params(scan_range_params), export_sink(export_sink), result_file_options(result_file_options), upload(upload), download(download), +<<<<<<< HEAD cloud_configuration(cloud_configuration) {} +======= + cloud_configuration(cloud_configuration), + _fs_options(fs_options) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: FSOptions() : FSOptions(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr) {} @@ -73,6 +87,12 @@ struct FSOptions { FSOptions(const TCloudConfiguration* cloud_configuration) : FSOptions(nullptr, nullptr, nullptr, nullptr, nullptr, cloud_configuration) {} +<<<<<<< HEAD +======= + FSOptions(const std::unordered_map& fs_options) + : FSOptions(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, fs_options) {} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const THdfsProperties* hdfs_properties() const; const TBrokerScanRangeParams* scan_range_params; @@ -81,6 +101,20 @@ struct FSOptions { const TUploadReq* upload; const TDownloadReq* download; const TCloudConfiguration* cloud_configuration; +<<<<<<< HEAD +======= + const std::unordered_map _fs_options; + + static constexpr const char* FS_S3_ENDPOINT = "fs.s3a.endpoint"; + static constexpr const char* FS_S3_ENDPOINT_REGION = "fs.s3a.endpoint.region"; + static constexpr const char* FS_S3_ACCESS_KEY = "fs.s3a.access.key"; + static constexpr const char* FS_S3_SECRET_KEY = "fs.s3a.secret.key"; + static constexpr const char* FS_S3_PATH_STYLE_ACCESS = "fs.s3a.path.style.access"; + static constexpr const char* FS_S3_CONNECTION_SSL_ENABLED = "fs.s3a.connection.ssl.enabled"; + static constexpr const char* FS_S3_READ_AHEAD_RANGE = "fs.s3a.readahead.range"; + static constexpr const char* FS_S3_RETRY_LIMIT = "fs.s3a.retry.limit"; + static constexpr const char* FS_S3_RETRY_INTERVAL = "fs.s3a.retry.interval"; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; struct SequentialFileOptions { @@ -112,6 +146,10 @@ struct FileInfo { std::string path; std::optional size; std::string encryption_meta; +<<<<<<< HEAD +======= + std::shared_ptr fs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; struct FileWriteStat { @@ -138,8 +176,15 @@ class FileSystem { FileSystem() = default; virtual ~FileSystem() = default; +<<<<<<< HEAD static StatusOr> CreateUniqueFromString(std::string_view uri, FSOptions options = FSOptions()); +======= + static StatusOr> Create(std::string_view uri, const FSOptions& options); + + static StatusOr> CreateUniqueFromString(std::string_view uri, + const FSOptions& options = FSOptions()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static StatusOr> CreateSharedFromString(std::string_view uri); diff --git a/be/src/fs/fs_broker.cpp b/be/src/fs/fs_broker.cpp index e20908b3f7fb1..f899693e0be0e 100644 --- a/be/src/fs/fs_broker.cpp +++ b/be/src/fs/fs_broker.cpp @@ -21,13 +21,20 @@ #include #include +<<<<<<< HEAD #include "common/config.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fs/fs.h" #include "gen_cpp/FileBrokerService_types.h" #include "gen_cpp/TFileBrokerService.h" #include "runtime/broker_mgr.h" #include "runtime/client_cache.h" #include "runtime/exec_env.h" +<<<<<<< HEAD +======= +#include "util/thrift_rpc_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using namespace fmt::literals; @@ -91,6 +98,7 @@ static Status to_status(const TBrokerOperationStatus& st, const TNetworkAddress& template static Status call_method(const TNetworkAddress& broker, Method method, const Request& request, Response* response, int retry_count = 1, int timeout_ms = DEFAULT_TIMEOUT_MS) { +<<<<<<< HEAD TFileBrokerServiceClient* client; #ifndef BE_TEST Status status; @@ -127,6 +135,20 @@ static Status call_method(const TNetworkAddress& broker, Method method, const Re fmt::format("Fail to call broker, error={}, broker={}", e.what(), broker.hostname)); } } +======= +#ifdef BE_TEST + TFileBrokerServiceClient* client = g_broker_client; + (client->*method)(*response, request); + return Status::OK(); +#else + return ThriftRpcHelper::rpc( + broker, + [method, response, &request](BrokerServiceConnection& client) { + (client.get()->*method)(*response, request); + }, + timeout_ms, retry_count); +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // This function will *NOT* return EOF status. diff --git a/be/src/fs/fs_s3.cpp b/be/src/fs/fs_s3.cpp index 2e30576131a0f..1646b0c3c6cb4 100644 --- a/be/src/fs/fs_s3.cpp +++ b/be/src/fs/fs_s3.cpp @@ -14,10 +14,16 @@ #include "fs/fs_s3.h" +<<<<<<< HEAD #include #include #include #include +======= +#include +#include +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -43,7 +49,10 @@ #include "io/s3_input_stream.h" #include "io/s3_output_stream.h" #include "util/hdfs_util.h" +<<<<<<< HEAD #include "util/random.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -69,6 +78,7 @@ bool operator==(const Aws::Client::ClientConfiguration& lhs, const Aws::Client:: lhs.maxConnections == rhs.maxConnections && lhs.scheme == rhs.scheme; } +<<<<<<< HEAD class S3ClientFactory { public: using ClientConfiguration = Aws::Client::ClientConfiguration; @@ -153,6 +163,14 @@ class S3ClientFactory { S3ClientPtr _clients[kMaxItems]; Random _rand; }; +======= +bool S3ClientFactory::ClientCacheKey::operator==(const ClientCacheKey& rhs) const { + if (config && rhs.config && aws_cloud_configuration && rhs.aws_cloud_configuration) { + return *config == *(rhs.config) && *aws_cloud_configuration == *(rhs.aws_cloud_configuration); + } + return !config && !rhs.config && !aws_cloud_configuration && !rhs.aws_cloud_configuration; +} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) S3ClientFactory::S3ClientFactory() : _rand((int)::time(nullptr)) {} @@ -175,7 +193,11 @@ std::shared_ptr S3ClientFactory::_get_aws_cre if (!aws_cloud_credential.iam_role_arn.empty()) { // Do assume role +<<<<<<< HEAD Aws::Client::ClientConfiguration clientConfiguration{}; +======= + Aws::Client::ClientConfiguration clientConfiguration = S3ClientFactory::getClientConfig(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!aws_cloud_credential.sts_region.empty()) { clientConfiguration.region = aws_cloud_credential.sts_region; } @@ -197,6 +219,15 @@ void S3ClientFactory::close() { } } +<<<<<<< HEAD +======= +// clang-format: off +static const std::vector retryable_errors = { + // tos qps limit ExceptionName + "ExceedAccountQPSLimit", "ExceedAccountRateLimit", "ExceedBucketQPSLimit", "ExceedBucketRateLimit"}; +// clang-format: on + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const TCloudConfiguration& t_cloud_configuration, S3ClientFactory::OperationType operation_type) { const AWSCloudConfiguration aws_cloud_configuration = CloudConfigurationFactory::create_aws(t_cloud_configuration); @@ -230,7 +261,13 @@ S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const TCloudConfigurati config.requestTimeoutMs = config::object_storage_request_timeout_ms; } +<<<<<<< HEAD ClientCacheKey client_cache_key{config, aws_cloud_configuration}; +======= + auto client_conf = std::make_shared(config); + auto aws_config = std::make_shared(aws_cloud_configuration); + ClientCacheKey client_cache_key{client_conf, aws_config}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) { // Duplicate code for cache s3 client std::lock_guard l(_lock); @@ -241,6 +278,11 @@ S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const TCloudConfigurati auto credential_provider = _get_aws_credentials_provider(aws_cloud_credential); +<<<<<<< HEAD +======= + config.retryStrategy = std::make_shared( + retryable_errors, config::object_storage_max_retries, config::object_storage_retry_scale_factor); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) S3ClientPtr client = std::make_shared( credential_provider, config, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, !path_style_access); @@ -261,8 +303,13 @@ S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const TCloudConfigurati S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const ClientConfiguration& config, const FSOptions& opts) { std::lock_guard l(_lock); +<<<<<<< HEAD ClientCacheKey client_cache_key{config, AWSCloudConfiguration{}}; +======= + auto client_conf = std::make_shared(config); + ClientCacheKey client_cache_key{client_conf, std::make_shared()}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < _items; i++) { if (_client_cache_keys[i] == client_cache_key) return _clients[i]; } @@ -280,9 +327,26 @@ S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const ClientConfigurati secret_access_key = hdfs_properties->secret_key; } } else { +<<<<<<< HEAD access_key_id = config::object_storage_access_key_id; secret_access_key = config::object_storage_secret_access_key; } +======= + // resolve path style + auto itr = opts._fs_options.find(FSOptions::FS_S3_PATH_STYLE_ACCESS); + if (itr != opts._fs_options.end()) { + path_style_access = itr->second.compare("true") == 0; + } + + // resolve ak,sk + itr = opts._fs_options.find(FSOptions::FS_S3_ACCESS_KEY); + access_key_id = itr != opts._fs_options.end() ? itr->second : config::object_storage_access_key_id; + + itr = opts._fs_options.find(FSOptions::FS_S3_SECRET_KEY); + secret_access_key = itr != opts._fs_options.end() ? itr->second : config::object_storage_secret_access_key; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!access_key_id.empty() && !secret_access_key.empty()) { auto credentials = std::make_shared(access_key_id, secret_access_key); client = std::make_shared(credentials, config, @@ -311,6 +375,21 @@ S3ClientFactory::S3ClientPtr S3ClientFactory::new_client(const ClientConfigurati return client; } +<<<<<<< HEAD +======= +// Only use for UT +bool S3ClientFactory::_find_client_cache_keys_by_config_TEST(const Aws::Client::ClientConfiguration& config, + AWSCloudConfiguration* cloud_config) { + auto aws_config = cloud_config == nullptr ? AWSCloudConfiguration{} : *cloud_config; + for (size_t i = 0; i < _items; i++) { + if (_client_cache_keys[i] == ClientCacheKey{std::make_shared(config), + std::make_shared(aws_config)}) + return true; + } + return false; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // If you find yourself change this code, see also `bool operator==(const Aws::Client::ClientConfiguration&, const Aws::Client::ClientConfiguration&)` static std::shared_ptr new_s3client( const S3URI& uri, const FSOptions& opts, @@ -343,19 +422,62 @@ static std::shared_ptr new_s3client( config.maxConnections = config::object_storage_max_connection; } } else { +<<<<<<< HEAD if (!uri.endpoint().empty()) { config.endpointOverride = uri.endpoint(); } else if (!config::object_storage_endpoint.empty()) { config.endpointOverride = config::object_storage_endpoint; +======= + // resolve endpoint + auto itr = opts._fs_options.find(FSOptions::FS_S3_ENDPOINT); + auto ssl_itr = opts._fs_options.find(FSOptions::FS_S3_CONNECTION_SSL_ENABLED); + + if (itr != opts._fs_options.end() && !itr->second.empty()) { + config.endpointOverride = itr->second; + } else if (!config::object_storage_endpoint.empty()) { + config.endpointOverride = config::object_storage_endpoint; + } else if (ssl_itr != opts._fs_options.end()) { + config.scheme = itr->second.compare("true") == 0 ? Aws::Http::Scheme::HTTPS : Aws::Http::Scheme::HTTP; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else if (config::object_storage_endpoint_use_https) { config.scheme = Aws::Http::Scheme::HTTPS; } else { config.scheme = Aws::Http::Scheme::HTTP; } +<<<<<<< HEAD if (!config::object_storage_region.empty()) { config.region = config::object_storage_region; } config.maxConnections = config::object_storage_max_connection; +======= + + // resolve region + itr = opts._fs_options.find(FSOptions::FS_S3_ENDPOINT_REGION); + if (itr != opts._fs_options.end() && !itr->second.empty()) { + config.region = itr->second; + } else if (!config::object_storage_region.empty()) { + config.region = config::object_storage_region; + } + config.maxConnections = config::object_storage_max_connection; + + // resolve retry + int64_t s3client_max_retries = config::object_storage_max_retries; + itr = opts._fs_options.find(FSOptions::FS_S3_RETRY_LIMIT); + if (itr != opts._fs_options.end() && !itr->second.empty()) { + s3client_max_retries = std::stoi(itr->second); + } + int64_t s3client_retry_scale_factor = config::object_storage_retry_scale_factor; + itr = opts._fs_options.find(FSOptions::FS_S3_RETRY_INTERVAL); + if (itr != opts._fs_options.end() && !itr->second.empty()) { + s3client_retry_scale_factor = std::stoi(itr->second); + } + config.retryStrategy = std::make_shared( + retryable_errors, s3client_max_retries, s3client_retry_scale_factor); + } + + if (!uri.endpoint().empty()) { + config.endpointOverride = uri.endpoint(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if (config::object_storage_connect_timeout_ms > 0) { config.connectTimeoutMs = config::object_storage_connect_timeout_ms; @@ -370,11 +492,19 @@ static std::shared_ptr new_s3client( } return S3ClientFactory::instance().new_client(config, opts); +<<<<<<< HEAD } class S3FileSystem : public FileSystem { public: S3FileSystem(const FSOptions& options) : _options(options) {} +======= +} // namespace starrocks + +class S3FileSystem : public FileSystem { +public: + S3FileSystem(const FSOptions& options) : _options(std::move(options)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~S3FileSystem() override = default; S3FileSystem(const S3FileSystem&) = delete; @@ -458,10 +588,30 @@ class S3FileSystem : public FileSystem { Status delete_dir_v1(const std::string& dirname); Status delete_dir_recursive_v1(const std::string& dirname); +<<<<<<< HEAD private: FSOptions _options; }; +======= + FSOptions _options; +}; + +static int64_t read_ahead_size_from_options(const FSOptions& options) { + int64_t read_ahead_size = 64 * 1024; // default value is 64KB + auto itr = options._fs_options.find(FSOptions::FS_S3_READ_AHEAD_RANGE); + if (itr != options._fs_options.end() && !itr->second.empty()) { + try { + read_ahead_size = std::stoi(itr->second); + } catch (std::logic_error const&) { + LOG_EVERY_N(WARNING, 10) << " Can not convert config " << FSOptions::FS_S3_READ_AHEAD_RANGE + << "'s value to int : " << itr->second; + } + } + return read_ahead_size; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr> S3FileSystem::new_random_access_file(const RandomAccessFileOptions& opts, const std::string& path) { S3URI uri; @@ -469,7 +619,13 @@ StatusOr> S3FileSystem::new_random_access_file return Status::InvalidArgument(fmt::format("Invalid S3 URI: {}", path)); } auto client = new_s3client(uri, _options); +<<<<<<< HEAD auto input_stream = std::make_unique(std::move(client), uri.bucket(), uri.key()); +======= + auto read_ahead_size = read_ahead_size_from_options(_options); + auto input_stream = + std::make_unique(std::move(client), uri.bucket(), uri.key(), read_ahead_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return RandomAccessFile::from(std::move(input_stream), path, false, opts.encryption_info); } @@ -480,7 +636,13 @@ StatusOr> S3FileSystem::new_random_access_file return Status::InvalidArgument(fmt::format("Invalid S3 URI: {}", file_info.path)); } auto client = new_s3client(uri, _options); +<<<<<<< HEAD auto input_stream = std::make_unique(std::move(client), uri.bucket(), uri.key()); +======= + auto read_ahead_size = read_ahead_size_from_options(_options); + auto input_stream = + std::make_unique(std::move(client), uri.bucket(), uri.key(), read_ahead_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (file_info.size.has_value()) { input_stream->set_size(file_info.size.value()); } @@ -494,7 +656,14 @@ StatusOr> S3FileSystem::new_sequential_file(cons return Status::InvalidArgument(fmt::format("Invalid S3 URI: {}", path)); } auto client = new_s3client(uri, _options); +<<<<<<< HEAD auto input_stream = std::make_unique(std::move(client), uri.bucket(), uri.key()); +======= + auto read_ahead_size = read_ahead_size_from_options(_options); + auto input_stream = + std::make_unique(std::move(client), uri.bucket(), uri.key(), read_ahead_size); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return SequentialFile::from(std::move(input_stream), path, opts.encryption_info); } diff --git a/be/src/fs/fs_s3.h b/be/src/fs/fs_s3.h index c054149d3f120..5810d0ece80a8 100644 --- a/be/src/fs/fs_s3.h +++ b/be/src/fs/fs_s3.h @@ -14,11 +14,105 @@ #pragma once +<<<<<<< HEAD #include "fs/fs.h" +======= +#include +#include + +#include "fs/credential/cloud_configuration.h" +#include "fs/fs.h" +#include "util/random.h" + +namespace Aws::S3 { +class S3Client; +} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { std::unique_ptr new_fs_s3(const FSOptions& options); void close_s3_clients(); +<<<<<<< HEAD +======= +class S3ClientFactory { +public: + using ClientConfiguration = Aws::Client::ClientConfiguration; + using S3Client = Aws::S3::S3Client; + using S3ClientPtr = std::shared_ptr; + using ClientConfigurationPtr = std::shared_ptr; + using AWSCloudConfigurationPtr = std::shared_ptr; + + static S3ClientFactory& instance() { + static S3ClientFactory obj; + return obj; + } + + // Indicates the different S3 operation of using the client. + // This class is used to set different configuration for clients + // with different purposes. + enum class OperationType { + UNKNOWN, + RENAME_FILE, + }; + + ~S3ClientFactory() = default; + + S3ClientFactory(const S3ClientFactory&) = delete; + void operator=(const S3ClientFactory&) = delete; + S3ClientFactory(S3ClientFactory&&) = delete; + void operator=(S3ClientFactory&&) = delete; + + S3ClientPtr new_client(const TCloudConfiguration& cloud_configuration, + S3ClientFactory::OperationType operation_type = S3ClientFactory::OperationType::UNKNOWN); + S3ClientPtr new_client(const ClientConfiguration& config, const FSOptions& opts); + + void close(); + + static ClientConfiguration& getClientConfig() { + // We cached config here and make a deep copy each time.Since aws sdk has changed the + // Aws::Client::ClientConfiguration default constructor to search for the region + // (where as before 1.8 it has been hard coded default of "us-east-1"). + // Part of that change is looking through the ec2 metadata, which can take a long time. + // For more details, please refer https://github.com/aws/aws-sdk-cpp/issues/1440 + static ClientConfiguration instance; + return instance; + } + + // Only use for UT + bool find_client_cache_keys_by_config_TEST(const Aws::Client::ClientConfiguration& config, + AWSCloudConfiguration* cloud_config = nullptr) { + return _find_client_cache_keys_by_config_TEST(config); + } + +private: + S3ClientFactory(); + + static std::shared_ptr _get_aws_credentials_provider( + const AWSCloudCredential& aws_cloud_credential); + + class ClientCacheKey { + public: + ClientConfigurationPtr config; + AWSCloudConfigurationPtr aws_cloud_configuration; + + bool operator==(const ClientCacheKey& rhs) const; + }; + + constexpr static int kMaxItems = 8; + + // Only use for UT + bool _find_client_cache_keys_by_config_TEST(const Aws::Client::ClientConfiguration& config, + AWSCloudConfiguration* cloud_config = nullptr); + + std::mutex _lock; + int _items{0}; + // _client_cache_keys[i] is the client cache key of |_clients[i]. + ClientCacheKey _client_cache_keys[kMaxItems]; + S3ClientPtr _clients[kMaxItems]; + Random _rand; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/fs/fs_starlet.cpp b/be/src/fs/fs_starlet.cpp index 56867a5a0c609..b20ae69d2a8ef 100644 --- a/be/src/fs/fs_starlet.cpp +++ b/be/src/fs/fs_starlet.cpp @@ -192,7 +192,11 @@ class StarletInputStream : public starrocks::io::SeekableInputStream { stats->append(kIOCountRemote, read_stats.io_count_remote); stats->append(kIONsReadLocalDisk, read_stats.io_ns_read_local_disk); stats->append(kIONsWriteLocalDisk, read_stats.io_ns_write_local_disk); +<<<<<<< HEAD stats->append(kIONsRemote, read_stats.io_ns_remote); +======= + stats->append(kIONsRemote, read_stats.io_ns_read_remote); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) stats->append(kPrefetchHitCount, read_stats.prefetch_hit_count); stats->append(kPrefetchWaitFinishNs, read_stats.prefetch_wait_finish_ns); stats->append(kPrefetchPendingNs, read_stats.prefetch_pending_ns); diff --git a/be/src/fs/hdfs/fs_hdfs.cpp b/be/src/fs/hdfs/fs_hdfs.cpp index 2305e8243ee71..b83f47b780fef 100644 --- a/be/src/fs/hdfs/fs_hdfs.cpp +++ b/be/src/fs/hdfs/fs_hdfs.cpp @@ -28,6 +28,10 @@ #include "service/backend_options.h" #include "testutil/sync_point.h" #include "udf/java/utils.h" +<<<<<<< HEAD +======= +#include "util/failpoint/fail_point.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/hdfs_util.h" using namespace fmt::literals; @@ -36,7 +40,11 @@ namespace starrocks { class GetHdfsFileReadOnlyHandle { public: +<<<<<<< HEAD GetHdfsFileReadOnlyHandle(const FSOptions options, std::string path, int buffer_size) +======= + GetHdfsFileReadOnlyHandle(const FSOptions& options, std::string path, int buffer_size) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : _options(std::move(options)), _path(std::move(path)), _buffer_size(buffer_size) {} StatusOr getOrCreateFS() { @@ -325,6 +333,10 @@ class HDFSWritableFile : public WritableFile { }; Status HDFSWritableFile::append(const Slice& data) { +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) tSize r = hdfsWrite(_fs, _file, data.data, data.size); if (r == -1) { // error auto error_msg = fmt::format("Fail to append {}: {}", _path, get_hdfs_err_msg()); @@ -342,6 +354,10 @@ Status HDFSWritableFile::append(const Slice& data) { } Status HDFSWritableFile::appendv(const Slice* data, size_t cnt) { +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (size_t i = 0; i < cnt; i++) { RETURN_IF_ERROR(append(data[i])); } @@ -354,6 +370,10 @@ Status HDFSWritableFile::close() { } FileSystem::on_file_write_close(this); auto ret = call_hdfs_scan_function_in_pthread([this]() { +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int r = hdfsHSync(_fs, _file); TEST_SYNC_POINT_CALLBACK("HDFSWritableFile::close", &r); auto st = Status::OK(); @@ -363,6 +383,10 @@ Status HDFSWritableFile::close() { st.update(Status::IOError(error_msg)); } +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) r = hdfsCloseFile(_fs, _file); if (r == -1) { auto error_msg = fmt::format("Fail to close file {}: {}", _path, get_hdfs_err_msg()); @@ -379,7 +403,11 @@ Status HDFSWritableFile::close() { class HdfsFileSystem : public FileSystem { public: +<<<<<<< HEAD HdfsFileSystem(const FSOptions& options) : _options(options) {} +======= + HdfsFileSystem(const FSOptions& options) : _options(std::move(options)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~HdfsFileSystem() override = default; HdfsFileSystem(const HdfsFileSystem&) = delete; diff --git a/be/src/fs/s3/poco_common.cpp b/be/src/fs/s3/poco_common.cpp new file mode 100644 index 0000000000000..7c84d775cd2c6 --- /dev/null +++ b/be/src/fs/s3/poco_common.cpp @@ -0,0 +1,139 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fs/s3/poco_common.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "runtime/current_thread.h" + +namespace starrocks::poco { + +bool isHTTPS(const Poco::URI& uri) { + if (uri.getScheme() == "https") + return true; + else if (uri.getScheme() == "http") + return false; + else + throw std::runtime_error(fmt::format("Unsupported scheme in URI '{}'", uri.toString())); +} + +void setTimeouts(Poco::Net::HTTPClientSession& session, const ConnectionTimeouts& timeouts) { + session.setTimeout(timeouts.connection_timeout, timeouts.send_timeout, timeouts.receive_timeout); + session.setKeepAliveTimeout(timeouts.http_keep_alive_timeout); +} + +std::string getCurrentExceptionMessage() { + std::stringstream ss; + + try { + throw; + } catch (const Poco::Exception& e) { + ss << fmt::format("Poco::Exception. e.code() = {}, e.displayText() = {}, e.what() = {}", e.code(), + e.displayText(), e.what()); + } catch (const std::exception& e) { + ss << fmt::format("std::exception. type: {}, e.what() = {}", typeid(e).name(), e.what()); + } catch (...) { + ss << fmt::format("Unknown exception from poco client"); + } + + return ss.str(); +} + +// 1) https://aws.amazon.com/premiumsupport/knowledge-center/s3-resolve-200-internalerror/ +// 2) https://github.com/aws/aws-sdk-cpp/issues/658 +bool checkRequestCanReturn2xxAndErrorInBody(Aws::Http::HttpRequest& request) { + auto query_params = request.GetQueryStringParameters(); + if (request.HasHeader("x-amz-copy-source")) { + // CopyObject https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html + if (query_params.empty()) return true; + + // UploadPartCopy https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html + if (query_params.contains("partNumber") && query_params.contains("uploadId")) return true; + + } else { + // CompleteMultipartUpload https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html + if (query_params.size() == 1 && query_params.contains("uploadId")) return true; + } + + return false; +} + +HTTPSessionPtr makeHTTPSessionImpl(const std::string& host, Poco::UInt16 port, bool https, bool keep_alive) { + HTTPSessionPtr session; + + if (https) { + session = std::make_shared(host, port); + } else { + session = std::make_shared(host, port); + } + + // doesn't work properly without patch + session->setKeepAlive(keep_alive); + return session; +} + +EndpointHTTPSessionPool::Base::ObjectPtr EndpointHTTPSessionPool::allocObject() { + SCOPED_THREAD_LOCAL_MEM_TRACKER_SETTER(_mem_tracker); + auto session = makeHTTPSessionImpl(_host, _port, _is_https, true); + return session; +} + +HTTPSessionPools& HTTPSessionPools::instance() { + static HTTPSessionPools instance; + return instance; +} + +PooledHTTPSessionPtr HTTPSessionPools::getSession(const Poco::URI& uri, const ConnectionTimeouts& timeouts, + bool resolve_host) { + const std::string& host = uri.getHost(); + uint16_t port = uri.getPort(); + bool is_https = isHTTPS(uri); + + const Key key = {.host = host, .port = port, .is_https = is_https}; + + EndpointPoolPtr pool = nullptr; + { + std::lock_guard lock(_mutex); + auto item = _endpoint_pools.find(key); + if (item == _endpoint_pools.end()) { + std::tie(item, std::ignore) = + _endpoint_pools.emplace(key, std::make_shared(host, port, is_https)); + } + pool = item->second; + } + + auto session = pool->get(timeouts.connection_timeout.totalMicroseconds()); + session->attachSessionData({}); + + return session; +} + +void HTTPSessionPools::shutdown() { + std::lock_guard lock(_mutex); + _endpoint_pools.clear(); +} + +PooledHTTPSessionPtr makeHTTPSession(const Poco::URI& uri, const ConnectionTimeouts& timeouts, bool resolve_host) { + return HTTPSessionPools::instance().getSession(uri, timeouts, resolve_host); +} + +} // namespace starrocks::poco diff --git a/be/src/fs/s3/poco_common.h b/be/src/fs/s3/poco_common.h new file mode 100644 index 0000000000000..5c368c40ddada --- /dev/null +++ b/be/src/fs/s3/poco_common.h @@ -0,0 +1,119 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +#include "fs/s3/pool_base.h" +#include "runtime/exec_env.h" +#include "runtime/mem_tracker.h" + +namespace starrocks::poco { + +struct ConnectionTimeouts { + Poco::Timespan connection_timeout; + Poco::Timespan send_timeout; + Poco::Timespan receive_timeout; + Poco::Timespan http_keep_alive_timeout{0}; + + ConnectionTimeouts() = default; + + ConnectionTimeouts(const Poco::Timespan& connection_timeout_, const Poco::Timespan& send_timeout_, + const Poco::Timespan& receive_timeout_) + : connection_timeout(connection_timeout_), send_timeout(send_timeout_), receive_timeout(receive_timeout_) {} +}; + +using PooledHTTPSessionPtr = PoolBase::Entry; +using HTTPSessionPtr = std::shared_ptr; + +bool isHTTPS(const Poco::URI& uri); + +void setTimeouts(Poco::Net::HTTPClientSession& session, const ConnectionTimeouts& timeouts); + +HTTPSessionPtr makeHTTPSessionImpl(const std::string& host, Poco::UInt16 port, bool https, bool keep_alive); + +PooledHTTPSessionPtr makeHTTPSession(const Poco::URI& uri, const ConnectionTimeouts& timeouts, bool resolve_host); + +std::string getCurrentExceptionMessage(); + +bool checkRequestCanReturn2xxAndErrorInBody(Aws::Http::HttpRequest& request); + +enum ResponseCode { + SUCCESS_RESPONSE_MIN = 200, + SUCCESS_RESPONSE_MAX = 299, + TOO_MANY_REQUEST = 429, + SERVICE_UNAVALIABLE = 503 +}; + +class EndpointHTTPSessionPool : public PoolBase { +public: + using Base = PoolBase; + EndpointHTTPSessionPool(std::string host, uint16_t port, bool is_https) + : Base(ENDPOINT_POOL_SIZE), _host(std::move(host)), _port(port), _is_https(is_https) { + _mem_tracker = GlobalEnv::GetInstance()->poco_connection_pool_mem_tracker(); + } + +private: + ObjectPtr allocObject() override; + + static constexpr size_t ENDPOINT_POOL_SIZE = 1024; + + const std::string _host; + const uint16_t _port; + const bool _is_https; + MemTracker* _mem_tracker = nullptr; +}; + +class HTTPSessionPools { +private: + struct Key { + std::string host; + uint16_t port; + bool is_https; + + bool operator==(const Key& rhs) const { + return std::tie(host, port, is_https) == std::tie(rhs.host, rhs.port, rhs.is_https); + } + }; + + struct Hasher { + uint32_t operator()(const Key& k) const { + return std::hash()(k.host) ^ std::hash()(k.port) ^ std::hash()(k.is_https); + } + }; + +public: + using EndpointPoolPtr = std::shared_ptr; + static HTTPSessionPools& instance(); + + PooledHTTPSessionPtr getSession(const Poco::URI& uri, const ConnectionTimeouts& timeouts, bool resolve_host); + + void shutdown(); + +private: + HTTPSessionPools() = default; + + std::mutex _mutex; + std::unordered_map _endpoint_pools; +}; + +} // namespace starrocks::poco diff --git a/be/src/fs/s3/poco_http_client.cpp b/be/src/fs/s3/poco_http_client.cpp new file mode 100644 index 0000000000000..658396242f425 --- /dev/null +++ b/be/src/fs/s3/poco_http_client.cpp @@ -0,0 +1,206 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fs/s3/poco_http_client.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/logging.h" +#include "fs/s3/poco_common.h" +#include "io/s3_zero_copy_iostream.h" +#include "util/defer_op.h" + +namespace starrocks::poco { + +PocoHttpClient::PocoHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration) + : timeouts(ConnectionTimeouts( + Poco::Timespan(clientConfiguration.connectTimeoutMs * 1000), // connection timeout. + Poco::Timespan(clientConfiguration.httpRequestTimeoutMs * 1000), // send timeout. + Poco::Timespan(clientConfiguration.httpRequestTimeoutMs * 1000) // receive timeout. + )) {} + +std::shared_ptr PocoHttpClient::MakeRequest( + const std::shared_ptr& request, + Aws::Utils::RateLimits::RateLimiterInterface* readLimiter, + Aws::Utils::RateLimits::RateLimiterInterface* writeLimiter) const { + auto response = Aws::MakeShared("PocoHttpClient", request); + MakeRequestInternal(*request, response, readLimiter, writeLimiter); + return response; +} + +void PocoHttpClient::MakeRequestInternal(Aws::Http::HttpRequest& request, + std::shared_ptr& response, + Aws::Utils::RateLimits::RateLimiterInterface*, + Aws::Utils::RateLimits::RateLimiterInterface*) const { + auto uri = request.GetUri().GetURIString(); + + const int MAX_REDIRECT_ATTEMPTS = 10; + try { + for (int attempt = 0; attempt < MAX_REDIRECT_ATTEMPTS; ++attempt) { + Poco::URI poco_uri(uri); + + // URI may changed, because of redirection + auto session = makeHTTPSession(poco_uri, timeouts, false); + DeferOp deal_error([&]() { + if (session->networkException() != nullptr) { + session.set_not_in_good_condition(); + } + }); + + Poco::Net::HTTPRequest poco_request(Poco::Net::HTTPRequest::HTTP_1_1); + + /** According to RFC-2616, Request-URI is allowed to be encoded. + * However, there is no clear agreement on which exact symbols must be encoded. + * Effectively, `Poco::URI` chooses smaller subset of characters to encode, + * whereas Amazon S3 and Google Cloud Storage expects another one. + * In order to successfully execute a request, a path must be exact representation + * of decoded path used by `AWSAuthSigner`. + * Therefore we shall encode some symbols "manually" to fit the signatures. + */ + + std::string path_and_query; + const std::string& query = poco_uri.getRawQuery(); + const std::string reserved = "?#:;+@&=%"; // Poco::URI::RESERVED_QUERY_PARAM without '/' plus percent sign. + Poco::URI::encode(poco_uri.getPath(), reserved, path_and_query); + + // `target_uri.getPath()` could return an empty string, but a proper HTTP request must + // always contain a non-empty URI in its first line (e.g. "POST / HTTP/1.1" or "POST /?list-type=2 HTTP/1.1"). + if (path_and_query.empty()) path_and_query = "/"; + + // Append the query param to URI + if (!query.empty()) { + path_and_query += '?'; + path_and_query += query; + } + + poco_request.setURI(path_and_query); + + switch (request.GetMethod()) { + case Aws::Http::HttpMethod::HTTP_GET: + poco_request.setMethod(Poco::Net::HTTPRequest::HTTP_GET); + break; + case Aws::Http::HttpMethod::HTTP_POST: + poco_request.setMethod(Poco::Net::HTTPRequest::HTTP_POST); + break; + case Aws::Http::HttpMethod::HTTP_DELETE: + poco_request.setMethod(Poco::Net::HTTPRequest::HTTP_DELETE); + break; + case Aws::Http::HttpMethod::HTTP_PUT: + poco_request.setMethod(Poco::Net::HTTPRequest::HTTP_PUT); + break; + case Aws::Http::HttpMethod::HTTP_HEAD: + poco_request.setMethod(Poco::Net::HTTPRequest::HTTP_HEAD); + break; + case Aws::Http::HttpMethod::HTTP_PATCH: + poco_request.setMethod(Poco::Net::HTTPRequest::HTTP_PATCH); + break; + } + + for (const auto& [header_name, header_value] : request.GetHeaders()) { + poco_request.set(header_name, header_value); + } + + auto& request_body_stream = session->sendRequest(poco_request); + + if (request.GetContentBody()) { + // Rewind content body buffer. + // NOTE: we should do that always (even if `attempt == 0`) because the same request can be retried also by AWS, + // see retryStrategy in Aws::Client::ClientConfiguration. + request.GetContentBody()->clear(); + request.GetContentBody()->seekg(0); + + // Todo, optimize this with zero copy + [[maybe_unused]] auto size = + Poco::StreamCopier::copyStream(*request.GetContentBody(), request_body_stream); + } + + Poco::Net::HTTPResponse poco_response; + + if (dynamic_cast(&(response->GetResponseBody()))) { + poco_response.setResponseIOStream( + &(response->GetResponseBody()), + (static_cast(response->GetResponseBody().rdbuf())) + ->GetBuffer(), + (static_cast(response->GetResponseBody())).getSize()); + } + + auto& response_body_stream = session->receiveResponse(poco_response); + + int status_code = static_cast(poco_response.getStatus()); + + if (poco_response.getStatus() == Poco::Net::HTTPResponse::HTTP_TEMPORARY_REDIRECT) { + auto location = poco_response.get("location"); + uri = location; + continue; + } + + response->SetResponseCode(static_cast(status_code)); + response->SetContentType(poco_response.getContentType()); + + for (const auto& [header_name, header_value] : poco_response) { + response->AddHeader(header_name, header_value); + } + + // Request is successful but for some special requests we can have actual error message in body + // TODO, there is one more copy, but in these cases that RequestCanReturn2xxAndErrorInBody, it's trivial. + if (status_code >= ResponseCode::SUCCESS_RESPONSE_MIN && + status_code <= ResponseCode::SUCCESS_RESPONSE_MAX && checkRequestCanReturn2xxAndErrorInBody(request)) { + // reading the full response + std::string response_string((std::istreambuf_iterator(response_body_stream)), + std::istreambuf_iterator()); + + const static std::string_view needle = ""; + if (auto it = std::search(response_string.begin(), response_string.end(), + std::default_searcher(needle.begin(), needle.end())); + it != response_string.end()) { + LOG(WARNING) << "Response for request contain tag in body, settings internal server error " + "(500 code)"; + response->SetResponseCode(Aws::Http::HttpResponseCode::INTERNAL_SERVER_ERROR); + } + + if (!poco_response.isBodyFilled()) { + response->GetResponseBody().write(response_string.data(), response_string.size()); + } + } else { + if (status_code == ResponseCode::TOO_MANY_REQUEST || status_code == ResponseCode::SERVICE_UNAVALIABLE) { + // pass + // TODO, throttling + } + if (!poco_response.isBodyFilled()) { + Poco::StreamCopier::copyStream(response_body_stream, response->GetResponseBody()); + } + } + + return; + } + throw std::runtime_error( + fmt::format("Too many redirects while trying to access {}", request.GetUri().GetURIString())); + } catch (...) { + response->SetClientErrorType(Aws::Client::CoreErrors::NETWORK_CONNECTION); + response->SetClientErrorMessage(getCurrentExceptionMessage()); + } +} + +} // namespace starrocks::poco diff --git a/be/src/fs/s3/poco_http_client.h b/be/src/fs/s3/poco_http_client.h new file mode 100644 index 0000000000000..1d82a7ae08aed --- /dev/null +++ b/be/src/fs/s3/poco_http_client.h @@ -0,0 +1,52 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include "fs/s3/poco_common.h" + +namespace Aws::Http::Standard { +class StandardHttpResponse; +} + +namespace starrocks::poco { + +class PocoHttpClient : public Aws::Http::HttpClient { +public: + explicit PocoHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration); + ~PocoHttpClient() override = default; + + std::shared_ptr MakeRequest( + const std::shared_ptr& request, + Aws::Utils::RateLimits::RateLimiterInterface* readLimiter, + Aws::Utils::RateLimits::RateLimiterInterface* writeLimiter) const override; + +private: + void MakeRequestInternal(Aws::Http::HttpRequest& request, + std::shared_ptr& response, + Aws::Utils::RateLimits::RateLimiterInterface* readLimiter, + Aws::Utils::RateLimits::RateLimiterInterface* writeLimiter) const; + + ConnectionTimeouts timeouts; +}; + +} // namespace starrocks::poco diff --git a/be/src/fs/s3/poco_http_client_factory.cpp b/be/src/fs/s3/poco_http_client_factory.cpp new file mode 100644 index 0000000000000..62542838293b0 --- /dev/null +++ b/be/src/fs/s3/poco_http_client_factory.cpp @@ -0,0 +1,44 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fs/s3/poco_http_client_factory.h" + +#include +#include +#include +#include + +#include "fs/s3/poco_http_client.h" + +namespace starrocks::poco { + +std::shared_ptr PocoHttpClientFactory::CreateHttpClient( + const Aws::Client::ClientConfiguration& clientConfiguration) const { + return std::make_shared(clientConfiguration); +} + +std::shared_ptr PocoHttpClientFactory::CreateHttpRequest( + const Aws::String& uri, Aws::Http::HttpMethod method, const Aws::IOStreamFactory& streamFactory) const { + return CreateHttpRequest(Aws::Http::URI(uri), method, streamFactory); +} + +std::shared_ptr PocoHttpClientFactory::CreateHttpRequest( + const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const Aws::IOStreamFactory& streamFactory) const { + auto request = Aws::MakeShared("PocoHttpClientFactory", uri, method); + request->SetResponseStreamFactory(streamFactory); + + return request; +} + +} // namespace starrocks::poco diff --git a/be/src/fs/s3/poco_http_client_factory.h b/be/src/fs/s3/poco_http_client_factory.h new file mode 100644 index 0000000000000..4350e3f552d60 --- /dev/null +++ b/be/src/fs/s3/poco_http_client_factory.h @@ -0,0 +1,41 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +namespace Aws::Http { +class HttpClient; +class HttpRequest; +} // namespace Aws::Http + +namespace starrocks::poco { + +class PocoHttpClientFactory : public Aws::Http::HttpClientFactory { +public: + PocoHttpClientFactory() : Aws::Http::HttpClientFactory() { Poco::Net::initializeSSL(); } + ~PocoHttpClientFactory() override { Poco::Net::uninitializeSSL(); } + [[nodiscard]] std::shared_ptr CreateHttpClient( + const Aws::Client::ClientConfiguration& clientConfiguration) const override; + [[nodiscard]] std::shared_ptr CreateHttpRequest( + const Aws::String& uri, Aws::Http::HttpMethod method, + const Aws::IOStreamFactory& streamFactory) const override; + [[nodiscard]] std::shared_ptr CreateHttpRequest( + const Aws::Http::URI& uri, Aws::Http::HttpMethod method, + const Aws::IOStreamFactory& streamFactory) const override; +}; + +} // namespace starrocks::poco diff --git a/be/src/fs/s3/pool_base.h b/be/src/fs/s3/pool_base.h new file mode 100644 index 0000000000000..63bf3be5af7ef --- /dev/null +++ b/be/src/fs/s3/pool_base.h @@ -0,0 +1,130 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace starrocks::poco { + +template +class PoolBase { +public: + using ObjectPtr = std::shared_ptr; + +private: + struct PooledObject { + PooledObject(ObjectPtr object, PoolBase& pool) : object(object), pool(pool) {} + + ObjectPtr object; + bool in_use = false; + bool in_good_condition = true; + PoolBase& pool; + }; + + struct PoolEntryHelper { + explicit PoolEntryHelper(PooledObject& data) : data(data) { data.in_use = true; } + ~PoolEntryHelper() { + std::unique_lock lock(data.pool._mutex); + data.in_use = false; + data.pool._available.notify_one(); + } + + PooledObject& data; + }; + +public: + class Entry { + public: + friend class PoolBase; + + Entry() = default; + + Object* operator->() && = delete; + const Object* operator->() const&& = delete; + Object& operator*() && = delete; + const Object& operator*() const&& = delete; + + Object* operator->() & { return &*_data->data.object; } + const Object* operator->() const& { return &*_data->data.object; } + Object& operator*() & { return *_data->data.object; } + const Object& operator*() const& { return *_data->data.object; } + + PoolBase* getPool() const { return &_data->data.pool; } + + void set_not_in_good_condition() { _data->data.in_good_condition = false; } + + private: + std::shared_ptr _data; + + explicit Entry(PooledObject& object) : _data(std::make_shared(object)) {} + }; + + PoolBase(size_t max_items) : _max_items(max_items) { _items.reserve(_max_items); } + + virtual ~PoolBase() = default; + + Entry get(Poco::Timespan::TimeDiff timeout) { + std::unique_lock lock(_mutex); + + while (true) { + for (auto& item : _items) { + if (!item->in_use) { + if (!item->in_good_condition) { + ObjectPtr object = allocObject(); + item = std::make_shared(object, *this); + } + return Entry(*item); + } + } + + if (_items.size() < _max_items) { + ObjectPtr object = allocObject(); + _items.emplace_back(std::make_shared(object, *this)); + return Entry(*_items.back()); + } + + if (timeout < 0) { + _available.wait(lock); + } else { + _available.wait_for(lock, std::chrono::microseconds(timeout)); + } + } + } + + void reserve(size_t count) { + std::unique_lock lock(_mutex); + while (_items.size() < count) { + _items.emplace_back(std::make_shared(allocObject(), *this)); + } + } + +protected: + virtual ObjectPtr allocObject() = 0; + +private: + const size_t _max_items; + std::vector> _items; + + mutable std::mutex _mutex; + std::condition_variable _available; +}; + +} // namespace starrocks::poco diff --git a/be/src/gen_cpp/CMakeLists.txt b/be/src/gen_cpp/CMakeLists.txt index 96c67a5702039..043f3725e07d8 100644 --- a/be/src/gen_cpp/CMakeLists.txt +++ b/be/src/gen_cpp/CMakeLists.txt @@ -58,7 +58,10 @@ set(SRC_FILES ${GEN_CPP_DIR}/descriptors.pb.cc ${GEN_CPP_DIR}/encryption.pb.cc ${GEN_CPP_DIR}/internal_service.pb.cc +<<<<<<< HEAD ${GEN_CPP_DIR}/doris_internal_service.pb.cc +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ${GEN_CPP_DIR}/types.pb.cc ${GEN_CPP_DIR}/snapshot.pb.cc ${GEN_CPP_DIR}/status.pb.cc diff --git a/be/src/geo/wkt_parse.cpp b/be/src/geo/wkt_parse.cpp index 1380eec255c9e..64916d60e1ff9 100644 --- a/be/src/geo/wkt_parse.cpp +++ b/be/src/geo/wkt_parse.cpp @@ -34,7 +34,11 @@ GeoParseStatus WktParse::parse_wkt(const char* str, size_t len, GeoShape** shape wkt__scan_bytes(str, len, ctx.scaninfo); // parse +<<<<<<< HEAD auto res = wkt_parse(&ctx); +======= + auto res = wkt_parse(ctx.scaninfo, &ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) wkt_lex_destroy(ctx.scaninfo); if (res == 0) { *shape = ctx.shape; diff --git a/be/src/geo/wkt_yacc.y b/be/src/geo/wkt_yacc.y index 9809bdae786ba..10dad5ac9466c 100644 --- a/be/src/geo/wkt_yacc.y +++ b/be/src/geo/wkt_yacc.y @@ -23,7 +23,11 @@ #include "geo/geo_types.h" class WktParseContext; +<<<<<<< HEAD void wkt_error(WktParseContext* ctx, const char* msg) { +======= +void wkt_error(void* scanner, WktParseContext* ctx, const char* msg) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } /* forword declare this class for wkt_parse declaration in yacc.y.cpp */ %} @@ -45,12 +49,20 @@ void wkt_error(WktParseContext* ctx, const char* msg) { /* we need WktParseContext to pass scaninfo to lexer */ #include "geo/wkt_parse_ctx.h" +<<<<<<< HEAD #define WKT_LEX_PARAM ctx->scaninfo } %define api.pure full %parse-param { WktParseContext* ctx } %lex-param { WKT_LEX_PARAM } +======= +} + +%define api.pure full +%parse-param {void* scanner} { WktParseContext* ctx } +%lex-param {void* scanner} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) /* for multi-thread */ %define api.prefix {wkt_} diff --git a/be/src/gutil/CMakeLists.txt b/be/src/gutil/CMakeLists.txt index b15d66b1af7ea..4bc3e9bc0fd37 100644 --- a/be/src/gutil/CMakeLists.txt +++ b/be/src/gutil/CMakeLists.txt @@ -56,6 +56,11 @@ if ("${CMAKE_BUILD_TARGET_ARCH}" STREQUAL "x86" OR "${CMAKE_BUILD_TARGET_ARCH}" set(SOURCE_FILES ${SOURCE_FILES} atomicops-internals-x86.cc) endif() +<<<<<<< HEAD +======= +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_library(Gutil STATIC ${SOURCE_FILES}) set_target_properties(Gutil PROPERTIES COMPILE_FLAGS "-funsigned-char -Wno-deprecated -Wno-char-subscripts") diff --git a/be/src/gutil/strings/join.h b/be/src/gutil/strings/join.h index b1483a00141bb..fba4b6ce04fbc 100644 --- a/be/src/gutil/strings/join.h +++ b/be/src/gutil/strings/join.h @@ -168,7 +168,11 @@ inline string JoinStrings(const CONTAINER& components, const StringPiece& delim) template string JoinMapped(const CONTAINER& components, const FUNC& functor, const StringPiece& delim) { string result; +<<<<<<< HEAD for (typename CONTAINER::const_iterator iter = components.begin(); iter != components.end(); iter++) { +======= + for (auto iter = components.begin(); iter != components.end(); iter++) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (iter != components.begin()) { result.append(delim.data(), delim.size()); } diff --git a/be/src/http/action/checksum_action.cpp b/be/src/http/action/checksum_action.cpp index e445ae2ae3cc9..95ae877468290 100644 --- a/be/src/http/action/checksum_action.cpp +++ b/be/src/http/action/checksum_action.cpp @@ -52,7 +52,10 @@ const std::string TABLET_ID = "tablet_id"; // do not use name "VERSION", // or will be conflict with "VERSION" in thrift/config.h const std::string TABLET_VERSION = "version"; +<<<<<<< HEAD const std::string SCHEMA_HASH = "schema_hash"; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void ChecksumAction::handle(HttpRequest* req) { LOG(INFO) << "accept one request " << req->debug_string(); diff --git a/be/src/http/action/datacache_action.cpp b/be/src/http/action/datacache_action.cpp index 84661d7e62889..add27df6f2f27 100644 --- a/be/src/http/action/datacache_action.cpp +++ b/be/src/http/action/datacache_action.cpp @@ -34,7 +34,10 @@ const static std::string HEADER_JSON = "application/json"; const static std::string ACTION_KEY = "action"; const static std::string ACTION_STAT = "stat"; const static std::string ACTION_APP_STAT = "app_stat"; +<<<<<<< HEAD const static std::string ACTION_INVALIDATE_ALL = "invalidate_all"; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string cache_status_str(const DataCacheStatus& status) { std::string str_status; diff --git a/be/src/http/action/memory_metrics_action.cpp b/be/src/http/action/memory_metrics_action.cpp index d442bb85371bc..e0859e234303f 100644 --- a/be/src/http/action/memory_metrics_action.cpp +++ b/be/src/http/action/memory_metrics_action.cpp @@ -49,7 +49,10 @@ void MemoryMetricsAction::handle(HttpRequest* req) { "bloom_filter_index", "compaction", "schema_change", +<<<<<<< HEAD "column_pool", +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) "page_cache", "datacache", "update", diff --git a/be/src/http/action/metrics_action.h b/be/src/http/action/metrics_action.h index 4c032c84f14dc..17d6934356737 100644 --- a/be/src/http/action/metrics_action.h +++ b/be/src/http/action/metrics_action.h @@ -50,6 +50,7 @@ typedef void (*MockFunc)(const std::string&); class MetricsAction : public HttpHandler { public: +<<<<<<< HEAD explicit MetricsAction(MetricRegistry* metrics) : _metrics(metrics), _mock_func(nullptr) { // The option can be removed if PBackendService is final removed. _options.black_wildcards = "*_pbackend_service*"; @@ -59,6 +60,11 @@ class MetricsAction : public HttpHandler { // The option can be removed if PBackendService is final removed. _options.black_wildcards = "*_pbackend_service*"; } +======= + explicit MetricsAction(MetricRegistry* metrics) : _metrics(metrics), _mock_func(nullptr) {} + // for tests + explicit MetricsAction(MetricRegistry* metrics, MockFunc func) : _metrics(metrics), _mock_func(func) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~MetricsAction() override = default; void handle(HttpRequest* req) override; diff --git a/be/src/http/action/stream_load.cpp b/be/src/http/action/stream_load.cpp index 5df68003866ae..abde64974575e 100644 --- a/be/src/http/action/stream_load.cpp +++ b/be/src/http/action/stream_load.cpp @@ -42,6 +42,10 @@ #include #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -57,6 +61,11 @@ #include "http/http_request.h" #include "http/http_response.h" #include "http/utils.h" +<<<<<<< HEAD +======= +#include "runtime/batch_write/batch_write_mgr.h" +#include "runtime/batch_write/batch_write_util.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/client_cache.h" #include "runtime/current_thread.h" #include "runtime/exec_env.h" @@ -154,7 +163,11 @@ void StreamLoadAction::handle(HttpRequest* req) { // status already set to fail if (ctx->status.ok()) { +<<<<<<< HEAD ctx->status = _handle(ctx); +======= + ctx->status = ctx->enable_batch_write ? _handle_batch_write(req, ctx) : _handle(ctx); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!ctx->status.ok() && !ctx->status.is_publish_timeout()) { LOG(WARNING) << "Fail to handle streaming load, id=" << ctx->id << " errmsg=" << ctx->status.message() << " " << ctx->brief(); @@ -213,6 +226,15 @@ Status StreamLoadAction::_handle(StreamLoadContext* ctx) { return Status::OK(); } +<<<<<<< HEAD +======= +Status StreamLoadAction::_handle_batch_write(starrocks::HttpRequest* http_req, StreamLoadContext* ctx) { + ctx->load_parameters = get_load_parameters_from_http(http_req); + ctx->buffer->flip(); + return _exec_env->batch_write_mgr()->append_data(ctx); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int StreamLoadAction::on_header(HttpRequest* req) { streaming_load_current_processing.increment(1); @@ -272,6 +294,20 @@ Status StreamLoadAction::_on_header(HttpRequest* http_req, StreamLoadContext* ct LOG(WARNING) << "parse basic authorization failed." << ctx->brief(); return Status::InternalError("no valid Basic authorization"); } +<<<<<<< HEAD +======= + + if (!http_req->header(HTTP_ENABLE_MERGE_COMMIT).empty()) { + auto value = http_req->header(HTTP_ENABLE_MERGE_COMMIT); + StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS; + ctx->enable_batch_write = StringParser::string_to_bool(value.c_str(), value.length(), &parse_result); + if (UNLIKELY(parse_result != StringParser::PARSE_SUCCESS)) { + return Status::InvalidArgument(fmt::format("Invalid parameter {}. The value must be bool type, but is {}", + HTTP_ENABLE_MERGE_COMMIT, value)); + } + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // check content length ctx->body_bytes = 0; size_t max_body_bytes = config::streaming_load_max_mb * 1024 * 1024; @@ -290,6 +326,12 @@ Status StreamLoadAction::_on_header(HttpRequest* http_req, StreamLoadContext* ct // For efficiency reasons, simdjson requires a string with a few bytes (simdjson::SIMDJSON_PADDING) at the end. ASSIGN_OR_RETURN(ctx->buffer, ByteBuffer::allocate_with_tracker(ctx->body_bytes + simdjson::SIMDJSON_PADDING)); +<<<<<<< HEAD +======= + } else if (ctx->enable_batch_write) { + // batch write does not support parsing data in stream mode + ASSIGN_OR_RETURN(ctx->buffer, ByteBuffer::allocate_with_tracker(ctx->body_bytes)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } else { #ifndef BE_TEST @@ -332,6 +374,13 @@ Status StreamLoadAction::_on_header(HttpRequest* http_req, StreamLoadContext* ct ctx->timeout_second = timeout_second; } +<<<<<<< HEAD +======= + if (ctx->enable_batch_write) { + return Status::OK(); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // begin transaction int64_t begin_txn_start_time = MonotonicNanos(); RETURN_IF_ERROR(_exec_env->stream_load_executor()->begin_txn(ctx)); @@ -353,12 +402,17 @@ void StreamLoadAction::on_chunk_data(HttpRequest* req) { int64_t start_read_data_time = MonotonicNanos(); +<<<<<<< HEAD +======= + bool processInBatchMode = ctx->format == TFileFormatType::FORMAT_JSON || ctx->enable_batch_write; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t len = 0; while ((len = evbuffer_get_length(evbuf)) > 0) { if (ctx->buffer == nullptr) { // Initialize buffer. ASSIGN_OR_SET_STATUS_AND_RETURN_IF_ERROR( ctx->status, ctx->buffer, +<<<<<<< HEAD ByteBuffer::allocate_with_tracker(ctx->format == TFileFormatType::FORMAT_JSON ? std::max(len, ctx->kDefaultBufferSize) : len)); @@ -366,6 +420,13 @@ void StreamLoadAction::on_chunk_data(HttpRequest* req) { } else if (ctx->buffer->remaining() < len) { if (ctx->format == TFileFormatType::FORMAT_JSON) { // For json format, we need build a complete json before we push the buffer to the pipe. +======= + ByteBuffer::allocate_with_tracker(processInBatchMode ? std::max(len, ctx->kDefaultBufferSize) + : len)); + } else if (ctx->buffer->remaining() < len) { + if (processInBatchMode) { + // For json format or batch write, we need build a complete data before we push the buffer to the pipe. +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // buffer capacity is not enough, so we try to expand the buffer. ASSIGN_OR_SET_STATUS_AND_RETURN_IF_ERROR( ctx->status, ByteBufferPtr buf, @@ -374,7 +435,11 @@ void StreamLoadAction::on_chunk_data(HttpRequest* req) { std::swap(buf, ctx->buffer); } else { +<<<<<<< HEAD // For non-json format, we could push buffer to the body_sink in streaming mode. +======= + // Otherwise, we could push buffer to the body_sink in streaming mode. +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // buffer capacity is not enough, so we push the buffer to the pipe and allocate new one. ctx->buffer->flip(); auto st = ctx->body_sink->append(std::move(ctx->buffer)); @@ -413,7 +478,15 @@ void StreamLoadAction::free_handler_ctx(void* param) { if (ctx->body_sink != nullptr) { ctx->body_sink->cancel(Status::Cancelled("Cancelled")); } +<<<<<<< HEAD _exec_env->load_stream_mgr()->remove(ctx->id); +======= + + if (!ctx->enable_batch_write) { + _exec_env->load_stream_mgr()->remove(ctx->id); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (ctx->unref()) { delete ctx; } diff --git a/be/src/http/action/stream_load.h b/be/src/http/action/stream_load.h index 229072d1e97ef..43b2a32b8ec9f 100644 --- a/be/src/http/action/stream_load.h +++ b/be/src/http/action/stream_load.h @@ -35,6 +35,10 @@ #pragma once #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/PlanNodes_types.h" #include "http/http_handler.h" @@ -70,6 +74,11 @@ class StreamLoadAction : public HttpHandler { Status _execute_plan_fragment(StreamLoadContext* ctx); Status _process_put(HttpRequest* http_req, StreamLoadContext* ctx); +<<<<<<< HEAD +======= + Status _handle_batch_write(HttpRequest* http_req, StreamLoadContext* ctx); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: ExecEnv* _exec_env; ConcurrentLimiter* _http_concurrent_limiter = nullptr; diff --git a/be/src/http/action/update_config_action.cpp b/be/src/http/action/update_config_action.cpp index 273bbc31932b7..88378f09bab3a 100644 --- a/be/src/http/action/update_config_action.cpp +++ b/be/src/http/action/update_config_action.cpp @@ -116,6 +116,7 @@ Status UpdateConfigAction::update_config(const std::string& name, const std::str }); _config_callback.emplace("datacache_disk_size", [&]() -> Status { std::vector spaces; +<<<<<<< HEAD Status st = DataCacheUtils::parse_conf_datacache_disk_spaces( config::datacache_disk_path, config::datacache_disk_size, config::ignore_broken_disk, &spaces); if (!st.ok()) { @@ -126,6 +127,21 @@ Status UpdateConfigAction::update_config(const std::string& name, const std::str return st; }); _config_callback.emplace("datacache_disk_path", _config_callback["datacache_disk_size"]); +======= + BlockCache::instance()->disk_spaces(&spaces); + for (auto& space : spaces) { + int64_t disk_size = + DataCacheUtils::parse_conf_datacache_disk_size(space.path, config::datacache_disk_size, -1); + if (disk_size < 0) { + LOG(WARNING) << "Failed to update datacache disk spaces for the invalid disk_size: " << disk_size; + return Status::InternalError("Fail to update datacache disk spaces"); + } + space.size = disk_size; + } + Status st = BlockCache::instance()->adjust_disk_spaces(spaces); + return st; + }); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _config_callback.emplace("max_compaction_concurrency", [&]() -> Status { if (!config::enable_event_based_compaction_framework) { return Status::InvalidArgument( diff --git a/be/src/http/default_path_handlers.cpp b/be/src/http/default_path_handlers.cpp index 1fee88a85b3f4..0341b2f3df50d 100644 --- a/be/src/http/default_path_handlers.cpp +++ b/be/src/http/default_path_handlers.cpp @@ -140,9 +140,12 @@ void mem_tracker_handler(MemTracker* mem_tracker, const WebPageHandler::Argument } else if (iter->second == "clone") { start_mem_tracker = GlobalEnv::GetInstance()->clone_mem_tracker(); cur_level = 2; +<<<<<<< HEAD } else if (iter->second == "column_pool") { start_mem_tracker = GlobalEnv::GetInstance()->column_pool_mem_tracker(); cur_level = 2; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else if (iter->second == "page_cache") { start_mem_tracker = GlobalEnv::GetInstance()->page_cache_mem_tracker(); cur_level = 2; diff --git a/be/src/http/download_action.cpp b/be/src/http/download_action.cpp index caa822f1a8820..e26fb8294f46b 100644 --- a/be/src/http/download_action.cpp +++ b/be/src/http/download_action.cpp @@ -50,8 +50,11 @@ namespace starrocks { const std::string FILE_PARAMETER = "file"; +<<<<<<< HEAD const std::string DB_PARAMETER = "db"; const std::string LABEL_PARAMETER = "label"; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::string TOKEN_PARAMETER = "token"; DownloadAction::DownloadAction(ExecEnv* exec_env, const std::vector& allow_dirs) diff --git a/be/src/http/http_client.h b/be/src/http/http_client.h index f0d5f63c8e6d2..d873950ec24c0 100644 --- a/be/src/http/http_client.h +++ b/be/src/http/http_client.h @@ -92,8 +92,15 @@ class HttpClient { } // used to get content length int64_t get_content_length() const { +<<<<<<< HEAD double cl = 0.0f; curl_easy_getinfo(_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl); +======= + // CURLINFO_CONTENT_LENGTH_DOWNLOAD is deprecated since v7.55.0 + // https://curl.se/libcurl/c/CURLINFO_CONTENT_LENGTH_DOWNLOAD.html + curl_off_t cl = 0; + curl_easy_getinfo(_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return cl; } diff --git a/be/src/http/http_common.h b/be/src/http/http_common.h index 24ebe8ecc83ec..fc13f7e2068f6 100644 --- a/be/src/http/http_common.h +++ b/be/src/http/http_common.h @@ -77,4 +77,15 @@ static const std::string HTTP_100_CONTINUE = "100-continue"; static const std::string HTTP_CHANNEL_ID = "channel_id"; static const std::string HTTP_COMPRESSION = "compression"; +<<<<<<< HEAD +======= +// Headers for batch write ========================== +static const std::string HTTP_ENABLE_MERGE_COMMIT = "enable_merge_commit"; +static const std::string HTTP_MERGE_COMMIT_ASYNC = "merge_commit_async"; +static const std::string HTTP_MERGE_COMMIT_INTERVAL_MS = "merge_commit_interval_ms"; +static const std::string HTTP_MERGE_COMMIT_PARALLEL = "merge_commit_parallel"; + +static const std::string HTTP_WAREHOUSE = "warehouse"; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/io/cache_input_stream.cpp b/be/src/io/cache_input_stream.cpp index f53054da13641..9b0e66a121af9 100644 --- a/be/src/io/cache_input_stream.cpp +++ b/be/src/io/cache_input_stream.cpp @@ -277,7 +277,10 @@ Status CacheInputStream::read_at_fully(int64_t offset, void* out, int64_t count) char* p = static_cast(out); char* pe = p + count; +<<<<<<< HEAD const int64_t _block_size = _cache->block_size(); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const int64_t start_block_id = offset / _block_size; const int64_t end_block_id = (end_offset - 1) / _block_size; @@ -395,6 +398,10 @@ void CacheInputStream::_populate_to_cache(const char* p, int64_t offset, int64_t options.evict_probability = _datacache_evict_probability; options.priority = _priority; options.ttl_seconds = _ttl_seconds; +<<<<<<< HEAD +======= + options.frequency = _frequency; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (options.async && sb) { auto cb = [sb](int code, const std::string& msg) { // We only need to keep the shared buffer pointer diff --git a/be/src/io/cache_input_stream.h b/be/src/io/cache_input_stream.h index a66152acd3389..0e7928346d387 100644 --- a/be/src/io/cache_input_stream.h +++ b/be/src/io/cache_input_stream.h @@ -75,6 +75,11 @@ class CacheInputStream : public SeekableInputStreamWrapper { void set_priority(const int8_t priority) { _priority = priority; } +<<<<<<< HEAD +======= + void set_frequency(const int8_t frequency) { _frequency = frequency; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_ttl_seconds(const uint64_t ttl_seconds) { _ttl_seconds = ttl_seconds; } int64_t get_align_size() const; @@ -119,6 +124,10 @@ class CacheInputStream : public SeekableInputStreamWrapper { std::unordered_map _block_map; int8_t _priority = 0; uint64_t _ttl_seconds = 0; +<<<<<<< HEAD +======= + int8_t _frequency = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: inline int64_t _calculate_remote_latency_per_block(int64_t io_bytes, int64_t read_time_ns); diff --git a/be/src/io/cache_select_input_stream.hpp b/be/src/io/cache_select_input_stream.hpp index 831c8d43d2eb9..9a6aec91723e4 100644 --- a/be/src/io/cache_select_input_stream.hpp +++ b/be/src/io/cache_select_input_stream.hpp @@ -28,6 +28,11 @@ class CacheSelectInputStream final : public CacheInputStream { set_enable_async_populate_mode(false); set_enable_cache_io_adaptor(false); set_enable_block_buffer(false); +<<<<<<< HEAD +======= + // Set a high frequecy for cache item that will be populated by cache select. + set_frequency(1); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } ~CacheSelectInputStream() override = default; @@ -87,4 +92,8 @@ class CacheSelectInputStream final : public CacheInputStream { } }; -} // namespace starrocks::io \ No newline at end of file +<<<<<<< HEAD +} // namespace starrocks::io +======= +} // namespace starrocks::io +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/io/direct_s3_output_stream.cpp b/be/src/io/direct_s3_output_stream.cpp index f0b6d4b512491..07fdbd744962d 100644 --- a/be/src/io/direct_s3_output_stream.cpp +++ b/be/src/io/direct_s3_output_stream.cpp @@ -24,6 +24,10 @@ #include "common/logging.h" #include "io/io_profiler.h" +<<<<<<< HEAD +======= +#include "util/failpoint/fail_point.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/stopwatch.hpp" namespace starrocks::io { @@ -62,6 +66,10 @@ Status DirectS3OutputStream::write(const void* data, int64_t size) { req.SetUploadId(_upload_id); req.SetContentLength(size); req.SetBody(std::make_shared(data, size)); +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto outcome = _client->UploadPart(req); if (!outcome.IsSuccess()) { return Status::IOError( @@ -78,7 +86,11 @@ Status DirectS3OutputStream::close() { return Status::OK(); } +<<<<<<< HEAD if (!_upload_id.empty()) { +======= + if (!_upload_id.empty() && !_etags.empty()) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(complete_multipart_upload()); } @@ -90,6 +102,10 @@ Status DirectS3OutputStream::create_multipart_upload() { Aws::S3::Model::CreateMultipartUploadRequest req; req.SetBucket(_bucket); req.SetKey(_object); +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Aws::S3::Model::CreateMultipartUploadOutcome outcome = _client->CreateMultipartUpload(req); if (outcome.IsSuccess()) { _upload_id = outcome.GetResult().GetUploadId(); @@ -116,6 +132,10 @@ Status DirectS3OutputStream::complete_multipart_upload() { multipart_upload.AddParts(part.WithETag(_etags[i]).WithPartNumber(i + 1)); } req.SetMultipartUpload(multipart_upload); +<<<<<<< HEAD +======= + FAIL_POINT_TRIGGER_RETURN(output_stream_io_error, Status::IOError("injected output_stream_io_error")); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto outcome = _client->CompleteMultipartUpload(req); if (outcome.IsSuccess()) { return Status::OK(); diff --git a/be/src/io/s3_input_stream.cpp b/be/src/io/s3_input_stream.cpp index 8245b9d5d411f..fb2035c056281 100644 --- a/be/src/io/s3_input_stream.cpp +++ b/be/src/io/s3_input_stream.cpp @@ -21,6 +21,10 @@ #include #include "io/io_profiler.h" +<<<<<<< HEAD +======= +#include "io/s3_zero_copy_iostream.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/stopwatch.hpp" #ifdef USE_STAROS @@ -43,6 +47,7 @@ StatusOr S3InputStream::read(void* out, int64_t count) { if (_offset >= _size) { return 0; } +<<<<<<< HEAD MonotonicStopWatch watch; watch.start(); @@ -62,6 +67,85 @@ StatusOr S3InputStream::read(void* out, int64_t count) { return body.gcount(); } else { return make_error_status(outcome.GetError()); +======= + MonotonicStopWatch watch; + watch.start(); + count = std::min(count, _size - _offset); + + // prefetch case: + // case1: pretech is disable: _read_ahead_size = -1 -> direct read from s3 + // case2: read size greater than _read_ahead_size -> direct read from s3 + // case3: read range is in buffer -> copy from buffer + // case4: read start is in buffer, end is outof buffer -> copy part data from buffer, load data from s3 to buffer, copy remain from buffer + // case5: read start is greater than buffer end -> load data from s3 to buffer, copy from buffer + // case6: read start is lower than buffer start -> load data from s3 to buffer, copy from buffer + if (count > _read_ahead_size) { + auto real_length = std::min(_offset + count, _size) - _offset; + + // https://www.rfc-editor.org/rfc/rfc9110.html#name-range + auto range = fmt::format("bytes={}-{}", _offset, _offset + real_length - 1); + Aws::S3::Model::GetObjectRequest request; + request.SetBucket(_bucket); + request.SetKey(_object); + request.SetRange(std::move(range)); + request.SetResponseStreamFactory([out, real_length]() { + return Aws::New(AWS_ALLOCATE_TAG, reinterpret_cast(out), real_length); + }); + + Aws::S3::Model::GetObjectOutcome outcome = _s3client->GetObject(request); + if (outcome.IsSuccess()) { + if (UNLIKELY(outcome.GetResult().GetContentLength() != real_length)) { + return Status::InternalError("The response length is different from request length for io stream!"); + } + _offset += real_length; + IOProfiler::add_read(count, watch.elapsed_time()); + return real_length; + } else { + return make_error_status(outcome.GetError()); + } + } else { + int64_t remain_to_read_length = count; + int64_t copy_length = 0; + if (_offset >= _buffer_start_offset && _offset < _buffer_start_offset + _buffer_data_length) { + // case 3: read range is in buffer, copy from buffer and remain_to_read_length will be zero. + // case 4: read start is in buffer, end is outof buffer, + // copy partial from buffer and remain_to_read_length will be > 0. + copy_length = std::min(count, _buffer_data_length - (_offset - _buffer_start_offset)); + memcpy(static_cast(out), _read_buffer.get() + (_offset - _buffer_start_offset), copy_length); + remain_to_read_length = remain_to_read_length - copy_length; + } + if (remain_to_read_length > 0) { + // case 4,5,6, load data from s3 + // case 4: load from s3 to buffer from offset: _buffer_start_offset + _buffer_data_length + // case 5,6: load from s3 to buffer from offset: _offset + int64_t read_start_offset = _offset; + if (_offset >= _buffer_start_offset && _offset < _buffer_start_offset + _buffer_data_length) { + read_start_offset = _buffer_start_offset + _buffer_data_length; + } + int64_t read_end_offset = std::min(read_start_offset + _read_ahead_size, _size); + auto range = fmt::format("bytes={}-{}", read_start_offset, read_end_offset); + Aws::S3::Model::GetObjectRequest request; + request.SetBucket(_bucket); + request.SetKey(_object); + request.SetRange(std::move(range)); + + Aws::S3::Model::GetObjectOutcome outcome = _s3client->GetObject(request); + if (outcome.IsSuccess()) { + Aws::IOStream& body = outcome.GetResult().GetBody(); + int64_t read_length = read_end_offset - read_start_offset; + body.read(reinterpret_cast(_read_buffer.get()), read_length); + _buffer_start_offset = read_start_offset; + _buffer_data_length = body.gcount(); + } else { + return make_error_status(outcome.GetError()); + } + memcpy(static_cast(out) + copy_length, _read_buffer.get(), remain_to_read_length); + copy_length += remain_to_read_length; + } + _offset += copy_length; + IOProfiler::add_read(count, watch.elapsed_time()); + return copy_length; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } diff --git a/be/src/io/s3_input_stream.h b/be/src/io/s3_input_stream.h index 19398c1658f03..35b482aea43ab 100644 --- a/be/src/io/s3_input_stream.h +++ b/be/src/io/s3_input_stream.h @@ -27,8 +27,19 @@ namespace starrocks::io { class S3InputStream final : public SeekableInputStream { public: +<<<<<<< HEAD explicit S3InputStream(std::shared_ptr client, std::string bucket, std::string object) : _s3client(std::move(client)), _bucket(std::move(bucket)), _object(std::move(object)) {} +======= + explicit S3InputStream(std::shared_ptr client, std::string bucket, std::string object, + int64_t read_ahead_size = 5 * 1024 * 1024) + : _s3client(std::move(client)), _bucket(std::move(bucket)), _object(std::move(object)) { + _read_ahead_size = read_ahead_size; + if (_read_ahead_size > 0) { + _read_buffer = std::make_unique(_read_ahead_size); + } + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~S3InputStream() override = default; @@ -52,12 +63,26 @@ class S3InputStream final : public SeekableInputStream { StatusOr read_all() override; +<<<<<<< HEAD +======= + // only for UT + int64_t get_read_ahead_size() const { return _read_ahead_size; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::shared_ptr _s3client; std::string _bucket; std::string _object; int64_t _offset{0}; int64_t _size{-1}; +<<<<<<< HEAD +======= + int64_t _read_ahead_size{-1}; + // _read_buffer start offset, indicate buffer[0]'s offset in s3 file. + int64_t _buffer_start_offset{-1}; + int64_t _buffer_data_length{-1}; + std::unique_ptr _read_buffer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks::io diff --git a/be/src/io/s3_output_stream.cpp b/be/src/io/s3_output_stream.cpp index 6d505c733633a..a97c2bd8d6f44 100644 --- a/be/src/io/s3_output_stream.cpp +++ b/be/src/io/s3_output_stream.cpp @@ -23,6 +23,10 @@ #include "common/logging.h" #include "io/io_profiler.h" +<<<<<<< HEAD +======= +#include "io/s3_zero_copy_iostream.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/stopwatch.hpp" namespace starrocks::io { @@ -111,7 +115,11 @@ Status S3OutputStream::singlepart_upload() { req.SetBucket(_bucket); req.SetKey(_object); req.SetContentLength(static_cast(_buffer.size())); +<<<<<<< HEAD req.SetBody(std::make_shared(_buffer)); +======= + req.SetBody(Aws::MakeShared(AWS_ALLOCATE_TAG, _buffer.data(), _buffer.size())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Aws::S3::Model::PutObjectOutcome outcome = _client->PutObject(req); if (!outcome.IsSuccess()) { std::string error_msg = @@ -133,7 +141,11 @@ Status S3OutputStream::multipart_upload() { req.SetPartNumber(static_cast(_etags.size() + 1)); req.SetUploadId(_upload_id); req.SetContentLength(static_cast(_buffer.size())); +<<<<<<< HEAD req.SetBody(std::make_shared(_buffer)); +======= + req.SetBody(Aws::MakeShared(AWS_ALLOCATE_TAG, _buffer.data(), _buffer.size())); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto outcome = _client->UploadPart(req); if (outcome.IsSuccess()) { _etags.push_back(outcome.GetResult().GetETag()); diff --git a/be/src/io/s3_zero_copy_iostream.h b/be/src/io/s3_zero_copy_iostream.h new file mode 100644 index 0000000000000..4ba2c604be41a --- /dev/null +++ b/be/src/io/s3_zero_copy_iostream.h @@ -0,0 +1,51 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +namespace starrocks::io { + +#define STRINGIZE_DETAIL(x) #x +#define STRINGIZE(x) STRINGIZE_DETAIL(x) +#define AWS_ALLOCATE_TAG __FILE__ ":" STRINGIZE(__LINE__) + +class S3ZeroCopyIOStream : public Aws::IOStream { +public: + S3ZeroCopyIOStream(char* buf, size_t size) + : Aws::IOStream(new Aws::Utils::Stream::PreallocatedStreamBuf(reinterpret_cast(buf), size)), + _buf_size(size) { + DCHECK(rdbuf()); + } + + S3ZeroCopyIOStream(const char* buf, size_t size) : S3ZeroCopyIOStream(const_cast(buf), size) {} + + size_t getSize() { return _buf_size; } + + S3ZeroCopyIOStream(const S3ZeroCopyIOStream&) = delete; + void operator=(const S3ZeroCopyIOStream&) = delete; + S3ZeroCopyIOStream(S3ZeroCopyIOStream&&) = delete; + void operator=(S3ZeroCopyIOStream&&) = delete; + + ~S3ZeroCopyIOStream() { + // corresponding new in constructor + delete rdbuf(); + } + +private: + size_t _buf_size = 0; +}; + +} // namespace starrocks::io \ No newline at end of file diff --git a/be/src/runtime/CMakeLists.txt b/be/src/runtime/CMakeLists.txt index a902c29afe83c..236b0011f9068 100644 --- a/be/src/runtime/CMakeLists.txt +++ b/be/src/runtime/CMakeLists.txt @@ -20,6 +20,10 @@ set(EXECUTABLE_OUTPUT_PATH "${BUILD_DIR}/src/runtime") set(RUNTIME_FILES broker_mgr.cpp buffer_control_block.cpp +<<<<<<< HEAD +======= + buffer_control_result_writer.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) client_cache.cpp local_pass_through_buffer.cpp data_stream_mgr.cpp @@ -29,6 +33,10 @@ set(RUNTIME_FILES datetime_value.cpp descriptors.cpp exec_env.cpp +<<<<<<< HEAD +======= + global_variables.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) user_function_cache.cpp jdbc_driver_manager.cpp mem_pool.cpp @@ -38,11 +46,18 @@ set(RUNTIME_FILES runtime_state.cpp string_value.cpp decimalv2_value.cpp +<<<<<<< HEAD large_int_value.cpp +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) fragment_mgr.cpp load_path_mgr.cpp dummy_load_path_mgr.cpp types.cpp +<<<<<<< HEAD +======= + agg_state_desc.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) mem_tracker.cpp data_stream_recvr.cpp export_sink.cpp @@ -50,12 +65,23 @@ set(RUNTIME_FILES load_channel.cpp local_tablets_channel.cpp snapshot_loader.cpp +<<<<<<< HEAD query_statistics.cpp +======= + query_statistics.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) message_body_sink.cpp stream_load/transaction_mgr.cpp stream_load/stream_load_context.cpp stream_load/stream_load_executor.cpp stream_load/stream_load_pipe.cpp +<<<<<<< HEAD +======= + stream_load/time_bounded_stream_load_pipe.cpp + batch_write/isomorphic_batch_write.cpp + batch_write/batch_write_mgr.cpp + batch_write/batch_write_util.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) routine_load/data_consumer.cpp routine_load/data_consumer_group.cpp routine_load/data_consumer_pool.cpp @@ -71,8 +97,16 @@ set(RUNTIME_FILES statistic_result_writer.cpp metadata_result_writer.cpp variable_result_writer.cpp +<<<<<<< HEAD memory/system_allocator.cpp memory/mem_chunk_allocator.cpp +======= + arrow_result_writer.cpp + memory/roaring_hook.cpp + memory/system_allocator.cpp + memory/mem_chunk_allocator.cpp + memory/column_allocator.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) chunk_cursor.cpp sorted_chunks_merger.cpp tablets_channel.cpp diff --git a/be/src/runtime/agg_state_desc.cpp b/be/src/runtime/agg_state_desc.cpp new file mode 100644 index 0000000000000..a10db044f6e7d --- /dev/null +++ b/be/src/runtime/agg_state_desc.cpp @@ -0,0 +1,124 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/agg_state_desc.h" + +#include + +#include "exprs/agg/aggregate.h" +#include "exprs/agg/aggregate_factory.h" + +namespace starrocks { + +// Create a new AggStateDesc from a thrift TTypeDesc. +AggStateDesc AggStateDesc::from_thrift(const TAggStateDesc& desc) { + VLOG(2) << "TAggStateDesc:" << apache::thrift::ThriftDebugString(desc); + std::string agg_func_name = desc.agg_func_name; + // return type + auto return_type = TypeDescriptor::from_thrift(desc.ret_type); + // arg types + std::vector arg_types; + for (auto& arg_type : desc.arg_types) { + arg_types.emplace_back(TypeDescriptor::from_thrift(arg_type)); + } + bool result_nullable = desc.result_nullable; + int func_version = desc.func_version; + return AggStateDesc{agg_func_name, std::move(return_type), std::move(arg_types), result_nullable, func_version}; +} + +// Transform this AggStateDesc to a thrift TTypeDesc. +void AggStateDesc::to_thrift(TAggStateDesc* t) { + t->agg_func_name = _func_name; + t->result_nullable = _is_result_nullable; + t->func_version = _func_version; + // return type + t->ret_type = _return_type.to_thrift(); + // arg types + for (auto& arg_type : _arg_types) { + t->arg_types.push_back(arg_type.to_thrift()); + } +} + +AggStateDesc AggStateDesc::from_protobuf(const AggStateDescPB& desc) { + auto& agg_func_name = desc.agg_func_name(); + bool is_result_nullable = desc.is_result_nullable(); + int func_version = desc.func_version(); + std::vector arg_types; + // arg types + for (auto& arg_type : desc.arg_types()) { + arg_types.emplace_back(TypeDescriptor::from_protobuf(arg_type)); + } + // ret type + auto ret_type = TypeDescriptor::from_protobuf(desc.ret_type()); + return AggStateDesc{agg_func_name, std::move(ret_type), std::move(arg_types), is_result_nullable, func_version}; +} + +void AggStateDesc::to_protobuf(AggStateDescPB* desc) { + desc->set_agg_func_name(this->get_func_name()); + desc->set_is_result_nullable(this->is_result_nullable()); + desc->set_func_version(this->get_func_version()); + // arg types + for (auto& arg_type : this->get_arg_types()) { + auto* arg_type_pb = desc->add_arg_types(); + *arg_type_pb = arg_type.to_protobuf(); + } + // ret type + auto ret_type_desc = this->get_return_type(); + auto* ret_type_pb = desc->mutable_ret_type(); + *ret_type_pb = ret_type_desc.to_protobuf(); +} + +void AggStateDesc::thrift_to_protobuf(const TAggStateDesc& desc, AggStateDescPB* pb) { + pb->set_agg_func_name(desc.agg_func_name); + pb->set_is_result_nullable(desc.result_nullable); + pb->set_func_version(desc.func_version); + // arg types + for (auto& arg_type : desc.arg_types) { + auto arg_type_desc = TypeDescriptor::from_thrift(arg_type); + auto* arg_type_pb = pb->add_arg_types(); + *arg_type_pb = arg_type_desc.to_protobuf(); + } + // ret type + auto ret_type_desc = TypeDescriptor::from_thrift(desc.ret_type); + auto* ret_type_pb = pb->mutable_ret_type(); + *ret_type_pb = ret_type_desc.to_protobuf(); +} + +std::string AggStateDesc::debug_string() const { + std::stringstream ss; + ss << "[" << _func_name << ", args:<"; + for (size_t i = 0; i < _arg_types.size(); i++) { + if (i != _arg_types.size() - 1) { + ss << _arg_types[i] << ", "; + } else { + ss << _arg_types[i] << ">"; + } + } + ss << ", ret:" << _return_type << ", result_nullable:" << _is_result_nullable << ", func_version:" << _func_version + << "]"; + return ss.str(); +} + +const AggregateFunction* AggStateDesc::get_agg_state_func(AggStateDesc* agg_state_desc) { + DCHECK(agg_state_desc); + auto* agg_function = get_aggregate_function(agg_state_desc->get_func_name(), agg_state_desc->get_return_type(), + agg_state_desc->get_arg_types(), agg_state_desc->is_result_nullable(), + TFunctionBinaryType::BUILTIN, agg_state_desc->get_func_version()); + if (agg_function == nullptr) { + LOG(WARNING) << "Failed to get aggregate function for " << agg_state_desc->debug_string(); + } + return agg_function; +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/agg_state_desc.h b/be/src/runtime/agg_state_desc.h new file mode 100644 index 0000000000000..592efea31728e --- /dev/null +++ b/be/src/runtime/agg_state_desc.h @@ -0,0 +1,114 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include + +#include +#include +#include + +#include "gen_cpp/Types_types.h" +#include "runtime/types.h" + +namespace starrocks { + +struct TypeDescriptor; + +class AggStateDesc; +using AggStateDescPtr = std::shared_ptr; + +class AggregateFunction; + +class AggStateDesc { +public: + AggStateDesc(std::string func_name, TypeDescriptor return_type, std::vector arg_types, + bool is_result_nullable, int func_version) + : _func_name(std::move(func_name)), + _return_type(std::move(return_type)), + _arg_types(std::move(arg_types)), + _is_result_nullable(is_result_nullable), + _func_version(func_version) {} + + // copy assignment operator + AggStateDesc(const AggStateDesc& other) + : _func_name(other._func_name), + _return_type(other._return_type), + _arg_types(other._arg_types), + _is_result_nullable(other._is_result_nullable), + _func_version(other._func_version) {} + AggStateDesc& operator=(const AggStateDesc& other) { + if (this != &other) { + this->_func_name = other._func_name; + this->_return_type = other._return_type; + this->_arg_types = other._arg_types; + this->_is_result_nullable = other._is_result_nullable; + this->_func_version = other._func_version; + } + return *this; + } + + // move assignment operator + AggStateDesc(AggStateDesc&& other) noexcept + : _func_name(std::move(other._func_name)), + _return_type(std::move(other._return_type)), + _arg_types(std::move(other._arg_types)), + _is_result_nullable(other._is_result_nullable), + _func_version(other._func_version) {} + AggStateDesc& operator=(AggStateDesc&& other) noexcept { + if (this != &other) { + this->_func_name = std::move(other._func_name); + this->_return_type = std::move(other._return_type); + this->_arg_types = std::move(other._arg_types); + this->_is_result_nullable = other._is_result_nullable; + this->_func_version = other._func_version; + } + return *this; + } + + const std::string& get_func_name() const { return _func_name; } + const TypeDescriptor& get_return_type() const { return _return_type; } + const std::vector& get_arg_types() const { return _arg_types; } + bool is_result_nullable() const { return _is_result_nullable; } + int get_func_version() const { return _func_version; } + std::string debug_string() const; + + // Transform this AggStateDesc to a thrift TTypeDesc. + void to_thrift(TAggStateDesc* t); + // Transform this AggStateDesc to a protobuf AggStateDescPB. + void to_protobuf(AggStateDescPB* desc); + + // Create a new AggStateDesc from a thrift TTypeDesc. + static AggStateDesc from_thrift(const TAggStateDesc& desc); + // Create a new AggStateDesc from a protobuf AggStateDescPB. + static AggStateDesc from_protobuf(const AggStateDescPB& desc); + // Convert thrift TAggStateDesc to protobuf AggStateDescPB. + static void thrift_to_protobuf(const TAggStateDesc& desc, AggStateDescPB* pb); + // Get the aggregate function state descriptor. + static const AggregateFunction* get_agg_state_func(AggStateDesc* agg_state_desc); + +private: + // nested aggregate function name + std::string _func_name; + // nested aggregate function return type + TypeDescriptor _return_type; + // nested aggregate function argument types + std::vector _arg_types; + // nested aggregate function input is nullable + bool _is_result_nullable; + // nested aggregate function version + int _func_version; +}; + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/arrow_result_writer.cpp b/be/src/runtime/arrow_result_writer.cpp new file mode 100644 index 0000000000000..20e256be676d7 --- /dev/null +++ b/be/src/runtime/arrow_result_writer.cpp @@ -0,0 +1,85 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/arrow_result_writer.h" + +#include +#include +#include +#include +#include + +#include "column/const_column.h" +#include "exprs/cast_expr.h" +#include "exprs/expr.h" +#include "rapidjson/writer.h" +#include "runtime/buffer_control_block.h" +#include "runtime/current_thread.h" +#include "runtime/exec_env.h" +#include "runtime/result_buffer_mgr.h" + +namespace starrocks { + +ArrowResultWriter::ArrowResultWriter(BufferControlBlock* sinker, std::vector& output_expr_ctxs, + RuntimeProfile* parent_profile, const RowDescriptor& row_desc) + : BufferControlResultWriter(sinker, parent_profile), _output_expr_ctxs(output_expr_ctxs), _row_desc(row_desc) {} + +Status ArrowResultWriter::init(RuntimeState* state) { + _init_profile(); + if (nullptr == _sinker) { + return Status::InternalError("sinker is NULL pointer."); + } + + _prepare_id_to_col_name_map(); + RETURN_IF_ERROR(convert_to_arrow_schema(_row_desc, _id_to_col_name, &_arrow_schema, _output_expr_ctxs)); + + state->exec_env()->result_mgr()->set_arrow_schema(state->fragment_instance_id(), _arrow_schema); + + return Status::OK(); +} + +void ArrowResultWriter::_init_profile() { + _append_chunk_timer = ADD_TIMER(_parent_profile, "AppendChunkTime"); +} + +Status ArrowResultWriter::append_chunk(Chunk* chunk) { + return Status::OK(); +} + +Status ArrowResultWriter::close() { + return Status::OK(); +} + +StatusOr ArrowResultWriter::process_chunk(Chunk* chunk) { + SCOPED_TIMER(_append_chunk_timer); + std::shared_ptr result; + RETURN_IF_ERROR(convert_chunk_to_arrow_batch(chunk, _output_expr_ctxs, _arrow_schema, arrow::default_memory_pool(), + &result)); + RETURN_IF_ERROR(_sinker->add_arrow_batch(result)); + return TFetchDataResultPtrs{}; +} + +void ArrowResultWriter::_prepare_id_to_col_name_map() { + for (auto* tuple_desc : _row_desc.tuple_descriptors()) { + auto& slots = tuple_desc->slots(); + int64_t tuple_id = tuple_desc->id(); + for (auto slot : slots) { + int64_t slot_id = slot->id(); + int64_t id = tuple_id << 32 | slot_id; + _id_to_col_name.emplace(id, slot->col_name()); + } + } +} + +} // namespace starrocks diff --git a/be/src/runtime/arrow_result_writer.h b/be/src/runtime/arrow_result_writer.h new file mode 100644 index 0000000000000..0be210f6878d6 --- /dev/null +++ b/be/src/runtime/arrow_result_writer.h @@ -0,0 +1,62 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "common/statusor.h" +#include "runtime/buffer_control_result_writer.h" +#include "runtime/result_writer.h" +#include "runtime/runtime_state.h" + +namespace arrow { +class Schema; +} + +namespace starrocks { + +class ExprContext; +class BufferControlBlock; +class RuntimeProfile; +using TFetchDataResultPtr = std::unique_ptr; +using TFetchDataResultPtrs = std::vector; + +// convert the row batch to arrow protocol row +class ArrowResultWriter final : public BufferControlResultWriter { +public: + ArrowResultWriter(BufferControlBlock* sinker, std::vector& output_expr_ctxs, + RuntimeProfile* parent_profile, const RowDescriptor& row_desc); + + Status init(RuntimeState* state) override; + + Status append_chunk(Chunk* chunk) override; + + Status close() override; + + StatusOr process_chunk(Chunk* chunk) override; + +private: + void _init_profile(); + + void _prepare_id_to_col_name_map(); + + std::vector& _output_expr_ctxs; + + const RowDescriptor& _row_desc; + + std::shared_ptr _arrow_schema; + + std::unordered_map _id_to_col_name; +}; + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/batch_write/batch_write_mgr.cpp b/be/src/runtime/batch_write/batch_write_mgr.cpp new file mode 100644 index 0000000000000..5fa187725fab8 --- /dev/null +++ b/be/src/runtime/batch_write/batch_write_mgr.cpp @@ -0,0 +1,227 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/batch_write/batch_write_mgr.h" + +#include "brpc/controller.h" +#include "butil/endpoint.h" +#include "gen_cpp/internal_service.pb.h" +#include "http/http_common.h" +#include "runtime/batch_write/batch_write_util.h" +#include "runtime/exec_env.h" +#include "runtime/stream_load/time_bounded_stream_load_pipe.h" +#include "testutil/sync_point.h" + +namespace starrocks { + +Status BatchWriteMgr::register_stream_load_pipe(StreamLoadContext* pipe_ctx) { + BatchWriteId batch_write_id = { + .db = pipe_ctx->db, .table = pipe_ctx->table, .load_params = pipe_ctx->load_parameters}; + ASSIGN_OR_RETURN(IsomorphicBatchWriteSharedPtr batch_write, _get_batch_write(batch_write_id, true)); + return batch_write->register_stream_load_pipe(pipe_ctx); +} + +void BatchWriteMgr::unregister_stream_load_pipe(StreamLoadContext* pipe_ctx) { + BatchWriteId batch_write_id = { + .db = pipe_ctx->db, .table = pipe_ctx->table, .load_params = pipe_ctx->load_parameters}; + auto batch_write = _get_batch_write(batch_write_id, false); + if (!batch_write.ok()) { + return; + } + batch_write.value()->unregister_stream_load_pipe(pipe_ctx); +} + +StatusOr BatchWriteMgr::get_batch_write(const BatchWriteId& batch_write_id) { + return _get_batch_write(batch_write_id, false); +} + +Status BatchWriteMgr::append_data(StreamLoadContext* data_ctx) { + TEST_SYNC_POINT_CALLBACK("BatchWriteMgr::append_data::cb", &data_ctx); + TEST_SUCC_POINT("BatchWriteMgr::append_data::success"); + TEST_ERROR_POINT("BatchWriteMgr::append_data::fail"); + BatchWriteId batch_write_id = { + .db = data_ctx->db, .table = data_ctx->table, .load_params = data_ctx->load_parameters}; + ASSIGN_OR_RETURN(IsomorphicBatchWriteSharedPtr batch_write, _get_batch_write(batch_write_id, true)); + return batch_write->append_data(data_ctx); +} + +StatusOr BatchWriteMgr::_get_batch_write(const starrocks::BatchWriteId& batch_write_id, + bool create_if_missing) { + { + std::shared_lock lock(_mutex); + auto it = _batch_write_map.find(batch_write_id); + if (it != _batch_write_map.end()) { + return it->second; + } + } + if (!create_if_missing) { + return Status::NotFound(""); + } + + std::unique_lock lock(_mutex); + if (_stopped) { + return Status::ServiceUnavailable("Batch write is stopped"); + } + auto it = _batch_write_map.find(batch_write_id); + if (it != _batch_write_map.end()) { + return it->second; + } + + auto batch_write = std::make_shared(batch_write_id, _executor.get()); + Status st = batch_write->init(); + if (!st.ok()) { + LOG(ERROR) << "Fail to init batch write, " << batch_write_id << ", status: " << st; + return Status::InternalError("Fail to init batch write, error: " + st.to_string()); + } + _batch_write_map.emplace(batch_write_id, batch_write); + LOG(INFO) << "Create batch write, " << batch_write_id; + return batch_write; +} + +void BatchWriteMgr::stop() { + std::vector stop_writes; + { + std::unique_lock lock(_mutex); + if (_stopped) { + return; + } + _stopped = true; + for (auto& [_, batch_write] : _batch_write_map) { + stop_writes.emplace_back(batch_write); + } + _batch_write_map.clear(); + } + for (auto& batch_write : stop_writes) { + batch_write->stop(); + } +} + +StatusOr BatchWriteMgr::create_and_register_pipe( + ExecEnv* exec_env, BatchWriteMgr* batch_write_mgr, const std::string& db, const std::string& table, + const std::map& load_parameters, const std::string& label, long txn_id, + const TUniqueId& load_id, int32_t batch_write_interval_ms) { + std::string pipe_name = fmt::format("txn_{}_label_{}_id_{}", txn_id, label, print_id(load_id)); + auto pipe = std::make_shared(pipe_name, batch_write_interval_ms); + RETURN_IF_ERROR(exec_env->load_stream_mgr()->put(load_id, pipe)); + StreamLoadContext* ctx = new StreamLoadContext(exec_env, load_id); + ctx->ref(); + ctx->id = load_id; + ctx->db = db; + ctx->table = table; + ctx->label = label; + ctx->txn_id = txn_id; + ctx->enable_batch_write = true; + ctx->load_parameters = load_parameters; + ctx->body_sink = pipe; + + DeferOp op([&] { + // batch write manager will hold a reference if register success. + // need to release the reference to delete the context if register failed + StreamLoadContext::release(ctx); + }); + RETURN_IF_ERROR(batch_write_mgr->register_stream_load_pipe(ctx)); + return ctx; +} + +static std::string s_empty; + +#define GET_PARAMETER_OR_EMPTY(parameters, key) \ + (parameters.find(key) != parameters.end() ? parameters.at(key) : s_empty) + +#define ASSIGN_AND_RETURN(lhs, rhs) \ + lhs = rhs; \ + return + +void BatchWriteMgr::receive_stream_load_rpc(ExecEnv* exec_env, brpc::Controller* cntl, + const PStreamLoadRequest* request, PStreamLoadResponse* response) { + auto* ctx = new StreamLoadContext(exec_env); + ctx->ref(); + DeferOp defer([&]() { + response->set_json_result(ctx->to_json()); + StreamLoadContext::release(ctx); + }); + ctx->db = request->db(); + ctx->table = request->table(); + std::map parameters; + for (const PStringPair& pair : request->parameters()) { + parameters.emplace(pair.key(), pair.val()); + } + + { + auto value = GET_PARAMETER_OR_EMPTY(parameters, HTTP_ENABLE_MERGE_COMMIT); + StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS; + ctx->enable_batch_write = StringParser::string_to_bool(value.c_str(), value.length(), &parse_result); + if (UNLIKELY(parse_result != StringParser::PARSE_SUCCESS)) { + ASSIGN_AND_RETURN(ctx->status, Status::InvalidArgument(fmt::format( + "Invalid parameter {}. The value must be bool type, but is {}", + HTTP_ENABLE_MERGE_COMMIT, value))); + } + if (!ctx->enable_batch_write) { + ASSIGN_AND_RETURN(ctx->status, + Status::InvalidArgument(fmt::format( + "RPC interface only support batch write currently. Must set {} to true", + HTTP_ENABLE_MERGE_COMMIT, value))); + } + } + ctx->label = GET_PARAMETER_OR_EMPTY(parameters, HTTP_LABEL_KEY); + if (ctx->label.empty()) { + ctx->label = generate_uuid_string(); + } + std::string timeout = GET_PARAMETER_OR_EMPTY(parameters, HTTP_TIMEOUT); + if (!timeout.empty()) { + StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS; + auto timeout_second = + StringParser::string_to_unsigned_int(timeout.c_str(), timeout.length(), &parse_result); + if (UNLIKELY(parse_result != StringParser::PARSE_SUCCESS)) { + ASSIGN_AND_RETURN(ctx->status, Status::InvalidArgument(fmt::format("Invalid timeout format: {}", timeout))); + } + ctx->timeout_second = timeout_second; + } + std::string remote_host; + butil::ip2hostname(cntl->remote_side().ip, &remote_host); + ctx->auth.user = request->user(); + ctx->auth.passwd = request->passwd(); + ctx->auth.user_ip = remote_host; + ctx->load_parameters = get_load_parameters_from_brpc(parameters); + + butil::IOBuf& io_buf = cntl->request_attachment(); + size_t max_bytes = config::streaming_load_max_batch_size_mb * 1024 * 1024; + if (io_buf.empty()) { + ASSIGN_AND_RETURN(ctx->status, Status::InternalError(fmt::format("The data can not be empty"))); + } else if (io_buf.size() > max_bytes) { + ASSIGN_AND_RETURN(ctx->status, Status::InternalError(fmt::format( + "The data size {} exceed the max size {}. You can change the max size" + " by modify config::streaming_load_max_batch_size_mb on BE", + io_buf.size(), max_bytes))); + } + auto st_or = ByteBuffer::allocate_with_tracker(io_buf.size()); + if (st_or.ok()) { + ctx->buffer = std::move(st_or.value()); + } else { + ASSIGN_AND_RETURN(ctx->status, + Status::InternalError(fmt::format("Can't allocate buffer, data size: {}, error: {}", + io_buf.size(), st_or.status().to_string()))); + } + auto copy_size = io_buf.copy_to(ctx->buffer->ptr, io_buf.size()); + if (copy_size != io_buf.size()) { + ASSIGN_AND_RETURN(ctx->status, + Status::InternalError(fmt::format("Failed to copy buffer, data size: {}, copied size: {}", + io_buf.size(), copy_size))); + } + ctx->buffer->pos += io_buf.size(); + ctx->buffer->flip(); + ctx->status = exec_env->batch_write_mgr()->append_data(ctx); +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/batch_write/batch_write_mgr.h b/be/src/runtime/batch_write/batch_write_mgr.h new file mode 100644 index 0000000000000..a18b70aaa8d82 --- /dev/null +++ b/be/src/runtime/batch_write/batch_write_mgr.h @@ -0,0 +1,67 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "common/statusor.h" +#include "runtime/batch_write/isomorphic_batch_write.h" +#include "runtime/stream_load/stream_load_context.h" +#include "util/bthreads/executor.h" + +namespace brpc { +class Controller; +} + +namespace starrocks { + +class ExecEnv; +class PStreamLoadRequest; +class PStreamLoadResponse; +class StreamLoadContext; + +class BatchWriteMgr { +public: + BatchWriteMgr(std::unique_ptr executor) : _executor(std::move(executor)){}; + + Status register_stream_load_pipe(StreamLoadContext* pipe_ctx); + void unregister_stream_load_pipe(StreamLoadContext* pipe_ctx); + StatusOr get_batch_write(const BatchWriteId& batch_write_id); + + Status append_data(StreamLoadContext* data_ctx); + + void stop(); + + static StatusOr create_and_register_pipe( + ExecEnv* exec_env, BatchWriteMgr* batch_write_mgr, const string& db, const string& table, + const std::map& load_parameters, const string& label, long txn_id, + const TUniqueId& load_id, int32_t batch_write_interval_ms); + + static void receive_stream_load_rpc(ExecEnv* exec_env, brpc::Controller* cntl, const PStreamLoadRequest* request, + PStreamLoadResponse* response); + +private: + StatusOr _get_batch_write(const BatchWriteId& batch_write_id, + bool create_if_missing); + + std::unique_ptr _executor; + std::shared_mutex _mutex; + std::unordered_map + _batch_write_map; + bool _stopped{false}; +}; + +} // namespace starrocks diff --git a/be/src/runtime/batch_write/batch_write_util.cpp b/be/src/runtime/batch_write/batch_write_util.cpp new file mode 100644 index 0000000000000..6a2d7524da6e0 --- /dev/null +++ b/be/src/runtime/batch_write/batch_write_util.cpp @@ -0,0 +1,105 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/batch_write/batch_write_util.h" + +#include + +#include "http/http_common.h" +#include "http/http_request.h" + +namespace starrocks { + +const std::vector LOAD_PARAMETER_NAMES = {HTTP_FORMAT_KEY, + HTTP_COLUMNS, + HTTP_WHERE, + HTTP_MAX_FILTER_RATIO, + HTTP_TIMEOUT, + HTTP_PARTITIONS, + HTTP_TEMP_PARTITIONS, + HTTP_NEGATIVE, + HTTP_STRICT_MODE, + HTTP_TIMEZONE, + HTTP_LOAD_MEM_LIMIT, + HTTP_EXEC_MEM_LIMIT, + HTTP_PARTIAL_UPDATE, + HTTP_PARTIAL_UPDATE_MODE, + HTTP_TRANSMISSION_COMPRESSION_TYPE, + HTTP_LOAD_DOP, + HTTP_MERGE_CONDITION, + HTTP_LOG_REJECTED_RECORD_NUM, + HTTP_COMPRESSION, + HTTP_WAREHOUSE, + HTTP_ENABLE_MERGE_COMMIT, + HTTP_MERGE_COMMIT_ASYNC, + HTTP_MERGE_COMMIT_INTERVAL_MS, + HTTP_MERGE_COMMIT_PARALLEL, + HTTP_COLUMN_SEPARATOR, + HTTP_ROW_DELIMITER, + HTTP_TRIM_SPACE, + HTTP_ENCLOSE, + HTTP_ESCAPE, + HTTP_JSONPATHS, + HTTP_JSONROOT, + HTTP_STRIP_OUTER_ARRAY}; + +std::ostream& operator<<(std::ostream& out, const BatchWriteId& id) { + out << "db: " << id.db << ", table: " << id.table << ", load_params: {"; + bool first = true; + for (const auto& [key, value] : id.load_params) { + if (!first) { + out << ","; + } + first = false; + out << key << ":" << value; + } + out << "}"; + return out; +} + +BatchWriteLoadParams get_load_parameters( + const std::function(const std::string&)>& getter_func) { + std::map load_params; + for (const auto& name : LOAD_PARAMETER_NAMES) { + auto value_opt = getter_func(name); + if (value_opt) { + load_params.emplace(name, *value_opt); + } + } + return load_params; +} + +BatchWriteLoadParams get_load_parameters_from_brpc(const std::map& input_params) { + return get_load_parameters([&input_params](const std::string& param_name) -> std::optional { + auto it = input_params.find(param_name); + if (it != input_params.end()) { + return it->second; + } else { + return std::nullopt; + } + }); +} + +BatchWriteLoadParams get_load_parameters_from_http(HttpRequest* http_req) { + return get_load_parameters([http_req](const std::string& param_name) -> std::optional { + std::string value = http_req->header(param_name); + if (!value.empty()) { + return value; + } else { + return std::nullopt; + } + }); +} + +} // namespace starrocks diff --git a/be/src/runtime/batch_write/batch_write_util.h b/be/src/runtime/batch_write/batch_write_util.h new file mode 100644 index 0000000000000..dee7c3c615aab --- /dev/null +++ b/be/src/runtime/batch_write/batch_write_util.h @@ -0,0 +1,64 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include "common/config.h" + +namespace starrocks { + +#define TRACE_BATCH_WRITE LOG_IF(INFO, config::batch_write_trace_log_enable) + +using BatchWriteLoadParams = std::map; + +struct BatchWriteId { + std::string db; + std::string table; + BatchWriteLoadParams load_params; +}; + +// Hash function for BatchWriteId +struct BatchWriteIdHash { + std::size_t operator()(const BatchWriteId& id) const { + std::size_t hash = std::hash{}(id.db); + hash ^= std::hash{}(id.table) << 1; + + for (const auto& param : id.load_params) { + hash ^= std::hash{}(param.first) << 1; + hash ^= std::hash{}(param.second) << 1; + } + + return hash; + } +}; + +// Equality function for BatchWriteId +struct BatchWriteIdEqual { + bool operator()(const BatchWriteId& lhs, const BatchWriteId& rhs) const { + return lhs.db == rhs.db && lhs.table == rhs.table && lhs.load_params == rhs.load_params; + } +}; + +std::ostream& operator<<(std::ostream& out, const BatchWriteId& id); + +class HttpRequest; + +BatchWriteLoadParams get_load_parameters_from_http(HttpRequest* http_req); +BatchWriteLoadParams get_load_parameters_from_brpc(const std::map& input_params); + +} // namespace starrocks diff --git a/be/src/runtime/batch_write/isomorphic_batch_write.cpp b/be/src/runtime/batch_write/isomorphic_batch_write.cpp new file mode 100644 index 0000000000000..db8670c029559 --- /dev/null +++ b/be/src/runtime/batch_write/isomorphic_batch_write.cpp @@ -0,0 +1,464 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/batch_write/isomorphic_batch_write.h" + +#include +#include +#include + +#include +#include + +#include "agent/master_info.h" +#include "common/utils.h" +#include "gen_cpp/FrontendService.h" +#include "gen_cpp/internal_service.pb.h" +#include "http/http_common.h" +#include "runtime/client_cache.h" +#include "runtime/exec_env.h" +#include "runtime/stream_load/stream_load_context.h" +#include "runtime/stream_load/time_bounded_stream_load_pipe.h" +#include "testutil/sync_point.h" +#include "util/bthreads/executor.h" +#include "util/thrift_rpc_helper.h" + +namespace starrocks { + +class AsyncAppendDataContext { +public: + AsyncAppendDataContext(StreamLoadContext* data_ctx) : _data_ctx(data_ctx), _latch(1) { data_ctx->ref(); } + + ~AsyncAppendDataContext() { StreamLoadContext::release(_data_ctx); } + + AsyncAppendDataContext(const AsyncAppendDataContext&) = delete; + void operator=(const AsyncAppendDataContext&) = delete; + AsyncAppendDataContext(AsyncAppendDataContext&&) = delete; + void operator=(AsyncAppendDataContext&&) = delete; + + const BThreadCountDownLatch& latch() const { return _latch; } + + StreamLoadContext* data_ctx() { return _data_ctx; } + + void set_txn(int64_t txn_id, const std::string& label) { + std::lock_guard l(_result_lock); + _txn_id = txn_id; + _label = label; + } + + // called after async process finishes + void finish_async(const Status& status) { + { + std::lock_guard l(_result_lock); + if (_async_finished) { + return; + } + _async_finished = true; + _status = status; + } + _latch.count_down(); + } + + Status get_status() { + std::lock_guard l(_result_lock); + return _status; + } + + int64_t txn_id() const { + std::lock_guard l(_result_lock); + return _txn_id; + } + + const std::string& label() const { + std::lock_guard l(_result_lock); + return _label; + } + + void ref() { _refs.fetch_add(1); } + // If unref() returns true, this object should be delete + bool unref() { return _refs.fetch_sub(1) == 1; } + + static void release(AsyncAppendDataContext* ctx) { + if (ctx != nullptr && ctx->unref()) { + delete ctx; + } + } + +private: + StreamLoadContext* const _data_ctx; + BThreadCountDownLatch _latch; + std::atomic _refs{0}; + mutable bthread::Mutex _result_lock; + bool _async_finished{false}; + Status _status; + // the txn and label that data belongs to if success (_status is OK) + int64_t _txn_id{-1}; + std::string _label; + +public: + // statistics ======================= + std::atomic_long create_time_ts{-1}; + std::atomic_long task_pending_cost_ns{-1}; + std::atomic_long total_async_cost_ns{-1}; + std::atomic_long append_pipe_cost_ns{-1}; + std::atomic_long rpc_cost_ns{-1}; + std::atomic_long wait_pipe_cost_ns{-1}; + std::atomic_long pipe_left_active_ns{-1}; + std::atomic_long total_cost_ns{-1}; + std::atomic_int num_retries{-1}; +}; + +IsomorphicBatchWrite::IsomorphicBatchWrite(BatchWriteId batch_write_id, bthreads::ThreadPoolExecutor* executor) + : _batch_write_id(std::move(batch_write_id)), _executor(executor) {} + +Status IsomorphicBatchWrite::init() { + TEST_ERROR_POINT("IsomorphicBatchWrite::init::error"); + auto it = _batch_write_id.load_params.find(HTTP_MERGE_COMMIT_ASYNC); + if (it != _batch_write_id.load_params.end()) { + _batch_write_async = it->second == "true"; + } + bthread::ExecutionQueueOptions opts; + opts.executor = _executor; + if (int r = bthread::execution_queue_start(&_queue_id, &opts, _execute_tasks, this); r != 0) { + LOG(ERROR) << "Fail to start execution queue for batch write, " << _batch_write_id << ", result: " << r; + return Status::InternalError(fmt::format("fail to start bthread execution queue: {}", r)); + } + LOG(INFO) << "Init batch write, " << _batch_write_id; + return Status::OK(); +} + +void IsomorphicBatchWrite::stop() { + { + std::unique_lock lock(_mutex); + if (_stopped) { + return; + } + _stopped = true; + } + if (_queue_id.value != kInvalidQueueId) { + int r = bthread::execution_queue_stop(_queue_id); + LOG_IF(WARNING, r != 0) << "Fail to stop execution queue, " << _batch_write_id << ", result: " << r; + r = bthread::execution_queue_join(_queue_id); + LOG_IF(WARNING, r != 0) << "Fail to join execution queue, " << _batch_write_id << ", result: " << r; + } + + std::vector release_contexts; + { + std::unique_lock lock(_mutex); + release_contexts.insert(release_contexts.end(), _alive_stream_load_pipe_ctxs.begin(), + _alive_stream_load_pipe_ctxs.end()); + release_contexts.insert(release_contexts.end(), _dead_stream_load_pipe_ctxs.begin(), + _dead_stream_load_pipe_ctxs.end()); + _alive_stream_load_pipe_ctxs.clear(); + _dead_stream_load_pipe_ctxs.clear(); + } + for (StreamLoadContext* ctx : release_contexts) { + LOG(INFO) << "Stop stream load pipe, txn_id: " << ctx->txn_id << ", label: " << ctx->label + << ", load_id: " << print_id(ctx->id) << ", " << _batch_write_id; + StreamLoadContext::release(ctx); + } + LOG(INFO) << "Stop batch write, " << _batch_write_id; +} + +Status IsomorphicBatchWrite::register_stream_load_pipe(StreamLoadContext* pipe_ctx) { + std::unique_lock lock(_mutex); + if (_stopped.load(std::memory_order_acquire)) { + return Status::ServiceUnavailable("Batch write is stopped"); + } + if (_alive_stream_load_pipe_ctxs.emplace(pipe_ctx).second) { + pipe_ctx->ref(); + _cv.notify_one(); + } + TRACE_BATCH_WRITE << "Register stream load pipe, txn_id: " << pipe_ctx->txn_id << ", label: " << pipe_ctx->label + << ", load_id: " << print_id(pipe_ctx->id) << ", " << _batch_write_id; + return Status::OK(); +} + +void IsomorphicBatchWrite::unregister_stream_load_pipe(StreamLoadContext* pipe_ctx) { + bool find = false; + { + std::unique_lock lock(_mutex); + find = _alive_stream_load_pipe_ctxs.erase(pipe_ctx) > 0; + if (!find) { + find = _dead_stream_load_pipe_ctxs.erase(pipe_ctx) > 0; + } + } + TRACE_BATCH_WRITE << "Unregister stream load pipe, txn_id: " << pipe_ctx->txn_id << ", label: " << pipe_ctx->label + << ", load_id: " << print_id(pipe_ctx->id) << ", " << _batch_write_id << ", find: " << find; + if (find) { + StreamLoadContext::release(pipe_ctx); + } +} + +bool IsomorphicBatchWrite::contain_pipe(StreamLoadContext* pipe_ctx) { + std::unique_lock lock(_mutex); + auto it = _alive_stream_load_pipe_ctxs.find(pipe_ctx); + if (it != _alive_stream_load_pipe_ctxs.end()) { + return true; + } + return _dead_stream_load_pipe_ctxs.find(pipe_ctx) != _dead_stream_load_pipe_ctxs.end(); +} + +Status IsomorphicBatchWrite::append_data(StreamLoadContext* data_ctx) { + if (_stopped.load(std::memory_order_acquire)) { + return Status::ServiceUnavailable("Batch write is stopped"); + } + int64_t start_ts = MonotonicNanos(); + AsyncAppendDataContext* async_ctx = new AsyncAppendDataContext(data_ctx); + async_ctx->ref(); + async_ctx->create_time_ts.store(MonotonicNanos()); + DeferOp defer([&] { AsyncAppendDataContext::release(async_ctx); }); + Task task{.context = async_ctx}; + // this reference is for async task + async_ctx->ref(); + int r = bthread::execution_queue_execute(_queue_id, task); + if (r != 0) { + AsyncAppendDataContext::release(async_ctx); + LOG(ERROR) << "Fail to add task, " << _batch_write_id << ", user label: " << data_ctx->label << ", ret: " << r; + return Status::InternalError(fmt::format("Failed to add task to execution queue, result: {}", r)); + } + async_ctx->latch().wait(); + async_ctx->total_cost_ns.store(MonotonicNanos() - async_ctx->create_time_ts); + TRACE_BATCH_WRITE << "wait async finish, " << _batch_write_id << ", user label: " << async_ctx->data_ctx()->label + << ", data size: " << data_ctx->receive_bytes + << ", total_cost: " << (async_ctx->total_cost_ns / 1000) + << "us, total_async_cost: " << (async_ctx->total_async_cost_ns / 1000) + << "us, task_pending_cost: " << (async_ctx->task_pending_cost_ns / 1000) + << "us, append_pipe_cost: " << (async_ctx->append_pipe_cost_ns / 1000) + << "us, rpc_cost: " << (async_ctx->rpc_cost_ns / 1000) + << "us, wait_pipe_cost: " << (async_ctx->wait_pipe_cost_ns / 1000) + << "us, num retries: " << async_ctx->num_retries + << ", pipe_left_active: " << (async_ctx->pipe_left_active_ns / 1000) + << ", async_status: " << async_ctx->get_status() << ", txn_id: " << async_ctx->txn_id() + << ", label: " << async_ctx->label(); + RETURN_IF_ERROR(async_ctx->get_status()); + data_ctx->txn_id = async_ctx->txn_id(); + data_ctx->batch_write_label = async_ctx->label(); + data_ctx->batch_left_time_nanos = async_ctx->pipe_left_active_ns; + if (_batch_write_async) { + return Status::OK(); + } + int64_t timeout_ms = + data_ctx->timeout_second > 0 ? data_ctx->timeout_second * 1000 : config::batch_write_default_timeout_ms; + int64_t left_timeout_ns = std::max((int64_t)0, timeout_ms * 1000 * 1000 - (MonotonicNanos() - start_ts)); + return _wait_for_load_status(data_ctx, left_timeout_ns); +} + +int IsomorphicBatchWrite::_execute_tasks(void* meta, bthread::TaskIterator& iter) { + if (iter.is_queue_stopped()) { + return 0; + } + + auto batch_write = static_cast(meta); + for (; iter; ++iter) { + int64_t start_ts = MonotonicNanos(); + AsyncAppendDataContext* ctx = iter->context; + ctx->task_pending_cost_ns.store(MonotonicNanos() - ctx->create_time_ts); + auto st = batch_write->_execute_write(ctx); + ctx->finish_async(st); + ctx->total_async_cost_ns.store(MonotonicNanos() - start_ts); + TRACE_BATCH_WRITE << "async task finish, " << batch_write->_batch_write_id + << ", user label: " << ctx->data_ctx()->label + << ", data size: " << ctx->data_ctx()->receive_bytes + << ", total_async_cost: " << (ctx->total_async_cost_ns / 1000) + << "us, task_pending_cost: " << (ctx->task_pending_cost_ns / 1000) + << "us, append_pipe_cost: " << (ctx->append_pipe_cost_ns / 1000) + << "us, rpc_cost: " << (ctx->rpc_cost_ns / 1000) + << "us, wait_pipe_cost: " << (ctx->wait_pipe_cost_ns / 1000) + << "us, num retries: " << ctx->num_retries + << ", pipe_left_active: " << (ctx->pipe_left_active_ns / 1000) << "us, status: " << st + << ", txn_id: " << ctx->txn_id() << ", label: " << ctx->label(); + ; + AsyncAppendDataContext::release(ctx); + } + return 0; +} + +Status IsomorphicBatchWrite::_execute_write(AsyncAppendDataContext* async_ctx) { + Status st; + int64_t append_pipe_cost_ns = 0; + int64_t rpc_cost_ns = 0; + int64_t wait_pipe_cost_ns = 0; + int num_retries = 0; + while (num_retries <= config::batch_write_rpc_request_retry_num) { + if (_stopped.load(std::memory_order_acquire)) { + return Status::ServiceUnavailable("Batch write is stopped"); + } + int64_t append_ts = MonotonicNanos(); + st = _write_data(async_ctx); + int64_t rpc_ts = MonotonicNanos(); + append_pipe_cost_ns += rpc_ts - append_ts; + if (st.ok()) { + break; + } + // TODO check if the error is retryable + st = _send_rpc_request(async_ctx->data_ctx()); + int64_t wait_ts = MonotonicNanos(); + rpc_cost_ns += wait_ts - rpc_ts; + st = _wait_for_stream_load_pipe(); + wait_pipe_cost_ns += MonotonicNanos() - wait_ts; + num_retries += 1; + } + async_ctx->append_pipe_cost_ns.store(append_pipe_cost_ns); + async_ctx->rpc_cost_ns.store(rpc_cost_ns); + async_ctx->wait_pipe_cost_ns.store(wait_pipe_cost_ns); + async_ctx->num_retries.store(num_retries); + return st; +} + +Status IsomorphicBatchWrite::_write_data(AsyncAppendDataContext* async_ctx) { + // TODO write data outside the lock + std::unique_lock lock(_mutex); + Status st; + StreamLoadContext* data_ctx = async_ctx->data_ctx(); + for (auto it = _alive_stream_load_pipe_ctxs.begin(); it != _alive_stream_load_pipe_ctxs.end();) { + StreamLoadContext* pipe_ctx = *it; + // add reference to the buffer to avoid being released if append fails + ByteBufferPtr buffer = data_ctx->buffer; + st = pipe_ctx->body_sink->append(std::move(buffer)); + if (st.ok()) { + data_ctx->buffer.reset(); + async_ctx->pipe_left_active_ns.store( + static_cast(pipe_ctx->body_sink.get())->left_active_ns()); + async_ctx->set_txn(pipe_ctx->txn_id, pipe_ctx->label); + return st; + } + _dead_stream_load_pipe_ctxs.emplace(pipe_ctx); + it = _alive_stream_load_pipe_ctxs.erase(it); + } + return st.ok() ? Status::CapacityLimitExceed("") : st; +} + +Status IsomorphicBatchWrite::_wait_for_stream_load_pipe() { + std::unique_lock lock(_mutex); + _cv.wait_for(lock, std::chrono::milliseconds(config::batch_write_rpc_request_retry_interval_ms), + [&]() { return !_alive_stream_load_pipe_ctxs.empty(); }); + if (!_alive_stream_load_pipe_ctxs.empty()) { + return Status::OK(); + } + return Status::TimedOut(""); +} + +Status IsomorphicBatchWrite::_send_rpc_request(StreamLoadContext* data_ctx) { + TNetworkAddress master_addr = get_master_address(); + TMergeCommitRequest request; + request.__set_db(_batch_write_id.db); + request.__set_tbl(_batch_write_id.table); + request.__set_user(data_ctx->auth.user); + request.__set_passwd(data_ctx->auth.passwd); + request.__set_user_ip(data_ctx->auth.user_ip); + auto backend_id = get_backend_id(); + if (backend_id.has_value()) { + request.__set_backend_id(backend_id.value()); + } + request.__set_backend_host(BackendOptions::get_localhost()); + request.__set_params(_batch_write_id.load_params); + + TMergeCommitResult response; + Status st; + +#ifndef BE_TEST + int64_t start_ts = MonotonicNanos(); + st = ThriftRpcHelper::rpc( + master_addr.hostname, master_addr.port, + [&request, &response](FrontendServiceConnection& client) { client->requestMergeCommit(response, request); }, + config::batch_write_rpc_reqeust_timeout_ms); + TRACE_BATCH_WRITE << "receive requestBatchWrite response, " << _batch_write_id + << ", user label: " << data_ctx->label << ", master: " << master_addr + << ", cost: " << ((MonotonicNanos() - start_ts) / 1000) << "us, status: " << st + << ", response: " << response; +#else + TEST_SYNC_POINT_CALLBACK("IsomorphicBatchWrite::send_rpc_request::request", &request); + TEST_SYNC_POINT_CALLBACK("IsomorphicBatchWrite::send_rpc_request::status", &st); + TEST_SYNC_POINT_CALLBACK("IsomorphicBatchWrite::send_rpc_request::response", &response); +#endif + + return st.ok() ? Status(response.status) : st; +} + +bool is_final_load_status(const TTransactionStatus::type& status) { + switch (status) { + case TTransactionStatus::VISIBLE: + case TTransactionStatus::ABORTED: + case TTransactionStatus::UNKNOWN: + return true; + default: + return false; + } +} + +// TODO just poll the load status periodically. improve it later, such as cache the label, and FE notify the BE +Status IsomorphicBatchWrite::_wait_for_load_status(StreamLoadContext* data_ctx, int64_t timeout_ns) { + int64_t start_ts = MonotonicNanos(); + int64_t wait_load_finish_ns = std::max((int64_t)0, data_ctx->batch_left_time_nanos) + 1000000; + bthread_usleep(std::min(wait_load_finish_ns, timeout_ns) / 1000); + TGetLoadTxnStatusRequest request; + request.__set_db(_batch_write_id.db); + request.__set_tbl(_batch_write_id.table); + request.__set_txnId(data_ctx->txn_id); + set_request_auth(&request, data_ctx->auth); + TGetLoadTxnStatusResult response; + Status st; + do { + if (_stopped.load(std::memory_order_acquire)) { + return Status::ServiceUnavailable("Batch write is stopped"); + } +#ifndef BE_TEST + int64_t rpc_ts = MonotonicNanos(); + TNetworkAddress master_addr = get_master_address(); + st = ThriftRpcHelper::rpc( + master_addr.hostname, master_addr.port, + [&request, &response](FrontendServiceConnection& client) { + client->getLoadTxnStatus(response, request); + }, + config::batch_write_rpc_reqeust_timeout_ms); + TRACE_BATCH_WRITE << "receive getLoadTxnStatus response, " << _batch_write_id + << ", user label: " << data_ctx->label << ", txn_id: " << data_ctx->txn_id + << ", label: " << data_ctx->batch_write_label << ", master: " << master_addr + << ", cost: " << ((MonotonicNanos() - rpc_ts) / 1000) << "us, status: " << st + << ", response: " << response; +#else + TEST_SYNC_POINT_CALLBACK("IsomorphicBatchWrite::_wait_for_load_status::request", &request); + TEST_SYNC_POINT_CALLBACK("IsomorphicBatchWrite::_wait_for_load_status::status", &st); + TEST_SYNC_POINT_CALLBACK("IsomorphicBatchWrite::_wait_for_load_status::response", &response); +#endif + if (st.ok() && is_final_load_status(response.status)) { + break; + } + int64_t left_timeout_ns = timeout_ns - (MonotonicNanos() - start_ts); + if (left_timeout_ns <= 0) { + break; + } + bthread_usleep( + std::min(config::batch_write_poll_load_status_interval_ms * (int64_t)1000, left_timeout_ns / 1000)); + } while (true); + if (!st.ok()) { + return Status::InternalError("Failed to get load status, " + st.to_string()); + } + switch (response.status) { + case TTransactionStatus::PREPARE: + case TTransactionStatus::PREPARED: + return Status::TimedOut("load timeout, txn status: " + to_string(response.status)); + case TTransactionStatus::COMMITTED: + return Status::PublishTimeout("Load has not been published before timeout"); + case TTransactionStatus::VISIBLE: + return Status::OK(); + case TTransactionStatus::ABORTED: + return Status::InternalError("Load is aborted because of failure"); + default: + return Status::InternalError("Load status is unknown: " + to_string(response.status)); + } +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/batch_write/isomorphic_batch_write.h b/be/src/runtime/batch_write/isomorphic_batch_write.h new file mode 100644 index 0000000000000..3175a484133e0 --- /dev/null +++ b/be/src/runtime/batch_write/isomorphic_batch_write.h @@ -0,0 +1,89 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common/statusor.h" +#include "runtime/batch_write/batch_write_util.h" +#include "util/countdown_latch.h" + +namespace starrocks { + +namespace bthreads { +class ThreadPoolExecutor; +} + +class StreamLoadContext; + +using BThreadCountDownLatch = GenericCountDownLatch; + +class AsyncAppendDataContext; +struct Task { + AsyncAppendDataContext* context; +}; + +class IsomorphicBatchWrite { +public: + explicit IsomorphicBatchWrite(BatchWriteId batch_write_id, bthreads::ThreadPoolExecutor* executor); + + Status init(); + + Status register_stream_load_pipe(StreamLoadContext* pipe_ctx); + void unregister_stream_load_pipe(StreamLoadContext* pipe_ctx); + // For testing + bool contain_pipe(StreamLoadContext* pipe_ctx); + + Status append_data(StreamLoadContext* data_ctx); + + void stop(); + bool is_stopped() const { return _stopped.load(std::memory_order_relaxed); } + +private: + static int _execute_tasks(void* meta, bthread::TaskIterator& iter); + + Status _execute_write(AsyncAppendDataContext* async_ctx); + Status _write_data(AsyncAppendDataContext* data_ctx); + Status _wait_for_stream_load_pipe(); + Status _send_rpc_request(StreamLoadContext* data_ctx); + Status _wait_for_load_status(StreamLoadContext* data_ctx, int64_t timeout_ns); + + BatchWriteId _batch_write_id; + bthreads::ThreadPoolExecutor* _executor; + bool _batch_write_async{false}; + + std::mutex _mutex; + std::condition_variable _cv; + std::unordered_set _alive_stream_load_pipe_ctxs; + std::unordered_set _dead_stream_load_pipe_ctxs; + + // Undocemented rule of bthread that -1(0xFFFFFFFFFFFFFFFF) is an invalid ExecutionQueueId + constexpr static uint64_t kInvalidQueueId = (uint64_t)-1; + bthread::ExecutionQueueId _queue_id{kInvalidQueueId}; + + std::atomic _stopped{false}; +}; +using IsomorphicBatchWriteSharedPtr = std::shared_ptr; + +} // namespace starrocks diff --git a/be/src/runtime/broker_mgr.cpp b/be/src/runtime/broker_mgr.cpp index 9242f56f71c13..8e90b9fa902ab 100644 --- a/be/src/runtime/broker_mgr.cpp +++ b/be/src/runtime/broker_mgr.cpp @@ -45,6 +45,10 @@ #include "util/misc.h" #include "util/starrocks_metrics.h" #include "util/thread.h" +<<<<<<< HEAD +======= +#include "util/thrift_rpc_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -81,6 +85,7 @@ void BrokerMgr::ping(const TNetworkAddress& addr) { request.__set_clientId(_client_id); TBrokerOperationStatus response; +<<<<<<< HEAD Status status; // 500ms is enough BrokerServiceConnection client(_exec_env->broker_client_cache(), addr, 500, &status); @@ -102,6 +107,15 @@ void BrokerMgr::ping(const TNetworkAddress& addr) { } catch (apache::thrift::TException& e) { (void)client.reopen(500); LOG(WARNING) << "Broker ping failed, broker:" << addr << " failed:" << e.what(); +======= + Status rpc_status; + + // 500ms is enough + rpc_status = ThriftRpcHelper::rpc( + addr, [&response, &request](BrokerServiceConnection& client) { client->ping(response, request); }, 500); + if (!rpc_status.ok()) { + LOG(WARNING) << "Broker ping failed, broker:" << addr << " failed:" << rpc_status; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } diff --git a/be/src/runtime/buffer_control_block.cpp b/be/src/runtime/buffer_control_block.cpp index 040b05d1cfd14..f397aa75b571e 100644 --- a/be/src/runtime/buffer_control_block.cpp +++ b/be/src/runtime/buffer_control_block.cpp @@ -34,12 +34,22 @@ #include "runtime/buffer_control_block.h" +<<<<<<< HEAD +======= +#include +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include "gen_cpp/InternalService_types.h" #include "gen_cpp/internal_service.pb.h" #include "service/brpc.h" #include "util/defer_op.h" +<<<<<<< HEAD +======= +#include "util/race_detect.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/thrift_util.h" namespace starrocks { @@ -96,13 +106,25 @@ BufferControlBlock::BufferControlBlock(const TUniqueId& id, int buffer_size) _is_cancelled(false), _buffer_bytes(0), _buffer_limit(buffer_size), +<<<<<<< HEAD _packet_num(0) {} +======= + _packet_num(0), + _arrow_rows_limit(buffer_size * 4096), + _arrow_rows(0) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) BufferControlBlock::~BufferControlBlock() { cancel(); _batch_queue.clear(); +<<<<<<< HEAD + _buffer_bytes = 0; +======= + _arrow_batch_queue.clear(); _buffer_bytes = 0; + _arrow_rows = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } Status BufferControlBlock::init() { @@ -132,6 +154,28 @@ Status BufferControlBlock::add_batch(TFetchDataResult* result, bool need_free) { return Status::OK(); } +<<<<<<< HEAD +======= +Status BufferControlBlock::add_arrow_batch(std::shared_ptr& result) { + if (_is_cancelled) { + return Status::Cancelled("Cancelled BufferControlBlock::add_arrow_batch"); + } + + std::unique_lock l(_lock); + while ((_arrow_batch_queue.size() > _buffer_limit || _arrow_rows > _arrow_rows_limit) && !_is_cancelled) { + _data_removal.wait(l); + } + + if (_is_cancelled) { + return Status::Cancelled("Cancelled BufferControlBlock::add_arrow_batch"); + } + + _process_arrow_batch_without_lock(result); + + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr> BufferControlBlock::_serialize_result(TFetchDataResult* result) { uint8_t* buf = nullptr; uint32_t len = 0; @@ -160,6 +204,7 @@ void BufferControlBlock::_process_batch_without_lock(std::unique_ptr BufferControlBlock::try_add_batch(std::unique_ptr& result) { if (_is_cancelled) { return Status::Cancelled("Cancelled BufferControlBlock::add_batch"); @@ -198,6 +243,31 @@ StatusOr BufferControlBlock::try_add_batch(std::vector& result) { + _arrow_rows += result->num_rows(); + _arrow_batch_queue.push_back(std::move(result)); + _data_arriaval.notify_one(); +} + +Status BufferControlBlock::add_to_result_buffer(std::vector>&& results) { + if (_is_cancelled) { + return Status::Cancelled("Cancelled BufferControlBlock::add_batch"); + } + for (auto& result : results) { + ASSIGN_OR_RETURN(auto ser_res, _serialize_result(result.get())); + result.reset(); + { + std::unique_lock l(_lock); + _buffer_bytes += ser_res->attachment.length(); + _batch_queue.push_back(std::move(ser_res)); + l.unlock(); + _data_arriaval.notify_one(); + } + } + + std::unique_lock l(_lock); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!_waiting_rpc.empty() && !_batch_queue.empty()) { std::unique_ptr ser = std::move(_batch_queue.front()); _batch_queue.pop_front(); @@ -209,7 +279,34 @@ StatusOr BufferControlBlock::try_add_batch(std::vectoron_data(ser.get(), packet_num); } +<<<<<<< HEAD return true; +======= + + return Status::OK(); +} + +bool BufferControlBlock::is_full() const { + if (_is_cancelled) { + return false; + } + std::unique_lock l(_lock); + if ((_batch_queue.size() > _buffer_limit || _buffer_bytes > _max_memory_usage) && !_is_cancelled) { + return true; + } + if (_is_cancelled) { + return false; + } + return false; +} + +void BufferControlBlock::cancel_pending_rpc() { + std::unique_lock l(_lock); + while (!_batch_queue.empty()) { + _buffer_bytes -= _batch_queue.front()->attachment.length(); + _batch_queue.pop_front(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // seems no use? @@ -290,6 +387,43 @@ void BufferControlBlock::get_batch(GetResultBatchCtx* ctx) { _waiting_rpc.push_back(ctx); } +<<<<<<< HEAD +======= +Status BufferControlBlock::get_arrow_batch(std::shared_ptr* result) { + std::unique_lock l(_lock); + if (!_status.ok()) { + return _status; + } + + if (_is_cancelled) { + return Status::Cancelled("Cancelled BufferControlBlock::get_arrow_batch"); + } + + while (_arrow_batch_queue.empty() && !_is_close && !_is_cancelled) { + _data_arriaval.wait(l); + } + + if (_is_cancelled) { + return Status::Cancelled("Cancelled BufferControlBlock::get_arrow_batch"); + } + + if (!_arrow_batch_queue.empty()) { + const auto batch = std::move(_arrow_batch_queue.front()); + *result = batch; + _arrow_batch_queue.pop_front(); + _arrow_rows -= batch->num_rows(); + _data_removal.notify_one(); + return Status::OK(); + } + + if (_is_close) { + return Status::OK(); + } + + return Status::InternalError("Internal error, BufferControlBlock::get_arrow_batch"); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status BufferControlBlock::close(Status exec_status) { std::unique_lock l(_lock); if (_is_close) { diff --git a/be/src/runtime/buffer_control_block.h b/be/src/runtime/buffer_control_block.h index 6ff6af4f810ca..7ed561661c63e 100644 --- a/be/src/runtime/buffer_control_block.h +++ b/be/src/runtime/buffer_control_block.h @@ -46,8 +46,18 @@ #include "common/statusor.h" #include "gen_cpp/Types_types.h" #include "runtime/query_statistics.h" +<<<<<<< HEAD #include "util/runtime_profile.h" +======= +#include "util/race_detect.h" +#include "util/runtime_profile.h" + +namespace arrow { +class RecordBatch; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace google::protobuf { class Closure; } // namespace google::protobuf @@ -95,15 +105,29 @@ class BufferControlBlock { // this method is reserved and is only used in the non-pipeline engine Status add_batch(TFetchDataResult* result, bool need_free = true); Status add_batch(std::unique_ptr& result); +<<<<<<< HEAD // non-blocking version of add_batch StatusOr try_add_batch(std::unique_ptr& result); StatusOr try_add_batch(std::vector>& results); +======= + Status add_arrow_batch(std::shared_ptr& result); + + // non-blocking version of add_batch + Status add_to_result_buffer(std::vector>&& results); + bool is_full() const; + // cancel all pending rpc. this is called from pipeline->cancelled + void cancel_pending_rpc(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // get result from batch, use timeout? Status get_batch(TFetchDataResult* result); void get_batch(GetResultBatchCtx* ctx); +<<<<<<< HEAD +======= + Status get_arrow_batch(std::shared_ptr* result); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // close buffer block, set _status to exec_status and set _is_close to true; // called because data has been read or error happened. @@ -129,10 +153,20 @@ class BufferControlBlock { private: void _process_batch_without_lock(std::unique_ptr& result); +<<<<<<< HEAD +======= + void _process_arrow_batch_without_lock(std::shared_ptr& result); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr> _serialize_result(TFetchDataResult*); // as no idea of whether sending sorted results, can't use concurrentQueue here. typedef std::list> ResultQueue; +<<<<<<< HEAD +======= + typedef std::list> ArrowResultQueue; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // result's query id TUniqueId _fragment_id; std::atomic_bool _is_close; @@ -141,11 +175,23 @@ class BufferControlBlock { std::atomic_int64_t _buffer_bytes; int _buffer_limit; std::atomic _packet_num; +<<<<<<< HEAD // blocking queue for batch ResultQueue _batch_queue; // protects all subsequent data in this block std::mutex _lock; +======= + int _arrow_rows_limit; + int _arrow_rows; + + // blocking queue for batch + ResultQueue _batch_queue; + ArrowResultQueue _arrow_batch_queue; + + // protects all subsequent data in this block + mutable std::mutex _lock; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // signal arrival of new batch or the eos/cancelled condition std::condition_variable _data_arriaval; // signal removal of data by stream consumer diff --git a/be/src/runtime/buffer_control_result_writer.cpp b/be/src/runtime/buffer_control_result_writer.cpp new file mode 100644 index 0000000000000..2cba14034bdcc --- /dev/null +++ b/be/src/runtime/buffer_control_result_writer.cpp @@ -0,0 +1,63 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/buffer_control_result_writer.h" + +#include "runtime/buffer_control_block.h" + +namespace starrocks { + +BufferControlResultWriter::BufferControlResultWriter(BufferControlBlock* sinker, RuntimeProfile* parent_profile) + : _sinker(sinker), _parent_profile(parent_profile) {} + +bool BufferControlResultWriter::is_full() const { + return _sinker->is_full(); +} + +Status BufferControlResultWriter::add_to_write_buffer(Chunk* chunk) { + ASSIGN_OR_RETURN(auto results, process_chunk(chunk)); + SCOPED_TIMER(_result_send_timer); + size_t num_rows = 0; + for (auto& result : results) { + num_rows += result->result_batch.rows.size(); + } + + auto status = _sinker->add_to_result_buffer(std::move(results)); + if (status.ok()) { + // rows append to sink result buffer + _written_rows += num_rows; + } else { + LOG(WARNING) << "Append result batch to sink failed: status=" << status.to_string(); + } + return status; + return Status::OK(); +} + +void BufferControlResultWriter::cancel() { + _sinker->cancel_pending_rpc(); +} + +Status BufferControlResultWriter::close() { + COUNTER_SET(_sent_rows_counter, _written_rows); + return Status::OK(); +} + +void BufferControlResultWriter::_init_profile() { + _append_chunk_timer = ADD_TIMER(_parent_profile, "AppendChunkTime"); + _convert_tuple_timer = ADD_CHILD_TIMER(_parent_profile, "TupleConvertTime", "AppendChunkTime"); + _result_send_timer = ADD_CHILD_TIMER(_parent_profile, "ResultRendTime", "AppendChunkTime"); + _sent_rows_counter = ADD_COUNTER(_parent_profile, "NumSentRows", TUnit::UNIT); +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/buffer_control_result_writer.h b/be/src/runtime/buffer_control_result_writer.h new file mode 100644 index 0000000000000..e73aa41fdda6a --- /dev/null +++ b/be/src/runtime/buffer_control_result_writer.h @@ -0,0 +1,48 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "runtime/result_writer.h" +#include "util/runtime_profile.h" + +namespace starrocks { +class BufferControlBlock; +class BufferControlResultWriter : public ResultWriter { +public: + BufferControlResultWriter(BufferControlBlock* sinker, RuntimeProfile* parent_profile); + + Status add_to_write_buffer(Chunk* chunk) override; + bool is_full() const override; + void cancel() override; + Status close() override; + +protected: + virtual void _init_profile(); + + BufferControlBlock* _sinker; + + // parent profile from result sink. not owned + RuntimeProfile* _parent_profile; + + // total time cost on append chunk operation + RuntimeProfile::Counter* _append_chunk_timer = nullptr; + // tuple convert timer, child timer of _append_chunk_timer + RuntimeProfile::Counter* _convert_tuple_timer = nullptr; + // file write timer, child timer of _append_chunk_timer + RuntimeProfile::Counter* _result_send_timer = nullptr; + // number of sent rows + RuntimeProfile::Counter* _sent_rows_counter = nullptr; +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/chunk_cursor.h b/be/src/runtime/chunk_cursor.h index 7f2c74ba680bb..d6e77c4b8e6ec 100644 --- a/be/src/runtime/chunk_cursor.h +++ b/be/src/runtime/chunk_cursor.h @@ -71,7 +71,11 @@ class ChunkCursor { [[nodiscard]] ChunkPtr clone_empty_chunk(size_t reserved_row_number) const; +<<<<<<< HEAD [[nodiscard]] Status chunk_supplier(Chunk**); +======= + Status chunk_supplier(Chunk**); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool chunk_probe_supplier(Chunk**); bool chunk_has_supplier(); diff --git a/be/src/runtime/customized_result_writer.cpp b/be/src/runtime/customized_result_writer.cpp index a2c0ed7c66423..c221d55dfdbe7 100644 --- a/be/src/runtime/customized_result_writer.cpp +++ b/be/src/runtime/customized_result_writer.cpp @@ -29,7 +29,11 @@ namespace starrocks { CustomizedResultWriter::CustomizedResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, starrocks::RuntimeProfile* parent_profile) +<<<<<<< HEAD : _sinker(sinker), _output_expr_ctxs(output_expr_ctxs), _parent_profile(parent_profile) {} +======= + : BufferControlResultWriter(sinker, parent_profile), _output_expr_ctxs(output_expr_ctxs) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CustomizedResultWriter::~CustomizedResultWriter() = default; @@ -45,6 +49,7 @@ Status CustomizedResultWriter::init(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD void CustomizedResultWriter::_init_profile() { _total_timer = ADD_TIMER(_parent_profile, "TotalSendTime"); _serialize_timer = ADD_CHILD_TIMER(_parent_profile, "SerializeTime", "TotalSendTime"); @@ -53,6 +58,9 @@ void CustomizedResultWriter::_init_profile() { Status CustomizedResultWriter::append_chunk(Chunk* chunk) { SCOPED_TIMER(_total_timer); +======= +Status CustomizedResultWriter::append_chunk(Chunk* chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto process_status = _process_chunk(chunk); if (!process_status.ok() || process_status.value() == nullptr) { return process_status.status(); @@ -71,7 +79,12 @@ Status CustomizedResultWriter::append_chunk(Chunk* chunk) { } StatusOr CustomizedResultWriter::process_chunk(Chunk* chunk) { +<<<<<<< HEAD SCOPED_TIMER(_total_timer); +======= + SCOPED_TIMER(_append_chunk_timer); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TFetchDataResultPtrs results; auto process_status = _process_chunk(chunk); if (!process_status.ok()) { @@ -83,6 +96,7 @@ StatusOr CustomizedResultWriter::process_chunk(Chunk* chun return results; } +<<<<<<< HEAD StatusOr CustomizedResultWriter::try_add_batch(TFetchDataResultPtrs& results) { size_t num_rows = 0; for (auto& result : results) { @@ -103,6 +117,8 @@ StatusOr CustomizedResultWriter::try_add_batch(TFetchDataResultPtrs& resul return status; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr CustomizedResultWriter::_process_chunk(Chunk* chunk) { if (nullptr == chunk || 0 == chunk->num_rows()) { return nullptr; @@ -156,9 +172,12 @@ StatusOr CustomizedResultWriter::_process_chunk(Chunk* chun return result; } +<<<<<<< HEAD Status CustomizedResultWriter::close() { COUNTER_SET(_sent_rows_counter, _written_rows); return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/customized_result_writer.h b/be/src/runtime/customized_result_writer.h index 2217e2ed5a096..a8793119394bb 100644 --- a/be/src/runtime/customized_result_writer.h +++ b/be/src/runtime/customized_result_writer.h @@ -14,8 +14,12 @@ #pragma once +<<<<<<< HEAD #include "runtime/result_writer.h" #include "runtime/runtime_state.h" +======= +#include "runtime/buffer_control_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/type_pack.h" namespace starrocks { @@ -25,7 +29,11 @@ class MysqlRowBuffer; class BufferControlBlock; class RuntimeProfile; +<<<<<<< HEAD class CustomizedResultWriter final : public ResultWriter { +======= +class CustomizedResultWriter final : public BufferControlResultWriter { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: CustomizedResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile); @@ -36,6 +44,7 @@ class CustomizedResultWriter final : public ResultWriter { Status append_chunk(Chunk* chunk) override; +<<<<<<< HEAD Status close() override; StatusOr process_chunk(Chunk* chunk) override; @@ -60,6 +69,16 @@ class CustomizedResultWriter final : public ResultWriter { RuntimeProfile::Counter* _serialize_timer = nullptr; // number of sent rows RuntimeProfile::Counter* _sent_rows_counter = nullptr; +======= + StatusOr process_chunk(Chunk* chunk) override; + +private: + StatusOr _process_chunk(Chunk* chunk); + +private: + const std::vector& _output_expr_ctxs; + std::vector _pack_funcs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/runtime/data_stream_mgr.h b/be/src/runtime/data_stream_mgr.h index 2971b74991125..e7f146ae6a86f 100644 --- a/be/src/runtime/data_stream_mgr.h +++ b/be/src/runtime/data_stream_mgr.h @@ -46,7 +46,11 @@ #include "common/object_pool.h" #include "common/status.h" #include "gen_cpp/Types_types.h" // for TUniqueId +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" +======= +#include "gen_cpp/internal_service.pb.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/descriptors.h" // for PlanNodeId #include "runtime/local_pass_through_buffer.h" #include "runtime/mem_tracker.h" diff --git a/be/src/runtime/data_stream_sender.cpp b/be/src/runtime/data_stream_sender.cpp index bf38ce5c6f475..acb89ddeae02c 100644 --- a/be/src/runtime/data_stream_sender.cpp +++ b/be/src/runtime/data_stream_sender.cpp @@ -59,6 +59,10 @@ #include "util/brpc_stub_cache.h" #include "util/compression/block_compression.h" #include "util/compression/compression_utils.h" +<<<<<<< HEAD +======= +#include "util/internal_service_recoverable_stub.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/ref_count_closure.h" #include "util/thrift_client.h" #include "util/uid_util.h" @@ -119,7 +123,11 @@ class DataStreamSender::Channel { // of close operation, client should call close_wait() to finish channel's close. // We split one close operation into two phases in order to make multiple channels // can run parallel. +<<<<<<< HEAD void close(RuntimeState* state); +======= + void close(RuntimeState* state) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Get close wait's response, to finish channel close operation. void close_wait(RuntimeState* state); @@ -178,7 +186,11 @@ class DataStreamSender::Channel { size_t _current_request_bytes = 0; +<<<<<<< HEAD PInternalService_Stub* _brpc_stub = nullptr; +======= + std::shared_ptr _brpc_stub; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int32_t _brpc_timeout_ms = 500; // whether the dest can be treated as query statistics transfer chain. @@ -340,10 +352,13 @@ Status DataStreamSender::Channel::close_internal() { return Status::OK(); } +<<<<<<< HEAD void DataStreamSender::Channel::close(RuntimeState* state) { state->log_error(close_internal().message()); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void DataStreamSender::Channel::close_wait(RuntimeState* state) { if (_need_close) { auto st = _wait_prev_request(); diff --git a/be/src/runtime/data_stream_sender.h b/be/src/runtime/data_stream_sender.h index 7ed692e5387a8..f3074d64783b0 100644 --- a/be/src/runtime/data_stream_sender.h +++ b/be/src/runtime/data_stream_sender.h @@ -42,7 +42,10 @@ #include "common/object_pool.h" #include "common/status.h" #include "exec/data_sink.h" +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/internal_service.pb.h" #include "serde/protobuf_serde.h" #include "util/raw_container.h" diff --git a/be/src/runtime/descriptors.cpp b/be/src/runtime/descriptors.cpp index 19e9bfb7e4baa..e3465a956dfd1 100644 --- a/be/src/runtime/descriptors.cpp +++ b/be/src/runtime/descriptors.cpp @@ -34,6 +34,11 @@ #include "runtime/descriptors.h" +<<<<<<< HEAD +======= +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -45,6 +50,10 @@ #include "gen_cpp/Descriptors_types.h" #include "gen_cpp/PlanNodes_types.h" #include "gen_cpp/descriptors.pb.h" +<<<<<<< HEAD +======= +#include "runtime/runtime_state.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/compression/block_compression.h" #include "util/thrift_util.h" @@ -137,11 +146,16 @@ std::string TableDescriptor::debug_string() const { // ============== HDFS Table Descriptor ============ +<<<<<<< HEAD HdfsPartitionDescriptor::HdfsPartitionDescriptor(const THdfsTable& thrift_table, const THdfsPartition& thrift_partition) +======= +HdfsPartitionDescriptor::HdfsPartitionDescriptor(const THdfsPartition& thrift_partition) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) : _file_format(thrift_partition.file_format), _location(thrift_partition.location.suffix), _thrift_partition_key_exprs(thrift_partition.partition_key_exprs) {} +<<<<<<< HEAD HdfsPartitionDescriptor::HdfsPartitionDescriptor(const THudiTable& thrift_table, const THdfsPartition& thrift_partition) : _file_format(thrift_partition.file_format), _location(thrift_partition.location.suffix), @@ -157,6 +171,8 @@ HdfsPartitionDescriptor::HdfsPartitionDescriptor(const TIcebergTable& thrift_tab const THdfsPartition& thrift_partition) : _thrift_partition_key_exprs(thrift_partition.partition_key_exprs) {} +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status HdfsPartitionDescriptor::create_part_key_exprs(RuntimeState* state, ObjectPool* pool) { RETURN_IF_ERROR(Expr::create_expr_trees(pool, _thrift_partition_key_exprs, &_partition_key_value_evals, state)); RETURN_IF_ERROR(Expr::prepare(_partition_key_value_evals, state)); @@ -170,7 +186,11 @@ HdfsTableDescriptor::HdfsTableDescriptor(const TTableDescriptor& tdesc, ObjectPo _columns = tdesc.hdfsTable.columns; _partition_columns = tdesc.hdfsTable.partition_columns; for (const auto& entry : tdesc.hdfsTable.partitions) { +<<<<<<< HEAD auto* partition = pool->add(new HdfsPartitionDescriptor(tdesc.hdfsTable, entry.second)); +======= + auto* partition = pool->add(new HdfsPartitionDescriptor(entry.second)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _partition_id_to_desc_map[entry.first] = partition; } _hive_column_names = tdesc.hdfsTable.hive_column_names; @@ -242,7 +262,10 @@ IcebergTableDescriptor::IcebergTableDescriptor(const TTableDescriptor& tdesc, Ob _columns = tdesc.icebergTable.columns; _t_iceberg_schema = tdesc.icebergTable.iceberg_schema; _partition_column_names = tdesc.icebergTable.partition_column_names; +<<<<<<< HEAD _t_iceberg_equal_delete_schema = tdesc.icebergTable.iceberg_equal_delete_schema; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } std::vector IcebergTableDescriptor::partition_index_in_schema() { @@ -276,12 +299,20 @@ Status IcebergTableDescriptor::set_partition_desc_map(const starrocks::TIcebergT ASSIGN_OR_RETURN(TPartitionMap * tPartitionMap, deserialize_partition_map(thrift_table.compressed_partitions, pool)); for (const auto& entry : tPartitionMap->partitions) { +<<<<<<< HEAD auto* partition = pool->add(new HdfsPartitionDescriptor(thrift_table, entry.second)); +======= + auto* partition = pool->add(new HdfsPartitionDescriptor(entry.second)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _partition_id_to_desc_map[entry.first] = partition; } } else { for (const auto& entry : thrift_table.partitions) { +<<<<<<< HEAD auto* partition = pool->add(new HdfsPartitionDescriptor(thrift_table, entry.second)); +======= + auto* partition = pool->add(new HdfsPartitionDescriptor(entry.second)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _partition_id_to_desc_map[entry.first] = partition; } } @@ -294,7 +325,11 @@ DeltaLakeTableDescriptor::DeltaLakeTableDescriptor(const TTableDescriptor& tdesc _columns = tdesc.deltaLakeTable.columns; _partition_columns = tdesc.deltaLakeTable.partition_columns; for (const auto& entry : tdesc.deltaLakeTable.partitions) { +<<<<<<< HEAD auto* partition = pool->add(new HdfsPartitionDescriptor(tdesc.deltaLakeTable, entry.second)); +======= + auto* partition = pool->add(new HdfsPartitionDescriptor(entry.second)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _partition_id_to_desc_map[entry.first] = partition; } } @@ -305,7 +340,11 @@ HudiTableDescriptor::HudiTableDescriptor(const TTableDescriptor& tdesc, ObjectPo _columns = tdesc.hudiTable.columns; _partition_columns = tdesc.hudiTable.partition_columns; for (const auto& entry : tdesc.hudiTable.partitions) { +<<<<<<< HEAD auto* partition = pool->add(new HdfsPartitionDescriptor(tdesc.hudiTable, entry.second)); +======= + auto* partition = pool->add(new HdfsPartitionDescriptor(entry.second)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _partition_id_to_desc_map[entry.first] = partition; } _hudi_instant_time = tdesc.hudiTable.instant_time; @@ -385,6 +424,10 @@ bool HiveTableDescriptor::is_partition_col(const SlotDescriptor* slot) const { } HdfsPartitionDescriptor* HiveTableDescriptor::get_partition(int64_t partition_id) const { +<<<<<<< HEAD +======= + std::shared_lock lock(_map_mutex); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto it = _partition_id_to_desc_map.find(partition_id); if (it == _partition_id_to_desc_map.end()) { return nullptr; @@ -407,6 +450,10 @@ IcebergMetadataTableDescriptor::IcebergMetadataTableDescriptor(const TTableDescr : HiveTableDescriptor(tdesc, pool) { _hive_column_names = tdesc.hdfsTable.hive_column_names; _hive_column_types = tdesc.hdfsTable.hive_column_types; +<<<<<<< HEAD +======= + _time_zone = tdesc.hdfsTable.__isset.time_zone ? tdesc.hdfsTable.time_zone : TimezoneUtils::default_time_zone; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } const std::string& IcebergMetadataTableDescriptor::get_hive_column_names() const { @@ -417,6 +464,13 @@ const std::string& IcebergMetadataTableDescriptor::get_hive_column_types() const return _hive_column_types; } +<<<<<<< HEAD +======= +const std::string& IcebergMetadataTableDescriptor::get_time_zone() const { + return _time_zone; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr HiveTableDescriptor::deserialize_partition_map( const TCompressedPartitionMap& compressed_partition_map, ObjectPool* pool) { const std::string& base64_partition_map = compressed_partition_map.compressed_serialized_partitions; @@ -440,6 +494,20 @@ StatusOr HiveTableDescriptor::deserialize_partition_map( return tPartitionMap; } +<<<<<<< HEAD +======= +Status HiveTableDescriptor::add_partition_value(RuntimeState* runtime_state, ObjectPool* pool, int64_t id, + const THdfsPartition& thrift_partition) { + auto* partition = pool->add(new HdfsPartitionDescriptor(thrift_partition)); + RETURN_IF_ERROR(partition->create_part_key_exprs(runtime_state, pool)); + { + std::unique_lock lock(_map_mutex); + _partition_id_to_desc_map[id] = partition; + } + return Status::OK(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // ============================================= OlapTableDescriptor::OlapTableDescriptor(const TTableDescriptor& tdesc) : TableDescriptor(tdesc) {} @@ -729,7 +797,18 @@ Status DescriptorTbl::create(RuntimeState* state, ObjectPool* pool, const TDescr desc = pool->add(new OdpsTableDescriptor(tdesc, pool)); break; } +<<<<<<< HEAD case TTableType::LOGICAL_ICEBERG_METADATA_TABLE: { +======= + case TTableType::LOGICAL_ICEBERG_METADATA_TABLE: + case TTableType::ICEBERG_REFS_TABLE: + case TTableType::ICEBERG_HISTORY_TABLE: + case TTableType::ICEBERG_METADATA_LOG_ENTRIES_TABLE: + case TTableType::ICEBERG_SNAPSHOTS_TABLE: + case TTableType::ICEBERG_MANIFESTS_TABLE: + case TTableType::ICEBERG_FILES_TABLE: + case TTableType::ICEBERG_PARTITIONS_TABLE: { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) desc = pool->add(new IcebergMetadataTableDescriptor(tdesc, pool)); break; } @@ -759,7 +838,13 @@ Status DescriptorTbl::create(RuntimeState* state, ObjectPool* pool, const TDescr for (const auto& tdesc : thrift_tbl.slotDescriptors) { SlotDescriptor* slot_d = pool->add(new SlotDescriptor(tdesc)); (*tbl)->_slot_desc_map[tdesc.id] = slot_d; +<<<<<<< HEAD +======= + if (!slot_d->col_name().empty()) { + (*tbl)->_slot_with_column_name_map[tdesc.id] = slot_d; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // link to parent auto entry = (*tbl)->_tuple_desc_map.find(tdesc.parent); @@ -802,6 +887,20 @@ SlotDescriptor* DescriptorTbl::get_slot_descriptor(SlotId id) const { } } +<<<<<<< HEAD +======= +SlotDescriptor* DescriptorTbl::get_slot_descriptor_with_column(SlotId id) const { + // TODO: is there some boost function to do exactly this? + auto i = _slot_with_column_name_map.find(id); + + if (i == _slot_with_column_name_map.end()) { + return nullptr; + } else { + return i->second; + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // return all registered tuple descriptors void DescriptorTbl::get_tuple_descs(std::vector* descs) const { descs->clear(); diff --git a/be/src/runtime/descriptors.h b/be/src/runtime/descriptors.h index 84cfe65a61d1e..c8acb79d125ca 100644 --- a/be/src/runtime/descriptors.h +++ b/be/src/runtime/descriptors.h @@ -38,6 +38,10 @@ #include #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -164,11 +168,15 @@ class TableDescriptor { class HdfsPartitionDescriptor { public: +<<<<<<< HEAD HdfsPartitionDescriptor(const THdfsTable& thrift_table, const THdfsPartition& thrift_partition); HdfsPartitionDescriptor(const THudiTable& thrift_table, const THdfsPartition& thrift_partition); HdfsPartitionDescriptor(const TDeltaLakeTable& thrift_table, const THdfsPartition& thrift_partition); HdfsPartitionDescriptor(const TIcebergTable& thrift_table, const THdfsPartition& thrift_partition); +======= + HdfsPartitionDescriptor(const THdfsPartition& thrift_partition); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t id() const { return _id; } THdfsFileFormat::type file_format() { return _file_format; } std::string& location() { return _location; } @@ -208,10 +216,20 @@ class HiveTableDescriptor : public TableDescriptor { StatusOr deserialize_partition_map(const TCompressedPartitionMap& compressed_partition_map, ObjectPool* pool); +<<<<<<< HEAD +======= + Status add_partition_value(RuntimeState* runtime_state, ObjectPool* pool, int64_t id, + const THdfsPartition& thrift_partition); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: std::string _hdfs_base_path; std::vector _columns; std::vector _partition_columns; +<<<<<<< HEAD +======= + mutable std::shared_mutex _map_mutex; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::map _partition_id_to_desc_map; std::string _table_location; }; @@ -243,7 +261,10 @@ class IcebergTableDescriptor : public HiveTableDescriptor { ~IcebergTableDescriptor() override = default; bool has_partition() const override { return false; } const TIcebergSchema* get_iceberg_schema() const { return &_t_iceberg_schema; } +<<<<<<< HEAD const TIcebergSchema* get_iceberg_equal_delete_schema() const { return &_t_iceberg_equal_delete_schema; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_unpartitioned_table() { return _partition_column_names.empty(); } const std::vector& partition_column_names() { return _partition_column_names; } const std::vector full_column_names(); @@ -254,7 +275,10 @@ class IcebergTableDescriptor : public HiveTableDescriptor { private: TIcebergSchema _t_iceberg_schema; +<<<<<<< HEAD TIcebergSchema _t_iceberg_equal_delete_schema; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector _partition_column_names; }; @@ -340,11 +364,19 @@ class IcebergMetadataTableDescriptor : public HiveTableDescriptor { ~IcebergMetadataTableDescriptor() override = default; const std::string& get_hive_column_names() const; const std::string& get_hive_column_types() const; +<<<<<<< HEAD +======= + const std::string& get_time_zone() const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool has_partition() const override { return false; } private: std::string _hive_column_names; std::string _hive_column_types; +<<<<<<< HEAD +======= + std::string _time_zone; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; class KuduTableDescriptor : public HiveTableDescriptor { @@ -488,6 +520,10 @@ class DescriptorTbl { TableDescriptor* get_table_descriptor(TableId id) const; TupleDescriptor* get_tuple_descriptor(TupleId id) const; SlotDescriptor* get_slot_descriptor(SlotId id) const; +<<<<<<< HEAD +======= + SlotDescriptor* get_slot_descriptor_with_column(SlotId id) const; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // return all registered tuple descriptors void get_tuple_descs(std::vector* descs) const; @@ -502,6 +538,10 @@ class DescriptorTbl { TableDescriptorMap _tbl_desc_map; TupleDescriptorMap _tuple_desc_map; SlotDescriptorMap _slot_desc_map; +<<<<<<< HEAD +======= + SlotDescriptorMap _slot_with_column_name_map; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DescriptorTbl() = default; }; diff --git a/be/src/runtime/exec_env.cpp b/be/src/runtime/exec_env.cpp index 9deba4072cf56..d7a5c83fbc366 100644 --- a/be/src/runtime/exec_env.cpp +++ b/be/src/runtime/exec_env.cpp @@ -41,7 +41,10 @@ #include "agent/agent_server.h" #include "agent/master_info.h" #include "block_cache/block_cache.h" +<<<<<<< HEAD #include "column/column_pool.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/config.h" #include "common/configbase.h" #include "common/logging.h" @@ -53,7 +56,10 @@ #include "exec/workgroup/scan_executor.h" #include "exec/workgroup/scan_task_queue.h" #include "exec/workgroup/work_group.h" +<<<<<<< HEAD #include "exprs/jit/jit_engine.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fs/fs_s3.h" #include "gen_cpp/BackendService.h" #include "gen_cpp/TFileBrokerService.h" @@ -61,6 +67,10 @@ #include "gutil/strings/split.h" #include "gutil/strings/strip.h" #include "gutil/strings/substitute.h" +<<<<<<< HEAD +======= +#include "runtime/batch_write/batch_write_mgr.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/broker_mgr.h" #include "runtime/client_cache.h" #include "runtime/data_stream_mgr.h" @@ -91,6 +101,10 @@ #include "storage/storage_engine.h" #include "storage/tablet_schema_map.h" #include "storage/update_manager.h" +<<<<<<< HEAD +======= +#include "udf/python/env.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/bfd_parser.h" #include "util/brpc_stub_cache.h" #include "util/cpu_info.h" @@ -100,6 +114,13 @@ #include "util/priority_thread_pool.hpp" #include "util/starrocks_metrics.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include "exprs/jit/jit_engine.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { // Calculate the total memory limit of all load tasks on this BE @@ -234,7 +255,10 @@ Status GlobalEnv::_init_mem_tracker() { int64_t compaction_mem_limit = calc_max_compaction_memory(_process_mem_tracker->limit()); _compaction_mem_tracker = regist_tracker(compaction_mem_limit, "compaction", _process_mem_tracker.get()); _schema_change_mem_tracker = regist_tracker(-1, "schema_change", _process_mem_tracker.get()); +<<<<<<< HEAD _column_pool_mem_tracker = regist_tracker(-1, "column_pool", _process_mem_tracker.get()); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _page_cache_mem_tracker = regist_tracker(-1, "page_cache", _process_mem_tracker.get()); _jit_cache_mem_tracker = regist_tracker(-1, "jit_cache", _process_mem_tracker.get()); int32_t update_mem_percent = std::max(std::min(100, config::update_memory_limit_percent), 0); @@ -245,12 +269,19 @@ Status GlobalEnv::_init_mem_tracker() { int64_t consistency_mem_limit = calc_max_consistency_memory(_process_mem_tracker->limit()); _consistency_mem_tracker = regist_tracker(consistency_mem_limit, "consistency", _process_mem_tracker.get()); _datacache_mem_tracker = regist_tracker(-1, "datacache", _process_mem_tracker.get()); +<<<<<<< HEAD +======= + _poco_connection_pool_mem_tracker = regist_tracker(-1, "poco_connection_pool", _process_mem_tracker.get()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _replication_mem_tracker = regist_tracker(-1, "replication", _process_mem_tracker.get()); MemChunkAllocator::init_instance(_chunk_allocator_mem_tracker.get(), config::chunk_reserved_bytes_limit); +<<<<<<< HEAD SetMemTrackerForColumnPool op(_column_pool_mem_tracker); ForEach(op); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _init_storage_page_cache(); // TODO: move to StorageEngine return Status::OK(); } @@ -507,6 +538,20 @@ Status ExecEnv::init(const std::vector& store_paths, bool as_cn) { _stream_context_mgr = new StreamContextMgr(); _transaction_mgr = new TransactionMgr(this); +<<<<<<< HEAD +======= + std::unique_ptr batch_write_thread_pool; + RETURN_IF_ERROR(ThreadPoolBuilder("batch_write") + .set_min_threads(config::batch_write_thread_pool_num_min) + .set_max_threads(config::batch_write_thread_pool_num_max) + .set_max_queue_size(config::batch_write_thread_pool_queue_size) + .set_idle_timeout(MonoDelta::FromMilliseconds(10000)) + .build(&batch_write_thread_pool)); + auto batch_write_executor = + std::make_unique(batch_write_thread_pool.release(), kTakesOwnership); + _batch_write_mgr = new BatchWriteMgr(std::move(batch_write_executor)); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _routine_load_task_executor = new RoutineLoadTaskExecutor(this); RETURN_IF_ERROR(_routine_load_task_executor->init()); @@ -515,6 +560,14 @@ Status ExecEnv::init(const std::vector& store_paths, bool as_cn) { _runtime_filter_cache = new RuntimeFilterCache(8); RETURN_IF_ERROR(_runtime_filter_cache->init()); _profile_report_worker = new ProfileReportWorker(this); +<<<<<<< HEAD +======= + auto runtime_filter_event_func = [] { + auto pool = ExecEnv::GetInstance()->runtime_filter_worker(); + return (pool == nullptr) ? 0U : pool->queue_size(); + }; + REGISTER_GAUGE_STARROCKS_METRIC(runtime_filter_event_queue_len, runtime_filter_event_func); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _backend_client_cache->init_metrics(StarRocksMetrics::instance()->metrics(), "backend"); _frontend_client_cache->init_metrics(StarRocksMetrics::instance()->metrics(), "frontend"); @@ -528,8 +581,13 @@ Status ExecEnv::init(const std::vector& store_paths, bool as_cn) { exit(-1); } +<<<<<<< HEAD #if defined(USE_STAROS) && !defined(BE_TEST) _lake_location_provider = new lake::StarletLocationProvider(); +======= +#if defined(USE_STAROS) && !defined(BE_TEST) && !defined(BUILD_FORMAT_LIB) + _lake_location_provider = std::make_shared(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _lake_update_manager = new lake::UpdateManager(_lake_location_provider, GlobalEnv::GetInstance()->update_mem_tracker()); _lake_tablet_manager = @@ -545,7 +603,11 @@ Status ExecEnv::init(const std::vector& store_paths, bool as_cn) { } #elif defined(BE_TEST) +<<<<<<< HEAD _lake_location_provider = new lake::FixedLocationProvider(_store_paths.front().path); +======= + _lake_location_provider = std::make_shared(_store_paths.front().path); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _lake_update_manager = new lake::UpdateManager(_lake_location_provider, GlobalEnv::GetInstance()->update_mem_tracker()); _lake_tablet_manager = @@ -570,11 +632,22 @@ Status ExecEnv::init(const std::vector& store_paths, bool as_cn) { _spill_dir_mgr = std::make_shared(); RETURN_IF_ERROR(_spill_dir_mgr->init(config::spill_local_storage_dir)); +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto jit_engine = JITEngine::get_instance(); status = jit_engine->init(); if (!status.ok()) { LOG(WARNING) << "Failed to init JIT engine: " << status.message(); } +<<<<<<< HEAD +======= +#endif + + RETURN_IF_ERROR(PythonEnvManager::getInstance().init(config::python_envs)); + PythonEnvManager::getInstance().start_background_cleanup_thread(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -657,6 +730,13 @@ void ExecEnv::stop() { _stream_mgr->close(); } +<<<<<<< HEAD +======= + if (_batch_write_mgr) { + _batch_write_mgr->stop(); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_routine_load_task_executor) { _routine_load_task_executor->stop(); } @@ -668,6 +748,11 @@ void ExecEnv::stop() { #ifndef BE_TEST close_s3_clients(); #endif +<<<<<<< HEAD +======= + + PythonEnvManager::getInstance().close(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void ExecEnv::destroy() { @@ -715,7 +800,10 @@ void ExecEnv::destroy() { SAFE_DELETE(_stream_mgr); SAFE_DELETE(_external_scan_context_mgr); SAFE_DELETE(_lake_tablet_manager); +<<<<<<< HEAD SAFE_DELETE(_lake_location_provider); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SAFE_DELETE(_lake_update_manager); SAFE_DELETE(_lake_replication_txn_manager); SAFE_DELETE(_cache_mgr); diff --git a/be/src/runtime/exec_env.h b/be/src/runtime/exec_env.h index 101cf8620320d..337f16c9b2bc5 100644 --- a/be/src/runtime/exec_env.h +++ b/be/src/runtime/exec_env.h @@ -61,6 +61,10 @@ class LoadPathMgr; class LoadStreamMgr; class StreamContextMgr; class TransactionMgr; +<<<<<<< HEAD +======= +class BatchWriteMgr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class MemTracker; class MetricRegistry; class StorageEngine; @@ -139,7 +143,10 @@ class GlobalEnv { MemTracker* short_key_index_mem_tracker() { return _short_key_index_mem_tracker.get(); } MemTracker* compaction_mem_tracker() { return _compaction_mem_tracker.get(); } MemTracker* schema_change_mem_tracker() { return _schema_change_mem_tracker.get(); } +<<<<<<< HEAD MemTracker* column_pool_mem_tracker() { return _column_pool_mem_tracker.get(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MemTracker* page_cache_mem_tracker() { return _page_cache_mem_tracker.get(); } MemTracker* jit_cache_mem_tracker() { return _jit_cache_mem_tracker.get(); } MemTracker* update_mem_tracker() { return _update_mem_tracker.get(); } @@ -149,6 +156,10 @@ class GlobalEnv { MemTracker* consistency_mem_tracker() { return _consistency_mem_tracker.get(); } MemTracker* replication_mem_tracker() { return _replication_mem_tracker.get(); } MemTracker* datacache_mem_tracker() { return _datacache_mem_tracker.get(); } +<<<<<<< HEAD +======= + MemTracker* poco_connection_pool_mem_tracker() { return _poco_connection_pool_mem_tracker.get(); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MemTracker* jemalloc_metadata_traker() { return _jemalloc_metadata_tracker.get(); } MemTracker* jemalloc_fragmentation_traker() { return _jemalloc_fragmentation_tracker.get(); } std::vector>& mem_trackers() { return _mem_trackers; } @@ -206,9 +217,12 @@ class GlobalEnv { // The memory used for schema change std::shared_ptr _schema_change_mem_tracker; +<<<<<<< HEAD // The memory used for column pool std::shared_ptr _column_pool_mem_tracker; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // The memory used for page cache std::shared_ptr _page_cache_mem_tracker; @@ -231,6 +245,12 @@ class GlobalEnv { // The memory used for datacache std::shared_ptr _datacache_mem_tracker; +<<<<<<< HEAD +======= + // The memory used for poco connection pool + std::shared_ptr _poco_connection_pool_mem_tracker; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector> _mem_trackers; }; @@ -298,6 +318,10 @@ class ExecEnv { SmallFileMgr* small_file_mgr() { return _small_file_mgr; } StreamContextMgr* stream_context_mgr() { return _stream_context_mgr; } TransactionMgr* transaction_mgr() { return _transaction_mgr; } +<<<<<<< HEAD +======= + BatchWriteMgr* batch_write_mgr() { return _batch_write_mgr; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& store_paths() const { return _store_paths; } @@ -327,7 +351,11 @@ class ExecEnv { lake::TabletManager* lake_tablet_manager() const { return _lake_tablet_manager; } +<<<<<<< HEAD lake::LocationProvider* lake_location_provider() const { return _lake_location_provider; } +======= + std::shared_ptr lake_location_provider() const { return _lake_location_provider; } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) lake::UpdateManager* lake_update_manager() const { return _lake_update_manager; } @@ -387,6 +415,10 @@ class ExecEnv { BrpcStubCache* _brpc_stub_cache = nullptr; StreamContextMgr* _stream_context_mgr = nullptr; TransactionMgr* _transaction_mgr = nullptr; +<<<<<<< HEAD +======= + BatchWriteMgr* _batch_write_mgr = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [[maybe_unused]] StorageEngine* _storage_engine = nullptr; @@ -403,7 +435,11 @@ class ExecEnv { ProfileReportWorker* _profile_report_worker = nullptr; lake::TabletManager* _lake_tablet_manager = nullptr; +<<<<<<< HEAD lake::LocationProvider* _lake_location_provider = nullptr; +======= + std::shared_ptr _lake_location_provider; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) lake::UpdateManager* _lake_update_manager = nullptr; lake::ReplicationTxnManager* _lake_replication_txn_manager = nullptr; diff --git a/be/src/runtime/file_result_writer.h b/be/src/runtime/file_result_writer.h index 7c758fb385453..c8439f82778cf 100644 --- a/be/src/runtime/file_result_writer.h +++ b/be/src/runtime/file_result_writer.h @@ -103,6 +103,11 @@ struct ResultFileOptions { }; // write result to file +<<<<<<< HEAD +======= +// used in no-pipeline or file_sink_operator +// won't used in result_sink_operator +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class FileResultWriter final : public ResultWriter { public: FileResultWriter(const ResultFileOptions* file_option, const std::vector& output_expr_ctxs, diff --git a/be/src/runtime/fragment_mgr.cpp b/be/src/runtime/fragment_mgr.cpp index dae5df005b3fc..c757ced97b0e7 100644 --- a/be/src/runtime/fragment_mgr.cpp +++ b/be/src/runtime/fragment_mgr.cpp @@ -65,6 +65,10 @@ #include "util/stopwatch.hpp" #include "util/thread.h" #include "util/threadpool.h" +<<<<<<< HEAD +======= +#include "util/thrift_rpc_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/thrift_util.h" #include "util/uid_util.h" #include "util/url_coding.h" @@ -81,10 +85,13 @@ std::string to_load_error_http_path(const std::string& file_name) { return url.str(); } +<<<<<<< HEAD using apache::thrift::TException; using apache::thrift::TProcessor; using apache::thrift::transport::TTransportException; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class RuntimeProfile; class FragmentExecState { @@ -94,14 +101,22 @@ class FragmentExecState { ~FragmentExecState(); +<<<<<<< HEAD [[nodiscard]] Status prepare(const TExecPlanFragmentParams& params); +======= + Status prepare(const TExecPlanFragmentParams& params); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // just no use now void callback(const Status& status, RuntimeProfile* profile, bool done); std::string to_http_path(const std::string& file_name); +<<<<<<< HEAD [[nodiscard]] Status execute(); +======= + Status execute(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void cancel(const PPlanFragmentCancelReason& reason); @@ -120,7 +135,11 @@ class FragmentExecState { int backend_num() const { return _backend_num; } // Update status of this fragment execute +<<<<<<< HEAD [[nodiscard]] Status update_status(const Status& status) { +======= + Status update_status(const Status& status) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(_status_lock); if (!status.ok() && _exec_status.ok()) { _exec_status = status; @@ -237,6 +256,7 @@ void FragmentExecState::coordinator_callback(const Status& status, RuntimeProfil DCHECK(status.ok() || done); // if !status.ok() => done Status exec_status = update_status(status); +<<<<<<< HEAD Status coord_status; FrontendServiceConnection coord(_exec_env->frontend_client_cache(), _coord_addr, config::thrift_rpc_timeout_ms, &coord_status); @@ -248,6 +268,8 @@ void FragmentExecState::coordinator_callback(const Status& status, RuntimeProfil return; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TReportExecStatusParams params; params.protocol_version = FrontendServiceVersion::V1; params.__set_query_id(_query_id); @@ -309,10 +331,13 @@ void FragmentExecState::coordinator_callback(const Status& status, RuntimeProfil if (!runtime_state->tablet_fail_infos().empty()) { params.__set_failInfos(runtime_state->tablet_fail_infos()); } +<<<<<<< HEAD // Send new errors to coordinator runtime_state->get_unreported_errors(&(params.error_log)); params.__isset.error_log = (params.error_log.size() > 0); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } auto backend_id = get_backend_id(); @@ -324,6 +349,7 @@ void FragmentExecState::coordinator_callback(const Status& status, RuntimeProfil Status rpc_status; VLOG_ROW << "debug: reportExecStatus params is " << apache::thrift::ThriftDebugString(params).c_str(); +<<<<<<< HEAD try { try { coord->reportExecStatus(res, params); @@ -347,6 +373,16 @@ void FragmentExecState::coordinator_callback(const Status& status, RuntimeProfil msg << "ReportExecStatus() to " << _coord_addr << " failed:\n" << e.what(); LOG(WARNING) << msg.str(); rpc_status = Status::InternalError(msg.str()); +======= + + rpc_status = ThriftRpcHelper::rpc( + _coord_addr.hostname, _coord_addr.port, + [&res, ¶ms](FrontendServiceConnection& client) { client->reportExecStatus(res, params); }, + config::thrift_rpc_timeout_ms); + + if (rpc_status.ok()) { + rpc_status = Status(res.status); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if (!rpc_status.ok()) { @@ -703,6 +739,7 @@ void FragmentMgr::report_fragments(const std::vector& non_pipeline_ne continue; } +<<<<<<< HEAD Status fe_connection_status; FrontendServiceConnection fe_connection(fragment_exec_state->exec_env()->frontend_client_cache(), @@ -719,6 +756,8 @@ void FragmentMgr::report_fragments(const std::vector& non_pipeline_ne continue; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector report_exec_status_params_vector; TReportExecStatusParams params; @@ -756,6 +795,7 @@ void FragmentMgr::report_fragments(const std::vector& non_pipeline_ne Status rpc_status; VLOG_ROW << "debug: reportExecStatus params is " << apache::thrift::ThriftDebugString(params).c_str(); +<<<<<<< HEAD try { try { fe_connection->batchReportExecStatus(res, report_batch); @@ -773,6 +813,18 @@ void FragmentMgr::report_fragments(const std::vector& non_pipeline_ne std::stringstream msg; msg << "ReportExecStatus() to " << fragment_exec_state->coord_addr() << " failed:\n" << e.what(); LOG(WARNING) << msg.str(); +======= + rpc_status = ThriftRpcHelper::rpc( + fragment_exec_state->coord_addr(), + [&res, &report_batch](FrontendServiceConnection& client) { + client->batchReportExecStatus(res, report_batch); + }, + config::thrift_rpc_timeout_ms); + + if (!rpc_status.ok()) { + LOG(WARNING) << "thrift rpc error:" << rpc_status; + continue; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } const std::vector& status_list = res.status_list; @@ -875,7 +927,11 @@ Status FragmentMgr::exec_external_plan_fragment(const TScanOpenParams& params, c LOG(WARNING) << "tuple descriptor is null. id: " << slot_ref.tuple_id; return Status::InvalidArgument("tuple descriptor is null"); } +<<<<<<< HEAD auto* slot_desc = desc_tbl->get_slot_descriptor(slot_ref.slot_id); +======= + auto* slot_desc = desc_tbl->get_slot_descriptor_with_column(slot_ref.slot_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (slot_desc == nullptr) { LOG(WARNING) << "slot descriptor is null. id: " << slot_ref.slot_id; return Status::InvalidArgument("slot descriptor is null"); @@ -950,7 +1006,10 @@ Status FragmentMgr::exec_external_plan_fragment(const TScanOpenParams& params, c query_options.query_type = TQueryType::EXTERNAL; // For spark sql / flink sql, we dont use page cache. query_options.use_page_cache = false; +<<<<<<< HEAD query_options.use_column_pool = false; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) query_options.enable_profile = config::enable_profile_for_external_plan; exec_fragment_params.__set_query_options(query_options); VLOG_ROW << "external exec_plan_fragment params is " diff --git a/be/src/runtime/fragment_mgr.h b/be/src/runtime/fragment_mgr.h index 3ecc7da949e0c..ae00b3564730d 100644 --- a/be/src/runtime/fragment_mgr.h +++ b/be/src/runtime/fragment_mgr.h @@ -72,6 +72,7 @@ class FragmentMgr : public RestMonitorIface { ~FragmentMgr() override; // execute one plan fragment +<<<<<<< HEAD [[nodiscard]] Status exec_plan_fragment(const TExecPlanFragmentParams& params); [[nodiscard]] Status exec_plan_fragment(const TExecPlanFragmentParams& params, const FinishCallback& cb); @@ -87,6 +88,23 @@ class FragmentMgr : public RestMonitorIface { } [[nodiscard]] Status cancel(const TUniqueId& fragment_id, const PPlanFragmentCancelReason& reason); +======= + Status exec_plan_fragment(const TExecPlanFragmentParams& params); + + Status exec_plan_fragment(const TExecPlanFragmentParams& params, const FinishCallback& cb); + + // TODO(zc): report this is over + Status exec_plan_fragment(const TExecPlanFragmentParams& params, const StartSuccCallback& start_cb, + const FinishCallback& cb); + + void close(); + + Status cancel(const TUniqueId& fragment_id) { + return cancel(fragment_id, PPlanFragmentCancelReason::INTERNAL_ERROR); + } + + Status cancel(const TUniqueId& fragment_id, const PPlanFragmentCancelReason& reason); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void receive_runtime_filter(const PTransmitRuntimeFilterParams& params, const std::shared_ptr& shared_rf); @@ -95,7 +113,11 @@ class FragmentMgr : public RestMonitorIface { void debug(std::stringstream& ss) override; +<<<<<<< HEAD [[nodiscard]] Status trigger_profile_report(const PTriggerProfileReportRequest* request); +======= + Status trigger_profile_report(const PTriggerProfileReportRequest* request); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void report_fragments(const std::vector& non_pipeline_need_report_fragment_ids); @@ -107,10 +129,15 @@ class FragmentMgr : public RestMonitorIface { // input: TScanOpenParams fragment_instance_id // output: selected_columns, query_id parsed from params // execute external query, all query info are packed in TScanOpenParams +<<<<<<< HEAD [[nodiscard]] Status exec_external_plan_fragment(const TScanOpenParams& params, const TUniqueId& fragment_instance_id, std::vector* selected_columns, TUniqueId* query_id); +======= + Status exec_external_plan_fragment(const TScanOpenParams& params, const TUniqueId& fragment_instance_id, + std::vector* selected_columns, TUniqueId* query_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t running_fragment_count() const { std::lock_guard lock(_lock); return _fragment_map.size(); diff --git a/be/src/runtime/global_dict/miscs.cpp b/be/src/runtime/global_dict/miscs.cpp index 3380e54c242bd..9fc335f775734 100644 --- a/be/src/runtime/global_dict/miscs.cpp +++ b/be/src/runtime/global_dict/miscs.cpp @@ -40,7 +40,11 @@ std::pair, std::vector> extract_column_ slices.emplace_back(slice); codes.emplace_back(code); } +<<<<<<< HEAD res->append_strings(slices); +======= + res->append_strings(slices.data(), slices.size()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) res->set_null(0); return std::make_pair(std::move(res), std::move(codes)); } diff --git a/be/src/runtime/global_dict/parser.cpp b/be/src/runtime/global_dict/parser.cpp index 0c11ba60fefce..4efc268ede182 100644 --- a/be/src/runtime/global_dict/parser.cpp +++ b/be/src/runtime/global_dict/parser.cpp @@ -202,7 +202,11 @@ class DictFuncExpr final : public Expr { } // res[i] = mapping[index[i]] +<<<<<<< HEAD std::vector _code_convert(const std::vector& index, const std::vector& mapping) { +======= + std::vector _code_convert(const Buffer& index, const std::vector& mapping) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector res(index.size()); SIMDGather::gather(res.data(), mapping.data(), index.data(), mapping.size(), index.size()); return res; diff --git a/be/src/runtime/global_dict/parser.h b/be/src/runtime/global_dict/parser.h index 0dab7951e8735..d512137ac4a87 100644 --- a/be/src/runtime/global_dict/parser.h +++ b/be/src/runtime/global_dict/parser.h @@ -55,6 +55,7 @@ class DictOptimizeParser { _mutable_dict_maps = dict_maps; } +<<<<<<< HEAD [[nodiscard]] Status init_dict_exprs(const std::map& exprs); [[nodiscard]] Status rewrite_expr(ExprContext* ctx, Expr* expr, SlotId slot_id); @@ -65,6 +66,17 @@ class DictOptimizeParser { int32_t targetSlotId); [[nodiscard]] Status eval_dict_expr(SlotId id); +======= + Status init_dict_exprs(const std::map& exprs); + + Status rewrite_expr(ExprContext* ctx, Expr* expr, SlotId slot_id); + + Status rewrite_conjuncts(std::vector* conjuncts_ctxs); + + Status eval_expression(ExprContext* conjunct, DictOptimizeContext* dict_opt_ctx, int32_t targetSlotId); + + Status eval_dict_expr(SlotId id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void close() noexcept; @@ -85,9 +97,14 @@ class DictOptimizeParser { void _check_could_apply_dict_optimize(Expr* expr, DictOptimizeContext* dict_opt_ctx); // use code mapping rewrite expr +<<<<<<< HEAD [[nodiscard]] Status _rewrite_expr_ctxs(std::vector* expr_ctxs, const std::vector& slot_ids); [[nodiscard]] Status _eval_and_rewrite(ExprContext* ctx, Expr* expr, DictOptimizeContext* dict_opt_ctx, int32_t targetSlotId); +======= + Status _rewrite_expr_ctxs(std::vector* expr_ctxs, const std::vector& slot_ids); + Status _eval_and_rewrite(ExprContext* ctx, Expr* expr, DictOptimizeContext* dict_opt_ctx, int32_t targetSlotId); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeState* _runtime_state = nullptr; GlobalDictMaps* _mutable_dict_maps = nullptr; diff --git a/be/src/runtime/global_variables.cpp b/be/src/runtime/global_variables.cpp new file mode 100644 index 0000000000000..7de24d9ad4721 --- /dev/null +++ b/be/src/runtime/global_variables.cpp @@ -0,0 +1,27 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/global_variables.h" + +namespace starrocks { + +bool GlobalVariables::_is_init = false; + +GlobalVariables::GlobalVariables() { + _one_size_not_null_column = NullColumn::create(1, 0); + _one_size_null_column = NullColumn::create(1, 1); + _is_init = true; +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/global_variables.h b/be/src/runtime/global_variables.h new file mode 100644 index 0000000000000..a650a831d54b5 --- /dev/null +++ b/be/src/runtime/global_variables.h @@ -0,0 +1,48 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "column/nullable_column.h" +#include "common/status.h" + +namespace starrocks { + +class GlobalVariables { +public: + static GlobalVariables* GetInstance() { + static GlobalVariables s_global_vars; + return &s_global_vars; + } + + GlobalVariables(); + ~GlobalVariables() { _is_init = false; } + + bool is_init() const { return _is_init; } + + const NullColumnPtr& one_size_not_null_column() const { + DCHECK(_is_init); + return _one_size_not_null_column; + } + const NullColumnPtr& one_size_null_column() const { + DCHECK(_is_init); + return _one_size_null_column; + } + +private: + static bool _is_init; + NullColumnPtr _one_size_not_null_column; + NullColumnPtr _one_size_null_column; +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/http_result_writer.cpp b/be/src/runtime/http_result_writer.cpp index d1fbd096f1d3c..652611e702bab 100644 --- a/be/src/runtime/http_result_writer.cpp +++ b/be/src/runtime/http_result_writer.cpp @@ -30,9 +30,14 @@ namespace starrocks { HttpResultWriter::HttpResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile, TResultSinkFormatType::type format_type) +<<<<<<< HEAD : _sinker(sinker), _output_expr_ctxs(output_expr_ctxs), _parent_profile(parent_profile), +======= + : BufferControlResultWriter(sinker, parent_profile), + _output_expr_ctxs(output_expr_ctxs), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _format_type(format_type) {} Status HttpResultWriter::init(RuntimeState* state) { @@ -44,6 +49,7 @@ Status HttpResultWriter::init(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD void HttpResultWriter::_init_profile() { _append_chunk_timer = ADD_TIMER(_parent_profile, "AppendChunkTime"); _convert_tuple_timer = ADD_CHILD_TIMER(_parent_profile, "TupleConvertTime", "AppendChunkTime"); @@ -51,6 +57,8 @@ void HttpResultWriter::_init_profile() { _sent_rows_counter = ADD_COUNTER(_parent_profile, "NumSentRows", TUnit::UNIT); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // transform one row into json format Status HttpResultWriter::_transform_row_to_json(const Columns& result_columns, int idx) { int num_columns = result_columns.size(); @@ -72,11 +80,14 @@ Status HttpResultWriter::append_chunk(Chunk* chunk) { return Status::NotSupported("HttpResultWriter doesn't support non-pipeline engine"); } +<<<<<<< HEAD Status HttpResultWriter::close() { COUNTER_SET(_sent_rows_counter, _written_rows); return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr HttpResultWriter::process_chunk(Chunk* chunk) { SCOPED_TIMER(_append_chunk_timer); int num_rows = chunk->num_rows(); @@ -146,6 +157,7 @@ StatusOr HttpResultWriter::process_chunk(Chunk* chunk) { return results; } +<<<<<<< HEAD StatusOr HttpResultWriter::try_add_batch(TFetchDataResultPtrs& results) { SCOPED_TIMER(_result_send_timer); size_t num_rows = 0; @@ -167,4 +179,6 @@ StatusOr HttpResultWriter::try_add_batch(TFetchDataResultPtrs& results) { return status; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/http_result_writer.h b/be/src/runtime/http_result_writer.h index aace2f5f01405..678723cb9be2d 100644 --- a/be/src/runtime/http_result_writer.h +++ b/be/src/runtime/http_result_writer.h @@ -33,10 +33,15 @@ // under the License. #pragma once +<<<<<<< HEAD #include "common/statusor.h" #include "runtime/result_writer.h" #include "runtime/runtime_state.h" +======= +#include "runtime/buffer_control_result_writer.h" +#include "runtime/result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/raw_container.h" namespace starrocks { @@ -47,7 +52,11 @@ class RuntimeProfile; using TFetchDataResultPtr = std::unique_ptr; using TFetchDataResultPtrs = std::vector; // convert the row batch to mysql protocol row +<<<<<<< HEAD class HttpResultWriter final : public ResultWriter { +======= +class HttpResultWriter final : public BufferControlResultWriter { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: HttpResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile, TResultSinkFormatType::type format_type); @@ -56,6 +65,7 @@ class HttpResultWriter final : public ResultWriter { Status append_chunk(Chunk* chunk) override; +<<<<<<< HEAD Status close() override; StatusOr process_chunk(Chunk* chunk) override; @@ -80,6 +90,16 @@ class HttpResultWriter final : public ResultWriter { RuntimeProfile::Counter* _result_send_timer = nullptr; // number of sent rows RuntimeProfile::Counter* _sent_rows_counter = nullptr; +======= + StatusOr process_chunk(Chunk* chunk) override; + +private: + Status _transform_row_to_json(const Columns& column, int idx); + + const std::vector& _output_expr_ctxs; + + raw::RawString _row_str; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const size_t _max_row_buffer_size = 1024 * 1024 * 1024; diff --git a/be/src/runtime/lake_snapshot_loader.cpp b/be/src/runtime/lake_snapshot_loader.cpp index dec91b4e6797f..43fc60a52a388 100644 --- a/be/src/runtime/lake_snapshot_loader.cpp +++ b/be/src/runtime/lake_snapshot_loader.cpp @@ -14,7 +14,10 @@ #include +<<<<<<< HEAD #include "common/config.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fs/fs_broker.h" #include "fs/fs_util.h" #include "gen_cpp/TFileBrokerService.h" diff --git a/be/src/runtime/lake_tablets_channel.cpp b/be/src/runtime/lake_tablets_channel.cpp index c81b848d932ab..6814336abb29d 100644 --- a/be/src/runtime/lake_tablets_channel.cpp +++ b/be/src/runtime/lake_tablets_channel.cpp @@ -17,8 +17,11 @@ #include #include +<<<<<<< HEAD #include #include +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include @@ -69,8 +72,13 @@ class LakeTabletsChannel : public TabletsChannel { Status open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema, bool is_incremental) override; +<<<<<<< HEAD void add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response) override; +======= + void add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response, + bool* close_channel_ptr) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status incremental_open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema) override; @@ -81,6 +89,13 @@ class LakeTabletsChannel : public TabletsChannel { void abort(const std::vector& tablet_ids, const std::string& reason) override { return abort(); } +<<<<<<< HEAD +======= + void update_profile() override { + // TODO add profile for lake + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MemTracker* mem_tracker() { return _mem_tracker; } private: @@ -120,9 +135,18 @@ class LakeTabletsChannel : public TabletsChannel { info->set_schema_hash(0); // required field } +<<<<<<< HEAD void add_txn_log(const TxnLogPtr& txn_log) { std::lock_guard l(_mtx); _response->mutable_lake_tablet_data()->add_txn_logs()->CopyFrom(*txn_log); +======= + // NOT thread-safe + void add_txn_logs(const std::vector& logs) { + _response->mutable_lake_tablet_data()->mutable_txn_logs()->Reserve(logs.size()); + for (auto& log : logs) { + _response->mutable_lake_tablet_data()->add_txn_logs()->CopyFrom(*log); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } private: @@ -136,19 +160,77 @@ class LakeTabletsChannel : public TabletsChannel { std::unique_ptr _channel_row_idx_start_points; }; +<<<<<<< HEAD // called by open() or incremental_open to build AsyncDeltaWriter for tablets Status _create_delta_writers(const PTabletWriterOpenRequest& params, bool is_incremental); Status _build_chunk_meta(const ChunkPB& pb_chunk); +======= + class TxnLogCollector { + public: + void add(TxnLogPtr log) { + std::lock_guard l(_mtx); + _logs.emplace_back(std::move(log)); + } + + void update_status(const Status& st) { + std::lock_guard l(_mtx); + _st.update(st); + } + + Status status() const { + std::lock_guard l(_mtx); + return _st; + } + + std::vector logs() { + std::lock_guard l(_mtx); + return _logs; + } + + // Returns true on notified, false on timeout + bool wait(int64_t timeout_ms) { + std::unique_lock l(_mtx); + while (!_notified) { + if (_cond.wait_for(l, timeout_ms * 1000L) == ETIMEDOUT) { + return false; + } + } + return true; + } + + void notify() { + { + std::lock_guard l(_mtx); + _notified = true; + } + _cond.notify_all(); + } + + private: + mutable bthread::Mutex _mtx; + bthread::ConditionVariable _cond; + std::vector _logs; + Status _st; + bool _notified{false}; + }; + + // called by open() or incremental_open to build AsyncDeltaWriter for tablets + Status _create_delta_writers(const PTabletWriterOpenRequest& params, bool is_incremental); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr> _create_write_context(Chunk* chunk, const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response); int _close_sender(const int64_t* partitions, size_t partitions_size); +<<<<<<< HEAD Status _deserialize_chunk(const ChunkPB& pchunk, Chunk& chunk, faststring* uncompressed_buffer); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void _flush_stale_memtables(); LoadChannel* _load_channel; @@ -185,7 +267,11 @@ class LakeTabletsChannel : public TabletsChannel { std::unique_ptr _mem_pool; bool _is_incremental_channel{false}; lake::DeltaWriterFinishMode _finish_mode{lake::DeltaWriterFinishMode::kWriteTxnLog}; +<<<<<<< HEAD +======= + TxnLogCollector _txn_log_collector; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::set _immutable_partition_ids; std::map _column_to_expr_value; @@ -234,6 +320,10 @@ LakeTabletsChannel::~LakeTabletsChannel() { Status LakeTabletsChannel::open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema, bool is_incremental) { +<<<<<<< HEAD +======= + DCHECK_EQ(-1, _txn_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) SCOPED_TIMER(_open_timer); COUNTER_UPDATE(_open_counter, 1); std::unique_lock l(_rw_mtx); @@ -284,7 +374,13 @@ Status LakeTabletsChannel::open(const PTabletWriterOpenRequest& params, PTabletW } void LakeTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, +<<<<<<< HEAD PTabletWriterAddBatchResult* response) { +======= + PTabletWriterAddBatchResult* response, bool* close_channel_ptr) { + bool& close_channel = *close_channel_ptr; + close_channel = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MonotonicStopWatch watch; watch.start(); std::shared_lock rolk(_rw_mtx); @@ -405,8 +501,11 @@ void LakeTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequ // _channel_row_idx_start_points no longer used, free its memory. context->_channel_row_idx_start_points.reset(); +<<<<<<< HEAD bool close_channel = false; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Submit `AsyncDeltaWriter::finish()` tasks if needed if (request.eos()) { int unfinished_senders = _close_sender(request.partition_ids().data(), request.partition_ids().size()); @@ -433,6 +532,7 @@ void LakeTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequ if (!res.ok()) { context->update_status(res.status()); LOG(ERROR) << "Fail to finish tablet " << id << ": " << res.status(); +<<<<<<< HEAD } else if (_finish_mode == lake::DeltaWriterFinishMode::kWriteTxnLog) { context->add_finished_tablet(id); VLOG(5) << "Finished tablet " << id; @@ -442,6 +542,18 @@ void LakeTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequ VLOG(5) << "Finished tablet " << id; } else { CHECK(false) << "Unhandled finish mode: " << _finish_mode; +======= + } else { + context->add_finished_tablet(id); + VLOG(5) << "Finished tablet " << id; + } + if (_finish_mode == lake::DeltaWriterFinishMode::kDontWriteTxnLog) { + if (!res.ok()) { + _txn_log_collector.update_status(res.status()); + } else { + _txn_log_collector.add(std::move(res).value()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } count_down_latch.count_down(); }); @@ -505,6 +617,26 @@ void LakeTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequ if (close_channel) { _load_channel->remove_tablets_channel(_key); +<<<<<<< HEAD +======= + if (_finish_mode == lake::DeltaWriterFinishMode::kDontWriteTxnLog) { + _txn_log_collector.notify(); + } + } + + // Sender 0 is responsible for waiting for all other senders to finish and collecting txn logs + if (_finish_mode == lake::kDontWriteTxnLog && request.eos() && (request.sender_id() == 0) && + response->status().status_code() == TStatusCode::OK) { + rolk.unlock(); + auto t = request.timeout_ms() - (int64_t)(watch.elapsed_time() / 1000 / 1000); + auto ok = _txn_log_collector.wait(t); + auto st = ok ? _txn_log_collector.status() : Status::TimedOut(fmt::format("wait txn log timed out: {}", t)); + if (st.ok()) { + context->add_txn_logs(_txn_log_collector.logs()); + } else { + context->update_status(st); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } diff --git a/be/src/runtime/load_channel.cpp b/be/src/runtime/load_channel.cpp index 9d7e513967ffb..5b1a0c9d5df1e 100644 --- a/be/src/runtime/load_channel.cpp +++ b/be/src/runtime/load_channel.cpp @@ -83,6 +83,14 @@ LoadChannel::LoadChannel(LoadChannelMgr* mgr, LakeTabletManager* lake_tablet_mgr _index_num = ADD_COUNTER(_profile, "IndexNum", TUnit::UNIT); ADD_COUNTER(_profile, "LoadMemoryLimit", TUnit::BYTES)->set(_mem_tracker->limit()); _peak_memory_usage = ADD_PEAK_COUNTER(_profile, "PeakMemoryUsage", TUnit::BYTES); +<<<<<<< HEAD +======= + _deserialize_chunk_count = ADD_COUNTER(_profile, "DeserializeChunkCount", TUnit::UNIT); + _deserialize_chunk_timer = ADD_TIMER(_profile, "DeserializeChunkTime"); + _profile_report_count = ADD_COUNTER(_profile, "ProfileReportCount", TUnit::UNIT); + _profile_report_timer = ADD_TIMER(_profile, "ProfileReportTime"); + _profile_serialized_size = ADD_COUNTER(_profile, "ProfileSerializedSize", TUnit::BYTES); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } LoadChannel::~LoadChannel() { @@ -164,7 +172,18 @@ void LoadChannel::_add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& r fmt::format("cannot find the tablets channel associated with the key {}", key.to_string())); return; } +<<<<<<< HEAD channel->add_chunk(chunk, request, response); +======= + bool close_channel; + channel->add_chunk(chunk, request, response, &close_channel); + if (close_channel && _should_enable_profile()) { + // If close_channel is true, the channel has been removed from _tablets_channels + // in TabletsChannel::add_chunk, so there will be no chance to get the channel to + // update the profile later. So update the profile here + channel->update_profile(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void LoadChannel::add_chunk(const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response) { @@ -306,6 +325,11 @@ Status LoadChannel::_build_chunk_meta(const ChunkPB& pb_chunk) { } Status LoadChannel::_deserialize_chunk(const ChunkPB& pchunk, Chunk& chunk, faststring* uncompressed_buffer) { +<<<<<<< HEAD +======= + COUNTER_UPDATE(_deserialize_chunk_count, 1); + SCOPED_TIMER(_deserialize_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (pchunk.compress_type() == CompressionTypePB::NO_COMPRESSION) { TRY_CATCH_BAD_ALLOC({ serde::ProtobufChunkDeserializer des(_chunk_meta); @@ -337,6 +361,7 @@ Status LoadChannel::_deserialize_chunk(const ChunkPB& pchunk, Chunk& chunk, fast return Status::OK(); } +<<<<<<< HEAD void LoadChannel::report_profile(PTabletWriterAddBatchResult* result, bool print_profile) { // report profile if enable profile or the query has run for a long time if (!_enable_profile) { @@ -350,6 +375,41 @@ void LoadChannel::report_profile(PTabletWriterAddBatchResult* result, bool print } int64_t last_report_tims_ns = _last_report_time_ns.load(); +======= +std::vector> LoadChannel::_get_all_channels() { + std::vector> channels; + std::lock_guard l(_lock); + channels.reserve(_tablets_channels.size()); + for (auto& it : _tablets_channels) { + channels.push_back(it.second); + } + return channels; +} + +bool LoadChannel::_should_enable_profile() { + if (_enable_profile) { + return true; + } + if (_big_query_profile_threshold_ns <= 0) { + return false; + } + int64_t query_run_duration = MonotonicNanos() - _create_time_ns; + return query_run_duration > _big_query_profile_threshold_ns; +} + +void LoadChannel::report_profile(PTabletWriterAddBatchResult* result, bool print_profile) { + if (!_should_enable_profile()) { + return; + } + + bool expect = false; + if (!_is_reporting_profile.compare_exchange_strong(expect, true)) { + // skip concurrent report + return; + } + DeferOp defer([this]() { _is_reporting_profile.store(false); }); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t now = MonotonicNanos(); bool should_report; if (_closed) { @@ -357,15 +417,32 @@ void LoadChannel::report_profile(PTabletWriterAddBatchResult* result, bool print bool old = false; should_report = _final_report.compare_exchange_strong(old, true); } else { +<<<<<<< HEAD // runtime profile report bool time_to_report = now - last_report_tims_ns >= _runtime_profile_report_interval_ns; should_report = time_to_report && _last_report_time_ns.compare_exchange_strong(last_report_tims_ns, now); +======= + // runtime profile report periodically + should_report = now - _last_report_time_ns >= _runtime_profile_report_interval_ns; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } if (!should_report) { return; } +<<<<<<< HEAD COUNTER_SET(_peak_memory_usage, _mem_tracker->peak_consumption()); +======= + _last_report_time_ns.store(now); + COUNTER_UPDATE(_profile_report_count, 1); + SCOPED_TIMER(_profile_report_timer); + + COUNTER_SET(_peak_memory_usage, _mem_tracker->peak_consumption()); + auto channels = _get_all_channels(); + for (auto& channel : channels) { + channel->update_profile(); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _profile->inc_version(); if (print_profile) { @@ -385,6 +462,10 @@ void LoadChannel::report_profile(PTabletWriterAddBatchResult* result, bool print << ", status: " << st; return; } +<<<<<<< HEAD +======= + COUNTER_UPDATE(_profile_serialized_size, len); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) result->set_load_channel_profile((char*)buf, len); } } // namespace starrocks diff --git a/be/src/runtime/load_channel.h b/be/src/runtime/load_channel.h index 630d5d3395309..7dfd6c9081ee0 100644 --- a/be/src/runtime/load_channel.h +++ b/be/src/runtime/load_channel.h @@ -126,6 +126,11 @@ class LoadChannel { void _add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response); Status _build_chunk_meta(const ChunkPB& pb_chunk); Status _deserialize_chunk(const ChunkPB& pchunk, Chunk& chunk, faststring* uncompressed_buffer); +<<<<<<< HEAD +======= + bool _should_enable_profile(); + std::vector> _get_all_channels(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) LoadChannelMgr* _load_mgr; LakeTabletManager* _lake_tablet_mgr; @@ -163,9 +168,21 @@ class LoadChannel { int64_t _runtime_profile_report_interval_ns = std::numeric_limits::max(); std::atomic _last_report_time_ns{0}; std::atomic _final_report{false}; +<<<<<<< HEAD RuntimeProfile::Counter* _index_num = nullptr; RuntimeProfile::Counter* _peak_memory_usage = nullptr; +======= + std::atomic _is_reporting_profile{false}; + + RuntimeProfile::Counter* _index_num = nullptr; + RuntimeProfile::Counter* _peak_memory_usage = nullptr; + RuntimeProfile::Counter* _deserialize_chunk_count = nullptr; + RuntimeProfile::Counter* _deserialize_chunk_timer = nullptr; + RuntimeProfile::Counter* _profile_report_count = nullptr; + RuntimeProfile::Counter* _profile_report_timer = nullptr; + RuntimeProfile::Counter* _profile_serialized_size = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; inline std::ostream& operator<<(std::ostream& os, const LoadChannel& load_channel) { diff --git a/be/src/runtime/load_path_mgr.cpp b/be/src/runtime/load_path_mgr.cpp index 19c8111ce5b71..71105656c0221 100644 --- a/be/src/runtime/load_path_mgr.cpp +++ b/be/src/runtime/load_path_mgr.cpp @@ -146,7 +146,10 @@ void LoadPathMgr::get_load_data_path(std::vector* data_paths) { } const std::string ERROR_FILE_NAME = "error_log"; +<<<<<<< HEAD const std::string REJECTED_RECORD_FILE_NAME = "rejected_record"; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status LoadPathMgr::get_load_error_file_name(const TUniqueId& fragment_instance_id, std::string* error_path) { std::stringstream ss; diff --git a/be/src/runtime/local_tablets_channel.cpp b/be/src/runtime/local_tablets_channel.cpp index b4d1e1a64eaf2..db2fbfb3b61ee 100644 --- a/be/src/runtime/local_tablets_channel.cpp +++ b/be/src/runtime/local_tablets_channel.cpp @@ -16,6 +16,10 @@ #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -67,6 +71,7 @@ LocalTabletsChannel::LocalTabletsChannel(LoadChannel* load_channel, const Tablet }); _profile = parent_profile->create_child(fmt::format("Index (id={})", key.index_id)); +<<<<<<< HEAD _primary_tablets_num = ADD_COUNTER(_profile, "PrimaryTabletsNum", TUnit::UNIT); _secondary_tablets_num = ADD_COUNTER(_profile, "SecondaryTabletsNum", TUnit::UNIT); _open_counter = ADD_COUNTER(_profile, "OpenCount", TUnit::UNIT); @@ -78,6 +83,20 @@ LocalTabletsChannel::LocalTabletsChannel(LoadChannel* load_channel, const Tablet _wait_write_timer = ADD_CHILD_TIMER(_profile, "WaitWriteTime", "AddChunkTime"); _wait_replica_timer = ADD_CHILD_TIMER(_profile, "WaitReplicaTime", "AddChunkTime"); _wait_txn_persist_timer = ADD_CHILD_TIMER(_profile, "WaitTxnPersistTime", "AddChunkTime"); +======= + _profile_update_counter = ADD_COUNTER(_profile, "ProfileUpdateCount", TUnit::UNIT); + _profile_update_timer = ADD_TIMER(_profile, "ProfileUpdateTime"); + _open_counter = ADD_COUNTER(_profile, "OpenRpcCount", TUnit::UNIT); + _open_timer = ADD_TIMER(_profile, "OpenRpcTime"); + _add_chunk_counter = ADD_COUNTER(_profile, "AddChunkRpcCount", TUnit::UNIT); + _add_row_num = ADD_COUNTER(_profile, "AddRowNum", TUnit::UNIT); + _add_chunk_timer = ADD_TIMER(_profile, "AddChunkRpcTime"); + _wait_flush_timer = ADD_CHILD_TIMER(_profile, "WaitFlushTime", "AddChunkRpcTime"); + _wait_write_timer = ADD_CHILD_TIMER(_profile, "WaitWriteTime", "AddChunkRpcTime"); + _wait_replica_timer = ADD_CHILD_TIMER(_profile, "WaitReplicaTime", "AddChunkRpcTime"); + _wait_txn_persist_timer = ADD_CHILD_TIMER(_profile, "WaitTxnPersistTime", "AddChunkRpcTime"); + _tablets_profile = std::make_unique("TabletsProfile"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } LocalTabletsChannel::~LocalTabletsChannel() { @@ -150,7 +169,13 @@ void LocalTabletsChannel::add_segment(brpc::Controller* cntl, const PTabletWrite } void LocalTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, +<<<<<<< HEAD PTabletWriterAddBatchResult* response) { +======= + PTabletWriterAddBatchResult* response, bool* close_channel_ptr) { + bool& close_channel = *close_channel_ptr; + close_channel = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MonotonicStopWatch watch; watch.start(); std::shared_lock lk(_rw_mtx); @@ -295,8 +320,11 @@ void LocalTabletsChannel::add_chunk(Chunk* chunk, const PTabletWriterAddChunkReq // _channel_row_idx_start_points no longer used, release it to free memory. context->_channel_row_idx_start_points.reset(); +<<<<<<< HEAD bool close_channel = false; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // NOTE: Must close sender *AFTER* the write requests submitted, otherwise a delta writer commit request may // be executed ahead of the write requests submitted by other senders. if (request.eos() && _close_sender(request.partition_ids().data(), request.partition_ids_size()) == 0) { @@ -652,8 +680,11 @@ Status LocalTabletsChannel::_open_all_writers(const PTabletWriterOpenRequest& pa std::vector tablet_ids; tablet_ids.reserve(params.tablets_size()); std::vector failed_tablet_ids; +<<<<<<< HEAD int32_t primary_num = 0; int32_t secondary_num = 0; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (const PTabletWithPartition& tablet : params.tablets()) { DeltaWriterOptions options; options.tablet_id = tablet.tablet_id(); @@ -681,6 +712,7 @@ Status LocalTabletsChannel::_open_all_writers(const PTabletWriterOpenRequest& pa } if (options.replicas.size() > 0 && options.replicas[0].node_id() == options.node_id) { options.replica_state = Primary; +<<<<<<< HEAD primary_num += 1; } else { options.replica_state = Secondary; @@ -689,6 +721,13 @@ Status LocalTabletsChannel::_open_all_writers(const PTabletWriterOpenRequest& pa } else { options.replica_state = Peer; primary_num += 1; +======= + } else { + options.replica_state = Secondary; + } + } else { + options.replica_state = Peer; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } options.merge_condition = params.merge_condition(); options.partial_update_mode = params.partial_update_mode(); @@ -734,8 +773,11 @@ Status LocalTabletsChannel::_open_all_writers(const PTabletWriterOpenRequest& pa ss << " _num_remaining_senders: " << _num_remaining_senders; LOG(INFO) << ss.str(); } +<<<<<<< HEAD COUNTER_UPDATE(_primary_tablets_num, primary_num); COUNTER_UPDATE(_secondary_tablets_num, secondary_num); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } @@ -990,6 +1032,153 @@ void LocalTabletsChannel::WriteCallback::run(const Status& st, const CommittedRo delete this; } +<<<<<<< HEAD +======= +void LocalTabletsChannel::update_profile() { + if (_profile == nullptr) { + return; + } + + bool expect = false; + if (!_is_updating_profile.compare_exchange_strong(expect, true)) { + // skip concurrent update + return; + } + DeferOp defer([this]() { _is_updating_profile.store(false); }); + _profile->inc_version(); + COUNTER_UPDATE(_profile_update_counter, 1); + SCOPED_TIMER(_profile_update_timer); + + std::vector async_writers; + { + std::shared_lock lk(_rw_mtx); + async_writers.reserve(_delta_writers.size()); + for (auto& [tablet_id, delta_writer] : _delta_writers) { + async_writers.push_back(delta_writer.get()); + } + } + + bool replicated_storage = true; + std::vector peer_or_primary_replica_profiles; + std::vector secondary_replica_profiles; + for (auto async_writer : async_writers) { + DeltaWriter* writer = async_writer->writer(); + RuntimeProfile* profile = _tablets_profile->create_child(fmt::format("{}", writer->tablet()->tablet_id())); + auto replica_state = writer->replica_state(); + if (replica_state == Peer) { + _update_peer_replica_profile(writer, profile); + peer_or_primary_replica_profiles.push_back(profile); + replicated_storage = false; + } else if (replica_state == Primary) { + _update_primary_replica_profile(writer, profile); + peer_or_primary_replica_profiles.push_back(profile); + } else if (writer->replica_state() == Secondary) { + _update_secondary_replica_profile(writer, profile); + secondary_replica_profiles.push_back(profile); + } else { + // ignore unknown replica state + } + } + + ObjectPool obj_pool; + if (!peer_or_primary_replica_profiles.empty()) { + auto* merged_profile = RuntimeProfile::merge_isomorphic_profiles(&obj_pool, peer_or_primary_replica_profiles); + RuntimeProfile* final_profile = _profile->create_child(replicated_storage ? "PrimaryReplicas" : "PeerReplicas"); + auto* tablets_counter = ADD_COUNTER(final_profile, "TabletsNum", TUnit::UNIT); + COUNTER_UPDATE(tablets_counter, peer_or_primary_replica_profiles.size()); + final_profile->copy_all_info_strings_from(merged_profile); + final_profile->copy_all_counters_from(merged_profile); + } + + if (!secondary_replica_profiles.empty()) { + auto* merged_profile = RuntimeProfile::merge_isomorphic_profiles(&obj_pool, secondary_replica_profiles); + RuntimeProfile* final_profile = _profile->create_child("SecondaryReplicas"); + auto* tablets_counter = ADD_COUNTER(final_profile, "TabletsNum", TUnit::UNIT); + COUNTER_UPDATE(tablets_counter, peer_or_primary_replica_profiles.size()); + final_profile->copy_all_info_strings_from(merged_profile); + final_profile->copy_all_counters_from(merged_profile); + } +} + +#define ADD_AND_UPDATE_COUNTER(profile, name, type, val) (ADD_COUNTER(profile, name, type))->update(val) +#define ADD_AND_UPDATE_TIMER(profile, name, val) (ADD_TIMER(profile, name))->update(val) + +void LocalTabletsChannel::_update_peer_replica_profile(DeltaWriter* writer, RuntimeProfile* profile) { + const DeltaWriterStat& writer_stat = writer->get_writer_stat(); + ADD_AND_UPDATE_COUNTER(profile, "WriterTaskCount", TUnit::UNIT, writer_stat.task_count); + ADD_AND_UPDATE_TIMER(profile, "WriterTaskPendingTime", writer_stat.pending_time_ns); + ADD_AND_UPDATE_COUNTER(profile, "WriteCount", TUnit::UNIT, writer_stat.write_count); + ADD_AND_UPDATE_COUNTER(profile, "RowCount", TUnit::UNIT, writer_stat.row_count); + ADD_AND_UPDATE_TIMER(profile, "WriteTime", writer_stat.write_time_ns); + ADD_AND_UPDATE_COUNTER(profile, "MemtableFullCount", TUnit::UNIT, writer_stat.memtable_full_count); + ADD_AND_UPDATE_COUNTER(profile, "MemoryExceedCount", TUnit::UNIT, writer_stat.memory_exceed_count); + ADD_AND_UPDATE_TIMER(profile, "WriteWaitFlushTime", writer_stat.write_wait_flush_tims_ns); + ADD_AND_UPDATE_TIMER(profile, "CloseTime", writer_stat.write_wait_flush_tims_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitTime", writer_stat.commit_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitWaitFlushTime", writer_stat.commit_wait_flush_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitRowsetBuildTime", writer_stat.commit_rowset_build_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitFinishPkTime", writer_stat.commit_finish_pk_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitWaitReplicaTime", writer_stat.commit_wait_replica_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitTxnCommitTime", writer_stat.commit_txn_commit_time_ns); + + const FlushStatistic& flush_stat = writer->get_flush_stats(); + ADD_AND_UPDATE_COUNTER(profile, "MemtableFlushedCount", TUnit::UNIT, flush_stat.flush_count); + ADD_AND_UPDATE_COUNTER(profile, "MemtableFlushingCount", TUnit::UNIT, flush_stat.cur_flush_count); + ADD_AND_UPDATE_COUNTER(profile, "MemtableQueueCount", TUnit::UNIT, flush_stat.queueing_memtable_num); + ADD_AND_UPDATE_COUNTER(profile, "FlushTaskPendingTime", TUnit::UNIT, flush_stat.pending_time_ns); + auto& memtable_stat = flush_stat.memtable_stats; + ADD_AND_UPDATE_COUNTER(profile, "MemtableInsertCount", TUnit::UNIT, memtable_stat.insert_count); + ADD_AND_UPDATE_TIMER(profile, "MemtableInsertTime", memtable_stat.insert_time_ns); + ADD_AND_UPDATE_TIMER(profile, "MemtableFinalizeTime", memtable_stat.finalize_time_ns); + ADD_AND_UPDATE_COUNTER(profile, "MemtableSortCount", TUnit::UNIT, memtable_stat.sort_count); + ADD_AND_UPDATE_TIMER(profile, "MemtableSortTime", memtable_stat.sort_time_ns); + ADD_AND_UPDATE_COUNTER(profile, "MemtableAggCount", TUnit::UNIT, memtable_stat.agg_count); + ADD_AND_UPDATE_TIMER(profile, "MemtableAggTime", memtable_stat.agg_time_ns); + ADD_AND_UPDATE_TIMER(profile, "MemtableFlushTime", memtable_stat.flush_time_ns); + ADD_AND_UPDATE_TIMER(profile, "MemtableIOTime", memtable_stat.io_time_ns); + ADD_AND_UPDATE_COUNTER(profile, "MemtableMemorySize", TUnit::BYTES, memtable_stat.flush_memory_size); + ADD_AND_UPDATE_COUNTER(profile, "MemtableDiskSize", TUnit::BYTES, memtable_stat.flush_disk_size); +} + +void LocalTabletsChannel::_update_primary_replica_profile(DeltaWriter* writer, RuntimeProfile* profile) { + _update_peer_replica_profile(writer, profile); + auto* replicate_token = writer->replicate_token(); + if (replicate_token == nullptr) { + return; + } + auto& replicate_stat = replicate_token->get_stat(); + ADD_AND_UPDATE_COUNTER(profile, "ReplicatePendingTaskCount", TUnit::UNIT, replicate_stat.num_pending_tasks); + ADD_AND_UPDATE_COUNTER(profile, "ReplicateExecutingTaskCount", TUnit::UNIT, replicate_stat.num_running_tasks); + ADD_AND_UPDATE_COUNTER(profile, "ReplicateFinishedTaskCount", TUnit::UNIT, replicate_stat.num_finished_tasks); + ADD_AND_UPDATE_TIMER(profile, "ReplicateTaskPendingTime", replicate_stat.pending_time_ns); + ADD_AND_UPDATE_TIMER(profile, "ReplicateTaskExecuteTime", replicate_stat.execute_time_ns); +} + +void LocalTabletsChannel::_update_secondary_replica_profile(DeltaWriter* writer, RuntimeProfile* profile) { + const DeltaWriterStat& writer_stat = writer->get_writer_stat(); + ADD_AND_UPDATE_COUNTER(profile, "RowCount", TUnit::UNIT, writer_stat.row_count); + ADD_AND_UPDATE_COUNTER(profile, "DataSize", TUnit::BYTES, writer_stat.add_segment_data_size); + ADD_AND_UPDATE_COUNTER(profile, "AddSegmentCount", TUnit::UNIT, writer_stat.add_segment_count); + ADD_AND_UPDATE_TIMER(profile, "AddSegmentTime", writer_stat.add_segment_time_ns); + ADD_AND_UPDATE_TIMER(profile, "AddSegmentIOTime", writer_stat.add_segment_io_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitTime", writer_stat.commit_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitRowsetBuildTime", writer_stat.commit_rowset_build_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitFinishPkTime", writer_stat.commit_finish_pk_time_ns); + ADD_AND_UPDATE_TIMER(profile, "CommitTxnCommitTime", writer_stat.commit_txn_commit_time_ns); + + auto* segment_flush_token = writer->segment_flush_token(); + if (segment_flush_token == nullptr) { + return; + } + auto& stat = segment_flush_token->get_stat(); + ADD_AND_UPDATE_COUNTER(profile, "FlushPendingTaskCount", TUnit::UNIT, stat.num_pending_tasks); + ADD_AND_UPDATE_COUNTER(profile, "FlushExecutingTaskCount", TUnit::UNIT, stat.num_running_tasks); + ADD_AND_UPDATE_COUNTER(profile, "FlushFinishedTaskCount", TUnit::UNIT, stat.num_finished_tasks); + ADD_AND_UPDATE_TIMER(profile, "FlushTaskPendingTime", stat.pending_time_ns); + ADD_AND_UPDATE_TIMER(profile, "FlushTaskExecuteTime", stat.execute_time_ns); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::shared_ptr new_local_tablets_channel(LoadChannel* load_channel, const TabletsChannelKey& key, MemTracker* mem_tracker, RuntimeProfile* parent_profile) { return std::make_shared(load_channel, key, mem_tracker, parent_profile); diff --git a/be/src/runtime/local_tablets_channel.h b/be/src/runtime/local_tablets_channel.h index d37f0572dab23..e76c35d9ed8a0 100644 --- a/be/src/runtime/local_tablets_channel.h +++ b/be/src/runtime/local_tablets_channel.h @@ -49,8 +49,13 @@ class LocalTabletsChannel : public TabletsChannel { Status open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema, bool is_incremental) override; +<<<<<<< HEAD void add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response) override; +======= + void add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, PTabletWriterAddBatchResult* response, + bool* close_channel_ptr) override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status incremental_open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema) override; @@ -64,6 +69,11 @@ class LocalTabletsChannel : public TabletsChannel { void abort(const std::vector& tablet_ids, const std::string& reason) override; +<<<<<<< HEAD +======= + void update_profile() override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MemTracker* mem_tracker() { return _mem_tracker; } private: @@ -179,6 +189,13 @@ class LocalTabletsChannel : public TabletsChannel { void _flush_stale_memtables(); +<<<<<<< HEAD +======= + void _update_peer_replica_profile(DeltaWriter* writer, RuntimeProfile* profile); + void _update_primary_replica_profile(DeltaWriter* writer, RuntimeProfile* profile); + void _update_secondary_replica_profile(DeltaWriter* writer, RuntimeProfile* profile); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) LoadChannel* _load_channel; TabletsChannelKey _key; @@ -226,12 +243,19 @@ class LocalTabletsChannel : public TabletsChannel { std::map _column_to_expr_value; // Profile counters +<<<<<<< HEAD // replicated_storage=false, the number of tablets // replicated_storage=true, the number of primary tablets RuntimeProfile::Counter* _primary_tablets_num = nullptr; // Only available for replicated_storage=true, the number of // secondary tablets RuntimeProfile::Counter* _secondary_tablets_num = nullptr; +======= + // Number of times that update_profile() is called + RuntimeProfile::Counter* _profile_update_counter = nullptr; + // Accumulated time for update_profile() + RuntimeProfile::Counter* _profile_update_timer = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Number of times that open() is called RuntimeProfile::Counter* _open_counter = nullptr; // Accumulated time of open() @@ -250,6 +274,12 @@ class LocalTabletsChannel : public TabletsChannel { RuntimeProfile::Counter* _wait_replica_timer = nullptr; // Accumulated time to wait for txn persist in add_chunk() RuntimeProfile::Counter* _wait_txn_persist_timer = nullptr; +<<<<<<< HEAD +======= + + std::atomic _is_updating_profile{false}; + std::unique_ptr _tablets_profile; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; std::shared_ptr new_local_tablets_channel(LoadChannel* load_channel, const TabletsChannelKey& key, diff --git a/be/src/runtime/mem_pool.h b/be/src/runtime/mem_pool.h index b160e189b722f..7741962bf6666 100644 --- a/be/src/runtime/mem_pool.h +++ b/be/src/runtime/mem_pool.h @@ -115,7 +115,15 @@ class MemPool { /// Allocates a section of memory of 'size' bytes with DEFAULT_ALIGNMENT at the end /// of the the current chunk. Creates a new chunk if there aren't any chunks /// with enough capacity. +<<<<<<< HEAD uint8_t* allocate(int64_t size) { return allocate(size, DEFAULT_ALIGNMENT); } +======= + uint8_t* allocate(int64_t size) { return allocate(size, DEFAULT_ALIGNMENT, 0); } + + uint8_t* allocate_with_reserve(int64_t size, int reserve) { + return allocate(size, DEFAULT_ALIGNMENT, reserve); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Don't check memory limit uint8_t* allocate_aligned(int64_t size, int alignment) { @@ -123,7 +131,11 @@ class MemPool { DCHECK_LE(alignment, config::memory_max_alignment); // alignment should be a power of 2 DCHECK((alignment & (alignment - 1)) == 0); +<<<<<<< HEAD return allocate(size, alignment); +======= + return allocate(size, alignment, 0); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } /// Makes all allocated chunks available for re-use, but doesn't delete any chunks. @@ -193,14 +205,22 @@ class MemPool { } template +<<<<<<< HEAD uint8_t* ALWAYS_INLINE allocate(int64_t size, int alignment) { +======= + uint8_t* ALWAYS_INLINE allocate(int64_t size, int alignment, int reserve) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK_GE(size, 0); if (UNLIKELY(size == 0)) return reinterpret_cast(&k_zero_length_region_); if (current_chunk_idx_ != -1) { ChunkInfo& info = chunks_[current_chunk_idx_]; int64_t aligned_allocated_bytes = BitUtil::RoundUpToPowerOf2(info.allocated_bytes, alignment); +<<<<<<< HEAD if (aligned_allocated_bytes + size <= info.chunk.size) { +======= + if (aligned_allocated_bytes + size + reserve <= info.chunk.size) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Ensure the requested alignment is respected. int64_t padding = aligned_allocated_bytes - info.allocated_bytes; uint8_t* result = info.chunk.data + aligned_allocated_bytes; @@ -218,7 +238,11 @@ class MemPool { // guarantee alignment. //static_assert( //INITIAL_CHUNK_SIZE >= config::FLAGS_MEMORY_MAX_ALIGNMENT, "Min chunk size too low"); +<<<<<<< HEAD if (UNLIKELY(!find_chunk(size, CHECK_LIMIT_FIRST))) return nullptr; +======= + if (UNLIKELY(!find_chunk(size + reserve, CHECK_LIMIT_FIRST))) return nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkInfo& info = chunks_[current_chunk_idx_]; uint8_t* result = info.chunk.data + info.allocated_bytes; @@ -255,6 +279,11 @@ class MemPool { }; // Stamp out templated implementations here so they're included in IR module +<<<<<<< HEAD template uint8_t* MemPool::allocate(int64_t size, int alignment); template uint8_t* MemPool::allocate(int64_t size, int alignment); +======= +template uint8_t* MemPool::allocate(int64_t size, int alignment, int reserve); +template uint8_t* MemPool::allocate(int64_t size, int alignment, int reserve); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/memory/allocator.h b/be/src/runtime/memory/allocator.h new file mode 100644 index 0000000000000..4e9128910ca4a --- /dev/null +++ b/be/src/runtime/memory/allocator.h @@ -0,0 +1,72 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "common/compiler_util.h" + +namespace starrocks { + +// Allocator provides interfaces related to memory management, +// and their semantics are the same as the standard libc interface. +// In the future, we can use Allocator to replace mem_hook and achieve more precise memory management. +class Allocator { +public: + virtual ~Allocator() = default; + virtual void* alloc(size_t size) = 0; + virtual void free(void* ptr) = 0; + virtual void* realloc(void* ptr, size_t size) = 0; + virtual void* calloc(size_t n, size_t size) = 0; + virtual void cfree(void* ptr) = 0; + virtual void* memalign(size_t align, size_t size) = 0; + virtual void* aligned_alloc(size_t align, size_t size) = 0; + virtual void* valloc(size_t size) = 0; + virtual void* pvalloc(size_t size) = 0; + virtual int posix_memalign(void** ptr, size_t align, size_t size) = 0; + + // Follow std::allocator::allocate() style, throw std::bad_alloc if allocate fail + virtual void* checked_alloc(size_t size) = 0; +}; + +template +class AllocatorFactory : public Base { +public: + void* alloc(size_t size) override { return static_cast(this)->alloc(size); } + void free(void* ptr) override { static_cast(this)->free(ptr); } + void* realloc(void* ptr, size_t size) override { return static_cast(this)->realloc(ptr, size); } + void* calloc(size_t n, size_t size) override { return static_cast(this)->calloc(n, size); } + void cfree(void* ptr) override { static_cast(this)->cfree(ptr); } + void* memalign(size_t align, size_t size) override { return static_cast(this)->memalign(align, size); } + void* aligned_alloc(size_t align, size_t size) override { + return static_cast(this)->aligned_alloc(align, size); + } + void* valloc(size_t size) override { return static_cast(this)->valloc(size); } + void* pvalloc(size_t size) override { return static_cast(this)->pvalloc(size); } + int posix_memalign(void** ptr, size_t align, size_t size) override { + return static_cast(this)->posix_memalign(ptr, align, size); + } + + void* checked_alloc(size_t size) override { + void* result = static_cast(this)->alloc(size); + if (UNLIKELY(result == nullptr)) { + throw std::bad_alloc(); + } + return result; + } +}; + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/memory/column_allocator.cpp b/be/src/runtime/memory/column_allocator.cpp new file mode 100644 index 0000000000000..9cc294df06774 --- /dev/null +++ b/be/src/runtime/memory/column_allocator.cpp @@ -0,0 +1,21 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/memory/column_allocator.h" + +namespace starrocks { + +MemHookAllocator kDefaultColumnAllocator = MemHookAllocator{}; + +} \ No newline at end of file diff --git a/be/src/runtime/memory/column_allocator.h b/be/src/runtime/memory/column_allocator.h new file mode 100644 index 0000000000000..89ee32cc7176b --- /dev/null +++ b/be/src/runtime/memory/column_allocator.h @@ -0,0 +1,82 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "runtime/memory/mem_hook_allocator.h" + +namespace starrocks { + +extern MemHookAllocator kDefaultColumnAllocator; +inline thread_local Allocator* tls_column_allocator = &kDefaultColumnAllocator; + +// Implement the std::allocator: https://en.cppreference.com/w/cpp/memory/allocator +template +class ColumnAllocator { +public: + typedef T value_type; + typedef size_t size_type; + using propagate_on_container_copy_assignment = std::true_type; // for consistency + using propagate_on_container_move_assignment = std::true_type; // to avoid the pessimization + using propagate_on_container_swap = std::true_type; // to avoid the undefined behavior + + template + struct rebind { + using other = ColumnAllocator; + }; + ColumnAllocator() = default; + template + ColumnAllocator(const ColumnAllocator& other) {} + + ~ColumnAllocator() = default; + + // Allocator n elements, throw std::bad_malloc if allocate failed + T* allocate(size_t n) { + DCHECK(tls_column_allocator != nullptr); + return static_cast(tls_column_allocator->checked_alloc(n * sizeof(T))); + } + + void deallocate(T* ptr, size_t n) { + DCHECK(tls_column_allocator != nullptr); + tls_column_allocator->free(ptr); + } + + ColumnAllocator& operator=(const ColumnAllocator& rhs) = default; + + template + ColumnAllocator& operator=(const ColumnAllocator& rhs) { + return *this; + } + + bool operator==(const ColumnAllocator& rhs) const { return true; } + + bool operator!=(const ColumnAllocator& rhs) const { return false; } + + void swap(ColumnAllocator& rhs) {} +}; + +class ThreadLocalColumnAllocatorSetter { +public: + ThreadLocalColumnAllocatorSetter(Allocator* allocator) { + _prev = tls_column_allocator; + tls_column_allocator = allocator; + } + ~ThreadLocalColumnAllocatorSetter() { tls_column_allocator = _prev; } + +private: + Allocator* _prev = nullptr; +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/memory/counting_allocator.h b/be/src/runtime/memory/counting_allocator.h new file mode 100644 index 0000000000000..b9ae3eaee27dc --- /dev/null +++ b/be/src/runtime/memory/counting_allocator.h @@ -0,0 +1,180 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "common/compiler_util.h" +#include "exprs/expr_context.h" +#include "runtime/memory/allocator.h" +#include "runtime/memory/mem_hook_allocator.h" + +namespace starrocks { + +// used to record the memory changes after each operation, for example, +// if malloc allocates 4 bytes its value will be 4, and if free releases 4 bytes, its value will be -4 +inline thread_local int64_t tls_delta_memory = 0; + +template +class CountingAllocator final : public AllocatorFactory> { +public: + void* alloc(size_t size) override { + void* result = Base::alloc(size); + _memory_usage += tls_delta_memory; + return result; + } + void free(void* ptr) override { + Base::free(ptr); + _memory_usage += tls_delta_memory; + } + + void* realloc(void* ptr, size_t size) override { + void* result = Base::realloc(ptr, size); + _memory_usage += tls_delta_memory; + return result; + } + + void* calloc(size_t n, size_t size) override { + void* result = Base::calloc(n, size); + _memory_usage += tls_delta_memory; + return result; + } + + void cfree(void* ptr) override { + Base::cfree(ptr); + _memory_usage += tls_delta_memory; + } + + void* memalign(size_t align, size_t size) override { + void* result = Base::memalign(align, size); + _memory_usage += tls_delta_memory; + return result; + } + void* aligned_alloc(size_t align, size_t size) override { + void* result = Base::aligned_alloc(align, size); + _memory_usage += tls_delta_memory; + return result; + } + + void* valloc(size_t size) override { + void* result = Base::valloc(size); + _memory_usage += tls_delta_memory; + return result; + } + + void* pvalloc(size_t size) override { + void* result = Base::pvalloc(size); + _memory_usage += tls_delta_memory; + return result; + } + + int posix_memalign(void** ptr, size_t align, size_t size) override { + int result = Base::posix_memalign(ptr, align, size); + _memory_usage += tls_delta_memory; + return result; + } + + int64_t memory_usage() const { return _memory_usage; } + + int64_t _memory_usage = 0; +}; + +using CountingAllocatorWithHook = CountingAllocator; + +template +class STLCountingAllocator { +public: + typedef T value_type; + typedef size_t size_type; + using propagate_on_container_copy_assignment = std::true_type; // for consistency + using propagate_on_container_move_assignment = std::true_type; // to avoid the pessimization + using propagate_on_container_swap = std::true_type; // to avoid the undefined behavior + + template + struct rebind { + using other = STLCountingAllocator; + }; + STLCountingAllocator() = default; + explicit STLCountingAllocator(int64_t* counter) : _counter(counter) {} + explicit STLCountingAllocator(const STLCountingAllocator& rhs) : _counter(rhs._counter) {} + template + STLCountingAllocator(const STLCountingAllocator& other) : _counter(other._counter) {} + + ~STLCountingAllocator() = default; + + STLCountingAllocator(STLCountingAllocator&& rhs) noexcept { std::swap(_counter, rhs._counter); } + + STLCountingAllocator& operator=(STLCountingAllocator&& rhs) noexcept { + if (this != &rhs) { + std::swap(_counter, rhs._counter); + } + return *this; + } + + T* allocate(size_t n) { + DCHECK(_counter != nullptr); + T* result = static_cast(malloc(n * sizeof(T))); + // in ut mode, mem_hook won't take effect and tls_delta_memory will always be 0, + // we use logical size for counting, + // otherwise, we use the actual size allocated by memory allocator. +#ifndef BE_TEST + *_counter += tls_delta_memory; +#else + *_counter += (result != nullptr) ? n * sizeof(T) : 0; +#endif + if (UNLIKELY(result == nullptr)) { + throw std::bad_alloc(); + } + + return result; + } + + void deallocate(T* ptr, size_t n) { + DCHECK(_counter != nullptr); + free(ptr); +#ifndef BE_TEST + *_counter += tls_delta_memory; +#else + *_counter -= n * sizeof(T); +#endif + } + + STLCountingAllocator& operator=(const STLCountingAllocator& rhs) { + _counter = rhs._counter; + return *this; + } + + template + STLCountingAllocator& operator=(const STLCountingAllocator& rhs) { + _counter = rhs._counter; + return *this; + } + + bool operator==(const STLCountingAllocator& rhs) const { return _counter == rhs._counter; } + + bool operator!=(const STLCountingAllocator& rhs) const { return !(*this == rhs); } + + // CountingAllocator doesn't support swap + void swap(STLCountingAllocator& rhs) {} + + int64_t* _counter = nullptr; +}; +template +void swap(STLCountingAllocator& lhs, STLCountingAllocator& rhs) { + lhs.swap(rhs); +} + +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/memory/mem_hook_allocator.h b/be/src/runtime/memory/mem_hook_allocator.h new file mode 100644 index 0000000000000..b32e17accf92a --- /dev/null +++ b/be/src/runtime/memory/mem_hook_allocator.h @@ -0,0 +1,45 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include + +#include "malloc.h" +#include "runtime/memory/allocator.h" + +namespace starrocks { + +class MemHookAllocator : public AllocatorFactory { +public: + void* alloc(size_t size) override { return ::malloc(size); } + + void free(void* ptr) override { ::free(ptr); } + + void* realloc(void* ptr, size_t size) override { return ::realloc(ptr, size); } + + void* calloc(size_t n, size_t size) override { return ::calloc(n, size); } + + void cfree(void* ptr) override { ::free(ptr); } + + void* memalign(size_t align, size_t size) override { return ::memalign(align, size); } + + void* aligned_alloc(size_t align, size_t size) override { return ::aligned_alloc(align, size); } + + void* valloc(size_t size) override { return ::valloc(size); } + + void* pvalloc(size_t size) override { return ::pvalloc(size); } + + int posix_memalign(void** ptr, size_t align, size_t size) override { return ::posix_memalign(ptr, align, size); } +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/memory/roaring_hook.cpp b/be/src/runtime/memory/roaring_hook.cpp new file mode 100644 index 0000000000000..7b4897c249ee6 --- /dev/null +++ b/be/src/runtime/memory/roaring_hook.cpp @@ -0,0 +1,73 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/memory/roaring_hook.h" + +#include + +#include + +#include "roaring/memory.h" +#include "runtime/memory/mem_hook_allocator.h" + +namespace starrocks { + +static MemHookAllocator kDefaultRoaringAllocator = MemHookAllocator{}; +inline thread_local Allocator* tls_roaring_allocator = &kDefaultRoaringAllocator; + +ThreadLocalRoaringAllocatorSetter::ThreadLocalRoaringAllocatorSetter(Allocator* allocator) { + _prev = tls_roaring_allocator; + tls_roaring_allocator = allocator; +} + +ThreadLocalRoaringAllocatorSetter::~ThreadLocalRoaringAllocatorSetter() { + tls_roaring_allocator = _prev; +} + +void* my_roaring_malloc(size_t bytes) { + return tls_roaring_allocator->alloc(bytes); +} + +void* my_roaring_realloc(void* ptr, size_t size) { + return tls_roaring_allocator->realloc(ptr, size); +} + +void* my_roaring_calloc(size_t n, size_t size) { + return tls_roaring_allocator->calloc(n, size); +} + +void my_roaring_free(void* ptr) { + return tls_roaring_allocator->free(ptr); +} + +void* my_roaring_aligned_malloc(size_t align, size_t size) { + return tls_roaring_allocator->aligned_alloc(align, size); +} + +void my_roaring_aligned_free(void* ptr) { + return tls_roaring_allocator->free(ptr); +} + +void init_roaring_hook() { + roaring_memory_t global_memory_hook = { + .malloc = my_roaring_malloc, + .realloc = my_roaring_realloc, + .calloc = my_roaring_calloc, + .free = my_roaring_free, + .aligned_malloc = my_roaring_aligned_malloc, + .aligned_free = my_roaring_aligned_free, + }; + roaring_init_memory_hook(global_memory_hook); +} +} // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/memory/roaring_hook.h b/be/src/runtime/memory/roaring_hook.h new file mode 100644 index 0000000000000..0baffc9d8d89a --- /dev/null +++ b/be/src/runtime/memory/roaring_hook.h @@ -0,0 +1,32 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "runtime/memory/allocator.h" + +namespace starrocks { + +class ThreadLocalRoaringAllocatorSetter { +public: + ThreadLocalRoaringAllocatorSetter(Allocator* allocator); + ~ThreadLocalRoaringAllocatorSetter(); + +private: + Allocator* _prev = nullptr; +}; + +void init_roaring_hook(); + +} // namespace starrocks diff --git a/be/src/runtime/metadata_result_writer.cpp b/be/src/runtime/metadata_result_writer.cpp index bbf2943c45dfe..1ba1c5b2dfd0c 100644 --- a/be/src/runtime/metadata_result_writer.cpp +++ b/be/src/runtime/metadata_result_writer.cpp @@ -27,9 +27,14 @@ namespace starrocks { MetadataResultWriter::MetadataResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile, TResultSinkType::type sink_type) +<<<<<<< HEAD : _sinker(sinker), _output_expr_ctxs(output_expr_ctxs), _parent_profile(parent_profile), +======= + : BufferControlResultWriter(sinker, parent_profile), + _output_expr_ctxs(output_expr_ctxs), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _sink_type(sink_type) {} MetadataResultWriter::~MetadataResultWriter() = default; @@ -42,6 +47,7 @@ Status MetadataResultWriter::init(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD void MetadataResultWriter::_init_profile() { _total_timer = ADD_TIMER(_parent_profile, "TotalSendTime"); _serialize_timer = ADD_CHILD_TIMER(_parent_profile, "SerializeTime", "TotalSendTime"); @@ -50,6 +56,10 @@ void MetadataResultWriter::_init_profile() { Status MetadataResultWriter::append_chunk(Chunk* chunk) { SCOPED_TIMER(_total_timer); +======= +Status MetadataResultWriter::append_chunk(Chunk* chunk) { + SCOPED_TIMER(_append_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto process_status = _process_chunk(chunk); if (!process_status.ok() || process_status.value() == nullptr) { return process_status.status(); @@ -69,7 +79,11 @@ Status MetadataResultWriter::append_chunk(Chunk* chunk) { } StatusOr MetadataResultWriter::process_chunk(Chunk* chunk) { +<<<<<<< HEAD SCOPED_TIMER(_total_timer); +======= + SCOPED_TIMER(_append_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TFetchDataResultPtrs results; auto process_status = _process_chunk(chunk); if (!process_status.ok()) { @@ -81,6 +95,7 @@ StatusOr MetadataResultWriter::process_chunk(Chunk* chunk) return results; } +<<<<<<< HEAD StatusOr MetadataResultWriter::try_add_batch(TFetchDataResultPtrs& results) { size_t num_rows = 0; for (const auto& result : results) { @@ -101,6 +116,8 @@ StatusOr MetadataResultWriter::try_add_batch(TFetchDataResultPtrs& results return status; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr MetadataResultWriter::_process_chunk(Chunk* chunk) { if (nullptr == chunk || 0 == chunk->num_rows()) { return nullptr; @@ -148,7 +165,11 @@ StatusOr MetadataResultWriter::_process_chunk(Chunk* chunk) // 13 -> "key_metadata" Status MetadataResultWriter::_fill_iceberg_metadata(const Columns& columns, const Chunk* chunk, TFetchDataResult* result) const { +<<<<<<< HEAD SCOPED_TIMER(_serialize_timer); +======= + SCOPED_TIMER(_convert_tuple_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto content = down_cast(ColumnHelper::get_data_column(columns[0].get())); auto file_path = down_cast(ColumnHelper::get_data_column(columns[1].get())); @@ -228,10 +249,13 @@ Status MetadataResultWriter::_fill_iceberg_metadata(const Columns& columns, cons return Status::OK(); } +<<<<<<< HEAD Status MetadataResultWriter::close() { COUNTER_SET(_sent_rows_counter, _written_rows); return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks \ No newline at end of file diff --git a/be/src/runtime/metadata_result_writer.h b/be/src/runtime/metadata_result_writer.h index 776c903f03eef..1a102faf3bc9c 100644 --- a/be/src/runtime/metadata_result_writer.h +++ b/be/src/runtime/metadata_result_writer.h @@ -14,8 +14,12 @@ #pragma once +<<<<<<< HEAD #include "runtime/result_writer.h" #include "runtime/runtime_state.h" +======= +#include "runtime/buffer_control_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -24,7 +28,11 @@ class MysqlRowBuffer; class BufferControlBlock; class RuntimeProfile; +<<<<<<< HEAD class MetadataResultWriter final : public ResultWriter { +======= +class MetadataResultWriter final : public BufferControlResultWriter { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: MetadataResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile, TResultSinkType::type _sink_type); @@ -35,6 +43,7 @@ class MetadataResultWriter final : public ResultWriter { Status append_chunk(Chunk* chunk) override; +<<<<<<< HEAD Status close() override; StatusOr process_chunk(Chunk* chunk) override; @@ -44,11 +53,17 @@ class MetadataResultWriter final : public ResultWriter { private: void _init_profile(); +======= + StatusOr process_chunk(Chunk* chunk) override; + +private: +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr _process_chunk(Chunk* chunk); Status _fill_iceberg_metadata(const Columns& columns, const Chunk* chunk, TFetchDataResult* result) const; private: +<<<<<<< HEAD BufferControlBlock* _sinker; const std::vector& _output_expr_ctxs; @@ -60,6 +75,9 @@ class MetadataResultWriter final : public ResultWriter { RuntimeProfile::Counter* _serialize_timer = nullptr; // number of sent rows RuntimeProfile::Counter* _sent_rows_counter = nullptr; +======= + const std::vector& _output_expr_ctxs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TResultSinkType::type _sink_type; }; diff --git a/be/src/runtime/mysql_result_writer.cpp b/be/src/runtime/mysql_result_writer.cpp index 38e0b8046f755..971393305f66a 100644 --- a/be/src/runtime/mysql_result_writer.cpp +++ b/be/src/runtime/mysql_result_writer.cpp @@ -38,8 +38,15 @@ #include "column/chunk.h" #include "column/const_column.h" +<<<<<<< HEAD #include "exprs/expr.h" #include "runtime/buffer_control_block.h" +======= +#include "common/statusor.h" +#include "exprs/expr.h" +#include "runtime/buffer_control_block.h" +#include "runtime/buffer_control_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/current_thread.h" #include "types/logical_type.h" #include "util/mysql_row_buffer.h" @@ -48,11 +55,18 @@ namespace starrocks { MysqlResultWriter::MysqlResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, bool is_binary_format, RuntimeProfile* parent_profile) +<<<<<<< HEAD : _sinker(sinker), _output_expr_ctxs(output_expr_ctxs), _row_buffer(nullptr), _is_binary_format(is_binary_format), _parent_profile(parent_profile) {} +======= + : BufferControlResultWriter(sinker, parent_profile), + _output_expr_ctxs(output_expr_ctxs), + _row_buffer(nullptr), + _is_binary_format(is_binary_format) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) MysqlResultWriter::~MysqlResultWriter() { delete _row_buffer; @@ -73,6 +87,7 @@ Status MysqlResultWriter::init(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD void MysqlResultWriter::_init_profile() { _append_chunk_timer = ADD_TIMER(_parent_profile, "AppendChunkTime"); _convert_tuple_timer = ADD_CHILD_TIMER(_parent_profile, "TupleConvertTime", "AppendChunkTime"); @@ -80,6 +95,8 @@ void MysqlResultWriter::_init_profile() { _sent_rows_counter = ADD_COUNTER(_parent_profile, "NumSentRows", TUnit::UNIT); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status MysqlResultWriter::append_chunk(Chunk* chunk) { if (nullptr == chunk || 0 == chunk->num_rows()) { return Status::OK(); @@ -107,11 +124,14 @@ Status MysqlResultWriter::append_chunk(Chunk* chunk) { return add_status; } +<<<<<<< HEAD Status MysqlResultWriter::close() { COUNTER_SET(_sent_rows_counter, _written_rows); return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr MysqlResultWriter::_process_chunk(Chunk* chunk) { SCOPED_TIMER(_append_chunk_timer); int num_rows = chunk->num_rows(); @@ -140,7 +160,12 @@ StatusOr MysqlResultWriter::_process_chunk(Chunk* chunk) { DCHECK_EQ(0, _row_buffer->length()); if (_is_binary_format) { _row_buffer->start_binary_row(num_columns); +<<<<<<< HEAD }; +======= + } + // TODO: codegen here +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (auto& result_column : result_columns) { if (_is_binary_format && !result_column->is_nullable()) { _row_buffer->update_field_pos(); @@ -223,6 +248,7 @@ StatusOr MysqlResultWriter::process_chunk(Chunk* chunk) { return results; } +<<<<<<< HEAD StatusOr MysqlResultWriter::try_add_batch(TFetchDataResultPtrs& results) { SCOPED_TIMER(_result_send_timer); size_t num_rows = 0; @@ -244,4 +270,6 @@ StatusOr MysqlResultWriter::try_add_batch(TFetchDataResultPtrs& results) { return status; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/mysql_result_writer.h b/be/src/runtime/mysql_result_writer.h index d2d2fd04ff99e..f69a1fe9226ea 100644 --- a/be/src/runtime/mysql_result_writer.h +++ b/be/src/runtime/mysql_result_writer.h @@ -34,9 +34,13 @@ #pragma once +<<<<<<< HEAD #include "common/statusor.h" #include "runtime/result_writer.h" #include "runtime/runtime_state.h" +======= +#include "runtime/buffer_control_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -47,7 +51,11 @@ class RuntimeProfile; using TFetchDataResultPtr = std::unique_ptr; using TFetchDataResultPtrs = std::vector; // convert the row batch to mysql protocol row +<<<<<<< HEAD class MysqlResultWriter final : public ResultWriter { +======= +class MysqlResultWriter final : public BufferControlResultWriter { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: MysqlResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, bool is_binary_format, RuntimeProfile* parent_profile); @@ -58,6 +66,7 @@ class MysqlResultWriter final : public ResultWriter { Status append_chunk(Chunk* chunk) override; +<<<<<<< HEAD Status close() override; StatusOr process_chunk(Chunk* chunk) override; @@ -70,10 +79,19 @@ class MysqlResultWriter final : public ResultWriter { StatusOr _process_chunk(Chunk* chunk); BufferControlBlock* _sinker; +======= + StatusOr process_chunk(Chunk* chunk) override; + +private: + // this function is only used in non-pipeline engine + StatusOr _process_chunk(Chunk* chunk); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::vector& _output_expr_ctxs; MysqlRowBuffer* _row_buffer; bool _is_binary_format; +<<<<<<< HEAD RuntimeProfile* _parent_profile; // parent profile from result sink. not owned // total time cost on append chunk operation RuntimeProfile::Counter* _append_chunk_timer = nullptr; @@ -84,6 +102,8 @@ class MysqlResultWriter final : public ResultWriter { // number of sent rows RuntimeProfile::Counter* _sent_rows_counter = nullptr; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const size_t _max_row_buffer_size = 1024 * 1024 * 1024; }; diff --git a/be/src/runtime/plan_fragment_executor.cpp b/be/src/runtime/plan_fragment_executor.cpp index 0ce0c72acfb9f..28c30967184be 100644 --- a/be/src/runtime/plan_fragment_executor.cpp +++ b/be/src/runtime/plan_fragment_executor.cpp @@ -203,6 +203,7 @@ Status PlanFragmentExecutor::open() { } Status status = _open_internal_vectorized(); +<<<<<<< HEAD if (!status.ok() && !status.is_cancelled() && _runtime_state->log_has_space()) { LOG(WARNING) << "Fail to open fragment, instance_id=" << print_id(_runtime_state->fragment_instance_id()) << ", status=" << status; @@ -210,6 +211,11 @@ Status PlanFragmentExecutor::open() { // fetch results (e.g. insert) may not receive the message directly and can // only retrieve the log. _runtime_state->log_error(status.message()); +======= + if (!status.ok() && !status.is_cancelled()) { + LOG(WARNING) << "Fail to open fragment, instance_id=" << print_id(_runtime_state->fragment_instance_id()) + << ", status=" << status; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } update_status(status); @@ -515,6 +521,7 @@ Status PlanFragmentExecutor::_prepare_stream_load_pipe(const TExecPlanFragmentPa if (!iter->second[0].scan_range.broker_scan_range.__isset.channel_id) { return Status::OK(); } +<<<<<<< HEAD _channel_stream_load = true; for (; iter != scan_range_map.end(); iter++) { for (const auto& scan_range : iter->second) { @@ -539,6 +546,9 @@ Status PlanFragmentExecutor::_prepare_stream_load_pipe(const TExecPlanFragmentPa } } return Status::OK(); +======= + return Status::NotSupported("Non-pipeline engine does not support channel stream load"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } // namespace starrocks diff --git a/be/src/runtime/query_statistics.cpp b/be/src/runtime/query_statistics.cpp index 16a3dfd900ab8..16feb6e0a1a16 100644 --- a/be/src/runtime/query_statistics.cpp +++ b/be/src/runtime/query_statistics.cpp @@ -53,6 +53,19 @@ void QueryStatistics::to_pb(PQueryStatistics* statistics) { new_stats_item->set_scan_bytes(stats_item->scan_bytes); } } +<<<<<<< HEAD +======= + + for (const auto& [node_id, exec_stats_item] : _exec_stats_items) { + auto new_exec_stats_item = statistics->add_node_exec_stats_items(); + new_exec_stats_item->set_node_id(node_id); + new_exec_stats_item->set_push_rows(exec_stats_item->push_rows); + new_exec_stats_item->set_pull_rows(exec_stats_item->pull_rows); + new_exec_stats_item->set_index_filter_rows(exec_stats_item->index_filter_rows); + new_exec_stats_item->set_rf_filter_rows(exec_stats_item->rf_filter_rows); + new_exec_stats_item->set_pred_filter_rows(exec_stats_item->pred_filter_rows); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void QueryStatistics::to_params(TAuditStatistics* params) { @@ -81,6 +94,10 @@ void QueryStatistics::clear() { returned_rows = 0; spill_bytes = 0; _stats_items.clear(); +<<<<<<< HEAD +======= + _exec_stats_items.clear(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void QueryStatistics::update_stats_item(int64_t table_id, int64_t scan_rows, int64_t scan_bytes) { @@ -95,6 +112,24 @@ void QueryStatistics::update_stats_item(int64_t table_id, int64_t scan_rows, int } } +<<<<<<< HEAD +======= +void QueryStatistics::update_exec_stats_item(uint32_t node_id, int64_t push, int64_t pull, int64_t pred_filter, + int64_t index_filter, int64_t rf_filter) { + auto iter = _exec_stats_items.find(node_id); + if (iter == _exec_stats_items.end()) { + _exec_stats_items.insert( + {node_id, std::make_shared(push, pull, pred_filter, index_filter, rf_filter)}); + } else { + iter->second->push_rows += push; + iter->second->pull_rows += pull; + iter->second->pred_filter_rows += pred_filter; + iter->second->index_filter_rows += index_filter; + iter->second->rf_filter_rows += rf_filter; + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void QueryStatistics::add_stats_item(QueryStatisticsItemPB& stats_item) { { std::lock_guard l(_lock); @@ -104,6 +139,14 @@ void QueryStatistics::add_stats_item(QueryStatisticsItemPB& stats_item) { this->scan_bytes += stats_item.scan_bytes(); } +<<<<<<< HEAD +======= +void QueryStatistics::add_exec_stats_item(uint32_t node_id, int64_t push, int64_t pull, int64_t pred_filter, + int64_t index_filter, int64_t rf_filter) { + update_exec_stats_item(node_id, push, pull, pred_filter, index_filter, rf_filter); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void QueryStatistics::add_scan_stats(int64_t scan_rows, int64_t scan_bytes) { this->scan_rows += scan_rows; this->scan_bytes += scan_bytes; @@ -137,14 +180,30 @@ void QueryStatistics::merge(int sender_id, QueryStatistics& other) { { std::unordered_map> other_stats_item; +<<<<<<< HEAD + { + std::lock_guard l(other._lock); + other_stats_item.swap(other._stats_items); +======= + std::unordered_map> other_exec_stats_items; { std::lock_guard l(other._lock); other_stats_item.swap(other._stats_items); + other_exec_stats_items.swap(other._exec_stats_items); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } std::lock_guard l(_lock); for (const auto& [table_id, stats_item] : other_stats_item) { update_stats_item(table_id, stats_item->scan_rows, stats_item->scan_bytes); } +<<<<<<< HEAD +======= + for (const auto& [node_id, exec_stats_item] : other_exec_stats_items) { + update_exec_stats_item(node_id, exec_stats_item->push_rows, exec_stats_item->pull_rows, + exec_stats_item->pred_filter_rows, exec_stats_item->index_filter_rows, + exec_stats_item->rf_filter_rows); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } @@ -171,6 +230,15 @@ void QueryStatistics::merge_pb(const PQueryStatistics& statistics) { const auto& stats_item = statistics.stats_items(i); update_stats_item(stats_item.table_id(), stats_item.scan_rows(), stats_item.scan_bytes()); } +<<<<<<< HEAD +======= + for (int i = 0; i < statistics.node_exec_stats_items_size(); ++i) { + const auto& exec_stats_item = statistics.node_exec_stats_items(i); + update_exec_stats_item(exec_stats_item.node_id(), exec_stats_item.push_rows(), exec_stats_item.pull_rows(), + exec_stats_item.pred_filter_rows(), exec_stats_item.index_filter_rows(), + exec_stats_item.rf_filter_rows()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } diff --git a/be/src/runtime/query_statistics.h b/be/src/runtime/query_statistics.h index 2bfaa72d06796..9f0a9e201cfcd 100644 --- a/be/src/runtime/query_statistics.h +++ b/be/src/runtime/query_statistics.h @@ -54,6 +54,11 @@ class QueryStatistics { void set_returned_rows(int64_t num_rows) { this->returned_rows = num_rows; } void add_stats_item(QueryStatisticsItemPB& stats_item); +<<<<<<< HEAD +======= + void add_exec_stats_item(uint32_t node_id, int64_t push, int64_t pull, int64_t pred_filter, int64_t index_filter, + int64_t rf_filter); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void add_scan_stats(int64_t scan_rows, int64_t scan_bytes); void add_cpu_costs(int64_t cpu_ns) { this->cpu_ns += cpu_ns; } void add_mem_costs(int64_t bytes) { mem_cost_bytes += bytes; } @@ -73,6 +78,12 @@ class QueryStatistics { private: void update_stats_item(int64_t table_id, int64_t scan_rows, int64_t scan_bytes); +<<<<<<< HEAD +======= + void update_exec_stats_item(uint32_t node_id, int64_t push, int64_t pull, int64_t pred_filter, int64_t index_filter, + int64_t rf_filter); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::atomic_int64_t scan_rows{0}; std::atomic_int64_t scan_bytes{0}; std::atomic_int64_t cpu_ns{0}; @@ -87,8 +98,31 @@ class QueryStatistics { int64_t scan_rows = 0; int64_t scan_bytes = 0; }; +<<<<<<< HEAD + SpinLock _lock; + std::unordered_map> _stats_items; +======= + + struct NodeExecStats { + std::atomic_int64_t push_rows; + std::atomic_int64_t pull_rows; + std::atomic_int64_t pred_filter_rows; + std::atomic_int64_t index_filter_rows; + std::atomic_int64_t rf_filter_rows; + + NodeExecStats() : push_rows(0), pull_rows(0), pred_filter_rows(0), index_filter_rows(0), rf_filter_rows(0) {} + + NodeExecStats(int64_t push, int64_t pull, int64_t pred_filter, int64_t index_filter, int64_t rf_filter) + : push_rows(push), + pull_rows(pull), + pred_filter_rows(pred_filter), + index_filter_rows(index_filter), + rf_filter_rows(rf_filter) {} + }; SpinLock _lock; std::unordered_map> _stats_items; + std::unordered_map> _exec_stats_items; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; // It is used for collecting sub plan query statistics in DataStreamRecvr. diff --git a/be/src/runtime/result_buffer_mgr.cpp b/be/src/runtime/result_buffer_mgr.cpp index 1d8142335a7b4..c6e073a1a97cb 100644 --- a/be/src/runtime/result_buffer_mgr.cpp +++ b/be/src/runtime/result_buffer_mgr.cpp @@ -118,6 +118,30 @@ void ResultBufferMgr::fetch_data(const PUniqueId& finst_id, GetResultBatchCtx* c cb->get_batch(ctx); } +<<<<<<< HEAD +======= +Status ResultBufferMgr::fetch_arrow_data(const TUniqueId& query_id, std::shared_ptr* result) { + std::shared_ptr cb = find_control_block(query_id); + if (cb == nullptr) { + return Status::InternalError("no result for this query"); + } + RETURN_IF_ERROR(cb->get_arrow_batch(result)); + return Status::OK(); +} + +void ResultBufferMgr::set_arrow_schema(const TUniqueId& query_id, const std::shared_ptr& arrow_schema) { + _arrow_schema_map.insert(std::make_pair(query_id, arrow_schema)); +} + +std::shared_ptr ResultBufferMgr::get_arrow_schema(const TUniqueId& query_id) { + auto iter = _arrow_schema_map.find(query_id); + if (_arrow_schema_map.end() != iter) { + return iter->second; + } + return nullptr; +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status ResultBufferMgr::cancel(const TUniqueId& query_id) { std::lock_guard l(_lock); auto iter = _buffer_map.find(query_id); diff --git a/be/src/runtime/result_buffer_mgr.h b/be/src/runtime/result_buffer_mgr.h index 3cb633277fd24..83bd106a0ebfd 100644 --- a/be/src/runtime/result_buffer_mgr.h +++ b/be/src/runtime/result_buffer_mgr.h @@ -34,6 +34,11 @@ #pragma once +<<<<<<< HEAD +======= +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -74,9 +79,22 @@ class ResultBufferMgr { // cancel one query at a future time. Status cancel_at_time(time_t cancel_time, const TUniqueId& query_id); +<<<<<<< HEAD +private: + typedef std::unordered_map> BufferMap; + typedef std::map> TimeoutMap; +======= + Status fetch_arrow_data(const TUniqueId& query_id, std::shared_ptr* result); + + void set_arrow_schema(const TUniqueId& query_id, const std::shared_ptr& arrow_schema); + + std::shared_ptr get_arrow_schema(const TUniqueId& query_id); + private: typedef std::unordered_map> BufferMap; typedef std::map> TimeoutMap; + typedef std::unordered_map> ArrowSchemaMap; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::shared_ptr find_control_block(const TUniqueId& query_id); @@ -98,5 +116,10 @@ class ResultBufferMgr { TimeoutMap _timeout_map; std::unique_ptr _cancel_thread; +<<<<<<< HEAD +======= + + ArrowSchemaMap _arrow_schema_map; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/runtime/result_queue_mgr.h b/be/src/runtime/result_queue_mgr.h index 43fffa2b1149b..b440310c2476e 100644 --- a/be/src/runtime/result_queue_mgr.h +++ b/be/src/runtime/result_queue_mgr.h @@ -43,12 +43,20 @@ class ResultQueueMgr { ResultQueueMgr(); ~ResultQueueMgr(); +<<<<<<< HEAD [[nodiscard]] Status fetch_result(const TUniqueId& fragment_instance_id, std::shared_ptr* result, bool* eos); void create_queue(const TUniqueId& fragment_instance_id, BlockQueueSharedPtr* queue); [[nodiscard]] Status cancel(const TUniqueId& fragment_id); +======= + Status fetch_result(const TUniqueId& fragment_instance_id, std::shared_ptr* result, bool* eos); + + void create_queue(const TUniqueId& fragment_instance_id, BlockQueueSharedPtr* queue); + + Status cancel(const TUniqueId& fragment_id); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void update_queue_status(const TUniqueId& fragment_id, const Status& status); diff --git a/be/src/runtime/result_sink.cpp b/be/src/runtime/result_sink.cpp index 71ae1dde22ef8..4ab66d80693b4 100644 --- a/be/src/runtime/result_sink.cpp +++ b/be/src/runtime/result_sink.cpp @@ -54,7 +54,11 @@ namespace starrocks { ResultSink::ResultSink(const RowDescriptor& row_desc, const std::vector& t_output_expr, const TResultSink& sink, int buffer_size) +<<<<<<< HEAD : _t_output_expr(t_output_expr), _buf_size(buffer_size) { +======= + : _row_desc(row_desc), _t_output_expr(t_output_expr), _buf_size(buffer_size) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!sink.__isset.type || sink.type == TResultSinkType::MYSQL_PROTOCAL) { _sink_type = TResultSinkType::MYSQL_PROTOCAL; } else { diff --git a/be/src/runtime/result_sink.h b/be/src/runtime/result_sink.h index a85665b269503..61a23a57fcd22 100644 --- a/be/src/runtime/result_sink.h +++ b/be/src/runtime/result_sink.h @@ -81,8 +81,16 @@ class ResultSink final : public DataSink { bool isBinaryFormat() const { return _is_binary_format; } +<<<<<<< HEAD private: Status prepare_exprs(RuntimeState* state); +======= + const RowDescriptor& get_row_desc() const { return _row_desc; } + +private: + Status prepare_exprs(RuntimeState* state); + const RowDescriptor& _row_desc; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TResultSinkType::type _sink_type; bool _is_binary_format; // set format_type when sink type is HTTP diff --git a/be/src/runtime/result_writer.h b/be/src/runtime/result_writer.h index d40d4af9fab64..77242601589df 100644 --- a/be/src/runtime/result_writer.h +++ b/be/src/runtime/result_writer.h @@ -34,6 +34,11 @@ #pragma once +<<<<<<< HEAD +======= +#include + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/vectorized_fwd.h" #include "common/status.h" #include "common/statusor.h" @@ -59,6 +64,7 @@ class ResultWriter { // convert one chunk to mysql result and // append this chunk to the result sink +<<<<<<< HEAD virtual Status append_chunk(Chunk* chunk) = 0; // decompose append_chunk into two functions: process_chunk and try_add_batch, @@ -72,12 +78,33 @@ class ResultWriter { virtual StatusOr try_add_batch(TFetchDataResultPtrs& results) { return Status::NotSupported("Not Implemented"); } +======= + // used in non-pipeline engine + virtual Status append_chunk(Chunk* chunk) = 0; + + // used in pipeline-engine no io block + virtual Status add_to_write_buffer(Chunk* chunk) { return Status::NotSupported("Not Implemented"); } + virtual bool is_full() const { throw std::runtime_error("not implements is full in ResultWriter"); } + virtual void cancel() { throw std::runtime_error("not implements is full in ResultWriter"); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual Status close() = 0; int64_t get_written_rows() const { return _written_rows; } protected: +<<<<<<< HEAD +======= + // used in pipeline engine, + // the former transform input chunk into multiple TFetchDataResult, the latter add TFetchDataResult + // to queue whose consumers are rpc threads that invoke fetch_data rpc. + // TODO: Avoid serialization overhead. + virtual StatusOr process_chunk(Chunk* chunk) { + return Status::NotSupported("Not Implemented"); + } + +protected: +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t _written_rows = 0; // number of rows written }; diff --git a/be/src/runtime/runtime_filter_worker.cpp b/be/src/runtime/runtime_filter_worker.cpp index d444ff2b432ae..a0d975eb095d2 100644 --- a/be/src/runtime/runtime_filter_worker.cpp +++ b/be/src/runtime/runtime_filter_worker.cpp @@ -14,14 +14,26 @@ #include "runtime/runtime_filter_worker.h" +<<<<<<< HEAD #include #include +======= +#include +#include +#include + +#include "column/bytes.h" +#include "common/config.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/pipeline/query_context.h" #include "exprs/runtime_filter_bank.h" #include "gen_cpp/PlanNodes_types.h" #include "gen_cpp/Types_types.h" // for TUniqueId +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/internal_service.pb.h" #include "runtime/current_thread.h" #include "runtime/exec_env.h" @@ -31,6 +43,11 @@ #include "service/backend_options.h" #include "util/brpc_stub_cache.h" #include "util/defer_op.h" +<<<<<<< HEAD +======= +#include "util/internal_service_recoverable_stub.h" +#include "util/metrics.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/thread.h" #include "util/time.h" @@ -58,7 +75,11 @@ static inline std::pair> static void send_rpc_runtime_filter(const TNetworkAddress& dest, RuntimeFilterRpcClosure* rpc_closure, int timeout_ms, int64_t http_min_size, const PTransmitRuntimeFilterParams& request) { +<<<<<<< HEAD PInternalService_Stub* stub = nullptr; +======= + std::shared_ptr stub = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool via_http = request.data().size() >= http_min_size; if (via_http) { if (auto res = HttpBrpcStubCache::getInstance()->get_http_stub(dest); res.ok()) { @@ -549,6 +570,13 @@ void RuntimeFilterWorker::close() { void RuntimeFilterWorker::open_query(const TUniqueId& query_id, const TQueryOptions& query_options, const TRuntimeFilterParams& params, bool is_pipeline) { VLOG_FILE << "RuntimeFilterWorker::open_query. query_id = " << query_id << ", params = " << params; +<<<<<<< HEAD +======= + if (_reach_queue_limit()) { + LOG(WARNING) << "runtime filter worker queue drop open query_id = " << query_id; + return; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeFilterWorkerEvent ev; ev.type = OPEN_QUERY; ev.query_id = query_id; @@ -568,9 +596,39 @@ void RuntimeFilterWorker::close_query(const TUniqueId& query_id) { _queue.put(std::move(ev)); } +<<<<<<< HEAD void RuntimeFilterWorker::send_part_runtime_filter(PTransmitRuntimeFilterParams&& params, const std::vector& addrs, int timeout_ms, int64_t rpc_http_min_size) { +======= +bool RuntimeFilterWorker::_reach_queue_limit() { + if (config::runtime_filter_queue_limit > 0) { + if (_queue.get_size() > config::runtime_filter_queue_limit) { + LOG(WARNING) << "runtime filter worker queue size is too large(" << _queue.get_size() + << "), queue limit = " << config::runtime_filter_queue_limit; + return true; + } + } else if (config::runtime_filter_queue_limit == 0) { + int64_t mem_usage = _metrics->total_rf_bytes(); + auto tracker = GlobalEnv::GetInstance()->query_pool_mem_tracker(); + if (tracker->limit_exceeded_precheck(mem_usage)) { + LOG(WARNING) << "runtime filter worker queue mem-useage is too large(" << mem_usage + << "), query pool consum(" << tracker->consumption() << "), limit(" << tracker->limit() << ")"; + return true; + } + } + return false; +} + +void RuntimeFilterWorker::send_part_runtime_filter(PTransmitRuntimeFilterParams&& params, + const std::vector& addrs, int timeout_ms, + int64_t rpc_http_min_size) { + if (_reach_queue_limit()) { + LOG(WARNING) << "runtime filter worker queue drop part runtime filter, query_id = " << params.query_id() + << ", filter_id = " << params.filter_id(); + return; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _exec_env->add_rf_event({params.query_id(), params.filter_id(), "", "SEND_PART_RF"}); RuntimeFilterWorkerEvent ev; ev.type = SEND_PART_RF; @@ -586,6 +644,14 @@ void RuntimeFilterWorker::send_part_runtime_filter(PTransmitRuntimeFilterParams& void RuntimeFilterWorker::send_broadcast_runtime_filter(PTransmitRuntimeFilterParams&& params, const std::vector& destinations, int timeout_ms, int64_t rpc_http_min_size) { +<<<<<<< HEAD +======= + if (_reach_queue_limit()) { + LOG(WARNING) << "runtime filter worker queue drop broadcast runtime filter, query_id = " << params.query_id() + << ", filter_id = " << params.filter_id(); + return; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _exec_env->add_rf_event({params.query_id(), params.filter_id(), "", "SEND_BROADCAST_RF"}); RuntimeFilterWorkerEvent ev; ev.type = SEND_BROADCAST_GRF; @@ -604,6 +670,14 @@ void RuntimeFilterWorker::receive_runtime_filter(const PTransmitRuntimeFilterPar << ", filter_id = " << params.filter_id() << ", # probe insts = " << params.probe_finst_ids_size() << ", is_pipeline = " << params.is_pipeline(); +<<<<<<< HEAD +======= + if (_reach_queue_limit()) { + LOG(WARNING) << "runtime filter worker queue drop receive runtime filter, query_id = " << params.query_id() + << ", filter_id = " << params.filter_id(); + return; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RuntimeFilterWorkerEvent ev; if (params.is_partial()) { _exec_env->add_rf_event({params.query_id(), params.filter_id(), "", "RECV_PART_RF"}); @@ -895,9 +969,12 @@ void RuntimeFilterWorker::execute() { break; } +<<<<<<< HEAD LOG_IF_EVERY_N(INFO, _queue.get_size() > CpuInfo::num_cores() * 10, 10) << "runtime filter worker queue may be too large, size: " << _queue.get_size(); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _metrics->update_event_nums(ev.type, -1); switch (ev.type) { case RECEIVE_TOTAL_RF: { @@ -965,4 +1042,11 @@ void RuntimeFilterWorker::execute() { LOG(INFO) << "RuntimeFilterWorker going to exit."; } +<<<<<<< HEAD +======= +size_t RuntimeFilterWorker::queue_size() const { + return _queue.get_size(); +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/runtime_filter_worker.h b/be/src/runtime/runtime_filter_worker.h index 83db444657053..5b399f6e1adb5 100644 --- a/be/src/runtime/runtime_filter_worker.h +++ b/be/src/runtime/runtime_filter_worker.h @@ -15,6 +15,10 @@ #pragma once #include +<<<<<<< HEAD +======= +#include +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include #include #include @@ -160,6 +164,17 @@ struct RuntimeFilterWorkerMetrics { void update_rf_bytes(EventType event_type, int64_t delta) { runtime_filter_bytes[event_type] += delta; } +<<<<<<< HEAD +======= + int64_t total_rf_bytes() { + int64_t total = 0; + for (int i = 0; i < EventType::MAX_COUNT; i++) { + total += runtime_filter_bytes[i]; + } + return total; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::array event_nums{}; std::array runtime_filter_bytes{}; }; @@ -203,6 +218,11 @@ class RuntimeFilterWorker { PTransmitRuntimeFilterParams&& params, int transmit_timeout_ms, int64_t rpc_http_min_size); +<<<<<<< HEAD +======= + bool _reach_queue_limit(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) UnboundedBlockingQueue _queue; std::unordered_map _mergers; ExecEnv* _exec_env; diff --git a/be/src/runtime/runtime_state.cpp b/be/src/runtime/runtime_state.cpp index 8997293930d7a..c40938783120e 100644 --- a/be/src/runtime/runtime_state.cpp +++ b/be/src/runtime/runtime_state.cpp @@ -46,7 +46,10 @@ #include "common/status.h" #include "exec/exec_node.h" #include "exec/pipeline/query_context.h" +<<<<<<< HEAD #include "exprs/jit/jit_engine.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "fs/fs_util.h" #ifdef USE_STAROS #include "fslib/star_cache_handler.h" @@ -62,6 +65,13 @@ #include "util/timezone_utils.h" #include "util/uid_util.h" +<<<<<<< HEAD +======= +#ifdef STARROCKS_JIT_ENABLE +#include "exprs/jit/jit_engine.h" +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { // for ut only @@ -241,6 +251,7 @@ ObjectPool* RuntimeState::global_obj_pool() const { return _query_ctx->object_pool(); } +<<<<<<< HEAD std::string RuntimeState::error_log() { std::lock_guard l(_error_log_lock); return boost::algorithm::join(_error_log, "\n"); @@ -274,6 +285,8 @@ void RuntimeState::get_unreported_errors(std::vector* new_errors) { } } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool RuntimeState::use_page_cache() { if (config::disable_storage_page_cache) { return false; @@ -284,6 +297,7 @@ bool RuntimeState::use_page_cache() { return true; } +<<<<<<< HEAD bool RuntimeState::use_column_pool() const { if (config::disable_column_pool) { return false; @@ -295,6 +309,8 @@ bool RuntimeState::use_column_pool() const { return true; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status RuntimeState::set_mem_limit_exceeded(MemTracker* tracker, int64_t failed_allocation_size, std::string_view msg) { DCHECK_GE(failed_allocation_size, 0); { @@ -319,7 +335,10 @@ Status RuntimeState::set_mem_limit_exceeded(MemTracker* tracker, int64_t failed_ << PrettyPrinter::print(failed_allocation_size, TUnit::BYTES) << " without exceeding limit." << std::endl; } +<<<<<<< HEAD log_error(ss.str()); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) DCHECK(_process_status.is_mem_limit_exceeded()); return _process_status; } @@ -523,8 +542,17 @@ Status RuntimeState::reset_epoch() { } bool RuntimeState::is_jit_enabled() const { +<<<<<<< HEAD return JITEngine::get_instance()->support_jit() && _query_options.__isset.jit_level && _query_options.jit_level != 0; +======= +#ifdef STARROCKS_JIT_ENABLE + return JITEngine::get_instance()->support_jit() && _query_options.__isset.jit_level && + _query_options.jit_level != 0; +#else + return false; +#endif +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void RuntimeState::update_load_datacache_metrics(TReportExecStatusParams* load_params) const { diff --git a/be/src/runtime/runtime_state.h b/be/src/runtime/runtime_state.h index 05fc4b4daa5c6..a810cf2230cd4 100644 --- a/be/src/runtime/runtime_state.h +++ b/be/src/runtime/runtime_state.h @@ -131,14 +131,20 @@ class RuntimeState { void set_desc_tbl(DescriptorTbl* desc_tbl) { _desc_tbl = desc_tbl; } int chunk_size() const { return _query_options.batch_size; } void set_chunk_size(int chunk_size) { _query_options.batch_size = chunk_size; } +<<<<<<< HEAD bool use_column_pool() const; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool abort_on_default_limit_exceeded() const { return _query_options.abort_on_default_limit_exceeded; } int64_t timestamp_ms() const { return _timestamp_us / 1000; } int64_t timestamp_us() const { return _timestamp_us; } const std::string& timezone() const { return _timezone; } const cctz::time_zone& timezone_obj() const { return _timezone_obj; } const std::string& user() const { return _user; } +<<<<<<< HEAD const std::vector& error_log() const { return _error_log; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) const std::string& last_query_id() const { return _last_query_id; } const TUniqueId& query_id() const { return _query_id; } const TUniqueId& fragment_instance_id() const { return _fragment_instance_id; } @@ -166,11 +172,16 @@ class RuntimeState { RuntimeProfile* load_channel_profile() { return _load_channel_profile.get(); } std::shared_ptr load_channel_profile_ptr() { return _load_channel_profile; } +<<<<<<< HEAD [[nodiscard]] Status query_status() { +======= + Status query_status() { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(_process_status_lock); return _process_status; }; +<<<<<<< HEAD // Appends error to the _error_log if there is space bool log_error(std::string_view error); @@ -190,6 +201,8 @@ class RuntimeState { // _unreported_error_idx to _errors_log.size() void get_unreported_errors(std::vector* new_errors); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool is_cancelled() const { return _is_cancelled.load(std::memory_order_acquire); } void set_is_cancelled(bool v) { _is_cancelled.store(v, std::memory_order_release); } @@ -223,19 +236,32 @@ class RuntimeState { // This value and tracker are only used for error reporting. // If 'msg' is not empty, it will be appended to query_status_ in addition to the // generic "Memory limit exceeded" error. +<<<<<<< HEAD [[nodiscard]] Status set_mem_limit_exceeded(MemTracker* tracker = nullptr, int64_t failed_allocation_size = 0, std::string_view msg = {}); [[nodiscard]] Status set_mem_limit_exceeded(std::string_view msg) { return set_mem_limit_exceeded(nullptr, 0, msg); } +======= + Status set_mem_limit_exceeded(MemTracker* tracker = nullptr, int64_t failed_allocation_size = 0, + std::string_view msg = {}); + + Status set_mem_limit_exceeded(std::string_view msg) { return set_mem_limit_exceeded(nullptr, 0, msg); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Returns a non-OK status if query execution should stop (e.g., the query was cancelled // or a mem limit was exceeded). Exec nodes should check this periodically so execution // doesn't continue if the query terminates abnormally. +<<<<<<< HEAD [[nodiscard]] Status check_query_state(const std::string& msg); [[nodiscard]] Status check_mem_limit(const std::string& msg); +======= + Status check_query_state(const std::string& msg); + + Status check_mem_limit(const std::string& msg); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector& output_files() { return _output_files; } @@ -264,7 +290,11 @@ class RuntimeState { bool has_reached_max_error_msg_num(bool is_summary = false); +<<<<<<< HEAD [[nodiscard]] Status create_rejected_record_file(); +======= + Status create_rejected_record_file(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool enable_log_rejected_record() { return _query_options.log_rejected_record_num == -1 || @@ -464,10 +494,17 @@ class RuntimeState { const phmap::flat_hash_map& load_dict_versions() { return _load_dict_versions; } using GlobalDictLists = std::vector; +<<<<<<< HEAD [[nodiscard]] Status init_query_global_dict(const GlobalDictLists& global_dict_list); [[nodiscard]] Status init_load_global_dict(const GlobalDictLists& global_dict_list); [[nodiscard]] Status init_query_global_dict_exprs(const std::map& exprs); +======= + Status init_query_global_dict(const GlobalDictLists& global_dict_list); + Status init_load_global_dict(const GlobalDictLists& global_dict_list); + + Status init_query_global_dict_exprs(const std::map& exprs); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void set_func_version(int func_version) { this->_func_version = func_version; } int func_version() const { return this->_func_version; } @@ -477,7 +514,11 @@ class RuntimeState { std::shared_ptr query_recv(); +<<<<<<< HEAD [[nodiscard]] Status reset_epoch(); +======= + Status reset_epoch(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t get_rpc_http_min_size() { return _query_options.__isset.rpc_http_min_size ? _query_options.rpc_http_min_size : kRpcHttpMinSize; @@ -533,10 +574,17 @@ class RuntimeState { void _init(const TUniqueId& fragment_instance_id, const TQueryOptions& query_options, const TQueryGlobals& query_globals, ExecEnv* exec_env); +<<<<<<< HEAD [[nodiscard]] Status create_error_log_file(); [[nodiscard]] Status _build_global_dict(const GlobalDictLists& global_dict_list, GlobalDictMaps* result, phmap::flat_hash_map* version); +======= + Status create_error_log_file(); + + Status _build_global_dict(const GlobalDictLists& global_dict_list, GlobalDictMaps* result, + phmap::flat_hash_map* version); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // put runtime state before _obj_pool, so that it will be deconstructed after // _obj_pool. Because some object in _obj_pool will use profile when deconstructing. @@ -551,9 +599,12 @@ class RuntimeState { // Lock protecting _error_log and _unreported_error_idx std::mutex _error_log_lock; +<<<<<<< HEAD // Logs error messages. std::vector _error_log; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::mutex _rejected_record_lock; std::string _rejected_record_file_path; std::unique_ptr _rejected_record_file; diff --git a/be/src/runtime/schema_table_sink.cpp b/be/src/runtime/schema_table_sink.cpp index ee8efbb6180d4..fc570cb7a6ea5 100644 --- a/be/src/runtime/schema_table_sink.cpp +++ b/be/src/runtime/schema_table_sink.cpp @@ -70,8 +70,12 @@ static Status set_config_remote(const StarRocksNodesInfo& nodes_info, int64_t be if (node_info == nullptr) { return Status::InternalError(strings::Substitute("set_config fail: be $0 not found", be_id)); } +<<<<<<< HEAD PInternalService_Stub* stub = ExecEnv::GetInstance()->brpc_stub_cache()->get_stub(node_info->host, node_info->brpc_port); +======= + auto stub = ExecEnv::GetInstance()->brpc_stub_cache()->get_stub(node_info->host, node_info->brpc_port); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (stub == nullptr) { return Status::InternalError(strings::Substitute("set_config fail to get brpc stub for $0:$1", node_info->host, node_info->brpc_port)); diff --git a/be/src/runtime/small_file_mgr.h b/be/src/runtime/small_file_mgr.h index 53396eb28caf4..57af1f0411769 100644 --- a/be/src/runtime/small_file_mgr.h +++ b/be/src/runtime/small_file_mgr.h @@ -48,6 +48,7 @@ class SmallFileMgr { ~SmallFileMgr(); // call init() when BE start up. load all local files +<<<<<<< HEAD [[nodiscard]] Status init(); // get file by specified file_id, return 'file_path' @@ -63,6 +64,23 @@ class SmallFileMgr { [[nodiscard]] Status _check_file(const CacheEntry& entry, const std::string& md5); [[nodiscard]] Status _download_file(int64_t file_id, const std::string& md5, std::string* file_path); +======= + Status init(); + + // get file by specified file_id, return 'file_path' + // if file does not exist, it will be downloaded from FE + Status get_file(int64_t file_id, const std::string& md5, std::string* file_path); + +private: + Status _load_local_files(); + + // load one single local file + Status _load_single_file(const std::string& path, const std::string& file_name); + + Status _check_file(const CacheEntry& entry, const std::string& md5); + + Status _download_file(int64_t file_id, const std::string& md5, std::string* file_path); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: std::mutex _lock; diff --git a/be/src/runtime/snapshot_loader.cpp b/be/src/runtime/snapshot_loader.cpp index 7a7fc17b7a10f..f2223efde3fbb 100644 --- a/be/src/runtime/snapshot_loader.cpp +++ b/be/src/runtime/snapshot_loader.cpp @@ -39,7 +39,10 @@ #include #include "agent/master_info.h" +<<<<<<< HEAD #include "common/config.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "common/logging.h" #include "fs/fs.h" #include "fs/fs_broker.h" @@ -51,7 +54,12 @@ #include "gen_cpp/TFileBrokerService.h" #include "runtime/broker_mgr.h" #include "runtime/exec_env.h" +<<<<<<< HEAD #include "storage/inverted/clucene/clucene_plugin.h" +======= +#include "storage/index/index_descriptor.h" +#include "storage/index/inverted/clucene/clucene_plugin.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "storage/snapshot_manager.h" #include "storage/storage_engine.h" #include "storage/tablet.h" @@ -1006,7 +1014,12 @@ Status SnapshotLoader::_replace_tablet_id(const std::string& file_name, int64_t *new_file_name = ss.str(); return Status::OK(); } else if (_end_with(file_name, ".idx") || _end_with(file_name, ".dat") || _end_with(file_name, "meta") || +<<<<<<< HEAD _end_with(file_name, ".del") || _end_with(file_name, ".cols") || _end_with(file_name, ".upt")) { +======= + _end_with(file_name, ".del") || _end_with(file_name, ".cols") || _end_with(file_name, ".upt") || + _end_with(file_name, ".vi")) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) *new_file_name = file_name; return Status::OK(); } else if (CLucenePlugin::is_index_files(file_name)) { diff --git a/be/src/runtime/statistic_result_writer.cpp b/be/src/runtime/statistic_result_writer.cpp index d099f9a246b5b..3719c6e07b549 100644 --- a/be/src/runtime/statistic_result_writer.cpp +++ b/be/src/runtime/statistic_result_writer.cpp @@ -33,11 +33,19 @@ const int STATISTIC_PARTITION_VERSION = 11; const int STATISTIC_EXTERNAL_VERSION = 5; const int STATISTIC_EXTERNAL_QUERY_VERSION = 6; const int STATISTIC_EXTERNAL_HISTOGRAM_VERSION = 7; +<<<<<<< HEAD +======= +const int STATISTIC_EXTERNAL_QUERY_VERSION_V2 = 8; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatisticResultWriter::StatisticResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, starrocks::RuntimeProfile* parent_profile) +<<<<<<< HEAD : _sinker(sinker), _output_expr_ctxs(output_expr_ctxs), _parent_profile(parent_profile) {} +======= + : BufferControlResultWriter(sinker, parent_profile), _output_expr_ctxs(output_expr_ctxs) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatisticResultWriter::~StatisticResultWriter() = default; @@ -50,6 +58,7 @@ Status StatisticResultWriter::init(RuntimeState* state) { } void StatisticResultWriter::_init_profile() { +<<<<<<< HEAD _total_timer = ADD_TIMER(_parent_profile, "TotalSendTime"); _serialize_timer = ADD_CHILD_TIMER(_parent_profile, "SerializeTime", "TotalSendTime"); _sent_rows_counter = ADD_COUNTER(_parent_profile, "NumSentRows", TUnit::UNIT); @@ -57,6 +66,14 @@ void StatisticResultWriter::_init_profile() { Status StatisticResultWriter::append_chunk(Chunk* chunk) { SCOPED_TIMER(_total_timer); +======= + BufferControlResultWriter::_init_profile(); + _serialize_timer = ADD_TIMER(_parent_profile, "SerializeTime"); +} + +Status StatisticResultWriter::append_chunk(Chunk* chunk) { + SCOPED_TIMER(_append_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto process_status = _process_chunk(chunk); if (!process_status.ok() || process_status.value() == nullptr) { return process_status.status(); @@ -76,7 +93,11 @@ Status StatisticResultWriter::append_chunk(Chunk* chunk) { } StatusOr StatisticResultWriter::process_chunk(Chunk* chunk) { +<<<<<<< HEAD SCOPED_TIMER(_total_timer); +======= + SCOPED_TIMER(_append_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TFetchDataResultPtrs results; auto process_status = _process_chunk(chunk); if (!process_status.ok()) { @@ -88,6 +109,7 @@ StatusOr StatisticResultWriter::process_chunk(Chunk* chunk return results; } +<<<<<<< HEAD StatusOr StatisticResultWriter::try_add_batch(TFetchDataResultPtrs& results) { size_t num_rows = 0; for (auto& result : results) { @@ -108,6 +130,8 @@ StatusOr StatisticResultWriter::try_add_batch(TFetchDataResultPtrs& result return status; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr StatisticResultWriter::_process_chunk(Chunk* chunk) { if (nullptr == chunk || 0 == chunk->num_rows()) { return nullptr; @@ -164,6 +188,12 @@ StatusOr StatisticResultWriter::_process_chunk(Chunk* chunk } else if (version == STATISTIC_EXTERNAL_HISTOGRAM_VERSION) { RETURN_IF_ERROR_WITH_WARN(_fill_statistic_histogram_external(version, result_columns, chunk, result.get()), "Fill table statistic data failed"); +<<<<<<< HEAD +======= + } else if (version == STATISTIC_EXTERNAL_QUERY_VERSION_V2) { + RETURN_IF_ERROR_WITH_WARN(_fill_full_statistic_query_external_v2(version, result_columns, chunk, result.get()), + "Fill table statistic data failed"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return result; } @@ -517,8 +547,49 @@ Status StatisticResultWriter::_fill_full_statistic_query_external(int version, c return Status::OK(); } +<<<<<<< HEAD Status StatisticResultWriter::close() { COUNTER_SET(_sent_rows_counter, _written_rows); +======= +Status StatisticResultWriter::_fill_full_statistic_query_external_v2(int version, const Columns& columns, + const Chunk* chunk, TFetchDataResult* result) { + SCOPED_TIMER(_serialize_timer); + + // mapping with Data.thrift.TStatisticData + DCHECK(columns.size() == 9); + + auto columnName = ColumnViewer(columns[1]); + auto rowCounts = ColumnViewer(columns[2]); + auto dataSizes = ColumnViewer(columns[3]); + auto countDistincts = ColumnViewer(columns[4]); + auto nullCounts = ColumnViewer(columns[5]); + auto maxColumn = ColumnViewer(columns[6]); + auto minColumn = ColumnViewer(columns[7]); + auto updateTime = ColumnViewer(columns[8]); + + std::vector data_list; + int num_rows = chunk->num_rows(); + + data_list.resize(num_rows); + for (int i = 0; i < num_rows; ++i) { + data_list[i].__set_columnName(columnName.value(i).to_string()); + data_list[i].__set_rowCount(rowCounts.value(i)); + data_list[i].__set_dataSize(dataSizes.value(i)); + data_list[i].__set_countDistinct(countDistincts.value(i)); + data_list[i].__set_nullCount(nullCounts.value(i)); + data_list[i].__set_max(maxColumn.value(i).to_string()); + data_list[i].__set_min(minColumn.value(i).to_string()); + data_list[i].__set_updateTime(updateTime.value(i).to_string()); + } + + result->result_batch.rows.resize(num_rows); + result->result_batch.__set_statistic_version(version); + + ThriftSerializer serializer(true, chunk->memory_usage()); + for (int i = 0; i < num_rows; ++i) { + RETURN_IF_ERROR(serializer.serialize(&data_list[i], &result->result_batch.rows[i])); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return Status::OK(); } diff --git a/be/src/runtime/statistic_result_writer.h b/be/src/runtime/statistic_result_writer.h index 7f6c3734b8bd8..717a72373522b 100644 --- a/be/src/runtime/statistic_result_writer.h +++ b/be/src/runtime/statistic_result_writer.h @@ -14,8 +14,12 @@ #pragma once +<<<<<<< HEAD #include "runtime/result_writer.h" #include "runtime/runtime_state.h" +======= +#include "runtime/buffer_control_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -24,7 +28,11 @@ class MysqlRowBuffer; class BufferControlBlock; class RuntimeProfile; +<<<<<<< HEAD class StatisticResultWriter final : public ResultWriter { +======= +class StatisticResultWriter final : public BufferControlResultWriter { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: StatisticResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile); @@ -35,6 +43,7 @@ class StatisticResultWriter final : public ResultWriter { Status append_chunk(Chunk* chunk) override; +<<<<<<< HEAD Status close() override; StatusOr process_chunk(Chunk* chunk) override; @@ -43,6 +52,12 @@ class StatisticResultWriter final : public ResultWriter { private: void _init_profile(); +======= + StatusOr process_chunk(Chunk* chunk) override; + +private: + void _init_profile() override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr _process_chunk(Chunk* chunk); @@ -65,10 +80,17 @@ class StatisticResultWriter final : public ResultWriter { Status _fill_full_statistic_query_external(int version, const Columns& columns, const Chunk* chunk, TFetchDataResult* result); +<<<<<<< HEAD +======= + Status _fill_full_statistic_query_external_v2(int version, const Columns& columns, const Chunk* chunk, + TFetchDataResult* result); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status _fill_statistic_histogram_external(int version, const Columns& columns, const Chunk* chunk, TFetchDataResult* result); private: +<<<<<<< HEAD BufferControlBlock* _sinker; const std::vector& _output_expr_ctxs; @@ -80,6 +102,10 @@ class StatisticResultWriter final : public ResultWriter { RuntimeProfile::Counter* _serialize_timer = nullptr; // number of sent rows RuntimeProfile::Counter* _sent_rows_counter = nullptr; +======= + const std::vector& _output_expr_ctxs; + RuntimeProfile::Counter* _serialize_timer = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/runtime/stream_load/stream_load_context.cpp b/be/src/runtime/stream_load/stream_load_context.cpp index 1a1feaa8b46ef..0bd9a9daf210f 100644 --- a/be/src/runtime/stream_load/stream_load_context.cpp +++ b/be/src/runtime/stream_load/stream_load_context.cpp @@ -136,7 +136,11 @@ std::string StreamLoadContext::to_json() const { // label writer.Key("Label"); +<<<<<<< HEAD writer.String(label.c_str()); +======= + writer.String(enable_batch_write ? batch_write_label.c_str() : label.c_str()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // status writer.Key("Status"); @@ -196,6 +200,17 @@ std::string StreamLoadContext::to_json() const { writer.Key("RejectedRecordPath"); writer.String(rejected_record_path.c_str()); } +<<<<<<< HEAD +======= + if (enable_batch_write) { + // if enable batch write, the user-provided label is treated as the request id + writer.Key("RequestId"); + writer.String(label.c_str()); + writer.Key("LeftTimeMs"); + writer.Int64(batch_left_time_nanos / 1000000); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) writer.EndObject(); return s.GetString(); } @@ -245,4 +260,13 @@ bool StreamLoadContext::check_and_set_http_limiter(ConcurrentLimiter* limiter) { return _http_limiter_guard->set_limiter(limiter); } +<<<<<<< HEAD +======= +void StreamLoadContext::release(StreamLoadContext* context) { + if (context != nullptr && context->unref()) { + delete context; + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/stream_load/stream_load_context.h b/be/src/runtime/stream_load/stream_load_context.h index 7875dfbb56810..3a1f9a158bd0e 100644 --- a/be/src/runtime/stream_load/stream_load_context.h +++ b/be/src/runtime/stream_load/stream_load_context.h @@ -176,6 +176,11 @@ class StreamLoadContext { bool check_and_set_http_limiter(ConcurrentLimiter* limiter); +<<<<<<< HEAD +======= + static void release(StreamLoadContext* context); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: // 1) Before the stream load receiving thread exits, Fragment may have been destructed. // At this time, mem_tracker may have been destructed, @@ -200,6 +205,12 @@ class StreamLoadContext { std::string db; std::string table; +<<<<<<< HEAD +======= + // if enable_batch_write is false, the label represents the txn + // otherwise, it just represents the request id of the load, and + // the batch_write_label represents the txn +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string label; // optional double max_filter_ratio = 0.0; @@ -280,6 +291,18 @@ class StreamLoadContext { int64_t load_deadline_sec = -1; std::unique_ptr _http_limiter_guard; +<<<<<<< HEAD +======= + // for batch write + bool enable_batch_write = false; + std::map load_parameters; + // the txn for the data belongs to. put the txn id into `txn_id`, + // and put label in this `batch_write_label` + std::string batch_write_label; + // A hint for the left time of this batch to finish + int64_t batch_left_time_nanos = -1; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: bool is_channel_stream_load_context() { return channel_id != -1; } ExecEnv* exec_env() { return _exec_env; } diff --git a/be/src/runtime/stream_load/stream_load_pipe.cpp b/be/src/runtime/stream_load/stream_load_pipe.cpp index e743e4dec13d9..39587cd790dd7 100644 --- a/be/src/runtime/stream_load/stream_load_pipe.cpp +++ b/be/src/runtime/stream_load/stream_load_pipe.cpp @@ -42,6 +42,7 @@ namespace starrocks { Status StreamLoadPipe::append(ByteBufferPtr&& buf) { if (buf != nullptr && buf->has_remaining()) { std::unique_lock l(_lock); +<<<<<<< HEAD if (_cancelled) { return _err_st; } @@ -49,10 +50,29 @@ Status StreamLoadPipe::append(ByteBufferPtr&& buf) { _put_cond.wait(l, [&]() { return _cancelled || _buf_queue.empty() || _buffered_bytes + buf->remaining() <= _max_buffered_bytes; }); +======= + + _num_waiting_append_buffer += 1; + // if _buf_queue is empty, we append this buf without size check + _put_cond.wait(l, [&]() { + return _cancelled || _finished || _buf_queue.empty() || + _buffered_bytes + buf->remaining() <= _max_buffered_bytes; + }); + _num_waiting_append_buffer -= 1; + + if (_finished) { + return Status::CapacityLimitExceed("Stream load pipe is finished"); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_cancelled) { return _err_st; } +<<<<<<< HEAD +======= + _num_append_buffers += 1; + _append_buffer_bytes += buf->remaining(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _buffered_bytes += buf->remaining(); _buf_queue.emplace_back(std::move(buf)); _get_cond.notify_one(); @@ -110,7 +130,11 @@ StatusOr StreamLoadPipe::read() { StatusOr StreamLoadPipe::no_block_read() { std::unique_lock l(_lock); +<<<<<<< HEAD _get_cond.wait_for(l, std::chrono::milliseconds(100), +======= + _get_cond.wait_for(l, std::chrono::milliseconds(_non_blocking_wait_ms), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [&]() { return _cancelled || _finished || !_buf_queue.empty(); }); // cancelled @@ -177,13 +201,18 @@ Status StreamLoadPipe::no_block_read(uint8_t* data, size_t* data_size, bool* eof if (_read_buf == nullptr || !_read_buf->has_remaining()) { std::unique_lock l(_lock); +<<<<<<< HEAD _get_cond.wait_for(l, std::chrono::milliseconds(100), +======= + _get_cond.wait_for(l, std::chrono::milliseconds(_non_blocking_wait_ms), +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) [&]() { return _cancelled || _finished || !_buf_queue.empty(); }); // cancelled if (_cancelled) { return _err_st; } +<<<<<<< HEAD // finished if (_buf_queue.empty()) { if (_finished) { @@ -205,6 +234,13 @@ Status StreamLoadPipe::no_block_read(uint8_t* data, size_t* data_size, bool* eof } return Status::TimedOut("stream load pipe time out"); } +======= + if (_buf_queue.empty()) { + *data_size = bytes_read; + *eof = _finished && (bytes_read == 0); + bool timeout = (bytes_read == 0) && !_finished; + return timeout ? Status::TimedOut("stream load pipe time out") : Status::OK(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } _read_buf = _buf_queue.front(); _buf_queue.pop_front(); @@ -233,6 +269,10 @@ Status StreamLoadPipe::finish() { std::lock_guard l(_lock); _finished = true; } +<<<<<<< HEAD +======= + _put_cond.notify_all(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _get_cond.notify_all(); return Status::OK(); } @@ -242,7 +282,11 @@ void StreamLoadPipe::cancel(const Status& status) { std::lock_guard l(_lock); _cancelled = true; if (_err_st.ok()) { +<<<<<<< HEAD _err_st = status; +======= + _err_st = status.ok() ? Status::Cancelled("Cancelled with ok status") : status; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } _get_cond.notify_all(); @@ -267,6 +311,7 @@ Status StreamLoadPipe::_append(const ByteBufferPtr& buf) { return Status::OK(); } +<<<<<<< HEAD Status StreamLoadPipe::_push_front_unlocked(const ByteBufferPtr& buf) { DCHECK(buf != nullptr && buf->has_remaining()); if (_cancelled) { @@ -278,6 +323,8 @@ Status StreamLoadPipe::_push_front_unlocked(const ByteBufferPtr& buf) { return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) CompressedStreamLoadPipeReader::CompressedStreamLoadPipeReader(std::shared_ptr pipe, TCompressionType::type compression_type) : StreamLoadPipeReader(std::move(pipe)), _compression_type(compression_type) {} @@ -342,12 +389,16 @@ StatusOr CompressedStreamLoadPipeReader::read() { return _decompressed_buffer; } +<<<<<<< HEAD StreamLoadPipeInputStream::StreamLoadPipeInputStream(std::shared_ptr file, bool non_blocking_read) : _pipe(std::move(file)) { if (non_blocking_read) { _pipe->set_non_blocking_read(); } } +======= +StreamLoadPipeInputStream::StreamLoadPipeInputStream(std::shared_ptr file) : _pipe(std::move(file)) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StreamLoadPipeInputStream::~StreamLoadPipeInputStream() { _pipe->close(); diff --git a/be/src/runtime/stream_load/stream_load_pipe.h b/be/src/runtime/stream_load/stream_load_pipe.h index babd97e54ef70..719406b775b7c 100644 --- a/be/src/runtime/stream_load/stream_load_pipe.h +++ b/be/src/runtime/stream_load/stream_load_pipe.h @@ -47,12 +47,32 @@ namespace starrocks { +<<<<<<< HEAD +======= +static constexpr size_t DEFAULT_STREAM_LOAD_PIPE_BUFFERED_BYTES = 1024 * 1024; +static constexpr size_t DEFAULT_STREAM_LOAD_PIPE_CHUNK_SIZE = 64 * 1024; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // StreamLoadPipe use to transfer data from producer to consumer // Data in pip is stored in chunks. class StreamLoadPipe : public MessageBodySink { public: +<<<<<<< HEAD StreamLoadPipe(size_t max_buffered_bytes = 1024 * 1024, size_t min_chunk_size = 64 * 1024) : _max_buffered_bytes(max_buffered_bytes), _min_chunk_size(min_chunk_size) {} +======= + StreamLoadPipe(size_t max_buffered_bytes = DEFAULT_STREAM_LOAD_PIPE_BUFFERED_BYTES, + size_t min_chunk_size = DEFAULT_STREAM_LOAD_PIPE_CHUNK_SIZE) + : StreamLoadPipe(false, -1, max_buffered_bytes, min_chunk_size) {} + + StreamLoadPipe(bool non_blocking_read, int32_t non_blocking_wait_ms, size_t max_buffered_bytes, + size_t min_chunk_size) + : _non_blocking_read(non_blocking_read), + _non_blocking_wait_ms(non_blocking_wait_ms), + _max_buffered_bytes(max_buffered_bytes), + _min_chunk_size(min_chunk_size) {} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~StreamLoadPipe() override = default; Status append(ByteBufferPtr&& buf) override; @@ -68,12 +88,20 @@ class StreamLoadPipe : public MessageBodySink { StatusOr no_block_read(); +<<<<<<< HEAD Status read(uint8_t* data, size_t* data_size, bool* eof); +======= + virtual Status read(uint8_t* data, size_t* data_size, bool* eof); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status no_block_read(uint8_t* data, size_t* data_size, bool* eof); // called when consumer finished +<<<<<<< HEAD void close() { cancel(Status::OK()); } +======= + void close() { cancel(Status::Cancelled("Close the pipe")); } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // called when producer finished Status finish() override; @@ -81,11 +109,29 @@ class StreamLoadPipe : public MessageBodySink { // called when producer/consumer failed void cancel(const Status& status) override; +<<<<<<< HEAD void set_non_blocking_read() { _non_blocking_read = true; } +======= + int32_t num_waiting_append_buffer() { + std::unique_lock l(_lock); + return _num_waiting_append_buffer; + } + + int32_t num_append_buffers() { + std::unique_lock l(_lock); + return _num_append_buffers; + } + + int64_t append_buffer_bytes() { + std::unique_lock l(_lock); + return _append_buffer_bytes; + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: Status _append(const ByteBufferPtr& buf); +<<<<<<< HEAD // Called when `no_block_read(uint8_t* data, size_t* data_size, bool* eof)` // timeout in the mid of read, we will push the read data back to the _buf_queue. // The lock is already acquired before calling this function @@ -95,12 +141,25 @@ class StreamLoadPipe : public MessageBodySink { // Blocking queue std::mutex _lock; size_t _buffered_bytes{0}; +======= + // Blocking queue + std::mutex _lock; + size_t _buffered_bytes{0}; + bool _non_blocking_read{false}; + int32_t _non_blocking_wait_ms; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t _max_buffered_bytes; size_t _min_chunk_size; std::deque _buf_queue; std::condition_variable _put_cond; std::condition_variable _get_cond; +<<<<<<< HEAD bool _non_blocking_read{false}; +======= + int32_t _num_waiting_append_buffer{0}; + int32_t _num_append_buffers{0}; + int64_t _append_buffer_bytes{0}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool _finished{false}; bool _cancelled{false}; @@ -137,7 +196,11 @@ class CompressedStreamLoadPipeReader : public StreamLoadPipeReader { // TODO: Make `StreamLoadPipe` as a derived class of `io::InputStream`. class StreamLoadPipeInputStream : public io::InputStream { public: +<<<<<<< HEAD explicit StreamLoadPipeInputStream(std::shared_ptr file, bool non_blocking_read); +======= + explicit StreamLoadPipeInputStream(std::shared_ptr file); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ~StreamLoadPipeInputStream() override; StatusOr read(void* data, int64_t size) override; diff --git a/be/src/runtime/stream_load/time_bounded_stream_load_pipe.cpp b/be/src/runtime/stream_load/time_bounded_stream_load_pipe.cpp new file mode 100644 index 0000000000000..d6cd36f2aff64 --- /dev/null +++ b/be/src/runtime/stream_load/time_bounded_stream_load_pipe.cpp @@ -0,0 +1,44 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "runtime/stream_load/time_bounded_stream_load_pipe.h" + +#include "runtime/batch_write/batch_write_util.h" + +namespace starrocks { + +StatusOr TimeBoundedStreamLoadPipe::read() { + RETURN_IF_ERROR(_finish_pipe_if_needed()); + return StreamLoadPipe::read(); +} + +Status TimeBoundedStreamLoadPipe::read(uint8_t* data, size_t* data_size, bool* eof) { + RETURN_IF_ERROR(_finish_pipe_if_needed()); + return StreamLoadPipe::read(data, data_size, eof); +} + +Status TimeBoundedStreamLoadPipe::_finish_pipe_if_needed() { + auto current_ts = _get_current_ns(); + if (_start_time_ns + _active_window_ns <= current_ts) { + auto st = StreamLoadPipe::finish(); + TRACE_BATCH_WRITE << "finish pipe: " << _name << ", expect active: " << (_active_window_ns / 1000000) + << " ms, actual active: " << (current_ts - _start_time_ns) / 1000000 + << " ms, num appends: " << num_append_buffers() << ", bytes: " << append_buffer_bytes() + << ", status: " << st; + return st; + } + return Status::OK(); +} + +} // namespace starrocks diff --git a/be/src/runtime/stream_load/time_bounded_stream_load_pipe.h b/be/src/runtime/stream_load/time_bounded_stream_load_pipe.h new file mode 100644 index 0000000000000..fe9c2159bc632 --- /dev/null +++ b/be/src/runtime/stream_load/time_bounded_stream_load_pipe.h @@ -0,0 +1,67 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include "runtime/stream_load/stream_load_pipe.h" +#include "testutil/sync_point.h" +#include "util/time.h" + +namespace starrocks { + +static constexpr int32_t DEFAULT_STREAM_LOAD_PIPE_NON_BLOCKING_WAIT_MS = 50; + +class TimeBoundedStreamLoadPipe : public StreamLoadPipe { +public: + TimeBoundedStreamLoadPipe(const std::string& name, int32_t active_window_ms, + int32_t non_blocking_wait_ms = DEFAULT_STREAM_LOAD_PIPE_NON_BLOCKING_WAIT_MS, + size_t max_buffered_bytes = DEFAULT_STREAM_LOAD_PIPE_BUFFERED_BYTES) + : StreamLoadPipe(true, non_blocking_wait_ms, max_buffered_bytes, DEFAULT_STREAM_LOAD_PIPE_CHUNK_SIZE) { + _name = name; + _active_window_ns = active_window_ms * (int64_t)1000000; + _start_time_ns = _get_current_ns(); + } + + Status append(ByteBufferPtr&& buf) override { return StreamLoadPipe::append(std::move(buf)); } + + Status append(const char* data, size_t size) override { + return Status::NotSupported("TimeBoundedStreamLoadPipe does not support input with char array"); + } + + StatusOr read() override; + + Status read(uint8_t* data, size_t* data_size, bool* eof) override; + + int64_t left_active_ns() { + int64_t left = _active_window_ns - (_get_current_ns() - _start_time_ns); + return std::max((int64_t)0, left); + } + +private: + int64_t _get_current_ns() { + int64_t current_ts = MonotonicNanos(); + TEST_SYNC_POINT_CALLBACK("TimeBoundedStreamLoadPipe::get_current_ns", ¤t_ts); + return current_ts; + } + + Status _finish_pipe_if_needed(); + + std::string _name; + int64_t _start_time_ns; + int64_t _active_window_ns; +}; + +} // namespace starrocks diff --git a/be/src/runtime/stream_load/transaction_mgr.h b/be/src/runtime/stream_load/transaction_mgr.h index bee14fd63dccb..d33d005985df3 100644 --- a/be/src/runtime/stream_load/transaction_mgr.h +++ b/be/src/runtime/stream_load/transaction_mgr.h @@ -92,7 +92,11 @@ class StreamContextMgr { Status create_channel_context(ExecEnv* exec_env, const string& label, int channel_id, const string& db_name, const string& table_name, TFileFormatType::type format, StreamLoadContext*& ctx, const TUniqueId& load_id, long txn_id) { +<<<<<<< HEAD auto pipe = std::make_shared(); +======= + auto pipe = std::make_shared(true); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(exec_env->load_stream_mgr()->put(load_id, pipe)); ctx = new StreamLoadContext(exec_env, load_id); if (ctx == nullptr) { diff --git a/be/src/runtime/table_function_table_sink.cpp b/be/src/runtime/table_function_table_sink.cpp index 52b76bc1066cf..719ad5221e02b 100644 --- a/be/src/runtime/table_function_table_sink.cpp +++ b/be/src/runtime/table_function_table_sink.cpp @@ -14,7 +14,19 @@ #include "table_function_table_sink.h" +<<<<<<< HEAD #include "exprs/expr.h" +======= +#include "common/logging.h" +#include "connector/file_chunk_sink.h" +#include "connector/hive_chunk_sink.h" +#include "exec/data_sink.h" +#include "exec/hdfs_scanner_text.h" +#include "exec/pipeline/sink/connector_sink_operator.h" +#include "exprs/expr.h" +#include "formats/column_evaluator.h" +#include "formats/csv/csv_file_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "glog/logging.h" #include "runtime/runtime_state.h" #include "util/runtime_profile.h" diff --git a/be/src/runtime/table_function_table_sink.h b/be/src/runtime/table_function_table_sink.h index a3b84264172ee..06f8b93c33324 100644 --- a/be/src/runtime/table_function_table_sink.h +++ b/be/src/runtime/table_function_table_sink.h @@ -14,6 +14,7 @@ #pragma once +<<<<<<< HEAD #include "common/logging.h" #include "connector/file_chunk_sink.h" #include "connector/hive_chunk_sink.h" @@ -22,6 +23,9 @@ #include "exec/pipeline/sink/connector_sink_operator.h" #include "formats/column_evaluator.h" #include "formats/csv/csv_file_writer.h" +======= +#include "exec/data_sink.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { diff --git a/be/src/runtime/tablets_channel.h b/be/src/runtime/tablets_channel.h index 647586acd13c3..986bcd3cdf2da 100644 --- a/be/src/runtime/tablets_channel.h +++ b/be/src/runtime/tablets_channel.h @@ -50,14 +50,23 @@ class TabletsChannel { TabletsChannel() = default; virtual ~TabletsChannel() = default; +<<<<<<< HEAD [[nodiscard]] virtual Status open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema, bool is_incremental) = 0; +======= + virtual Status open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, + std::shared_ptr schema, bool is_incremental) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual Status incremental_open(const PTabletWriterOpenRequest& params, PTabletWriterOpenResult* result, std::shared_ptr schema) = 0; virtual void add_chunk(Chunk* chunk, const PTabletWriterAddChunkRequest& request, +<<<<<<< HEAD PTabletWriterAddBatchResult* response) = 0; +======= + PTabletWriterAddBatchResult* response, bool* close_channel_ptr) = 0; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void cancel() = 0; @@ -68,6 +77,11 @@ class TabletsChannel { // timeout: in microseconds virtual bool drain_senders(int64_t timeout, const std::string& log_msg); +<<<<<<< HEAD +======= + virtual void update_profile() = 0; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) protected: // counter of remaining senders std::atomic _num_remaining_senders = 0; diff --git a/be/src/runtime/time_types.h b/be/src/runtime/time_types.h index 8640ab3899c41..6a2394120e2c5 100644 --- a/be/src/runtime/time_types.h +++ b/be/src/runtime/time_types.h @@ -239,7 +239,11 @@ class timestamp { // MIN_DATE | 0 static const Timestamp MIN_TIMESTAMP = (1892325482100162560LL); +<<<<<<< HEAD // seconds from 1970.01.01 +======= + // seconds since julian date epoch to 1970.01.01 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) static const Timestamp UNIX_EPOCH_SECONDS = (210866803200LL); }; diff --git a/be/src/runtime/types.cpp b/be/src/runtime/types.cpp index c909ebd9abfe1..5d1b96a2dea8d 100644 --- a/be/src/runtime/types.cpp +++ b/be/src/runtime/types.cpp @@ -129,9 +129,13 @@ void TypeDescriptor::to_thrift(TTypeDesc* thrift_type) const { curr_node.__set_scalar_type(TScalarType()); TScalarType& scalar_type = curr_node.scalar_type; scalar_type.__set_type(starrocks::to_thrift(type)); +<<<<<<< HEAD if (len != -1) { scalar_type.__set_len(len); } +======= + scalar_type.__set_len(len); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (scale != -1) { scalar_type.__set_scale(scale); } @@ -165,9 +169,13 @@ void TypeDescriptor::to_protobuf(PTypeDesc* proto_type) const { node->set_type(TTypeNodeType::SCALAR); PScalarType* scalar_type = node->mutable_scalar_type(); scalar_type->set_type(starrocks::to_thrift(type)); +<<<<<<< HEAD if (len != -1) { scalar_type->set_len(len); } +======= + scalar_type->set_len(len); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (scale != -1) { scalar_type->set_scale(scale); } diff --git a/be/src/runtime/types.h b/be/src/runtime/types.h index c7088675babbd..325f0df49e5ef 100644 --- a/be/src/runtime/types.h +++ b/be/src/runtime/types.h @@ -363,6 +363,11 @@ struct TypeDescriptor { void to_protobuf(PTypeDesc* proto_type) const; }; +<<<<<<< HEAD +======= +static const TypeDescriptor TYPE_INT_DESC = TypeDescriptor(LogicalType::TYPE_INT); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) inline std::ostream& operator<<(std::ostream& os, const TypeDescriptor& type) { os << type.debug_string(); return os; diff --git a/be/src/runtime/user_function_cache.cpp b/be/src/runtime/user_function_cache.cpp index 6b9698dce96aa..adbd59762c9bd 100644 --- a/be/src/runtime/user_function_cache.cpp +++ b/be/src/runtime/user_function_cache.cpp @@ -176,6 +176,11 @@ Status UserFunctionCache::_load_entry_from_lib(const std::string& dir, const std int UserFunctionCache::get_function_type(const std::string& url) { if (boost::algorithm::ends_with(url, JAVA_UDF_SUFFIX)) { return UDF_TYPE_JAVA; +<<<<<<< HEAD +======= + } else if (boost::algorithm::ends_with(url, PY_UDF_SUFFIX)) { + return UDF_TYPE_PYTHON; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return UDF_TYPE_UNKNOWN; } @@ -210,9 +215,15 @@ Status UserFunctionCache::_get_cache_entry(int64_t fid, const std::string& url, if (type == UDF_TYPE_JAVA) { suffix = JAVA_UDF_SUFFIX; } +<<<<<<< HEAD if (type != UDF_TYPE_JAVA) { return Status::NotSupported( fmt::format("unsupport udf type: {}, url: {}. url suffix must be '{}'", type, url, JAVA_UDF_SUFFIX)); +======= + if (type != UDF_TYPE_JAVA && type != UDF_TYPE_PYTHON) { + return Status::NotSupported(fmt::format("unsupport udf type: {}, url: {}. url suffix must be '{}' or '{}'", + type, url, JAVA_UDF_SUFFIX, PY_UDF_SUFFIX)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } UserFunctionCacheEntryPtr entry; @@ -283,12 +294,21 @@ Status UserFunctionCache::_download_lib(const std::string& url, UserFunctionCach template Status UserFunctionCache::_load_cache_entry_internal(const std::string& url, UserFunctionCacheEntryPtr& entry, Loader&& loader) { +<<<<<<< HEAD if (entry->function_type == UDF_TYPE_JAVA) { // nothing to do ASSIGN_OR_RETURN(entry->cache_handle, loader(entry->lib_file)); } else { return Status::NotSupported(fmt::format("unsupport udf type: {}, url: {}. url suffix must be '{}'", entry->function_type, url, JAVA_UDF_SUFFIX)); +======= + if (entry->function_type == UDF_TYPE_JAVA || entry->function_type == UDF_TYPE_PYTHON) { + // nothing to do + ASSIGN_OR_RETURN(entry->cache_handle, loader(entry->lib_file)); + } else { + return Status::NotSupported(fmt::format("unsupport udf type: {}, url: {}. url suffix must be '{}' or '{}'", + entry->function_type, url, JAVA_UDF_SUFFIX, PY_UDF_SUFFIX)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } entry->is_loaded.store(true); return Status::OK(); diff --git a/be/src/runtime/user_function_cache.h b/be/src/runtime/user_function_cache.h index d4f67fb82ca42..bbe6a61e47581 100644 --- a/be/src/runtime/user_function_cache.h +++ b/be/src/runtime/user_function_cache.h @@ -59,8 +59,15 @@ struct UserFunctionCacheEntry; class UserFunctionCache { public: static constexpr const char* JAVA_UDF_SUFFIX = ".jar"; +<<<<<<< HEAD static constexpr int UDF_TYPE_UNKNOWN = -1; static constexpr int UDF_TYPE_JAVA = 1; +======= + static constexpr const char* PY_UDF_SUFFIX = ".py.zip"; + static constexpr int UDF_TYPE_UNKNOWN = -1; + static constexpr int UDF_TYPE_JAVA = 1; + static constexpr int UDF_TYPE_PYTHON = 2; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using UserFunctionCacheEntryPtr = std::shared_ptr; // local_dir is the directory which contain cached library. diff --git a/be/src/runtime/variable_result_writer.cpp b/be/src/runtime/variable_result_writer.cpp index da5ce08577d98..4d4644c88e482 100644 --- a/be/src/runtime/variable_result_writer.cpp +++ b/be/src/runtime/variable_result_writer.cpp @@ -28,7 +28,11 @@ namespace starrocks { VariableResultWriter::VariableResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, starrocks::RuntimeProfile* parent_profile) +<<<<<<< HEAD : _sinker(sinker), _output_expr_ctxs(output_expr_ctxs), _parent_profile(parent_profile) {} +======= + : BufferControlResultWriter(sinker, parent_profile), _output_expr_ctxs(output_expr_ctxs) {} +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) VariableResultWriter::~VariableResultWriter() = default; @@ -40,6 +44,7 @@ Status VariableResultWriter::init(RuntimeState* state) { return Status::OK(); } +<<<<<<< HEAD void VariableResultWriter::_init_profile() { _total_timer = ADD_TIMER(_parent_profile, "TotalSendTime"); _serialize_timer = ADD_CHILD_TIMER(_parent_profile, "SerializeTime", "TotalSendTime"); @@ -48,6 +53,10 @@ void VariableResultWriter::_init_profile() { Status VariableResultWriter::append_chunk(Chunk* chunk) { SCOPED_TIMER(_total_timer); +======= +Status VariableResultWriter::append_chunk(Chunk* chunk) { + SCOPED_TIMER(_append_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto process_status = _process_chunk(chunk); if (!process_status.ok() || process_status.value() == nullptr) { return process_status.status(); @@ -66,7 +75,11 @@ Status VariableResultWriter::append_chunk(Chunk* chunk) { } StatusOr VariableResultWriter::process_chunk(Chunk* chunk) { +<<<<<<< HEAD SCOPED_TIMER(_total_timer); +======= + SCOPED_TIMER(_append_chunk_timer); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) TFetchDataResultPtrs results; auto process_status = _process_chunk(chunk); if (!process_status.ok()) { @@ -78,6 +91,7 @@ StatusOr VariableResultWriter::process_chunk(Chunk* chunk) return results; } +<<<<<<< HEAD StatusOr VariableResultWriter::try_add_batch(TFetchDataResultPtrs& results) { size_t num_rows = 0; for (auto& result : results) { @@ -97,6 +111,8 @@ StatusOr VariableResultWriter::try_add_batch(TFetchDataResultPtrs& results return status; } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StatusOr VariableResultWriter::_process_chunk(Chunk* chunk) { if (nullptr == chunk || 0 == chunk->num_rows()) { return nullptr; @@ -135,9 +151,12 @@ StatusOr VariableResultWriter::_process_chunk(Chunk* chunk) return result; } +<<<<<<< HEAD Status VariableResultWriter::close() { COUNTER_SET(_sent_rows_counter, _written_rows); return Status::OK(); } +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/runtime/variable_result_writer.h b/be/src/runtime/variable_result_writer.h index 4468289a6d744..075044a0186e2 100644 --- a/be/src/runtime/variable_result_writer.h +++ b/be/src/runtime/variable_result_writer.h @@ -14,8 +14,12 @@ #pragma once +<<<<<<< HEAD #include "runtime/result_writer.h" #include "runtime/runtime_state.h" +======= +#include "runtime/buffer_control_result_writer.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -24,7 +28,11 @@ class MysqlRowBuffer; class BufferControlBlock; class RuntimeProfile; +<<<<<<< HEAD class VariableResultWriter final : public ResultWriter { +======= +class VariableResultWriter final : public BufferControlResultWriter { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: VariableResultWriter(BufferControlBlock* sinker, const std::vector& output_expr_ctxs, RuntimeProfile* parent_profile); @@ -37,6 +45,7 @@ class VariableResultWriter final : public ResultWriter { StatusOr process_chunk(Chunk* chunk) override; +<<<<<<< HEAD StatusOr try_add_batch(TFetchDataResultPtrs& results) override; Status close() override; @@ -58,6 +67,13 @@ class VariableResultWriter final : public ResultWriter { RuntimeProfile::Counter* _serialize_timer = nullptr; // number of sent rows RuntimeProfile::Counter* _sent_rows_counter = nullptr; +======= +private: + StatusOr _process_chunk(Chunk* chunk); + +private: + const std::vector& _output_expr_ctxs; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; } // namespace starrocks diff --git a/be/src/script/CMakeLists.txt b/be/src/script/CMakeLists.txt index adcf24f0fb443..9b7cfbec7a8f3 100644 --- a/be/src/script/CMakeLists.txt +++ b/be/src/script/CMakeLists.txt @@ -21,6 +21,11 @@ set(EXEC_FILES ../thirdparty/wren/wren.c ) +<<<<<<< HEAD +======= +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_library(Script STATIC ${EXEC_FILES}) target_include_directories(Script PRIVATE ${SRC_DIR}/script ${SRC_DIR}/thirdparty/wren ${SRC_DIR}/thirdparty/wrenbind17) diff --git a/be/src/script/script.cpp b/be/src/script/script.cpp index 745361a9ea804..75eb2378cbeca 100644 --- a/be/src/script/script.cpp +++ b/be/src/script/script.cpp @@ -21,6 +21,10 @@ #include "common/greplog.h" #include "common/logging.h" #include "common/prof/heap_prof.h" +<<<<<<< HEAD +======= +#include "common/vlog_cntl.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "exec/schema_scanner/schema_be_tablets_scanner.h" #include "fs/key_cache.h" #include "gen_cpp/olap_file.pb.h" @@ -226,7 +230,10 @@ void bind_exec_env(ForeignModule& m) { REG_METHOD(GlobalEnv, metadata_mem_tracker); REG_METHOD(GlobalEnv, compaction_mem_tracker); REG_METHOD(GlobalEnv, schema_change_mem_tracker); +<<<<<<< HEAD REG_METHOD(GlobalEnv, column_pool_mem_tracker); +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) REG_METHOD(GlobalEnv, page_cache_mem_tracker); REG_METHOD(GlobalEnv, jit_cache_mem_tracker); REG_METHOD(GlobalEnv, update_mem_tracker); @@ -262,6 +269,16 @@ void bind_exec_env(ForeignModule& m) { REG_METHOD(HeapProf, to_dot_format); REG_METHOD(HeapProf, dump_dot_snapshot); } +<<<<<<< HEAD +======= + { + auto& cls = m.klass("VLogCntl"); + REG_STATIC_METHOD(VLogCntl, getInstance); + REG_METHOD(VLogCntl, enable); + REG_METHOD(VLogCntl, disable); + REG_METHOD(VLogCntl, setLogLevel); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } class StorageEngineRef { @@ -517,6 +534,10 @@ class StorageEngineRef { REG_VAR(EditVersionInfo, creation_time); REG_VAR(EditVersionInfo, rowsets); REG_VAR(EditVersionInfo, deltas); +<<<<<<< HEAD +======= + REG_VAR(EditVersionInfo, gtid); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) REG_METHOD(EditVersionInfo, get_compaction); } { @@ -602,7 +623,11 @@ Status execute_script(const std::string& script, std::string& output) { bind_common(m); bind_exec_env(m); StorageEngineRef::bind(m); +<<<<<<< HEAD vm.runFromSource("main", R"(import "starrocks" for ExecEnv, GlobalEnv, HeapProf, StorageEngine)"); +======= + vm.runFromSource("main", R"(import "starrocks" for ExecEnv, GlobalEnv, HeapProf, StorageEngine, VLogCntl)"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) try { vm.runFromSource("main", script); } catch (const std::exception& e) { diff --git a/be/src/serde/column_array_serde.cpp b/be/src/serde/column_array_serde.cpp index 80af89998522a..114ace736d313 100644 --- a/be/src/serde/column_array_serde.cpp +++ b/be/src/serde/column_array_serde.cpp @@ -178,7 +178,11 @@ class FixedLengthColumnSerde { static const uint8_t* deserialize(const uint8_t* buff, FixedLengthColumnBase* column, const int encode_level) { uint32_t size = 0; buff = read_little_endian_32(buff, &size); +<<<<<<< HEAD std::vector& data = column->get_data(); +======= + auto& data = column->get_data(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) raw::make_room(&data, size / sizeof(T)); if (EncodeContext::enable_encode_integer(encode_level) && size >= ENCODE_SIZE_LIMIT) { if (sizeof(T) == 4 && sorted) { // only support sorted 32-bit integers @@ -290,7 +294,11 @@ template class ObjectColumnSerde { public: static int64_t max_serialized_size(const ObjectColumn& column) { +<<<<<<< HEAD const std::vector& pool = column.get_pool(); +======= + const auto& pool = column.get_pool(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t size = sizeof(uint32_t); for (const auto& obj : pool) { size += sizeof(uint64_t); @@ -313,7 +321,11 @@ class ObjectColumnSerde { uint32_t num_objects = 0; buff = read_little_endian_32(buff, &num_objects); column->reset_column(); +<<<<<<< HEAD std::vector& pool = column->get_pool(); +======= + auto& pool = column->get_pool(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pool.reserve(num_objects); for (int i = 0; i < num_objects; i++) { uint64_t serialized_size = 0; @@ -331,7 +343,11 @@ class ObjectColumnSerde { class JsonColumnSerde { public: static int64_t max_serialized_size(const JsonColumn& column) { +<<<<<<< HEAD const std::vector& pool = column.get_pool(); +======= + const auto& pool = column.get_pool(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int64_t size = 0; size += sizeof(uint32_t); // format_version size += sizeof(uint32_t); // num_objects @@ -366,7 +382,11 @@ class JsonColumnSerde { CHECK_EQ(actual_version, kJsonMetaDefaultFormatVersion) << "Only format_version=1 is supported"; column->reset_column(); +<<<<<<< HEAD std::vector& pool = column->get_pool(); +======= + auto& pool = column->get_pool(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) pool.reserve(num_objects); for (int i = 0; i < num_objects; i++) { uint64_t serialized_size = 0; diff --git a/be/src/service/CMakeLists.txt b/be/src/service/CMakeLists.txt index 8641fad08e796..1735a3debc646 100644 --- a/be/src/service/CMakeLists.txt +++ b/be/src/service/CMakeLists.txt @@ -32,7 +32,11 @@ add_library(Service ) # only build starrocks_be when TEST is off +<<<<<<< HEAD if (NOT ${MAKE_TEST} STREQUAL "ON") +======= +if ((NOT ${MAKE_TEST} STREQUAL "ON") AND (NOT BUILD_FORMAT_LIB)) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) add_executable(starrocks_be starrocks_main.cpp ) diff --git a/be/src/service/internal_service.cpp b/be/src/service/internal_service.cpp index 66a6355c09123..7e491e8b19309 100644 --- a/be/src/service/internal_service.cpp +++ b/be/src/service/internal_service.cpp @@ -64,6 +64,10 @@ #include "gen_cpp/MVMaintenance_types.h" #include "gen_cpp/PlanNodes_types.h" #include "gutil/strings/substitute.h" +<<<<<<< HEAD +======= +#include "runtime/batch_write/batch_write_mgr.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "runtime/buffer_control_block.h" #include "runtime/command_executor.h" #include "runtime/data_stream_mgr.h" @@ -79,6 +83,10 @@ #include "storage/dictionary_cache_manager.h" #include "storage/storage_engine.h" #include "storage/txn_manager.h" +<<<<<<< HEAD +======= +#include "util/arrow/row_batch.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/failpoint/fail_point.h" #include "util/stopwatch.hpp" #include "util/thrift_util.h" @@ -427,6 +435,14 @@ Status PInternalServiceImplBase::_exec_plan_fragment(brpc::Controller* cntl, uint32_t len = ser_request.size(); RETURN_IF_ERROR(deserialize_thrift_msg(buf, &len, request->attachment_protocol(), &t_request)); } +<<<<<<< HEAD +======= + // incremental scan ranges deployment. + if (!t_request.__isset.fragment) { + return pipeline::FragmentExecutor::append_incremental_scan_ranges(_exec_env, t_request); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (UNLIKELY(!t_request.query_options.__isset.batch_size)) { return Status::InvalidArgument("batch_size is not set"); } @@ -483,6 +499,11 @@ inline std::string cancel_reason_to_string(::starrocks::PPlanFragmentCancelReaso return "InternalError"; case TIMEOUT: return "TimeOut"; +<<<<<<< HEAD +======= + case QUERY_FINISHED: + return "QueryFinished"; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) default: return "UnknownReason"; } @@ -885,6 +906,30 @@ void PInternalServiceImplBase::process_dictionary_cache(google::protobuf::Rpc } template +<<<<<<< HEAD +======= +void PInternalServiceImplBase::fetch_arrow_schema(google::protobuf::RpcController* controller, + const PFetchArrowSchemaRequest* request, + PFetchArrowSchemaResult* result, google::protobuf::Closure* done) { + ClosureGuard closure_guard(done); + std::shared_ptr schema = + ExecEnv::GetInstance()->result_mgr()->get_arrow_schema(UniqueId(request->finst_id()).to_thrift()); + if (schema == nullptr) { + const auto status = Status::NotFound("arrow schema not found"); + status.to_protobuf(result->mutable_status()); + return; + } + + std::string schema_as_str; + const auto status = serialize_arrow_schema(&schema, &schema_as_str); + if (status.ok()) { + result->set_schema(std::move(schema_as_str)); + } + status.to_protobuf(result->mutable_status()); +} + +template +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void PInternalServiceImplBase::_get_file_schema(google::protobuf::RpcController* controller, const PGetFileSchemaRequest* request, PGetFileSchemaResult* response, google::protobuf::Closure* done) { @@ -1243,7 +1288,20 @@ void PInternalServiceImplBase::exec_short_circuit(google::protobuf::RpcContro StarRocksMetrics::instance()->short_circuit_request_duration_us.increment(elapsed_time_ns / 1000); } +<<<<<<< HEAD template class PInternalServiceImplBase; template class PInternalServiceImplBase; +======= +template +void PInternalServiceImplBase::stream_load(google::protobuf::RpcController* cntl_base, + const PStreamLoadRequest* request, PStreamLoadResponse* response, + google::protobuf::Closure* done) { + ClosureGuard closure_guard(done); + auto* cntl = static_cast(cntl_base); + BatchWriteMgr::receive_stream_load_rpc(_exec_env, cntl, request, response); +} + +template class PInternalServiceImplBase; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/service/internal_service.h b/be/src/service/internal_service.h index 1b38fb7daaf95..8fa4a9894f7c5 100644 --- a/be/src/service/internal_service.h +++ b/be/src/service/internal_service.h @@ -41,7 +41,10 @@ #include "common/status.h" #include "exec/pipeline/pipeline_fwd.h" #include "gen_cpp/MVMaintenance_types.h" +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/internal_service.pb.h" #include "util/countdown_latch.h" #include "util/priority_thread_pool.hpp" @@ -180,6 +183,15 @@ class PInternalServiceImplBase : public T { const PProcessDictionaryCacheRequest* request, PProcessDictionaryCacheResult* response, google::protobuf::Closure* done) override; +<<<<<<< HEAD +======= + void fetch_arrow_schema(google::protobuf::RpcController* controller, const PFetchArrowSchemaRequest* request, + PFetchArrowSchemaResult* result, google::protobuf::Closure* done); + + void stream_load(google::protobuf::RpcController* controller, const PStreamLoadRequest* request, + PStreamLoadResponse* response, google::protobuf::Closure* done) override; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) private: void _transmit_chunk(::google::protobuf::RpcController* controller, const ::starrocks::PTransmitChunkParams* request, ::starrocks::PTransmitChunkResult* response, diff --git a/be/src/service/mem_hook.cpp b/be/src/service/mem_hook.cpp index 4bc039a643b50..025d2d3063708 100644 --- a/be/src/service/mem_hook.cpp +++ b/be/src/service/mem_hook.cpp @@ -18,6 +18,10 @@ #include "glog/logging.h" #include "jemalloc/jemalloc.h" #include "runtime/current_thread.h" +<<<<<<< HEAD +======= +#include "runtime/memory/counting_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "util/failpoint/fail_point.h" #include "util/stack_util.h" @@ -38,6 +42,15 @@ #define STARROCKS_CFREE(ptr) je_free(ptr) #define STARROCKS_VALLOC(size) je_valloc(size) +<<<<<<< HEAD +======= +#define SET_DELTA_MEMORY(value) \ + do { \ + starrocks::tls_delta_memory = value; \ + } while (0) +#define RESET_DELTA_MEMORY() SET_DELTA_MEMORY(0) + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #ifndef BE_TEST #define MEMORY_CONSUME_SIZE(size) \ do { \ @@ -57,6 +70,7 @@ } while (0) #define MEMORY_CONSUME_PTR(ptr) MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr)) #define MEMORY_RELEASE_PTR(ptr) MEMORY_RELEASE_SIZE(STARROCKS_MALLOC_SIZE(ptr)) +<<<<<<< HEAD #define TRY_MEM_CONSUME(size, err_ret) \ do { \ if (LIKELY(starrocks::tls_is_thread_status_init)) { \ @@ -64,6 +78,21 @@ } else { \ RETURN_IF_UNLIKELY(!starrocks::CurrentThread::try_mem_consume_without_cache(size), err_ret); \ } \ +======= +#define TRY_MEM_CONSUME(size, err_ret) \ + do { \ + if (LIKELY(starrocks::tls_is_thread_status_init)) { \ + if (UNLIKELY(!starrocks::tls_thread_status.try_mem_consume(size))) { \ + RESET_DELTA_MEMORY(); \ + return err_ret; \ + } \ + } else { \ + if (UNLIKELY(!starrocks::CurrentThread::try_mem_consume_without_cache(size))) { \ + RESET_DELTA_MEMORY(); \ + return err_ret; \ + } \ + } \ +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } while (0) #define SET_EXCEED_MEM_TRACKER() \ starrocks::tls_exceed_mem_tracker = starrocks::GlobalEnv::GetInstance()->process_mem_tracker() @@ -114,15 +143,29 @@ extern "C" { // malloc void* my_malloc(size_t size) __THROW { STARROCKS_REPORT_LARGE_MEM_ALLOC(size); +<<<<<<< HEAD +======= + int64_t alloc_size = STARROCKS_NALLOX(size, 0); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (IS_BAD_ALLOC_CATCHED()) { FAIL_POINT_INJECT_MEM_ALLOC_ERROR(nullptr); // NOTE: do NOT call `tc_malloc_size` here, it may call the new operator, which in turn will // call the `my_malloc`, and result in a deadloop. +<<<<<<< HEAD TRY_MEM_CONSUME(STARROCKS_NALLOX(size, 0), nullptr); void* ptr = STARROCKS_MALLOC(size); if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(STARROCKS_NALLOX(size, 0)); +======= + TRY_MEM_CONSUME(alloc_size, nullptr); + void* ptr = STARROCKS_MALLOC(size); + if (UNLIKELY(ptr == nullptr)) { + SET_EXCEED_MEM_TRACKER(); + MEMORY_RELEASE_SIZE(alloc_size); + RESET_DELTA_MEMORY(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { @@ -130,7 +173,13 @@ void* my_malloc(size_t size) __THROW { // NOTE: do NOT call `tc_malloc_size` here, it may call the new operator, which in turn will // call the `my_malloc`, and result in a deadloop. if (LIKELY(ptr != nullptr)) { +<<<<<<< HEAD MEMORY_CONSUME_SIZE(STARROCKS_NALLOX(size, 0)); +======= + MEMORY_CONSUME_SIZE(alloc_size); + } else { + RESET_DELTA_MEMORY(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } @@ -139,9 +188,18 @@ void* my_malloc(size_t size) __THROW { // free void my_free(void* p) __THROW { if (UNLIKELY(p == nullptr)) { +<<<<<<< HEAD return; } MEMORY_RELEASE_PTR(p); +======= + RESET_DELTA_MEMORY(); + return; + } + int64_t malloc_size = STARROCKS_MALLOC_SIZE(p); + MEMORY_RELEASE_SIZE(malloc_size); + SET_DELTA_MEMORY(-malloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) STARROCKS_FREE(p); } @@ -152,6 +210,7 @@ void* my_realloc(void* p, size_t size) __THROW { // (null pointer may be returned (in which case the old memory block may or may not be freed), // or some non-null pointer may be returned that may not be used to access storage) if (UNLIKELY(size == 0)) { +<<<<<<< HEAD return nullptr; } int64_t old_size = STARROCKS_MALLOC_SIZE(p); @@ -163,15 +222,40 @@ void* my_realloc(void* p, size_t size) __THROW { if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(STARROCKS_NALLOX(size, 0) - old_size); +======= + RESET_DELTA_MEMORY(); + return nullptr; + } + int64_t old_size = STARROCKS_MALLOC_SIZE(p); + int64_t new_size = STARROCKS_NALLOX(size, 0); + SET_DELTA_MEMORY(new_size - old_size); + + if (IS_BAD_ALLOC_CATCHED()) { + FAIL_POINT_INJECT_MEM_ALLOC_ERROR(nullptr); + TRY_MEM_CONSUME(new_size - old_size, nullptr); + void* ptr = STARROCKS_REALLOC(p, size); + if (UNLIKELY(ptr == nullptr)) { + SET_EXCEED_MEM_TRACKER(); + MEMORY_RELEASE_SIZE(new_size - old_size); + RESET_DELTA_MEMORY(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { void* ptr = STARROCKS_REALLOC(p, size); if (ptr != nullptr) { +<<<<<<< HEAD MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr) - old_size); } else { // nothing to do. // If tc_realloc() fails the original block is left untouched; it is not freed or moved +======= + MEMORY_CONSUME_SIZE(new_size - old_size); + } else { + // nothing to do. + // If tc_realloc() fails the original block is left untouched; it is not freed or moved + RESET_DELTA_MEMORY(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } @@ -183,6 +267,10 @@ void* my_calloc(size_t n, size_t size) __THROW { // If size is zero, the behavior is implementation defined (null pointer may be returned // or some non-null pointer may be returned that may not be used to access storage) if (UNLIKELY(size == 0)) { +<<<<<<< HEAD +======= + RESET_DELTA_MEMORY(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return nullptr; } @@ -193,22 +281,45 @@ void* my_calloc(size_t n, size_t size) __THROW { if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(n * size); +<<<<<<< HEAD } else { MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr) - n * size); +======= + RESET_DELTA_MEMORY(); + } else { + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size - n * size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { void* ptr = STARROCKS_CALLOC(n, size); +<<<<<<< HEAD MEMORY_CONSUME_PTR(ptr); +======= + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ptr; } } void my_cfree(void* ptr) __THROW { if (UNLIKELY(ptr == nullptr)) { +<<<<<<< HEAD return; } MEMORY_RELEASE_PTR(ptr); +======= + RESET_DELTA_MEMORY(); + return; + } + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_RELEASE_SIZE(alloc_size); + SET_DELTA_MEMORY(-alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) STARROCKS_CFREE(ptr); } @@ -222,13 +333,27 @@ void* my_memalign(size_t align, size_t size) __THROW { if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(size); +<<<<<<< HEAD } else { MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr) - size); +======= + RESET_DELTA_MEMORY(); + } else { + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size - size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { void* ptr = STARROCKS_ALIGNED_ALLOC(align, size); +<<<<<<< HEAD MEMORY_CONSUME_PTR(ptr); +======= + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ptr; } } @@ -243,13 +368,27 @@ void* my_aligned_alloc(size_t align, size_t size) __THROW { if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(size); +<<<<<<< HEAD } else { MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr) - size); +======= + RESET_DELTA_MEMORY(); + } else { + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size - size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { void* ptr = STARROCKS_ALIGNED_ALLOC(align, size); +<<<<<<< HEAD MEMORY_CONSUME_PTR(ptr); +======= + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ptr; } } @@ -264,13 +403,27 @@ void* my_valloc(size_t size) __THROW { if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(size); +<<<<<<< HEAD } else { MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr) - size); +======= + RESET_DELTA_MEMORY(); + } else { + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size - size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { void* ptr = STARROCKS_VALLOC(size); +<<<<<<< HEAD MEMORY_CONSUME_PTR(ptr); +======= + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ptr; } } @@ -285,13 +438,27 @@ void* my_pvalloc(size_t size) __THROW { if (UNLIKELY(ptr == nullptr)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(size); +<<<<<<< HEAD } else { MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(ptr) - size); +======= + RESET_DELTA_MEMORY(); + } else { + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size - size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ptr; } else { void* ptr = STARROCKS_VALLOC(size); +<<<<<<< HEAD MEMORY_CONSUME_PTR(ptr); +======= + int64_t alloc_size = STARROCKS_MALLOC_SIZE(ptr); + MEMORY_CONSUME_SIZE(alloc_size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ptr; } } @@ -306,14 +473,30 @@ int my_posix_memalign(void** r, size_t align, size_t size) __THROW { if (UNLIKELY(ret != 0)) { SET_EXCEED_MEM_TRACKER(); MEMORY_RELEASE_SIZE(size); +<<<<<<< HEAD } else { MEMORY_CONSUME_SIZE(STARROCKS_MALLOC_SIZE(*r) - size); +======= + SET_DELTA_MEMORY(0); + } else { + int64_t alloc_size = STARROCKS_MALLOC_SIZE(*r); + MEMORY_CONSUME_SIZE(alloc_size - size); + SET_DELTA_MEMORY(alloc_size); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ret; } else { int ret = STARROCKS_POSIX_MEMALIGN(r, align, size); if (ret == 0) { +<<<<<<< HEAD MEMORY_CONSUME_PTR(*r); +======= + int64_t alloc_size = STARROCKS_MALLOC_SIZE(*r); + MEMORY_CONSUME_SIZE(alloc_size); + SET_DELTA_MEMORY(alloc_size); + } else { + RESET_DELTA_MEMORY(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ret; } diff --git a/be/src/service/service_be/CMakeLists.txt b/be/src/service/service_be/CMakeLists.txt index 8de4b937aa50e..7a2c41f6a1a15 100644 --- a/be/src/service/service_be/CMakeLists.txt +++ b/be/src/service/service_be/CMakeLists.txt @@ -23,4 +23,8 @@ add_library(ServiceBE internal_service.cpp lake_service.cpp starrocks_be.cpp +<<<<<<< HEAD +======= + arrow_flight_sql_service.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ) diff --git a/be/src/service/service_be/arrow_flight_sql_service.cpp b/be/src/service/service_be/arrow_flight_sql_service.cpp new file mode 100644 index 0000000000000..e7ecdf59eda92 --- /dev/null +++ b/be/src/service/service_be/arrow_flight_sql_service.cpp @@ -0,0 +1,96 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "arrow_flight_sql_service.h" + +#include +#include +#include +#include +#include + +#include "common/status.h" +#include "exec/arrow_flight_batch_reader.h" +#include "exprs/base64.h" +#include "service/backend_options.h" +#include "util/uid_util.h" + +namespace starrocks { + +Status ArrowFlightSqlServer::start(int port) { + if (port <= 0) { + LOG(INFO) << "[ARROW] Arrow Flight SQL Server is disabled. You can modify `arrow_flight_port` in `be.conf` to " + "a positive value to enable it."; + return Status::OK(); + } + + _running = true; + + arrow::flight::Location bind_location; + RETURN_STATUS_IF_ERROR(arrow::flight::Location::ForGrpcTcp(BackendOptions::get_service_bind_address(), port) + .Value(&bind_location)); + arrow::flight::FlightServerOptions flight_options(bind_location); + RETURN_STATUS_IF_ERROR(Init(flight_options)); + + return Status::OK(); +} + +void ArrowFlightSqlServer::stop() { + if (!_running) { + return; + } + _running = false; + if (const auto status = Shutdown(); !status.ok()) { + LOG(INFO) << "[ARROW] Failed to stop Arrow Flight SQL Server [error=" << status << "]"; + } +} + +arrow::Result> ArrowFlightSqlServer::GetFlightInfoSchemas( + const arrow::flight::ServerCallContext& context, const arrow::flight::sql::GetDbSchemas& command, + const arrow::flight::FlightDescriptor& descriptor) { + return arrow::Status::NotImplemented("GetFlightInfoSchemas Result"); +} + +arrow::Result> ArrowFlightSqlServer::DoGetStatement( + const arrow::flight::ServerCallContext& context, const arrow::flight::sql::StatementQueryTicket& command) { + ARROW_ASSIGN_OR_RAISE(auto pair, decode_ticket(command.statement_handle)); + + const std::string query_id = pair.first; + const std::string result_fragment_id = pair.second; + TUniqueId queryid; + if (!parse_id(query_id, &queryid)) { + return arrow::Status::Invalid("Invalid query ID format:", query_id); + } + TUniqueId resultfragmentid; + if (!parse_id(result_fragment_id, &resultfragmentid)) { + return arrow::Status::Invalid("Invalid fragment ID format:", result_fragment_id); + } + + std::shared_ptr reader = std::make_shared(resultfragmentid); + return std::make_unique(reader); +} + +arrow::Result> ArrowFlightSqlServer::decode_ticket(const std::string& ticket) { + auto divider = ticket.find(':'); + if (divider == std::string::npos) { + return arrow::Status::Invalid("Malformed ticket"); + } + + std::string query_id = ticket.substr(0, divider); + std::string result_fragment_id = ticket.substr(divider + 1); + + return std::make_pair(std::move(query_id), std::move(result_fragment_id)); +} + +} // namespace starrocks diff --git a/be/src/service/service_be/arrow_flight_sql_service.h b/be/src/service/service_be/arrow_flight_sql_service.h new file mode 100644 index 0000000000000..f1b92638556b2 --- /dev/null +++ b/be/src/service/service_be/arrow_flight_sql_service.h @@ -0,0 +1,45 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include + +#include "common/status.h" + +namespace starrocks { + +class ArrowFlightSqlServer : public arrow::flight::sql::FlightSqlServerBase { +public: + Status start(int port); + void stop(); + + arrow::Result> GetFlightInfoSchemas( + const arrow::flight::ServerCallContext& context, const arrow::flight::sql::GetDbSchemas& command, + const arrow::flight::FlightDescriptor& descriptor) override; + + arrow::Result> DoGetStatement( + const arrow::flight::ServerCallContext& context, + const arrow::flight::sql::StatementQueryTicket& command) override; + +private: + static arrow::Result> decode_ticket(const std::string& ticket); + + bool _running = false; +}; + +} // namespace starrocks diff --git a/be/src/service/service_be/internal_service.cpp b/be/src/service/service_be/internal_service.cpp index 798bf3bb42530..bcf9eea3a778b 100644 --- a/be/src/service/service_be/internal_service.cpp +++ b/be/src/service/service_be/internal_service.cpp @@ -254,5 +254,8 @@ void BackendInternalServiceImpl::local_tablet_reader_scan_get_next(google::pr } template class BackendInternalServiceImpl; +<<<<<<< HEAD template class BackendInternalServiceImpl; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/service/service_be/internal_service.h b/be/src/service/service_be/internal_service.h index f9439a646dc8b..b008684031ed1 100644 --- a/be/src/service/service_be/internal_service.h +++ b/be/src/service/service_be/internal_service.h @@ -35,7 +35,10 @@ #pragma once #include "common/status.h" +<<<<<<< HEAD #include "gen_cpp/doris_internal_service.pb.h" +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gen_cpp/internal_service.pb.h" #include "service/internal_service.h" diff --git a/be/src/service/service_be/lake_service.cpp b/be/src/service/service_be/lake_service.cpp index 11815c36f13c6..54933046b78c9 100644 --- a/be/src/service/service_be/lake_service.cpp +++ b/be/src/service/service_be/lake_service.cpp @@ -147,7 +147,11 @@ void LakeServiceImpl::publish_version(::google::protobuf::RpcController* control return; } if (request->txn_ids_size() == 0 && request->txn_infos_size() == 0) { +<<<<<<< HEAD cntl->SetFailed("missing txn_ids and txn_infos"); +======= + cntl->SetFailed("neither txn_ids nor txn_infos is set, one of them must be set"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return; } if (request->tablet_ids_size() == 0) { @@ -261,9 +265,16 @@ void LakeServiceImpl::publish_version(::google::protobuf::RpcController* control } void LakeServiceImpl::_submit_publish_log_version_task(const int64_t* tablet_ids, size_t tablet_size, +<<<<<<< HEAD const int64_t* txn_ids, const int64_t* log_versions, size_t txn_size, ::starrocks::PublishLogVersionResponse* response) { +======= + std::span txn_infos, + const int64_t* log_versions, + ::starrocks::PublishLogVersionResponse* response) { + auto txn_size = txn_infos.size(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto thread_pool = publish_version_thread_pool(_env); auto latch = BThreadCountDownLatch(tablet_size); bthread::Mutex response_mtx; @@ -272,11 +283,19 @@ void LakeServiceImpl::_submit_publish_log_version_task(const int64_t* tablet_ids auto tablet_id = tablet_ids[i]; auto task = [&, tablet_id]() { DeferOp defer([&] { latch.count_down(); }); +<<<<<<< HEAD auto st = lake::publish_log_version(_tablet_mgr, tablet_id, txn_ids, log_versions, txn_size); if (!st.ok()) { g_publish_version_failed_tasks << 1; LOG(WARNING) << "Fail to publish log version: " << st << " tablet_id=" << tablet_id << " txn_ids=" << JoinElementsIterator(txn_ids, txn_ids + txn_size, ",") +======= + auto st = lake::publish_log_version(_tablet_mgr, tablet_id, txn_infos, log_versions); + if (!st.ok()) { + g_publish_version_failed_tasks << 1; + LOG(WARNING) << "Fail to publish log version: " << st << " tablet_id=" << tablet_id + << " txns=" << JoinMapped(txn_infos, txn_info_string, ",") +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) << " versions=" << JoinElementsIterator(log_versions, log_versions + txn_size, ","); std::lock_guard l(response_mtx); response->add_failed_tablets(tablet_id); @@ -286,10 +305,16 @@ void LakeServiceImpl::_submit_publish_log_version_task(const int64_t* tablet_ids auto st = thread_pool->submit_func(task); if (!st.ok()) { g_publish_version_failed_tasks << 1; +<<<<<<< HEAD LOG(WARNING) << "Fail to submit publish log version task, tablet_id: " << tablet_id << ", txn_ids: " << JoinElementsIterator(txn_ids, txn_ids + txn_size, ",") << ", versions: " << JoinElementsIterator(log_versions, log_versions + txn_size, ",") << ", error" << st; +======= + LOG(WARNING) << "Fail to submit publish log version task: " << st << " tablet_id=" << tablet_id + << " txns=" << JoinMapped(txn_infos, txn_info_string, ",") + << " versions=" << JoinElementsIterator(log_versions, log_versions + txn_size, ","); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::lock_guard l(response_mtx); response->add_failed_tablets(tablet_id); latch.count_down(); @@ -309,8 +334,13 @@ void LakeServiceImpl::publish_log_version(::google::protobuf::RpcController* con cntl->SetFailed("missing tablet_ids"); return; } +<<<<<<< HEAD if (!request->has_txn_id()) { cntl->SetFailed("missing txn_id"); +======= + if (!request->has_txn_id() && !request->has_txn_info()) { + cntl->SetFailed("missing txn_id and txn_info"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return; } if (!request->has_version()) { @@ -319,10 +349,26 @@ void LakeServiceImpl::publish_log_version(::google::protobuf::RpcController* con } auto tablet_ids = request->tablet_ids().data(); +<<<<<<< HEAD int64_t txn_id = request->txn_id(); int64_t version = request->version(); _submit_publish_log_version_task(tablet_ids, request->tablet_ids_size(), &txn_id, &version, 1, response); +======= + auto version = int64_t{request->version()}; + if (!request->has_txn_info()) { + DCHECK(request->has_txn_id()); + auto txn_info = TxnInfoPB(); + txn_info.set_txn_id(request->txn_id()); + txn_info.set_txn_type(TXN_NORMAL); + txn_info.set_combined_txn_log(false); + auto txn_infos = std::span(&txn_info, 1); + _submit_publish_log_version_task(tablet_ids, request->tablet_ids_size(), txn_infos, &version, response); + } else { + auto txn_infos = std::span(&request->txn_info(), 1); + _submit_publish_log_version_task(tablet_ids, request->tablet_ids_size(), txn_infos, &version, response); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void LakeServiceImpl::publish_log_version_batch(::google::protobuf::RpcController* controller, @@ -336,8 +382,13 @@ void LakeServiceImpl::publish_log_version_batch(::google::protobuf::RpcControlle cntl->SetFailed("missing tablet_ids"); return; } +<<<<<<< HEAD if (request->txn_ids_size() == 0) { cntl->SetFailed("missing txn_ids"); +======= + if (request->txn_ids_size() == 0 && request->txn_infos_size() == 0) { + cntl->SetFailed("neither txn_ids nor txn_infos is set, one of them must be set"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return; } if (request->versions_size() == 0) { @@ -345,6 +396,7 @@ void LakeServiceImpl::publish_log_version_batch(::google::protobuf::RpcControlle return; } +<<<<<<< HEAD auto tablet_ids = request->tablet_ids().data(); auto txn_ids = request->txn_ids().data(); auto versions = request->versions().data(); @@ -352,6 +404,25 @@ void LakeServiceImpl::publish_log_version_batch(::google::protobuf::RpcControlle _submit_publish_log_version_task(tablet_ids, request->tablet_ids_size(), txn_ids, versions, request->txn_ids_size(), response); +======= + auto txn_infos = std::vector{}; + auto tablet_ids = request->tablet_ids().data(); + auto versions = request->versions().data(); + if (request->txn_infos_size() == 0) { + DCHECK_EQ(request->txn_ids_size(), request->versions_size()); + txn_infos.reserve(request->txn_ids_size()); + for (auto txn_id : request->txn_ids()) { + auto& txn_info = txn_infos.emplace_back(); + txn_info.set_txn_id(txn_id); + txn_info.set_combined_txn_log(false); + txn_info.set_txn_type(TXN_NORMAL); + } + } else { + txn_infos.insert(txn_infos.begin(), request->txn_infos().begin(), request->txn_infos().end()); + } + + _submit_publish_log_version_task(tablet_ids, request->tablet_ids_size(), txn_infos, versions, response); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void LakeServiceImpl::abort_txn(::google::protobuf::RpcController* controller, @@ -453,8 +524,13 @@ void LakeServiceImpl::delete_txn_log(::google::protobuf::RpcController* controll return; } +<<<<<<< HEAD if (request->txn_ids_size() == 0) { cntl->SetFailed("missing txn_ids"); +======= + if (request->txn_ids_size() == 0 && request->txn_infos_size() == 0) { + cntl->SetFailed("neither txn_ids nor txn_infos is set, one of them must be set"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return; } diff --git a/be/src/service/service_be/lake_service.h b/be/src/service/service_be/lake_service.h index cb29056b6a698..8ae2a0daf06bc 100644 --- a/be/src/service/service_be/lake_service.h +++ b/be/src/service/service_be/lake_service.h @@ -95,8 +95,13 @@ class LakeServiceImpl : public ::starrocks::LakeService { ::starrocks::VacuumFullResponse* response, ::google::protobuf::Closure* done) override; private: +<<<<<<< HEAD void _submit_publish_log_version_task(const int64_t* tablet_ids, size_t tablet_size, const int64_t* txn_ids, const int64_t* log_versions, size_t txn_size, +======= + void _submit_publish_log_version_task(const int64_t* tablet_ids, size_t tablet_size, + std::span txn_infos, const int64_t* log_versions, +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ::starrocks::PublishLogVersionResponse* response); private: diff --git a/be/src/service/service_be/starrocks_be.cpp b/be/src/service/service_be/starrocks_be.cpp index a0f4ac53280d1..61bc7a85931d4 100644 --- a/be/src/service/service_be/starrocks_be.cpp +++ b/be/src/service/service_be/starrocks_be.cpp @@ -27,12 +27,24 @@ #include "common/process_exit.h" #include "common/status.h" #include "exec/pipeline/query_context.h" +<<<<<<< HEAD #include "gutil/strings/join.h" #include "runtime/exec_env.h" #include "runtime/fragment_mgr.h" #include "runtime/jdbc_driver_manager.h" #include "service/brpc.h" #include "service/service.h" +======= +#include "fs/s3/poco_common.h" +#include "gutil/strings/join.h" +#include "runtime/exec_env.h" +#include "runtime/fragment_mgr.h" +#include "runtime/global_variables.h" +#include "runtime/jdbc_driver_manager.h" +#include "service/brpc.h" +#include "service/service.h" +#include "service/service_be/arrow_flight_sql_service.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "service/service_be/http_service.h" #include "service/service_be/internal_service.h" #include "service/service_be/lake_service.h" @@ -60,8 +72,11 @@ Status init_datacache(GlobalEnv* global_env, const std::vector& stora config::datacache_enable = true; config::datacache_mem_size = std::to_string(config::block_cache_mem_size); config::datacache_disk_size = std::to_string(config::block_cache_disk_size); +<<<<<<< HEAD config::datacache_disk_path = config::block_cache_disk_path; config::datacache_meta_path = config::block_cache_meta_path; +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) config::datacache_block_size = config::block_cache_block_size; config::datacache_max_concurrent_inserts = config::block_cache_max_concurrent_inserts; config::datacache_checksum_enable = config::block_cache_checksum_enable; @@ -71,7 +86,11 @@ Status init_datacache(GlobalEnv* global_env, const std::vector& stora << ", you'd better use the configuration items prefixed `datacache` instead!"; } +<<<<<<< HEAD #if !defined(WITH_CACHELIB) && !defined(WITH_STARCACHE) +======= +#if !defined(WITH_STARCACHE) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (config::datacache_enable) { LOG(WARNING) << "No valid engines supported, skip initializing datacache module"; config::datacache_enable = false; @@ -88,6 +107,7 @@ Status init_datacache(GlobalEnv* global_env, const std::vector& stora } RETURN_IF_ERROR(DataCacheUtils::parse_conf_datacache_mem_size(config::datacache_mem_size, mem_limit, &cache_options.mem_space_size)); +<<<<<<< HEAD if (config::datacache_disk_path.value().empty()) { // If the disk cache does not be configured for datacache, set default path according storage path. std::vector datacache_paths; @@ -111,26 +131,83 @@ Status init_datacache(GlobalEnv* global_env, const std::vector& stora if (!cache_options.disk_spaces.empty() && total_quota_byts == 0) { // If disk cache quota is zero, turn on the automatic adjust switch. config::datacache_auto_adjust_enable = true; +======= + + size_t total_quota_bytes = 0; + for (auto& root_path : storage_paths) { + // Because we have unified the datacache between datalake and starlet, we also need to unify the + // cache path and quota. + // To reuse the old cache data in `starlet_cache` directory, we try to rename it to the new `datacache` + // directory if it exists. To avoid the risk of cross disk renaming of a large amount of cached data, + // we do not automatically rename it when the source and destination directories are on different disks. + // In this case, users should manually remount the directories and restart them. + std::string datacache_path = root_path.path + "/datacache"; + std::string starlet_cache_path = root_path.path + "/starlet_cache/star_cache"; +#ifdef USE_STAROS + if (config::datacache_unified_instance_enable) { + RETURN_IF_ERROR(DataCacheUtils::change_disk_path(starlet_cache_path, datacache_path)); + } +#endif + // Create it if not exist + Status st = FileSystem::Default()->create_dir_if_missing(datacache_path); + if (!st.ok()) { + LOG(ERROR) << "Fail to create datacache directory: " << datacache_path << ", reason: " << st.message(); + return Status::InternalError("Fail to create datacache directory"); + } + + int64_t disk_size = + DataCacheUtils::parse_conf_datacache_disk_size(datacache_path, config::datacache_disk_size, -1); +#ifdef USE_STAROS + // If the `datacache_disk_size` is manually set a positive value, we will use the maximum cache quota between + // dataleke and starlet cache as the quota of the unified cache. Otherwise, the cache quota will remain zero + // and then automatically adjusted based on the current avalible disk space. + if (config::datacache_unified_instance_enable && (!config::datacache_auto_adjust_enable || disk_size > 0)) { + int64_t starlet_cache_size = DataCacheUtils::parse_conf_datacache_disk_size( + datacache_path, fmt::format("{}%", config::starlet_star_cache_disk_size_percent), -1); + disk_size = std::max(disk_size, starlet_cache_size); + } +#endif + cache_options.disk_spaces.push_back({.path = datacache_path, .size = static_cast(disk_size)}); + total_quota_bytes += disk_size; + } + + if (cache_options.disk_spaces.empty() || total_quota_bytes != 0) { + config::datacache_auto_adjust_enable = false; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // Adjust the default engine based on build switches. if (config::datacache_engine == "") { #if defined(WITH_STARCACHE) config::datacache_engine = "starcache"; +<<<<<<< HEAD #else config::datacache_engine = "cachelib"; #endif } cache_options.meta_path = config::datacache_meta_path; +======= +#endif + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) cache_options.block_size = config::datacache_block_size; cache_options.max_flying_memory_mb = config::datacache_max_flying_memory_mb; cache_options.max_concurrent_inserts = config::datacache_max_concurrent_inserts; cache_options.enable_checksum = config::datacache_checksum_enable; cache_options.enable_direct_io = config::datacache_direct_io_enable; cache_options.enable_tiered_cache = config::datacache_tiered_cache_enable; +<<<<<<< HEAD cache_options.skip_read_factor = starrocks::config::datacache_skip_read_factor; cache_options.scheduler_threads_per_cpu = starrocks::config::datacache_scheduler_threads_per_cpu; cache_options.engine = config::datacache_engine; +======= + cache_options.skip_read_factor = config::datacache_skip_read_factor; + cache_options.scheduler_threads_per_cpu = config::datacache_scheduler_threads_per_cpu; + cache_options.enable_datacache_persistence = config::datacache_persistence_enable; + cache_options.inline_item_count_limit = config::datacache_inline_item_count_limit; + cache_options.engine = config::datacache_engine; + cache_options.eviction_policy = config::datacache_eviction_policy; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return cache->init(cache_options); } return Status::OK(); @@ -177,6 +254,14 @@ void start_be(const std::vector& paths, bool as_cn) { EXIT_IF_ERROR(global_env->init()); LOG(INFO) << process_name << " start step " << start_step++ << ": global env init successfully"; +<<<<<<< HEAD +======= + // make sure global variables are initialized + auto* global_vars = GlobalVariables::GetInstance(); + CHECK(global_vars->is_init()) << "global variables not initialized"; + LOG(INFO) << process_name << " start step " << start_step++ << ": global variables init successfully"; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto* storage_engine = init_storage_engine(global_env, paths, as_cn); LOG(INFO) << process_name << " start step " << start_step++ << ": storage engine init successfully"; @@ -189,11 +274,14 @@ void start_be(const std::vector& paths, bool as_cn) { EXIT_IF_ERROR(storage_engine->start_bg_threads()); LOG(INFO) << process_name << " start step " << start_step++ << ": storage engine start bg threads successfully"; +<<<<<<< HEAD #ifdef USE_STAROS init_staros_worker(); LOG(INFO) << process_name << " start step " << start_step++ << ": staros worker init successfully"; #endif +======= +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (!init_datacache(global_env, paths).ok()) { LOG(ERROR) << "Fail to init datacache"; exit(1); @@ -204,6 +292,19 @@ void start_be(const std::vector& paths, bool as_cn) { LOG(INFO) << process_name << " starts by skipping the datacache initialization"; } +<<<<<<< HEAD +======= +#ifdef USE_STAROS + BlockCache* block_cache = BlockCache::instance(); + if (config::datacache_unified_instance_enable && block_cache->is_initialized()) { + init_staros_worker(block_cache->starcache_instance()); + } else { + init_staros_worker(nullptr); + } + LOG(INFO) << process_name << " start step " << start_step++ << ": staros worker init successfully"; +#endif + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // set up thrift client before providing any service to the external // because these services may use thrift client, for example, stream // load will send thrift rpc to FE after http server is started @@ -234,11 +335,17 @@ void start_be(const std::vector& paths, bool as_cn) { auto brpc_server = std::make_unique(); BackendInternalServiceImpl internal_service(exec_env); +<<<<<<< HEAD BackendInternalServiceImpl backend_service(exec_env); LakeServiceImpl lake_service(exec_env, exec_env->lake_tablet_manager()); brpc_server->AddService(&internal_service, brpc::SERVER_DOESNT_OWN_SERVICE); brpc_server->AddService(&backend_service, brpc::SERVER_DOESNT_OWN_SERVICE); +======= + LakeServiceImpl lake_service(exec_env, exec_env->lake_tablet_manager()); + + brpc_server->AddService(&internal_service, brpc::SERVER_DOESNT_OWN_SERVICE); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) brpc_server->AddService(&lake_service, brpc::SERVER_DOESNT_OWN_SERVICE); brpc::ServerOptions options; @@ -278,6 +385,20 @@ void start_be(const std::vector& paths, bool as_cn) { } LOG(INFO) << process_name << " start step " << start_step++ << ": start http server successfully"; +<<<<<<< HEAD +======= + // Start Arrow Flight SQL server + auto arrow_flight_sql_server = std::make_unique(); + if (auto status = arrow_flight_sql_server->start(config::arrow_flight_port); !status.ok()) { + LOG(ERROR) << process_name << " Arrow Flight Sql Server did not start correctly, exiting: " << status.message() + << ". Its port might be occupied. You can modify `arrow_flight_port` in `be.conf` to an unused port " + "or set it to -1 to disable it."; + shutdown_logging(); + exit(1); + } + LOG(INFO) << process_name << " start step " << start_step++ << ": start arrow flight sql server successfully"; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Start heartbeat server std::unique_ptr heartbeat_server; if (auto ret = create_heartbeat_server(exec_env, config::heartbeat_service_port, @@ -312,6 +433,13 @@ void start_be(const std::vector& paths, bool as_cn) { heartbeat_server.reset(); LOG(INFO) << process_name << " exit step " << exit_step++ << ": heartbeat server exit successfully"; +<<<<<<< HEAD +======= + arrow_flight_sql_server->stop(); + arrow_flight_sql_server.reset(); + LOG(INFO) << process_name << " exit step " << exit_step++ << ": Arrow Flight SQL server exit successfully"; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) http_server->stop(); brpc_server->Stop(0); thrift_server->stop(); @@ -334,13 +462,25 @@ void start_be(const std::vector& paths, bool as_cn) { LOG(INFO) << process_name << " exit step " << exit_step++ << ": staros worker exit successfully"; #endif +<<<<<<< HEAD #if defined(WITH_CACHELIB) || defined(WITH_STARCACHE) +======= +#if defined(WITH_STARCACHE) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (config::datacache_enable) { (void)BlockCache::instance()->shutdown(); LOG(INFO) << process_name << " exit step " << exit_step++ << ": datacache shutdown successfully"; } #endif +<<<<<<< HEAD +======= + if (config::enable_poco_client_for_aws_sdk) { + starrocks::poco::HTTPSessionPools::instance().shutdown(); + LOG(INFO) << process_name << " exit step " << exit_step++ << ": poco connection pool shutdown successfully"; + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) http_server->join(); http_server.reset(); LOG(INFO) << process_name << " exit step " << exit_step++ << ": http server exit successfully"; diff --git a/be/src/service/staros_worker.cpp b/be/src/service/staros_worker.cpp index 34cda9e7efb33..66b95732d9c62 100644 --- a/be/src/service/staros_worker.cpp +++ b/be/src/service/staros_worker.cpp @@ -343,10 +343,22 @@ Status to_status(const absl::Status& absl_status) { } } +<<<<<<< HEAD void init_staros_worker() { if (g_starlet.get() != nullptr) { return; } +======= +void init_staros_worker(const std::shared_ptr& star_cache) { + if (g_starlet.get() != nullptr) { + return; + } + + if (star_cache) { + (void)fslib::set_star_cache(star_cache); + } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // skip staros reinit aws sdk staros::starlet::fslib::skip_aws_init_api = true; diff --git a/be/src/service/staros_worker.h b/be/src/service/staros_worker.h index 27e1737b4afe4..f5f79703adff5 100644 --- a/be/src/service/staros_worker.h +++ b/be/src/service/staros_worker.h @@ -27,6 +27,10 @@ #include "common/status.h" #include "fslib/configuration.h" #include "fslib/file_system.h" +<<<<<<< HEAD +======= +#include "starcache/star_cache.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { @@ -108,7 +112,11 @@ class StarOSWorker : public staros::starlet::Worker { }; extern std::shared_ptr g_worker; +<<<<<<< HEAD void init_staros_worker(); +======= +void init_staros_worker(const std::shared_ptr& star_cache); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) void shutdown_staros_worker(); void update_staros_starcache(); diff --git a/be/src/service/starrocks_main.cpp b/be/src/service/starrocks_main.cpp index 234c241bcd15b..df96c4ceb61b0 100644 --- a/be/src/service/starrocks_main.cpp +++ b/be/src/service/starrocks_main.cpp @@ -55,9 +55,17 @@ #include "common/process_exit.h" #include "common/status.h" #include "exec/pipeline/query_context.h" +<<<<<<< HEAD #include "runtime/exec_env.h" #include "runtime/heartbeat_flags.h" #include "runtime/jdbc_driver_manager.h" +======= +#include "fs/s3/poco_http_client_factory.h" +#include "runtime/exec_env.h" +#include "runtime/heartbeat_flags.h" +#include "runtime/jdbc_driver_manager.h" +#include "runtime/memory/roaring_hook.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "service/backend_options.h" #include "service/service.h" #include "service/staros_worker.h" @@ -179,6 +187,11 @@ int main(int argc, char** argv) { return -1; } +<<<<<<< HEAD +======= + starrocks::init_roaring_hook(); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #ifdef FIU_ENABLE if (!starrocks::failpoint::init_failpoint_from_conf(std::string(getenv("STARROCKS_HOME")) + "/conf/failpoint.json")) { @@ -210,6 +223,12 @@ int main(int argc, char** argv) { aws_sdk_options.httpOptions.compliantRfc3986Encoding = true; } Aws::InitAPI(aws_sdk_options); +<<<<<<< HEAD +======= + if (starrocks::config::enable_poco_client_for_aws_sdk) { + Aws::Http::SetHttpClientFactory(std::make_shared()); + } +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::vector paths; auto olap_res = starrocks::parse_conf_store_paths(starrocks::config::storage_root_path, &paths); diff --git a/be/src/simd/multi_version.h b/be/src/simd/multi_version.h new file mode 100644 index 0000000000000..e88a305bc8d39 --- /dev/null +++ b/be/src/simd/multi_version.h @@ -0,0 +1,39 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +// Only x86 support function multiversion. +// https://gcc.gnu.org/wiki/FunctionMultiVersioning +// TODO(GoHalo) Support aarch64 platform. +#if defined(__GNUC__) && defined(__x86_64__) +#include + +#define MFV_IMPL(IMPL, ATTR) \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wunused-function\"") \ + ATTR static inline IMPL _Pragma("GCC diagnostic pop") + +#define MFV_SSE42(IMPL) MFV_IMPL(IMPL, __attribute__((target("sse4.2")))) +#define MFV_AVX2(IMPL) MFV_IMPL(IMPL, __attribute__((target("avx2")))) +#define MFV_AVX512(IMPL) MFV_IMPL(IMPL, __attribute__((target("avx512f,avx512bw")))) +#define MFV_DEFAULT(IMPL) MFV_IMPL(IMPL, __attribute__((target("default")))) + +#else + +#define MFV_SSE42(IMPL) +#define MFV_AVX2(IMPL) +#define MFV_AVX512(IMPL) +#define MFV_DEFAULT(IMPL) IMPL + +#endif diff --git a/be/src/simd/simd.h b/be/src/simd/simd.h index 481253b06103c..e769ad3c6698b 100644 --- a/be/src/simd/simd.h +++ b/be/src/simd/simd.h @@ -16,7 +16,14 @@ #include #include +<<<<<<< HEAD #include +======= +#include +#include + +#include "column/column.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #ifdef __SSE2__ #include #elif defined(__ARM_NEON) && defined(__aarch64__) @@ -26,6 +33,7 @@ namespace SIMD { +<<<<<<< HEAD // Count the number of zeros of 8-bit signed integers. inline size_t count_zero(const int8_t* data, size_t size) { size_t count = 0; @@ -34,6 +42,18 @@ inline size_t count_zero(const int8_t* data, size_t size) { #if defined(__SSE2__) && defined(__POPCNT__) const __m128i zero16 = _mm_setzero_si128(); const int8_t* end64 = data + (size / 64 * 64); +======= +// Count the number of zeros of 8-bit integers. +template +inline typename std::enable_if::value || std::is_same::value, size_t>::type +count_zero(const T* data, size_t size) { + size_t count = 0; + const T* end = data + size; + +#if defined(__SSE2__) && defined(__POPCNT__) + const __m128i zero16 = _mm_setzero_si128(); + const T* end64 = data + (size / 64 * 64); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (; data < end64; data += 64) { count += __builtin_popcountll(static_cast(_mm_movemask_epi8(_mm_cmpeq_epi8( @@ -56,14 +76,27 @@ inline size_t count_zero(const int8_t* data, size_t size) { return count; } +<<<<<<< HEAD inline size_t count_zero(const uint32_t* data, size_t size) { size_t count = 0; const uint32_t* end = data + size; +======= +// Count the number of zeros of 32-bit integers. +template +inline typename std::enable_if::value || std::is_same::value, size_t>::type +count_zero(const T* data, size_t size) { + size_t count = 0; + const T* end = data + size; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #if defined(__SSE2__) && defined(__POPCNT__) // count per 16 int const __m128i zero16 = _mm_setzero_si128(); +<<<<<<< HEAD const uint32_t* end16 = data + (size / 16 * 16); +======= + const T* end16 = data + (size / 16 * 16); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (; data < end16; data += 16) { count += __builtin_popcountll(static_cast(_mm_movemask_ps(_mm_cvtepi32_ps(_mm_cmpeq_epi32( @@ -86,6 +119,7 @@ inline size_t count_zero(const uint32_t* data, size_t size) { return count; } +<<<<<<< HEAD inline size_t count_zero(const std::vector& nums) { return count_zero(nums.data(), nums.size()); } @@ -132,6 +166,42 @@ inline size_t count_nonzero(const std::vector& list) { // NOTE: memchr is much faster than a plain SIMD implementation template inline static size_t find_byte(const std::vector& list, size_t start, size_t count, T byte) { +======= +template +inline size_t count_zero(const Container& nums) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t) || sizeof(T) == sizeof(uint32_t)), + "only 8-bit or 32-bit integral types are supported"); + return count_zero(nums.data(), nums.size()); +} + +template +inline size_t count_zero(const Container& nums, size_t size) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t) || sizeof(T) == sizeof(uint32_t)), + "only 8-bit or 32-bit integral types are supported"); + return count_zero(nums.data(), size); +} + +template +inline size_t count_nonzero(const T* data, size_t size) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t) || sizeof(T) == sizeof(uint32_t)), + "only 8-bit or 32-bit integral types are supported"); + return size - count_zero(data, size); +} + +template +inline size_t count_nonzero(const Container& nums) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t) || sizeof(T) == sizeof(uint32_t)), + "only 8-bit or 32-bit integral types are supported"); + return count_nonzero(nums.data(), nums.size()); +} + +// NOTE: memchr is much faster than a plain SIMD implementation +template +inline static size_t find_byte(const Container& list, size_t start, size_t count, T byte) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (start >= list.size()) { return start; } @@ -143,8 +213,16 @@ inline static size_t find_byte(const std::vector& list, size_t start, size_t return (T*)p - list.data(); } +<<<<<<< HEAD template inline static size_t find_byte(const std::vector& list, size_t start, T byte) { +======= +template +inline static size_t find_byte(const Container& list, size_t start, T byte) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (start >= list.size()) { return start; } @@ -156,6 +234,7 @@ inline static size_t find_byte(const std::vector& list, size_t start, T byte) } // Find position for zero byte, return size of list if not found +<<<<<<< HEAD inline size_t find_zero(const std::vector& list, size_t start) { return find_byte(list, start, 0); } @@ -189,6 +268,61 @@ inline bool contain_nonzero(const std::vector& list, size_t start) { } inline bool contain_nonzero(const std::vector& list, size_t start, size_t count) { +======= +template +inline size_t find_zero(const Container& list, size_t start) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_byte(list, start, static_cast(0)); +} + +template +inline size_t find_zero(const Container& list, size_t start, size_t count) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_byte(list, start, count, static_cast(0)); +} + +template +inline size_t find_nonzero(const Container& list, size_t start) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_byte(list, start, static_cast(1)); +} + +template +inline size_t find_nonzero(const Container& list, size_t start, size_t count) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_byte(list, start, count, static_cast(1)); +} + +template +inline bool contain_zero(const Container& list) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_zero(list, 0) < list.size(); +} + +template +inline bool contain_nonzero(const Container& list) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_nonzero(list, 0) < list.size(); +} + +template +inline bool contain_nonzero(const Container& list, size_t start) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); + return find_nonzero(list, start) < list.size(); +} + +template +inline bool contain_nonzero(const Container& list, size_t start, size_t count) { + static_assert(std::is_integral::value && (sizeof(T) == sizeof(uint8_t)), + "only 8-bit integral types are supported"); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) size_t pos = find_nonzero(list, start, count); return pos < list.size() && pos < start + count; } diff --git a/be/src/starrocks_format/CMakeLists.txt b/be/src/starrocks_format/CMakeLists.txt new file mode 100644 index 0000000000000..605d78d083318 --- /dev/null +++ b/be/src/starrocks_format/CMakeLists.txt @@ -0,0 +1,82 @@ +# Copyright 2021-present StarRocks, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +set(CMAKE_VERBOSE_MAKEFILE ON) + +set(LIBRARY_OUTPUT_PATH "${BUILD_DIR}/src/starrocks_format") + +# where to put generated binaries +set(EXECUTABLE_OUTPUT_PATH "${BUILD_DIR}/src/starrocks_format") + +# Set starrocks libraries +set(STARROCKS_LIBS + ${WL_START_GROUP} + Common + Column + Connector + Exec + Exprs + FileSystem + Formats + Gutil + IO + Serde + Storage + Rowset + Runtime + Types + Util + Script + StarRocksGen + Webserver + TestUtil + BlockCache + ${WL_END_GROUP} +) + +add_library(hdfs_so SHARED IMPORTED GLOBAL) +set_target_properties(hdfs_so PROPERTIES IMPORTED_LOCATION ${THIRDPARTY_DIR}/hadoop/lib/native/libhdfs.so) + +set(STARROCKS_THIRDPARTY_DEPENDENCIES + ${STARROCKS_DEPENDENCIES} + ${STARROCKS_STD_DEPENDENCIES} + ${STARROCKS_MEMORY_DEPENDENCIES_LIBS} + ${STARROCKS_DYNAMIC_DEPENDENCIES_LIBS} +) + +# only build starrocks_be when TEST is off +if (NOT ${MAKE_TEST} STREQUAL "ON") + + add_library(starrocks_format SHARED + starrocks_lib.cpp + ) + + # This permits libraries loaded by dlopen to link to the symbols in the program. + target_link_libraries(starrocks_format + # -Wl,--whole-archive + ${STARROCKS_LIBS} + # -Wl,--no-whole-archive + ${STARROCKS_DEPENDENCIES} + ${STARROCKS_STD_DEPENDENCIES} + ${STARROCKS_DYNAMIC_DEPENDENCIES_LIBS} + hdfs_so + ) + + install(DIRECTORY DESTINATION ${OUTPUT_DIR}/format-lib/) + + install(TARGETS starrocks_format + DESTINATION ${OUTPUT_DIR}/format-lib/) + +endif() diff --git a/be/src/starrocks_format/starrocks_lib.cpp b/be/src/starrocks_format/starrocks_lib.cpp new file mode 100644 index 0000000000000..d6a61b3ce995a --- /dev/null +++ b/be/src/starrocks_format/starrocks_lib.cpp @@ -0,0 +1,84 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include +#include + +#include "common/config.h" +#include "fs/fs_s3.h" +#include "runtime/time_types.h" +#include "storage/lake/fixed_location_provider.h" +#include "storage/lake/tablet_manager.h" +#include "storage/olap_define.h" +#include "util/timezone_utils.h" + +namespace starrocks::lake { + +static bool _starrocks_format_inited = false; +Aws::SDKOptions aws_sdk_options; + +lake::TabletManager* _lake_tablet_manager = nullptr; + +void starrocks_format_initialize(void) { + setenv("STARROCKS_HOME", "./", 0); + setenv("UDF_RUNTIME_DIR", "./", 0); + + if (!_starrocks_format_inited) { + fprintf(stderr, "starrocks format module start to initialize\n"); + // load config file + std::string conffile = std::filesystem::current_path(); + conffile += "/starrocks.conf"; + const char* config_file_path = conffile.c_str(); + std::ifstream ifs(config_file_path); + if (!ifs.good()) { + config_file_path = nullptr; + } + if (!starrocks::config::init(config_file_path)) { + LOG(WARNING) << "read config file:" << config_file_path << " failed!"; + return; + } + + Aws::InitAPI(aws_sdk_options); + + date::init_date_cache(); + + TimezoneUtils::init_time_zones(); + + auto lake_location_provider = std::make_shared(""); + _lake_tablet_manager = new lake::TabletManager(lake_location_provider, config::lake_metadata_cache_limit); + LOG(INFO) << "starrocks format module has been initialized successfully"; + _starrocks_format_inited = true; + } else { + LOG(INFO) << "starrocks format module has already been initialized"; + } +} + +void starrocks_format_shutdown(void) { + if (_starrocks_format_inited) { + LOG(INFO) << "starrocks format module start to deinitialize"; + Aws::ShutdownAPI(aws_sdk_options); + SAFE_DELETE(_lake_tablet_manager); + // SAFE_DELETE(_lake_update_manager); + LOG(INFO) << "starrocks format module has been deinitialized successfully"; + } else { + LOG(INFO) << "starrocks format module has already been deinitialized"; + } +} + +} // namespace starrocks::lake diff --git a/be/src/starrocks_format/starrocks_lib.h b/be/src/starrocks_format/starrocks_lib.h new file mode 100644 index 0000000000000..63fd320acb9df --- /dev/null +++ b/be/src/starrocks_format/starrocks_lib.h @@ -0,0 +1,27 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "storage/lake/tablet_manager.h" + +namespace starrocks::lake { + +extern lake::TabletManager* _lake_tablet_manager; + +void starrocks_format_initialize(void); + +void starrocks_format_shutdown(void); + +} // namespace starrocks::lake diff --git a/be/src/storage/CMakeLists.txt b/be/src/storage/CMakeLists.txt index 6e45013d1df45..a484abef166b7 100644 --- a/be/src/storage/CMakeLists.txt +++ b/be/src/storage/CMakeLists.txt @@ -19,7 +19,11 @@ set(EXECUTABLE_OUTPUT_PATH "${BUILD_DIR}/src/storage") add_subdirectory(rowset) +<<<<<<< HEAD add_library(Storage STATIC +======= +set(STORAGE_FILES +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) aggregate_type.cpp base_tablet.cpp decimal12.cpp @@ -99,8 +103,14 @@ add_library(Storage STATIC rowset/ordinal_page_index.cpp rowset/page_io.cpp rowset/binary_dict_page.cpp +<<<<<<< HEAD rowset/dict_page.cpp rowset/binary_prefix_page.cpp +======= + rowset/binary_prefix_page.cpp + rowset/data_sample.cpp + rowset/dict_page.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) rowset/segment.cpp rowset/segment_writer.cpp rowset/segment_rewriter.cpp @@ -117,6 +127,10 @@ add_library(Storage STATIC rowset/rowid_range_option.cpp rowset/rowset_meta.cpp rowset/horizontal_update_rowset_writer.cpp +<<<<<<< HEAD +======= + rowset/bitmap_index_evaluator.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) rowset/metadata_cache.cpp task/engine_batch_load_task.cpp task/engine_checksum_task.cpp @@ -134,6 +148,10 @@ add_library(Storage STATIC column_not_in_predicate.cpp column_null_predicate.cpp column_or_predicate.cpp +<<<<<<< HEAD +======= + column_and_predicate.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) column_expr_predicate.cpp conjunctive_predicates.cpp predicate_tree/predicate_tree.cpp @@ -225,6 +243,10 @@ add_library(Storage STATIC sstable/iterator.cpp sstable/options.cpp sstable/merger.cpp +<<<<<<< HEAD +======= + lake/lake_delvec_loader.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) binlog_util.cpp binlog_file_writer.cpp binlog_file_reader.cpp @@ -235,6 +257,10 @@ add_library(Storage STATIC lake/txn_log_applier.cpp lake/lake_local_persistent_index.cpp persistent_index_compaction_manager.cpp +<<<<<<< HEAD +======= + lake/local_pk_index_manager.cpp +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) persistent_index_tablet_loader.cpp lake/lake_local_persistent_index_tablet_loader.cpp lake/lake_persistent_index.cpp @@ -248,6 +274,7 @@ add_library(Storage STATIC rows_mapper.cpp primary_key_compaction_conflict_resolver.cpp local_primary_key_compaction_conflict_resolver.cpp +<<<<<<< HEAD inverted/index_descriptor.hpp inverted/inverted_index_iterator.cpp inverted/inverted_index_iterator.cpp @@ -260,3 +287,29 @@ add_library(Storage STATIC inverted/clucene/clucene_inverted_reader.cpp inverted/clucene/clucene_inverted_util.hpp inverted/clucene/match_operator.cpp) +======= + index/inverted/inverted_index_iterator.cpp + index/inverted/inverted_index_option.cpp + index/inverted/inverted_plugin_factory.cpp + index/inverted/clucene/clucene_plugin.cpp + index/inverted/clucene/clucene_inverted_writer.cpp + index/inverted/clucene/clucene_inverted_reader.cpp + index/inverted/clucene/match_operator.cpp + index/vector/empty_index_reader.cpp + index/vector/vector_index_builder_factory.cpp + index/vector/vector_index_writer.cpp + index/vector/vector_index_builder.cpp + index/vector/vector_index_reader_factory.cpp + index/vector/tenann_index_reader.cpp + index/vector/tenann/del_id_filter.cpp + index/vector/tenann/tenann_index_builder.cpp + index/vector/tenann/tenann_index_utils.cpp) + +if (NOT BUILD_FORMAT_LIB) + list(APPEND STORAGE_FILES lake/starlet_location_provider.cpp) +endif() + +add_library(Storage STATIC + ${STORAGE_FILES} +) +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) diff --git a/be/src/storage/aggregate_iterator.cpp b/be/src/storage/aggregate_iterator.cpp index 2760eb5487b18..371702a96831b 100644 --- a/be/src/storage/aggregate_iterator.cpp +++ b/be/src/storage/aggregate_iterator.cpp @@ -58,7 +58,11 @@ class AggregateIterator final : public ChunkIterator { size_t merged_rows() const override { return _aggregator->merged_rows(); } +<<<<<<< HEAD [[nodiscard]] Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) override { +======= + Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(ChunkIterator::init_encoded_schema(dict_maps)); RETURN_IF_ERROR(_child->init_encoded_schema(dict_maps)); _curr_chunk = ChunkHelper::new_chunk(encoded_schema(), _chunk_size); @@ -67,7 +71,11 @@ class AggregateIterator final : public ChunkIterator { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status init_output_schema(const std::unordered_set& unused_output_column_ids) override { +======= + Status init_output_schema(const std::unordered_set& unused_output_column_ids) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(ChunkIterator::init_output_schema(unused_output_column_ids)); RETURN_IF_ERROR(_child->init_output_schema(unused_output_column_ids)); _curr_chunk = ChunkHelper::new_chunk(output_schema(), _chunk_size); diff --git a/be/src/storage/aggregate_type.cpp b/be/src/storage/aggregate_type.cpp index 65d71bc1053a6..cc53dc3c16a23 100644 --- a/be/src/storage/aggregate_type.cpp +++ b/be/src/storage/aggregate_type.cpp @@ -21,6 +21,7 @@ namespace starrocks { StorageAggregateType get_aggregation_type_by_string(const std::string& str) { +<<<<<<< HEAD std::string upper_str = str; std::transform(str.begin(), str.end(), upper_str.begin(), ::tolower); @@ -33,6 +34,21 @@ StorageAggregateType get_aggregation_type_by_string(const std::string& str) { if (upper_str == "hll_union") return STORAGE_AGGREGATE_HLL_UNION; if (upper_str == "bitmap_union") return STORAGE_AGGREGATE_BITMAP_UNION; if (upper_str == "percentile_union") return STORAGE_AGGREGATE_PERCENTILE_UNION; +======= + std::string lower_str = str; + std::transform(str.begin(), str.end(), lower_str.begin(), ::tolower); + + if (lower_str == "none") return STORAGE_AGGREGATE_NONE; + if (lower_str == "sum") return STORAGE_AGGREGATE_SUM; + if (lower_str == "min") return STORAGE_AGGREGATE_MIN; + if (lower_str == "max") return STORAGE_AGGREGATE_MAX; + if (lower_str == "replace") return STORAGE_AGGREGATE_REPLACE; + if (lower_str == "replace_if_not_null") return STORAGE_AGGREGATE_REPLACE_IF_NOT_NULL; + if (lower_str == "hll_union") return STORAGE_AGGREGATE_HLL_UNION; + if (lower_str == "bitmap_union") return STORAGE_AGGREGATE_BITMAP_UNION; + if (lower_str == "percentile_union") return STORAGE_AGGREGATE_PERCENTILE_UNION; + if (lower_str == "agg_state_union") return STORAGE_AGGREGATE_AGG_STATE_UNION; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) LOG(WARNING) << "invalid aggregation type string. [aggregation='" << str << "']"; return STORAGE_AGGREGATE_UNKNOWN; } @@ -59,6 +75,11 @@ std::string get_string_by_aggregation_type(StorageAggregateType type) { return "percentile_union"; case STORAGE_AGGREGATE_UNKNOWN: return "unknown"; +<<<<<<< HEAD +======= + case STORAGE_AGGREGATE_AGG_STATE_UNION: + return "agg_state_union"; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } return ""; } diff --git a/be/src/storage/aggregate_type.h b/be/src/storage/aggregate_type.h index 5c71c4670d720..2ecb0f0213a3f 100644 --- a/be/src/storage/aggregate_type.h +++ b/be/src/storage/aggregate_type.h @@ -29,7 +29,13 @@ enum StorageAggregateType { STORAGE_AGGREGATE_BITMAP_UNION = 7, // Replace if and only if added value is not null STORAGE_AGGREGATE_REPLACE_IF_NOT_NULL = 8, +<<<<<<< HEAD STORAGE_AGGREGATE_PERCENTILE_UNION = 9 +======= + STORAGE_AGGREGATE_PERCENTILE_UNION = 9, + // Generic aggregate function's state union + STORAGE_AGGREGATE_AGG_STATE_UNION = 10 +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; StorageAggregateType get_aggregation_type_by_string(const std::string& str); diff --git a/be/src/storage/async_delta_writer.cpp b/be/src/storage/async_delta_writer.cpp index da4d732f35199..c0738fd0bfd36 100644 --- a/be/src/storage/async_delta_writer.cpp +++ b/be/src/storage/async_delta_writer.cpp @@ -88,6 +88,10 @@ int AsyncDeltaWriter::_execute(void* meta, bthread::TaskIteratortxn_id() << " tablet_id: " << writer->tablet()->tablet_id() << ": " << st; } +<<<<<<< HEAD +======= + writer->update_task_stat(num_tasks, pending_time_ns); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) StarRocksMetrics::instance()->async_delta_writer_execute_total.increment(1); StarRocksMetrics::instance()->async_delta_writer_task_total.increment(num_tasks); StarRocksMetrics::instance()->async_delta_writer_task_execute_duration_us.increment(watch.elapsed_time() / 1000); diff --git a/be/src/storage/base_tablet.h b/be/src/storage/base_tablet.h index 1215e3f8137c1..65556d118f030 100644 --- a/be/src/storage/base_tablet.h +++ b/be/src/storage/base_tablet.h @@ -37,6 +37,10 @@ #include #include "storage/olap_define.h" +<<<<<<< HEAD +======= +#include "storage/rowset/base_rowset.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "storage/tablet_meta.h" #include "storage/utils.h" @@ -118,6 +122,12 @@ class BaseTablet : public std::enable_shared_from_this { virtual size_t num_rows() const = 0; +<<<<<<< HEAD +======= + virtual StatusOr has_delete_predicates(const Version& version) = 0; + +protected: +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) virtual void on_shutdown() {} protected: diff --git a/be/src/storage/chunk_aggregator.cpp b/be/src/storage/chunk_aggregator.cpp index 440766eb68fbf..5f94a85676039 100644 --- a/be/src/storage/chunk_aggregator.cpp +++ b/be/src/storage/chunk_aggregator.cpp @@ -16,6 +16,10 @@ #include "common/config.h" #include "exec/sorting/sorting.h" +<<<<<<< HEAD +======= +#include "exprs/agg/aggregate_state_allocator.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/casts.h" #include "storage/column_aggregate_func.h" @@ -169,7 +173,11 @@ void ChunkAggregator::aggregate() { _aggregate_loops[_aggregate_loops.size() - 1] += 1; } } +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(&kDefaultColumnAggregatorAllocator); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // 3. Copy the selected key rows // 4. Aggregate the value rows for (int i = 0; i < _key_fields; ++i) { @@ -192,7 +200,11 @@ bool ChunkAggregator::is_finish() { void ChunkAggregator::aggregate_reset() { _aggregate_chunk = ChunkHelper::new_chunk(*_schema, _reserve_rows); _aggregate_rows = 0; +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(&kDefaultColumnAggregatorAllocator); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (int i = 0; i < _num_fields; ++i) { auto p = _aggregate_chunk->get_column_by_index(i).get(); _column_aggregator[i]->update_aggregate(p); @@ -206,6 +218,10 @@ void ChunkAggregator::aggregate_reset() { } ChunkPtr ChunkAggregator::aggregate_result() { +<<<<<<< HEAD +======= + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(&kDefaultColumnAggregatorAllocator); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) for (int i = 0; i < _num_fields; ++i) { _column_aggregator[i]->finalize(); } diff --git a/be/src/storage/chunk_helper.cpp b/be/src/storage/chunk_helper.cpp index 52dce6f57794d..7c2b96ad036ab 100644 --- a/be/src/storage/chunk_helper.cpp +++ b/be/src/storage/chunk_helper.cpp @@ -14,15 +14,28 @@ #include "storage/chunk_helper.h" +<<<<<<< HEAD #include "column/array_column.h" #include "column/chunk.h" #include "column/column_helper.h" #include "column/column_pool.h" +======= +#include +#include + +#include "column/array_column.h" +#include "column/chunk.h" +#include "column/column_helper.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/json_column.h" #include "column/map_column.h" #include "column/schema.h" #include "column/struct_column.h" #include "column/type_traits.h" +<<<<<<< HEAD +======= +#include "column/vectorized_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/strings/fastmem.h" #include "runtime/current_thread.h" #include "runtime/descriptors.h" @@ -142,6 +155,10 @@ Field ChunkHelper::convert_field(ColumnId id, const TabletColumn& c) { f.set_short_key_length(c.index_length()); f.set_aggregate_method(c.aggregation()); +<<<<<<< HEAD +======= + f.set_agg_state_desc(c.get_agg_state_desc()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return f; } @@ -229,6 +246,7 @@ ColumnId ChunkHelper::max_column_id(const starrocks::Schema& schema) { } template +<<<<<<< HEAD struct ColumnDeleter { ColumnDeleter(size_t chunk_size) : chunk_size(chunk_size) {} void operator()(Column* ptr) const { return_column(down_cast(ptr), chunk_size); } @@ -252,11 +270,21 @@ inline std::shared_ptr get_column_ptr(size_t chunk_size) { template inline std::shared_ptr> get_decimal_column_ptr(int precision, int scale, size_t chunk_size) { auto column = get_column_ptr(chunk_size); +======= +inline std::shared_ptr get_column_ptr() { + return std::make_shared(); +} + +template +inline std::shared_ptr> get_decimal_column_ptr(int precision, int scale) { + auto column = get_column_ptr(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) column->set_precision(precision); column->set_scale(scale); return column; } +<<<<<<< HEAD template struct ColumnPtrBuilder { template @@ -265,31 +293,52 @@ struct ColumnPtrBuilder { return field.is_nullable() ? NullableColumn::create(std::move(c), get_column_ptr(chunk_size)) : c; +======= +struct ColumnPtrBuilder { + template + ColumnPtr operator()(const Field& field, int precision, int scale) { + auto NullableIfNeed = [&](ColumnPtr c) -> ColumnPtr { + return field.is_nullable() ? NullableColumn::create(std::move(c), get_column_ptr()) : c; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; if constexpr (ftype == TYPE_ARRAY) { auto elements = NullableColumn::wrap_if_necessary(field.sub_field(0).create_column()); +<<<<<<< HEAD auto offsets = get_column_ptr(chunk_size); +======= + auto offsets = get_column_ptr(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto array = ArrayColumn::create(std::move(elements), offsets); return NullableIfNeed(array); } else if constexpr (ftype == TYPE_MAP) { auto keys = NullableColumn::wrap_if_necessary(field.sub_field(0).create_column()); auto values = NullableColumn::wrap_if_necessary(field.sub_field(1).create_column()); +<<<<<<< HEAD auto offsets = get_column_ptr(chunk_size); +======= + auto offsets = get_column_ptr(); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) auto map = MapColumn::create(std::move(keys), std::move(values), offsets); return NullableIfNeed(map); } else if constexpr (ftype == TYPE_STRUCT) { std::vector names; std::vector fields; for (auto& sub_field : field.sub_fields()) { +<<<<<<< HEAD names.template emplace_back(sub_field.name()); fields.template emplace_back(sub_field.create_column()); +======= + names.emplace_back(sub_field.name()); + fields.emplace_back(sub_field.create_column()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } auto struct_column = StructColumn::create(std::move(fields), std::move(names)); return NullableIfNeed(struct_column); } else { switch (ftype) { case TYPE_DECIMAL32: +<<<<<<< HEAD return NullableIfNeed(get_decimal_column_ptr(precision, scale, chunk_size)); case TYPE_DECIMAL64: return NullableIfNeed(get_decimal_column_ptr(precision, scale, chunk_size)); @@ -297,12 +346,22 @@ struct ColumnPtrBuilder { return NullableIfNeed(get_decimal_column_ptr(precision, scale, chunk_size)); default: { return NullableIfNeed(get_column_ptr::ColumnType, force>(chunk_size)); +======= + return NullableIfNeed(get_decimal_column_ptr(precision, scale)); + case TYPE_DECIMAL64: + return NullableIfNeed(get_decimal_column_ptr(precision, scale)); + case TYPE_DECIMAL128: + return NullableIfNeed(get_decimal_column_ptr(precision, scale)); + default: { + return NullableIfNeed(get_column_ptr::ColumnType>()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } } } } }; +<<<<<<< HEAD template ColumnPtr column_from_pool(const Field& field, size_t chunk_size) { auto precision = field.type()->precision(); @@ -312,11 +371,24 @@ ColumnPtr column_from_pool(const Field& field, size_t chunk_size) { } Chunk* ChunkHelper::new_chunk_pooled(const Schema& schema, size_t chunk_size, bool force) { +======= +ColumnPtr column_from_pool(const Field& field) { + auto precision = field.type()->precision(); + auto scale = field.type()->scale(); + return field_type_dispatch_column(field.type()->type(), ColumnPtrBuilder(), field, precision, scale); +} + +Chunk* ChunkHelper::new_chunk_pooled(const Schema& schema, size_t chunk_size) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Columns columns; columns.reserve(schema.num_fields()); for (size_t i = 0; i < schema.num_fields(); i++) { const FieldPtr& f = schema.field(i); +<<<<<<< HEAD auto column = force ? column_from_pool(*f, chunk_size) : column_from_pool(*f, chunk_size); +======= + auto column = column_from_pool(*f); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) column->reserve(chunk_size); columns.emplace_back(std::move(column)); } @@ -426,8 +498,13 @@ ColumnPtr ChunkHelper::column_from_field(const Field& field) { std::vector names; std::vector fields; for (auto& sub_field : field.sub_fields()) { +<<<<<<< HEAD names.template emplace_back(sub_field.name()); fields.template emplace_back(sub_field.create_column()); +======= + names.emplace_back(sub_field.name()); + fields.emplace_back(sub_field.create_column()); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } auto struct_column = StructColumn::create(std::move(fields), std::move(names)); return NullableIfNeed(struct_column); @@ -631,4 +708,421 @@ bool ChunkPipelineAccumulator::is_finished() const { return _finalized && _out_chunk == nullptr && _in_chunk == nullptr; } +<<<<<<< HEAD +======= +template +inline constexpr bool is_object = std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v, ColumnT>; + +// Selective-copy data from SegmentedColumn according to provided index +class SegmentedColumnSelectiveCopy final : public ColumnVisitorAdapter { +public: + SegmentedColumnSelectiveCopy(SegmentedColumnPtr segment_column, const uint32_t* indexes, uint32_t from, + uint32_t size) + : ColumnVisitorAdapter(this), + _segment_column(std::move(segment_column)), + _indexes(indexes), + _from(from), + _size(size) {} + + template + Status do_visit(const FixedLengthColumnBase& column) { + using ColumnT = FixedLengthColumnBase; + using ContainerT = typename ColumnT::Container; + + _result = column.clone_empty(); + auto output = ColumnHelper::as_column(_result); + const size_t segment_size = _segment_column->segment_size(); + + std::vector buffers; + auto columns = _segment_column->columns(); + for (auto& seg_column : columns) { + buffers.push_back(&ColumnHelper::as_column(seg_column)->get_data()); + } + + ContainerT& output_items = output->get_data(); + output_items.resize(_size); + size_t from = _from; + for (size_t i = 0; i < _size; i++) { + size_t idx = _indexes[from + i]; + auto [segment_id, segment_offset] = _segment_address(idx, segment_size); + DCHECK_LT(segment_id, columns.size()); + DCHECK_LT(segment_offset, columns[segment_id]->size()); + + output_items[i] = (*buffers[segment_id])[segment_offset]; + } + return {}; + } + + // Implementation refers to BinaryColumn::append_selective + template + Status do_visit(const BinaryColumnBase& column) { + using ColumnT = BinaryColumnBase; + using ContainerT = typename ColumnT::Container*; + using Bytes = typename ColumnT::Bytes; + using Byte = typename ColumnT::Byte; + using Offsets = typename ColumnT::Offsets; + + _result = column.clone_empty(); + auto output = ColumnHelper::as_column(_result); + auto& output_offsets = output->get_offset(); + auto& output_bytes = output->get_bytes(); + const size_t segment_size = _segment_column->segment_size(); + + // input + auto columns = _segment_column->columns(); + std::vector input_bytes; + std::vector input_offsets; + for (auto& seg_column : columns) { + input_bytes.push_back(&ColumnHelper::as_column(seg_column)->get_bytes()); + input_offsets.push_back(&ColumnHelper::as_column(seg_column)->get_offset()); + } + +#ifndef NDEBUG + for (auto& src_col : columns) { + src_col->check_or_die(); + } +#endif + + // assign offsets + output_offsets.resize(_size + 1); + size_t num_bytes = 0; + size_t from = _from; + for (size_t i = 0; i < _size; i++) { + size_t idx = _indexes[from + i]; + auto [segment_id, segment_offset] = _segment_address(idx, segment_size); + DCHECK_LT(segment_id, columns.size()); + DCHECK_LT(segment_offset, columns[segment_id]->size()); + + Offsets& src_offsets = *input_offsets[segment_id]; + Offset str_size = src_offsets[segment_offset + 1] - src_offsets[segment_offset]; + + output_offsets[i + 1] = output_offsets[i] + str_size; + num_bytes += str_size; + } + output_bytes.resize(num_bytes); + + // copy bytes + Byte* dest_bytes = output_bytes.data(); + for (size_t i = 0; i < _size; i++) { + size_t idx = _indexes[from + i]; + auto [segment_id, segment_offset] = _segment_address(idx, segment_size); + Bytes& src_bytes = *input_bytes[segment_id]; + Offsets& src_offsets = *input_offsets[segment_id]; + Offset str_size = src_offsets[segment_offset + 1] - src_offsets[segment_offset]; + Byte* str_data = src_bytes.data() + src_offsets[segment_offset]; + + strings::memcpy_inlined(dest_bytes + output_offsets[i], str_data, str_size); + } + +#ifndef NDEBUG + output->check_or_die(); +#endif + + return {}; + } + + // Inefficient fallback implementation, it's usually used for Array/Struct/Map/Json + template + typename std::enable_if_t, Status> do_visit(const ColumnT& column) { + _result = column.clone_empty(); + auto output = ColumnHelper::as_column(_result); + const size_t segment_size = _segment_column->segment_size(); + output->reserve(_size); + + auto columns = _segment_column->columns(); + size_t from = _from; + for (size_t i = 0; i < _size; i++) { + size_t idx = _indexes[from + i]; + auto [segment_id, segment_offset] = _segment_address(idx, segment_size); + output->append(*columns[segment_id], segment_offset, 1); + } + return {}; + } + + Status do_visit(const NullableColumn& column) { + std::vector data_columns, null_columns; + for (auto& column : _segment_column->columns()) { + NullableColumn::Ptr nullable = ColumnHelper::as_column(column); + data_columns.push_back(nullable->data_column()); + null_columns.push_back(nullable->null_column()); + } + + auto segmented_data_column = std::make_shared(data_columns, _segment_column->segment_size()); + SegmentedColumnSelectiveCopy copy_data(segmented_data_column, _indexes, _from, _size); + (void)data_columns[0]->accept(©_data); + auto segmented_null_column = std::make_shared(null_columns, _segment_column->segment_size()); + SegmentedColumnSelectiveCopy copy_null(segmented_null_column, _indexes, _from, _size); + (void)null_columns[0]->accept(©_null); + _result = NullableColumn::create(copy_data.result(), ColumnHelper::as_column(copy_null.result())); + + return {}; + } + + Status do_visit(const ConstColumn& column) { return Status::NotSupported("SegmentedColumnVisitor"); } + + ColumnPtr result() { return _result; } + +private: + __attribute__((always_inline)) std::pair _segment_address(size_t idx, size_t segment_size) { + size_t segment_id = idx / segment_size; + size_t segment_offset = idx % segment_size; + return {segment_id, segment_offset}; + } + + SegmentedColumnPtr _segment_column; + ColumnPtr _result; + const uint32_t* _indexes; + uint32_t _from; + uint32_t _size; +}; + +SegmentedColumn::SegmentedColumn(const SegmentedChunkPtr& chunk, size_t column_index) + : _chunk(chunk), _column_index(column_index), _segment_size(chunk->segment_size()) {} + +SegmentedColumn::SegmentedColumn(std::vector columns, size_t segment_size) + : _segment_size(segment_size), _cached_columns(std::move(columns)) {} + +ColumnPtr SegmentedColumn::clone_selective(const uint32_t* indexes, uint32_t from, uint32_t size) { + if (num_segments() == 1) { + auto first = columns()[0]; + auto result = first->clone_empty(); + result->append_selective(*first, indexes, from, size); + return result; + } else { + SegmentedColumnSelectiveCopy visitor(shared_from_this(), indexes, from, size); + (void)columns()[0]->accept(&visitor); + return visitor.result(); + } +} + +ColumnPtr SegmentedColumn::materialize() const { + auto actual_columns = columns(); + if (actual_columns.empty()) { + return {}; + } + ColumnPtr result = actual_columns[0]->clone_empty(); + for (size_t i = 0; i < actual_columns.size(); i++) { + result->append(*actual_columns[i]); + } + return result; +} + +size_t SegmentedColumn::segment_size() const { + return _segment_size; +} + +size_t SegmentedColumn::num_segments() const { + return _chunk.lock()->num_segments(); +} + +size_t SegmentedChunk::segment_size() const { + return _segment_size; +} + +bool SegmentedColumn::is_nullable() const { + return columns()[0]->is_nullable(); +} + +bool SegmentedColumn::has_null() const { + for (auto& column : columns()) { + RETURN_IF(column->has_null(), true); + } + return false; +} + +size_t SegmentedColumn::size() const { + size_t result = 0; + for (auto& column : columns()) { + result += column->size(); + } + return result; +} + +std::vector SegmentedColumn::columns() const { + if (!_cached_columns.empty()) { + return _cached_columns; + } + std::vector columns; + for (auto& segment : _chunk.lock()->segments()) { + columns.push_back(segment->get_column_by_index(_column_index)); + } + return columns; +} + +void SegmentedColumn::upgrade_to_nullable() { + for (auto& segment : _chunk.lock()->segments()) { + auto& column = segment->get_column_by_index(_column_index); + column = NullableColumn::wrap_if_necessary(column); + } +} + +SegmentedChunk::SegmentedChunk(size_t segment_size) : _segment_size(segment_size) { + // put at least one chunk there + _segments.resize(1); + _segments[0] = std::make_shared(); +} + +SegmentedChunkPtr SegmentedChunk::create(size_t segment_size) { + return std::make_shared(segment_size); +} + +void SegmentedChunk::append_column(ColumnPtr column, SlotId slot_id) { + // It's only used when initializing the chunk, so append the column to first chunk is enough + DCHECK_EQ(_segments.size(), 1); + _segments[0]->append_column(std::move(column), slot_id); +} + +void SegmentedChunk::append_chunk(const ChunkPtr& chunk, const std::vector& slots) { + ChunkPtr open_segment = _segments.back(); + size_t append_rows = chunk->num_rows(); + size_t append_index = 0; + while (append_rows > 0) { + size_t open_segment_append_rows = std::min(_segment_size - open_segment->num_rows(), append_rows); + for (int i = 0; i < slots.size(); i++) { + SlotId slot = slots[i]; + ColumnPtr column = chunk->get_column_by_slot_id(slot); + open_segment->columns()[i]->append(*column, append_index, open_segment_append_rows); + } + append_index += open_segment_append_rows; + append_rows -= open_segment_append_rows; + if (open_segment->num_rows() == _segment_size) { + open_segment->check_or_die(); + open_segment = open_segment->clone_empty(); + _segments.emplace_back(open_segment); + } + } +} + +void SegmentedChunk::append_chunk(const ChunkPtr& chunk) { + ChunkPtr open_segment = _segments.back(); + size_t append_rows = chunk->num_rows(); + size_t append_index = 0; + while (append_rows > 0) { + size_t open_segment_append_rows = std::min(_segment_size - open_segment->num_rows(), append_rows); + open_segment->append_safe(*chunk, append_index, open_segment_append_rows); + append_index += open_segment_append_rows; + append_rows -= open_segment_append_rows; + if (open_segment->num_rows() == _segment_size) { + open_segment->check_or_die(); + open_segment = open_segment->clone_empty(); + _segments.emplace_back(open_segment); + } + } +} + +void SegmentedChunk::append(const SegmentedChunkPtr& chunk, size_t offset) { + auto& input_segments = chunk->segments(); + size_t segment_index = offset / chunk->_segment_size; + size_t segment_offset = offset % chunk->_segment_size; + for (size_t i = segment_index; i < chunk->num_segments(); i++) { + // The segment need to cutoff + if (i == segment_index && segment_offset > 0) { + auto cutoff = input_segments[i]->clone_empty(); + size_t count = input_segments[i]->num_rows() - segment_offset; + cutoff->append(*input_segments[i], segment_offset, count); + append_chunk(std::move(cutoff)); + } else { + append_chunk(input_segments[i]); + } + } + for (auto& segment : _segments) { + segment->check_or_die(); + } +} + +void SegmentedChunk::build_columns() { + DCHECK(_segments.size() >= 1); + size_t num_columns = _segments[0]->num_columns(); + for (int i = 0; i < num_columns; i++) { + _columns.emplace_back(std::make_shared(shared_from_this(), i)); + } +} + +size_t SegmentedChunk::memory_usage() const { + size_t result = 0; + for (auto& chunk : _segments) { + result += chunk->memory_usage(); + } + return result; +} + +size_t SegmentedChunk::num_rows() const { + size_t result = 0; + for (auto& chunk : _segments) { + result += chunk->num_rows(); + } + return result; +} + +SegmentedColumnPtr SegmentedChunk::get_column_by_slot_id(SlotId slot_id) { + DCHECK(!!_segments[0]); + auto& map = _segments[0]->get_slot_id_to_index_map(); + auto iter = map.find(slot_id); + if (iter == map.end()) { + return nullptr; + } + return _columns[iter->second]; +} + +const SegmentedColumns& SegmentedChunk::columns() const { + return _columns; +} + +SegmentedColumns& SegmentedChunk::columns() { + return _columns; +} + +Status SegmentedChunk::upgrade_if_overflow() { + for (auto& chunk : _segments) { + RETURN_IF_ERROR(chunk->upgrade_if_overflow()); + } + return {}; +} + +Status SegmentedChunk::downgrade() { + for (auto& chunk : _segments) { + RETURN_IF_ERROR(chunk->downgrade()); + } + return {}; +} + +bool SegmentedChunk::has_large_column() const { + for (auto& chunk : _segments) { + if (chunk->has_large_column()) { + return true; + } + } + return false; +} + +size_t SegmentedChunk::num_segments() const { + return _segments.size(); +} + +const std::vector& SegmentedChunk::segments() const { + return _segments; +} +std::vector& SegmentedChunk::segments() { + return _segments; +} + +ChunkUniquePtr SegmentedChunk::clone_empty(size_t reserve) { + return _segments[0]->clone_empty(reserve); +} + +void SegmentedChunk::reset() { + for (auto& chunk : _segments) { + chunk->reset(); + } +} + +void SegmentedChunk::check_or_die() { + for (auto& chunk : _segments) { + chunk->check_or_die(); + } +} + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/storage/chunk_helper.h b/be/src/storage/chunk_helper.h index e8a33fcd5d4d4..eb35300bc5983 100644 --- a/be/src/storage/chunk_helper.h +++ b/be/src/storage/chunk_helper.h @@ -15,8 +15,18 @@ #pragma once #include +<<<<<<< HEAD #include +======= +#include +#include + +#include "column/column_visitor.h" +#include "column/column_visitor_adapter.h" +#include "column/datum.h" +#include "column/fixed_length_column_base.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "column/vectorized_fwd.h" #include "storage/olap_common.h" #include "storage/olap_type_infra.h" @@ -69,7 +79,11 @@ class ChunkHelper { // Create an empty chunk according to the |slots| and reserve it of size |n|. static ChunkUniquePtr new_chunk(const std::vector& slots, size_t n); +<<<<<<< HEAD static Chunk* new_chunk_pooled(const Schema& schema, size_t n, bool force); +======= + static Chunk* new_chunk_pooled(const Schema& schema, size_t n); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) // Create a vectorized column from field . // REQUIRE: |type| must be scalar type. @@ -106,7 +120,11 @@ class ChunkAccumulator { void finalize(); bool empty() const; bool reach_limit() const; +<<<<<<< HEAD [[nodiscard]] Status push(ChunkPtr&& chunk); +======= + Status push(ChunkPtr&& chunk); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) ChunkPtr pull(); private: @@ -149,4 +167,71 @@ class ChunkPipelineAccumulator { bool _finalized = false; }; +<<<<<<< HEAD +======= +class SegmentedColumn final : public std::enable_shared_from_this { +public: + SegmentedColumn(const SegmentedChunkPtr& chunk, size_t column_index); + SegmentedColumn(std::vector columns, size_t segment_size); + ~SegmentedColumn() = default; + + ColumnPtr clone_selective(const uint32_t* indexes, uint32_t from, uint32_t size); + ColumnPtr materialize() const; + + bool is_nullable() const; + bool has_null() const; + size_t size() const; + void upgrade_to_nullable(); + size_t segment_size() const; + size_t num_segments() const; + std::vector columns() const; + +private: + SegmentedChunkWeakPtr _chunk; // The chunk it belongs to + size_t _column_index; // The index in original chunk + const size_t _segment_size; + + std::vector _cached_columns; // Only used for SelectiveCopy +}; + +// A big-chunk would be segmented into multi small ones, to avoid allocating large-continuous memory +// It's not a transparent replacement for Chunk, but must be aware of and set a reasonale chunk_size +class SegmentedChunk final : public std::enable_shared_from_this { +public: + SegmentedChunk(size_t segment_size); + ~SegmentedChunk() = default; + + static SegmentedChunkPtr create(size_t segment_size); + + void append_column(ColumnPtr column, SlotId slot_id); + void append_chunk(const ChunkPtr& chunk, const std::vector& slots); + void append_chunk(const ChunkPtr& chunk); + void append(const SegmentedChunkPtr& chunk, size_t offset); + void build_columns(); + + SegmentedColumnPtr get_column_by_slot_id(SlotId slot_id); + const SegmentedColumns& columns() const; + SegmentedColumns& columns(); + size_t num_segments() const; + const std::vector& segments() const; + std::vector& segments(); + ChunkUniquePtr clone_empty(size_t reserve); + + size_t segment_size() const; + void reset(); + size_t memory_usage() const; + size_t num_rows() const; + Status upgrade_if_overflow(); + Status downgrade(); + bool has_large_column() const; + void check_or_die(); + +private: + std::vector _segments; + SegmentedColumns _columns; + + const size_t _segment_size; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } // namespace starrocks diff --git a/be/src/storage/chunk_iterator.cpp b/be/src/storage/chunk_iterator.cpp index aa3da3a2d4441..887819ac25efe 100644 --- a/be/src/storage/chunk_iterator.cpp +++ b/be/src/storage/chunk_iterator.cpp @@ -31,13 +31,21 @@ class TimedChunkIterator final : public ChunkIterator { size_t merged_rows() const override { return _iter->merged_rows(); } +<<<<<<< HEAD [[nodiscard]] Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) override { +======= + Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(ChunkIterator::init_encoded_schema(dict_maps)); RETURN_IF_ERROR(_iter->init_encoded_schema(dict_maps)); return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] Status init_output_schema(const std::unordered_set& unused_output_column_ids) override { +======= + Status init_output_schema(const std::unordered_set& unused_output_column_ids) override { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) RETURN_IF_ERROR(ChunkIterator::init_output_schema(unused_output_column_ids)); RETURN_IF_ERROR(_iter->init_output_schema(unused_output_column_ids)); return Status::OK(); diff --git a/be/src/storage/chunk_iterator.h b/be/src/storage/chunk_iterator.h index caeea08f5a1a5..fb4970629e0e2 100644 --- a/be/src/storage/chunk_iterator.h +++ b/be/src/storage/chunk_iterator.h @@ -48,14 +48,22 @@ class ChunkIterator { // i.e, size of |chunk| must be greater than zero. // if the returned status is `EndOfFile`, size of |chunk| must be zero; // otherwise, the size of |chunk| is undefined. +<<<<<<< HEAD [[nodiscard]] Status get_next(Chunk* chunk) { +======= + Status get_next(Chunk* chunk) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status st = do_get_next(chunk); DCHECK_CHUNK(chunk); return st; } // like get_next(Chunk* chunk), but also returns each row's rowid(ordinal id) +<<<<<<< HEAD [[nodiscard]] Status get_next(Chunk* chunk, std::vector* rowid) { +======= + Status get_next(Chunk* chunk, std::vector* rowid) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status st = do_get_next(chunk, rowid); DCHECK_CHUNK(chunk); return st; @@ -63,22 +71,34 @@ class ChunkIterator { // like get_next(Chunk* chunk), but also returns each row source mask // row source mask sequence will be generated by HeapMergeIterator or be used by MaskMergeIterator. +<<<<<<< HEAD [[nodiscard]] Status get_next(Chunk* chunk, std::vector* source_masks) { +======= + Status get_next(Chunk* chunk, std::vector* source_masks) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status st = do_get_next(chunk, source_masks); DCHECK_CHUNK(chunk); return st; } // like get_next(Chunk* chunk), but also returns each row's rssid + rowid (after encode) +<<<<<<< HEAD [[nodiscard]] Status get_next(Chunk* chunk, std::vector* rssid_rowids) { +======= + Status get_next(Chunk* chunk, std::vector* rssid_rowids) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status st = do_get_next(chunk, rssid_rowids); DCHECK_CHUNK(chunk); return st; } // like get_next(Chunk* chunk), but also returns each row's rssid + rowid (after encode) +<<<<<<< HEAD [[nodiscard]] Status get_next(Chunk* chunk, std::vector* source_masks, std::vector* rssid_rowids) { +======= + Status get_next(Chunk* chunk, std::vector* source_masks, std::vector* rssid_rowids) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status st = do_get_next(chunk, source_masks, rssid_rowids); DCHECK_CHUNK(chunk); return st; @@ -96,7 +116,11 @@ class ChunkIterator { // If a Field uses the global dictionary strategy, the field will be rewritten as INT const Schema& encoded_schema() const { return _encoded_schema.num_fields() == 0 ? _schema : _encoded_schema; } +<<<<<<< HEAD [[nodiscard]] virtual Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) { +======= + virtual Status init_encoded_schema(ColumnIdToGlobalDictMap& dict_maps) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) _encoded_schema.reserve(schema().num_fields()); for (const auto& field : schema().fields()) { const auto cid = field->id(); @@ -109,7 +133,11 @@ class ChunkIterator { return Status::OK(); } +<<<<<<< HEAD [[nodiscard]] virtual Status init_output_schema(const std::unordered_set& unused_output_column_ids) { +======= + virtual Status init_output_schema(const std::unordered_set& unused_output_column_ids) { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) if (_is_init_output_schema) { return Status::OK(); } diff --git a/be/src/storage/column_aggregate_func.cpp b/be/src/storage/column_aggregate_func.cpp index 76f4368ec9e9b..9190bcda7ed5b 100644 --- a/be/src/storage/column_aggregate_func.cpp +++ b/be/src/storage/column_aggregate_func.cpp @@ -18,8 +18,18 @@ #include "column/map_column.h" #include "column/struct_column.h" #include "column/vectorized_fwd.h" +<<<<<<< HEAD #include "exprs/agg/aggregate.h" #include "exprs/agg/factory/aggregate_resolver.hpp" +======= +#include "exprs/agg/agg_state_union.h" +#include "exprs/agg/aggregate.h" +#include "exprs/agg/aggregate_state_allocator.h" +#include "exprs/agg/factory/aggregate_resolver.hpp" +#include "runtime/exec_env.h" +#include "runtime/mem_pool.h" +#include "runtime/runtime_state.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "storage/column_aggregator.h" #include "util/percentile_value.h" @@ -243,6 +253,7 @@ class AggFuncBasedValueAggregator : public ValueColumnAggregatorBase { public: AggFuncBasedValueAggregator(const AggregateFunction* agg_func) : _agg_func(agg_func) { _state = static_cast(std::aligned_alloc(_agg_func->alignof_size(), _agg_func->size())); +<<<<<<< HEAD _agg_func->create(nullptr, _state); } @@ -256,6 +267,38 @@ class AggFuncBasedValueAggregator : public ValueColumnAggregatorBase { void reset() override { _agg_func->destroy(nullptr, _state); _agg_func->create(nullptr, _state); +======= + // TODO: create a new FunctionContext by using specific FunctionContext::create_context + _func_ctx = new FunctionContext(); + _agg_func->create(_func_ctx, _state); + } + + AggFuncBasedValueAggregator(AggStateDesc* agg_state_desc, std::unique_ptr agg_state_unoin) + : _agg_func(agg_state_unoin.get()) { + _agg_state_unoin = std::move(agg_state_unoin); + _runtime_state = std::make_unique(ExecEnv::GetInstance()); + _mem_pool = std::make_unique(); + _func_ctx = FunctionContext::create_context(_runtime_state.get(), _mem_pool.get(), + agg_state_desc->get_return_type(), agg_state_desc->get_arg_types()); + _state = static_cast(std::aligned_alloc(_agg_func->alignof_size(), _agg_func->size())); + _agg_func->create(_func_ctx, _state); + } + + ~AggFuncBasedValueAggregator() override { + SCOPED_THREAD_LOCAL_AGG_STATE_ALLOCATOR_SETTER(&kDefaultColumnAggregatorAllocator); + if (_state != nullptr) { + _agg_func->destroy(_func_ctx, _state); + std::free(_state); + } + if (_func_ctx != nullptr) { + delete _func_ctx; + } + } + + void reset() override { + _agg_func->destroy(_func_ctx, _state); + _agg_func->create(_func_ctx, _state); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } void update_aggregate(Column* agg) override { @@ -263,6 +306,7 @@ class AggFuncBasedValueAggregator : public ValueColumnAggregatorBase { reset(); } +<<<<<<< HEAD void append_data(Column* agg) override { _agg_func->finalize_to_column(nullptr, _state, agg); } // |data| is readonly. @@ -271,6 +315,18 @@ class AggFuncBasedValueAggregator : public ValueColumnAggregatorBase { // |data| is readonly. void aggregate_batch_impl(int start, int end, const ColumnPtr& input) override { _agg_func->merge_batch_single_state(nullptr, _state, input.get(), start, end - start); +======= + void append_data(Column* agg) override { _agg_func->finalize_to_column(_func_ctx, _state, agg); } + + // |data| is readonly. + void aggregate_impl(int row, const ColumnPtr& data) override { + _agg_func->merge(_func_ctx, data.get(), _state, row); + } + + // |data| is readonly. + void aggregate_batch_impl(int start, int end, const ColumnPtr& input) override { + _agg_func->merge_batch_single_state(_func_ctx, _state, input.get(), start, end - start); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } bool need_deep_copy() const override { return false; }; @@ -304,7 +360,17 @@ class AggFuncBasedValueAggregator : public ValueColumnAggregatorBase { private: const AggregateFunction* _agg_func; +<<<<<<< HEAD + AggDataPtr _state{nullptr}; +======= + FunctionContext* _func_ctx = nullptr; AggDataPtr _state{nullptr}; + + // used for common aggregate functions + std::unique_ptr _agg_state_unoin = nullptr; + std::unique_ptr _runtime_state = nullptr; + std::unique_ptr _mem_pool = nullptr; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) }; #define CASE_DEFAULT_WARNING(TYPE) \ @@ -414,6 +480,24 @@ ColumnAggregatorPtr ColumnAggregatorFactory::create_value_column_aggregator(cons } else { return p; } +<<<<<<< HEAD +======= + } else if (method == STORAGE_AGGREGATE_AGG_STATE_UNION) { + if (field->get_agg_state_desc() == nullptr) { + CHECK(false) << "Bad agg state union method for column: " << field->name() + << " for its agg state type is null"; + return nullptr; + } + auto* agg_state_desc = field->get_agg_state_desc(); + auto func_name = agg_state_desc->get_func_name(); + DCHECK_EQ(field->is_nullable(), agg_state_desc->is_result_nullable()); + auto* agg_func = AggStateDesc::get_agg_state_func(agg_state_desc); + CHECK(agg_func != nullptr) << "Unknown aggregate function, name=" << func_name << ", type=" << type + << ", is_nullable=" << field->is_nullable() + << ", agg_state_desc=" << agg_state_desc->debug_string(); + auto agg_state_union = std::make_unique(*agg_state_desc, agg_func); + return std::make_unique(agg_state_desc, std::move(agg_state_union)); +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) } else { auto func_name = get_string_by_aggregation_type(method); // TODO(alvin): To keep compatible with old code, when type must not be the legacy type, diff --git a/be/src/storage/column_aggregate_func.h b/be/src/storage/column_aggregate_func.h index a0305d654e45b..914fd29b4448a 100644 --- a/be/src/storage/column_aggregate_func.h +++ b/be/src/storage/column_aggregate_func.h @@ -15,9 +15,18 @@ #pragma once #include "column/field.h" +<<<<<<< HEAD #include "storage/column_aggregator.h" namespace starrocks { +======= +#include "runtime/memory/mem_hook_allocator.h" +#include "storage/column_aggregator.h" + +namespace starrocks { + +static MemHookAllocator kDefaultColumnAggregatorAllocator = MemHookAllocator{}; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) class ColumnAggregatorFactory { public: static ColumnAggregatorPtr create_key_column_aggregator(const FieldPtr& field); diff --git a/be/src/storage/column_and_predicate.cpp b/be/src/storage/column_and_predicate.cpp new file mode 100644 index 0000000000000..871ab4a4bf848 --- /dev/null +++ b/be/src/storage/column_and_predicate.cpp @@ -0,0 +1,80 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "storage/column_and_predicate.h" + +namespace starrocks { +Status ColumnAndPredicate::evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const { + return _evaluate(column, selection, from, to); +} + +Status ColumnAndPredicate::evaluate_and(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const { + for (const ColumnPredicate* child : _child) { + RETURN_IF_ERROR(child->evaluate_and(column, selection, from, to)); + } + return Status::OK(); +} + +Status ColumnAndPredicate::evaluate_or(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const { + _buff.resize(column->size()); + RETURN_IF_ERROR(_evaluate(column, _buff.data(), from, to)); + const uint8_t* p = _buff.data(); + for (uint16_t i = from; i < to; i++) { + selection[i] |= p[i]; + } + return Status::OK(); +} + +std::string ColumnAndPredicate::debug_string() const { + std::stringstream ss; + ss << "AND("; + for (size_t i = 0; i < _child.size(); i++) { + if (i != 0) { + ss << ", "; + } + ss << i << ":" << _child[i]->debug_string(); + } + ss << ")"; + return ss.str(); +} + +Status ColumnAndPredicate::_evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const { + RETURN_IF_ERROR(_child[0]->evaluate(column, selection, from, to)); + for (size_t i = 1; i < _child.size(); i++) { + RETURN_IF_ERROR(_child[i]->evaluate_and(column, selection, from, to)); + } + return Status::OK(); +} + +// return false if page not satisfied +bool ColumnAndPredicate::zone_map_filter(const ZoneMapDetail& detail) const { + for (const ColumnPredicate* child : _child) { + RETURN_IF(!child->zone_map_filter(detail), false); + } + return true; +} + +Status ColumnAndPredicate::convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_ptr, + ObjectPool* obj_pool) const { + ColumnAndPredicate* new_pred = + obj_pool->add(new ColumnAndPredicate(get_type_info(target_type_ptr.get()), _column_id)); + for (auto pred : _child) { + const ColumnPredicate* new_child = nullptr; + RETURN_IF_ERROR(pred->convert_to(&new_child, get_type_info(target_type_ptr.get()), obj_pool)); + new_pred->_child.emplace_back(new_child); + } + *output = new_pred; + return Status::OK(); +} +} // namespace starrocks \ No newline at end of file diff --git a/be/src/storage/column_and_predicate.h b/be/src/storage/column_and_predicate.h new file mode 100644 index 0000000000000..a64e380dde056 --- /dev/null +++ b/be/src/storage/column_and_predicate.h @@ -0,0 +1,58 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "storage/column_predicate.h" + +namespace starrocks { + +class ColumnAndPredicate final : public ColumnPredicate { +public: + explicit ColumnAndPredicate(const TypeInfoPtr& type_info, ColumnId cid) : ColumnPredicate(type_info, cid) {} + + template + ColumnAndPredicate(const TypeInfoPtr& type_info, ColumnId cid, const Container& c) + : ColumnPredicate(type_info, cid), _child(c.begin(), c.end()) {} + + void add_child(ColumnPredicate* child) { _child.emplace_back(child); } + + template + void add_child(Iterator begin, Iterator end) { + _child.insert(_child.end(), begin, end); + } + + Status evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; + Status evaluate_and(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; + Status evaluate_or(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; + + bool filter(const BloomFilter& bf) const override { return true; } + bool zone_map_filter(const ZoneMapDetail& detail) const override; + + bool can_vectorized() const override { return false; } + PredicateType type() const override { return PredicateType::kAnd; } + Datum value() const override { return {}; } + std::vector values() const override { return std::vector{}; } + + Status convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_info, + ObjectPool* obj_pool) const override; + std::string debug_string() const override; + +private: + Status _evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const; + + std::vector _child; + mutable std::vector _buff; +}; +} // namespace starrocks \ No newline at end of file diff --git a/be/src/storage/column_expr_predicate.h b/be/src/storage/column_expr_predicate.h index 03e180fba56b1..ed64804e5b6ed 100644 --- a/be/src/storage/column_expr_predicate.h +++ b/be/src/storage/column_expr_predicate.h @@ -30,7 +30,11 @@ class Column; // And this class has a big limitation that it does not support range evaluatation. In another word, `from` supposed to be 0 always. // The fundamental reason is `ExprContext` requires `Column*` as a total piece, unless we can create a class to represent `ColumnSlice`. // And that task is almost impossible. +<<<<<<< HEAD class ColumnExprPredicate : public ColumnPredicate { +======= +class ColumnExprPredicate final : public ColumnPredicate { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: static StatusOr make_column_expr_predicate(TypeInfoPtr type_info, ColumnId column_id, RuntimeState* state, ExprContext* expr_ctx, @@ -38,9 +42,15 @@ class ColumnExprPredicate : public ColumnPredicate { ~ColumnExprPredicate() override; +<<<<<<< HEAD [[nodiscard]] Status evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; [[nodiscard]] Status evaluate_and(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; [[nodiscard]] Status evaluate_or(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; +======= + Status evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; + Status evaluate_and(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; + Status evaluate_or(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool zone_map_filter(const ZoneMapDetail& detail) const override; bool support_original_bloom_filter() const override { return false; } @@ -49,8 +59,13 @@ class ColumnExprPredicate : public ColumnPredicate { PredicateType type() const override { return PredicateType::kExpr; } bool can_vectorized() const override { return true; } +<<<<<<< HEAD [[nodiscard]] Status convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_info, ObjectPool* obj_pool) const override; +======= + Status convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_info, + ObjectPool* obj_pool) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override; RuntimeState* runtime_state() const { return _state; } const SlotDescriptor* slot_desc() const { return _slot_desc; } @@ -86,6 +101,7 @@ class ColumnExprPredicate : public ColumnPredicate { mutable std::vector _tmp_select; }; +<<<<<<< HEAD class ColumnTruePredicate : public ColumnPredicate { public: ColumnTruePredicate(TypeInfoPtr type_info, ColumnId column_id) : ColumnPredicate(std::move(type_info), column_id) {} @@ -93,12 +109,26 @@ class ColumnTruePredicate : public ColumnPredicate { [[nodiscard]] Status evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; [[nodiscard]] Status evaluate_and(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; [[nodiscard]] Status evaluate_or(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; +======= +class ColumnTruePredicate final : public ColumnPredicate { +public: + ColumnTruePredicate(TypeInfoPtr type_info, ColumnId column_id) : ColumnPredicate(std::move(type_info), column_id) {} + ~ColumnTruePredicate() override = default; + Status evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override; + Status evaluate_and(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; + Status evaluate_or(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) bool zone_map_filter(const ZoneMapDetail& detail) const override { return true; } bool support_original_bloom_filter() const override { return false; } PredicateType type() const override { return PredicateType::kTrue; } bool can_vectorized() const override { return true; } +<<<<<<< HEAD [[nodiscard]] Status convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_info, ObjectPool* obj_pool) const override; +======= + Status convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_info, + ObjectPool* obj_pool) const override; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) std::string debug_string() const override; }; diff --git a/be/src/storage/column_in_predicate.cpp b/be/src/storage/column_in_predicate.cpp index f9b7816c2b287..30194b40e5ef1 100644 --- a/be/src/storage/column_in_predicate.cpp +++ b/be/src/storage/column_in_predicate.cpp @@ -15,18 +15,32 @@ #include #include "column/column.h" +<<<<<<< HEAD #include "column/nullable_column.h" +======= +#include "column/column_helper.h" +#include "column/nullable_column.h" +#include "column/vectorized_fwd.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) #include "gutil/casts.h" #include "roaring/roaring.hh" #include "storage/column_predicate.h" #include "storage/in_predicate_utils.h" #include "storage/rowset/bitmap_index_reader.h" #include "storage/rowset/bloom_filter.h" +<<<<<<< HEAD +======= +#include "types/logical_type.h" +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) namespace starrocks { template +<<<<<<< HEAD class ColumnInPredicate : public ColumnPredicate { +======= +class ColumnInPredicate final : public ColumnPredicate { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) using ValueType = typename CppTypeTraits::CppType; static_assert(std::is_same_v); @@ -100,6 +114,11 @@ class ColumnInPredicate : public ColumnPredicate { return false; } +<<<<<<< HEAD +======= + bool support_bitmap_filter() const override { return true; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status seek_bitmap_dictionary(BitmapIndexIterator* iter, SparseRange<>* range) const override { range->clear(); for (auto value : _values) { @@ -172,7 +191,11 @@ class ColumnInPredicate : public ColumnPredicate { std::string debug_string() const override { std::stringstream ss; +<<<<<<< HEAD ss << "(columnId=" << _column_id << ",In("; +======= + ss << "((columnId=" << _column_id << ")IN("; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) int i = 0; for (auto& item : _values) { if (i++ != 0) { @@ -180,7 +203,11 @@ class ColumnInPredicate : public ColumnPredicate { } ss << this->type_info()->to_string(&item); } +<<<<<<< HEAD ss << ")"; +======= + ss << "))"; +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) return ss.str(); } @@ -190,7 +217,11 @@ class ColumnInPredicate : public ColumnPredicate { // Template specialization for binary column template +<<<<<<< HEAD class BinaryColumnInPredicate : public ColumnPredicate { +======= +class BinaryColumnInPredicate final : public ColumnPredicate { +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) public: BinaryColumnInPredicate(const TypeInfoPtr& type_info, ColumnId id, std::vector strings) : ColumnPredicate(type_info, id), _zero_padded_strs(std::move(strings)) { @@ -282,6 +313,11 @@ class BinaryColumnInPredicate : public ColumnPredicate { return false; } +<<<<<<< HEAD +======= + bool support_bitmap_filter() const override { return true; } + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) Status seek_bitmap_dictionary(BitmapIndexIterator* iter, SparseRange<>* range) const override { range->clear(); for (const std::string& s : _zero_padded_strs) { @@ -361,6 +397,89 @@ class BinaryColumnInPredicate : public ColumnPredicate { ItemHashSet _slices; }; +<<<<<<< HEAD +======= +class DictionaryCodeInPredicate final : public ColumnPredicate { +private: + enum LogicOp { ASSIGN, AND, OR }; + +public: + DictionaryCodeInPredicate(const TypeInfoPtr& type_info, ColumnId id, const std::vector& operands, + size_t size) + : ColumnPredicate(type_info, id), _bit_mask(size) { + for (auto item : operands) { + DCHECK(item < size); + _bit_mask[item] = 1; + } + } + + ~DictionaryCodeInPredicate() override = default; + + template + inline void t_evaluate(const Column* column, uint8_t* sel, uint16_t from, uint16_t to) const { + const Int32Column* dict_code_column = down_cast(ColumnHelper::get_data_column(column)); + const auto& data = dict_code_column->get_data(); + Filter filter(to - from, 1); + + if (column->has_null()) { + const NullColumn* null_column = down_cast(column)->null_column().get(); + const auto& null_data = null_column->get_data(); + for (auto i = from; i < to; i++) { + auto index = data[i] >= _bit_mask.size() ? 0 : data[i]; + filter[i - from] = (!null_data[i]) & _bit_mask[index]; + } + } else { + for (auto i = from; i < to; i++) { + filter[i - from] = _bit_mask[data[i]]; + } + } + + for (auto i = from; i < to; i++) { + if constexpr (Op == ASSIGN) { + sel[i] = filter[i - from]; + } else if constexpr (Op == AND) { + sel[i] &= filter[i - from]; + } else { + sel[i] |= filter[i - from]; + } + } + } + + Status evaluate(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override { + t_evaluate(column, selection, from, to); + return Status::OK(); + } + + Status evaluate_and(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override { + t_evaluate(column, selection, from, to); + return Status::OK(); + } + + Status evaluate_or(const Column* column, uint8_t* selection, uint16_t from, uint16_t to) const override { + t_evaluate(column, selection, from, to); + return Status::OK(); + } + + bool can_vectorized() const override { return false; } + + PredicateType type() const override { return PredicateType::kInList; } + + Status convert_to(const ColumnPredicate** output, const TypeInfoPtr& target_type_info, + ObjectPool* obj_pool) const override { + const auto to_type = target_type_info->type(); + if (to_type == LogicalType::TYPE_INT) { + *output = this; + return Status::OK(); + } + CHECK(false) << "Not support, from_type=" << LogicalType::TYPE_INT << ", to_type=" << to_type; + return Status::OK(); + } + +private: + std::vector _bit_mask; +}; + +>>>>>>> b42eff7ae3 ([Doc] Add meaning of 0 for variables (#53714)) template