blob: 6c8d7f99575ad512158fc471023b598df94a8fcf [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://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.
"""Global-index builds delegated to Rust, retaining Python's commit API."""
from pypaimon.execution.native.table import (_native_table, _options_to_native)
from pypaimon.execution.native.read.builder import (_predicate_to_native)
from pypaimon.execution.native.runtime import (native_runtime_available)
from pypaimon.execution.native.write.native_commit import _rest_catalog_supported, from_native_commit_messages
from pypaimon.common.options.core_options import CoreOptions
from pypaimon.common.options.options import Options
def build_native_global_index(builder, partition_filter, *, execution="local", concurrency=None, ray_remote_args=None):
"""Return unpublished messages, or None before building for an ineligible table.
Rust owns snapshot selection, range planning and index file generation.
Build errors propagate: a failed native build must not start a second build.
"""
table = builder._table
from pypaimon.globalindex.vindex_options import VINDEX_IDENTIFIERS
if (builder._index_type not in ('btree', 'bitmap', 'full-text') + tuple(VINDEX_IDENTIFIERS)
or not table.options.native_write_enabled()
or (table.options.deletion_vectors_enabled() and builder._index_type == 'full-text')
or table.options.query_auth_enabled
or table.is_primary_key_table
or table.options.file_format() != 'parquet'
or not native_runtime_available()
or not _rest_catalog_supported(table)):
return None
from pypaimon_rust.datafusion import GlobalIndexBuildBuilder
if not GlobalIndexBuildBuilder.supports_index_type(builder._index_type):
return None
# Keep build parameters separate from schema defaults: alias precedence is
# resolved within each source, then explicit build parameters win.
options = _build_options_to_native(builder._user_options)
table_overrides = {key: None for key, value in builder._user_options.items() if value is None}
parallelism = CoreOptions.GLOBAL_INDEX_BUILD_PARALLELISM.key()
table_values = table.options.options.to_map()
if parallelism not in builder._user_options and isinstance(table_values.get(parallelism), (bool, float)):
table_overrides[parallelism] = _build_options_to_native(
{parallelism: table_values[parallelism]})[parallelism]
native_table = table.copy_without_time_travel(table_overrides)
native = _native_table(native_table).new_global_index_build_builder()
native.with_index_column(builder._index_columns[0]).with_index_type(builder._index_type)
native.with_options(options)
if partition_filter is not None:
native.with_partition_filter(_predicate_to_native(partition_filter))
if execution == "ray":
from pypaimon.ray.vector_index_build import build_native_vector_index
# Planning may authorize and capture inputs; its errors must not select
# another engine or restart a build that may already have side effects.
plan = native.plan()
return build_native_vector_index(table, plan, concurrency, ray_remote_args)
return from_native_commit_messages(table, native.build())
def _build_options_to_native(options):
encoded = _options_to_native(options)
key = CoreOptions.GLOBAL_INDEX_BUILD_PARALLELISM.key()
if isinstance(options.get(key), (bool, float)):
# Retain Python's typed integer conversion before the string-only ABI.
encoded[key] = str(int(Options(options).get(CoreOptions.GLOBAL_INDEX_BUILD_PARALLELISM)))
return encoded
def build_native_index_shard(table, shard):
"""Execute captured metadata in Core; workers never replan or publish."""
native = _native_table(table).new_global_index_build_builder()
return from_native_commit_messages(table, native.build_shard(shard))