blob: 44bdc52bb20db0d41833a93eccff7f37bd490b4d [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.
from typing import Any, List, Optional
from pypaimon.common.predicate import Predicate
from pypaimon.schema.data_types import DataField
class PredicateBuilder:
"""Implementation of PredicateBuilder using Predicate."""
def __init__(self, row_field: List[DataField]):
self.field_names = [field.name for field in row_field]
def _get_field_index(self, field: str) -> int:
"""Get the index of a field in the schema."""
try:
return self.field_names.index(field)
except ValueError:
raise ValueError(f'The field {field} is not in field list {self.field_names}.')
def _build_predicate(self, method: str, field: str, literals: Optional[List[Any]] = None) -> Predicate:
"""Build a predicate with the given method, field, and literals."""
index = self._get_field_index(field)
return Predicate(
method=method,
index=index,
field=field,
literals=literals
)
def equal(self, field: str, literal: Any) -> Predicate:
"""Create an equality predicate."""
return self._build_predicate('equal', field, [literal])
def not_equal(self, field: str, literal: Any) -> Predicate:
"""Create a not-equal predicate."""
return self._build_predicate('notEqual', field, [literal])
def less_than(self, field: str, literal: Any) -> Predicate:
"""Create a less-than predicate."""
return self._build_predicate('lessThan', field, [literal])
def less_or_equal(self, field: str, literal: Any) -> Predicate:
"""Create a less-or-equal predicate."""
return self._build_predicate('lessOrEqual', field, [literal])
def greater_than(self, field: str, literal: Any) -> Predicate:
"""Create a greater-than predicate."""
return self._build_predicate('greaterThan', field, [literal])
def greater_or_equal(self, field: str, literal: Any) -> Predicate:
"""Create a greater-or-equal predicate."""
return self._build_predicate('greaterOrEqual', field, [literal])
def is_null(self, field: str) -> Predicate:
"""Create an is-null predicate."""
return self._build_predicate('isNull', field)
def is_not_null(self, field: str) -> Predicate:
"""Create an is-not-null predicate."""
return self._build_predicate('isNotNull', field)
def startswith(self, field: str, pattern_literal: Any) -> Predicate:
"""Create a starts-with predicate."""
return self._build_predicate('startsWith', field, [pattern_literal])
def endswith(self, field: str, pattern_literal: Any) -> Predicate:
"""Create an ends-with predicate."""
return self._build_predicate('endsWith', field, [pattern_literal])
def contains(self, field: str, pattern_literal: Any) -> Predicate:
"""Create a contains predicate."""
return self._build_predicate('contains', field, [pattern_literal])
def is_in(self, field: str, literals: List[Any]) -> Predicate:
"""Create an in predicate."""
return self._build_predicate('in', field, literals)
def is_not_in(self, field: str, literals: List[Any]) -> Predicate:
"""Create a not-in predicate."""
return self._build_predicate('notIn', field, literals)
def between(self, field: str, included_lower_bound: Any, included_upper_bound: Any) -> Predicate:
"""Create a between predicate."""
return self._build_predicate('between', field, [included_lower_bound, included_upper_bound])
def not_between(self, field: str, included_lower_bound: Any, included_upper_bound: Any) -> Predicate:
"""Create a not-between predicate."""
return self._build_predicate('notBetween', field, [included_lower_bound, included_upper_bound])
def like(self, field: str, pattern_literal: Any) -> Predicate:
"""Create a SQL LIKE predicate. Supports '%' (any sequence) and '_' (any single char)."""
return self._build_predicate('like', field, [pattern_literal])
@staticmethod
def and_predicates(predicates: List[Predicate]) -> Optional[Predicate]:
"""Create an AND predicate from multiple predicates."""
if len(predicates) == 0:
return None
if len(predicates) == 1:
return predicates[0]
return Predicate(
method='and',
index=None,
field=None,
literals=predicates
)
@staticmethod
def or_predicates(predicates: List[Predicate]) -> Optional[Predicate]:
"""Create an OR predicate from multiple predicates."""
if len(predicates) == 0:
return None
if len(predicates) == 1:
return predicates[0]
return Predicate(
method='or',
index=None,
field=None,
literals=predicates
)