blob: 3a9ffd6009f1907f07966f74a6854114d35538e4 [file] [log] [blame]
# 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.
# pylint: disable=eval-used,protected-access,redefined-outer-name
from datetime import date
from decimal import Decimal
from typing import TYPE_CHECKING, Any, Callable, Optional
from uuid import UUID
import mmh3 as mmh3
import pytest
from pydantic import (
BeforeValidator,
PlainSerializer,
RootModel,
WithJsonSchema,
)
from typing_extensions import Annotated
from pyiceberg.expressions import (
BoundEqualTo,
BoundGreaterThan,
BoundGreaterThanOrEqual,
BoundIn,
BoundIsNull,
BoundLessThan,
BoundLessThanOrEqual,
BoundLiteralPredicate,
BoundNotEqualTo,
BoundNotIn,
BoundNotNull,
BoundNotStartsWith,
BoundReference,
BoundStartsWith,
EqualTo,
GreaterThan,
GreaterThanOrEqual,
In,
LessThan,
LessThanOrEqual,
LiteralPredicate,
NotEqualTo,
NotIn,
NotNull,
NotStartsWith,
Reference,
SetPredicate,
StartsWith,
UnaryPredicate,
UnboundPredicate,
)
from pyiceberg.expressions.literals import (
DateLiteral,
DecimalLiteral,
LongLiteral,
TimestampLiteral,
literal,
)
from pyiceberg.partitioning import _to_partition_representation
from pyiceberg.schema import Accessor
from pyiceberg.transforms import (
BucketTransform,
DayTransform,
HourTransform,
IdentityTransform,
MonthTransform,
TimeTransform,
Transform,
TruncateTransform,
UnknownTransform,
VoidTransform,
YearTransform,
parse_transform,
)
from pyiceberg.typedef import UTF8, L
from pyiceberg.types import (
BinaryType,
BooleanType,
DateType,
DecimalType,
DoubleType,
FixedType,
FloatType,
IntegerType,
LongType,
NestedField,
PrimitiveType,
StringType,
TimestampType,
TimestamptzType,
TimeType,
UUIDType,
)
from pyiceberg.utils.datetime import (
date_str_to_days,
date_to_days,
time_str_to_micros,
timestamp_to_micros,
timestamptz_to_micros,
)
if TYPE_CHECKING:
import pyarrow as pa
@pytest.mark.parametrize(
"test_input,test_type,expected",
[
(1, IntegerType(), 1392991556),
(34, IntegerType(), 2017239379),
(34, LongType(), 2017239379),
(date_to_days(date(2017, 11, 16)), DateType(), -653330422),
(date_str_to_days("2017-11-16"), DateType(), -653330422),
(time_str_to_micros("22:31:08"), TimeType(), -662762989),
(
timestamp_to_micros("2017-11-16T22:31:08"),
TimestampType(),
-2047944441,
),
(
timestamptz_to_micros("2017-11-16T14:31:08-08:00"),
TimestamptzType(),
-2047944441,
),
(b"\x00\x01\x02\x03", BinaryType(), -188683207),
(b"\x00\x01\x02\x03", FixedType(4), -188683207),
("iceberg", StringType(), 1210000089),
(UUID("f79c3e09-677c-4bbd-a479-3f349cb785e7"), UUIDType(), 1488055340),
(b"\xf7\x9c>\tg|K\xbd\xa4y?4\x9c\xb7\x85\xe7", UUIDType(), 1488055340),
],
)
def test_bucket_hash_values(test_input: Any, test_type: PrimitiveType, expected: Any) -> None:
assert BucketTransform(num_buckets=8).transform(test_type, bucket=False)(test_input) == expected
@pytest.mark.parametrize(
"transform,value,expected",
[
(BucketTransform(2).transform(IntegerType()), 0, 0),
(BucketTransform(100).transform(IntegerType()), 34, 79),
(BucketTransform(100).transform(LongType()), 34, 79),
(BucketTransform(100).transform(DateType()), 17486, 26),
(BucketTransform(100).transform(TimeType()), 81068000000, 59),
(BucketTransform(100).transform(TimestampType()), 1510871468000000, 7),
(BucketTransform(100).transform(DecimalType(9, 2)), Decimal("14.20"), 59),
(BucketTransform(100).transform(StringType()), "iceberg", 89),
(
BucketTransform(100).transform(UUIDType()),
UUID("f79c3e09-677c-4bbd-a479-3f349cb785e7"),
40,
),
(
BucketTransform(100).transform(UUIDType()),
b"\xf7\x9c>\tg|K\xbd\xa4y?4\x9c\xb7\x85\xe7",
40,
),
(BucketTransform(128).transform(FixedType(3)), b"foo", 32),
(BucketTransform(128).transform(BinaryType()), b"\x00\x01\x02\x03", 57),
],
)
def test_buckets(transform: Callable[[Any], int], value: Any, expected: int) -> None:
assert transform(value) == expected
@pytest.mark.parametrize(
"type_var",
[
BinaryType(),
DateType(),
DecimalType(8, 5),
FixedType(8),
IntegerType(),
LongType(),
StringType(),
TimestampType(),
TimestamptzType(),
TimeType(),
UUIDType(),
],
)
def test_bucket_method(type_var: PrimitiveType) -> None:
bucket_transform = BucketTransform(8) # type: ignore
assert str(bucket_transform) == str(eval(repr(bucket_transform)))
assert bucket_transform.can_transform(type_var)
assert bucket_transform.result_type(type_var) == IntegerType()
assert bucket_transform.num_buckets == 8
assert bucket_transform.apply(None) is None
assert bucket_transform.to_human_string(type_var, "test") == "test"
def test_string_with_surrogate_pair() -> None:
string_with_surrogate_pair = "string with a surrogate pair: 💰"
as_bytes = bytes(string_with_surrogate_pair, UTF8)
bucket_transform = BucketTransform(100).transform(StringType(), bucket=False)
assert bucket_transform(string_with_surrogate_pair) == mmh3.hash(as_bytes)
@pytest.mark.parametrize(
"date_val,date_transform,expected",
[
(47, YearTransform(), "2017"),
(575, MonthTransform(), "2017-12"),
(17501, DayTransform(), "2017-12-01"),
],
)
def test_date_to_human_string(date_val: int, date_transform: Transform[Any, Any], expected: str) -> None:
assert date_transform.to_human_string(DateType(), date_val) == expected
@pytest.mark.parametrize(
"date_transform",
[
YearTransform(),
MonthTransform(),
DayTransform(),
],
)
def test_none_date_to_human_string(date_transform: TimeTransform[Any]) -> None:
assert date_transform.to_human_string(DateType(), None) == "null"
def test_hour_to_human_string() -> None:
assert HourTransform().to_human_string(TimestampType(), None) == "null"
assert HourTransform().to_human_string(TimestampType(), 420042) == "2017-12-01-18" # type: ignore
@pytest.mark.parametrize(
"negative_value,time_transform,expected",
[
(-1, YearTransform(), "1969"),
(-1, MonthTransform(), "1969-12"),
(-1, DayTransform(), "1969-12-31"),
(-1, HourTransform(), "1969-12-31-23"),
],
)
def test_negative_value_to_human_string(negative_value: int, time_transform: TimeTransform[Any], expected: str) -> None:
assert time_transform.to_human_string(TimestampType(), negative_value) == expected
@pytest.mark.parametrize(
"zero_value,time_transform,expected",
[
(0, YearTransform(), "1970"),
(0, MonthTransform(), "1970-01"),
(0, DayTransform(), "1970-01-01"),
(0, HourTransform(), "1970-01-01-00"),
],
)
def test_zero_value_to_human_string(zero_value: int, time_transform: TimeTransform[Any], expected: str) -> None:
assert time_transform.to_human_string(TimestampType(), zero_value) == expected
@pytest.mark.parametrize(
"type_var",
[
DateType(),
TimestampType(),
TimestamptzType(),
],
)
def test_time_methods(type_var: PrimitiveType) -> None:
assert YearTransform().can_transform(type_var)
assert MonthTransform().can_transform(type_var)
assert DayTransform().can_transform(type_var)
assert YearTransform().preserves_order
assert MonthTransform().preserves_order
assert DayTransform().preserves_order
assert YearTransform().result_type(type_var) == IntegerType()
assert MonthTransform().result_type(type_var) == IntegerType()
assert DayTransform().result_type(type_var) == DateType()
assert YearTransform().dedup_name == "time"
assert MonthTransform().dedup_name == "time"
assert DayTransform().dedup_name == "time"
@pytest.mark.parametrize(
"transform,type_var,value,expected",
[
(DayTransform(), DateType(), 17501, 17501),
(DayTransform(), DateType(), -1, -1),
(MonthTransform(), DateType(), 17501, 575),
(MonthTransform(), DateType(), -1, -1),
(YearTransform(), DateType(), 17501, 47),
(YearTransform(), DateType(), -1, -1),
(YearTransform(), TimestampType(), 1512151975038194, 47),
(YearTransform(), TimestampType(), -1, -1),
(MonthTransform(), TimestamptzType(), 1512151975038194, 575),
(MonthTransform(), TimestamptzType(), -1, -1),
(DayTransform(), TimestampType(), 1512151975038194, 17501),
(DayTransform(), TimestampType(), -1, -1),
(YearTransform(), DateType(), 0, 0),
(MonthTransform(), DateType(), 0, 0),
(DayTransform(), DateType(), 0, 0),
(YearTransform(), TimestampType(), 0, 0),
(MonthTransform(), TimestampType(), 0, 0),
(DayTransform(), TimestampType(), 0, 0),
],
)
def test_time_apply_method(transform: TimeTransform[Any], type_var: PrimitiveType, value: int, expected: int) -> None:
assert transform.transform(type_var)(value) == expected
@pytest.mark.parametrize(
"type_var",
[
TimestampType(),
TimestamptzType(),
],
)
def test_hour_method(type_var: PrimitiveType) -> None:
assert HourTransform().can_transform(type_var)
assert HourTransform().result_type(type_var) == IntegerType()
assert HourTransform().transform(type_var)(1512151975038194) == 420042 # type: ignore
assert HourTransform().transform(type_var)(0) == 0 # type: ignore
assert HourTransform().dedup_name == "time"
@pytest.mark.parametrize(
"transform,other_transform",
[
(YearTransform(), MonthTransform()),
(YearTransform(), DayTransform()),
(YearTransform(), HourTransform()),
(MonthTransform(), DayTransform()),
(MonthTransform(), HourTransform()),
(DayTransform(), HourTransform()),
],
)
def test_satisfies_order_of_method(transform: TimeTransform[Any], other_transform: TimeTransform[Any]) -> None:
assert transform.satisfies_order_of(transform)
assert other_transform.satisfies_order_of(transform)
assert not transform.satisfies_order_of(other_transform)
assert not transform.satisfies_order_of(VoidTransform())
assert not other_transform.satisfies_order_of(IdentityTransform())
@pytest.mark.parametrize(
"type_var,value,expected",
[
(LongType(), None, "null"),
(DateType(), 17501, "2017-12-01"),
(TimeType(), 36775038194, "10:12:55.038194"),
(TimestamptzType(), 1512151975038194, "2017-12-01T18:12:55.038194+00:00"),
(TimestampType(), 1512151975038194, "2017-12-01T18:12:55.038194"),
(LongType(), -1234567890000, "-1234567890000"),
(StringType(), "a/b/c=d", "a/b/c=d"),
(DecimalType(9, 2), Decimal("-1.50"), "-1.50"),
(FixedType(100), b"foo", "Zm9v"),
],
)
def test_identity_human_string(type_var: PrimitiveType, value: Any, expected: str) -> None:
identity = IdentityTransform() # type: ignore
assert identity.to_human_string(type_var, value) == expected
@pytest.mark.parametrize(
"type_var",
[
BinaryType(),
BooleanType(),
DateType(),
DecimalType(8, 2),
DoubleType(),
FixedType(16),
FloatType(),
IntegerType(),
LongType(),
StringType(),
TimestampType(),
TimestamptzType(),
TimeType(),
UUIDType(),
],
)
def test_identity_method(type_var: PrimitiveType) -> None:
identity_transform = IdentityTransform() # type: ignore
assert str(identity_transform) == str(eval(repr(identity_transform)))
assert identity_transform.can_transform(type_var)
assert identity_transform.result_type(type_var) == type_var
assert identity_transform.transform(type_var)("test") == "test"
@pytest.mark.parametrize("type_var", [IntegerType(), LongType()])
@pytest.mark.parametrize(
"input_var,expected",
[(1, 0), (5, 0), (9, 0), (10, 10), (11, 10), (-1, -10), (-10, -10), (-12, -20), (0, 0)],
)
def test_truncate_integer(type_var: PrimitiveType, input_var: int, expected: int) -> None:
trunc = TruncateTransform(10) # type: ignore
assert trunc.transform(type_var)(input_var) == expected
@pytest.mark.parametrize(
"input_var,expected",
[
(Decimal("12.34"), Decimal("12.30")),
(Decimal("12.30"), Decimal("12.30")),
(Decimal("12.29"), Decimal("12.20")),
(Decimal("0.05"), Decimal("0.00")),
(Decimal("-0.05"), Decimal("-0.10")),
(Decimal("0.0"), Decimal("0.0")),
],
)
def test_truncate_decimal(input_var: Decimal, expected: Decimal) -> None:
trunc = TruncateTransform(10) # type: ignore
assert trunc.transform(DecimalType(9, 2))(input_var) == expected
@pytest.mark.parametrize("input_var,expected", [("abcdefg", "abcde"), ("abc", "abc"), ("", "")])
def test_truncate_string(input_var: str, expected: str) -> None:
trunc = TruncateTransform(5) # type: ignore
assert trunc.transform(StringType())(input_var) == expected
@pytest.mark.parametrize(
"type_var,value,expected_human_str,expected",
[
(BinaryType(), b"\x00\x01\x02\x03", "AAECAw==", b"\x00"),
(BinaryType(), bytes("\u2603de", UTF8), "4piDZGU=", b"\xe2"),
(DecimalType(8, 5), Decimal("14.21"), "14.21", Decimal("14.21")),
(IntegerType(), 123, "123", 123),
(LongType(), 123, "123", 123),
(StringType(), "foo", "foo", "f"),
(StringType(), "\u2603de", "\u2603de", "\u2603"),
],
)
def test_truncate_method(type_var: PrimitiveType, value: Any, expected_human_str: str, expected: Any) -> None:
truncate_transform = TruncateTransform(1) # type: ignore
assert str(truncate_transform) == str(eval(repr(truncate_transform)))
assert truncate_transform.can_transform(type_var)
assert truncate_transform.result_type(type_var) == type_var
assert truncate_transform.to_human_string(type_var, value) == expected_human_str
assert truncate_transform.transform(type_var)(value) == expected
assert truncate_transform.to_human_string(type_var, None) == "null"
assert truncate_transform.width == 1
assert truncate_transform.transform(type_var)(None) is None
assert truncate_transform.preserves_order
assert truncate_transform.satisfies_order_of(truncate_transform)
def test_unknown_transform() -> None:
unknown_transform = UnknownTransform("unknown") # type: ignore
assert str(unknown_transform) == str(eval(repr(unknown_transform)))
with pytest.raises(AttributeError):
unknown_transform.transform(StringType())("test")
assert not unknown_transform.can_transform(FixedType(5))
assert isinstance(unknown_transform.result_type(BooleanType()), StringType)
def test_void_transform() -> None:
void_transform = VoidTransform() # type: ignore
assert void_transform is VoidTransform()
assert void_transform == eval(repr(void_transform))
assert void_transform.transform(StringType())("test") is None
assert void_transform.can_transform(BooleanType())
assert isinstance(void_transform.result_type(BooleanType()), BooleanType)
assert not void_transform.preserves_order
assert void_transform.satisfies_order_of(VoidTransform())
assert not void_transform.satisfies_order_of(BucketTransform(100))
assert void_transform.to_human_string(StringType(), "test") == "null"
assert void_transform.dedup_name == "void"
class FauxModel(RootModel):
root: Annotated[ # type: ignore
Transform,
BeforeValidator(parse_transform),
PlainSerializer(lambda c: str(c), return_type=str), # pylint: disable=W0108
WithJsonSchema({"type": "string"}, mode="serialization"),
]
def test_bucket_transform_serialize() -> None:
assert BucketTransform(num_buckets=22).model_dump_json() == '"bucket[22]"'
def test_bucket_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"bucket[22]"').root
assert transform == BucketTransform(num_buckets=22)
def test_bucket_transform_str() -> None:
assert str(BucketTransform(num_buckets=22)) == "bucket[22]"
def test_bucket_transform_repr() -> None:
assert repr(BucketTransform(num_buckets=22)) == "BucketTransform(num_buckets=22)"
def test_truncate_transform_serialize() -> None:
assert UnknownTransform("unknown").model_dump_json() == '"unknown"'
def test_unknown_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"unknown"').root
assert transform == UnknownTransform("unknown")
def test_unknown_transform_str() -> None:
assert str(UnknownTransform("unknown")) == "unknown"
def test_unknown_transform_repr() -> None:
assert repr(UnknownTransform("unknown")) == "UnknownTransform(transform='unknown')"
def test_void_transform_serialize() -> None:
assert VoidTransform().model_dump_json() == '"void"'
def test_void_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"void"').root
assert transform == VoidTransform()
def test_void_transform_str() -> None:
assert str(VoidTransform()) == "void"
def test_void_transform_repr() -> None:
assert repr(VoidTransform()) == "VoidTransform()"
def test_year_transform_serialize() -> None:
assert YearTransform().model_dump_json() == '"year"'
def test_year_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"year"').root
assert transform == YearTransform()
def test_month_transform_serialize() -> None:
assert MonthTransform().model_dump_json() == '"month"'
def test_month_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"month"').root
assert transform == MonthTransform()
def test_day_transform_serialize() -> None:
assert DayTransform().model_dump_json() == '"day"'
def test_day_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"day"').root
assert transform == DayTransform()
def test_hour_transform_serialize() -> None:
assert HourTransform().model_dump_json() == '"hour"'
def test_hour_transform_deserialize() -> None:
transform = FauxModel.model_validate_json('"hour"').root
assert transform == HourTransform()
@pytest.mark.parametrize(
"transform,transform_str",
[
(YearTransform(), "year"),
(MonthTransform(), "month"),
(DayTransform(), "day"),
(HourTransform(), "hour"),
],
)
def test_datetime_transform_str(transform: TimeTransform[Any], transform_str: str) -> None:
assert str(transform) == transform_str
@pytest.mark.parametrize(
"transform,transform_repr",
[
(YearTransform(), "YearTransform()"),
(MonthTransform(), "MonthTransform()"),
(DayTransform(), "DayTransform()"),
(HourTransform(), "HourTransform()"),
],
)
def test_datetime_transform_repr(transform: TimeTransform[Any], transform_repr: str) -> None:
assert repr(transform) == transform_repr
@pytest.fixture
def bound_reference_date() -> BoundReference[int]:
return BoundReference(field=NestedField(1, "field", DateType(), required=False), accessor=Accessor(position=0, inner=None))
@pytest.fixture
def bound_reference_timestamp() -> BoundReference[int]:
return BoundReference(
field=NestedField(1, "field", TimestampType(), required=False), accessor=Accessor(position=0, inner=None)
)
@pytest.fixture
def bound_reference_decimal() -> BoundReference[Decimal]:
return BoundReference(
field=NestedField(1, "field", DecimalType(8, 2), required=False), accessor=Accessor(position=0, inner=None)
)
@pytest.fixture
def bound_reference_long() -> BoundReference[int]:
return BoundReference(field=NestedField(1, "field", LongType(), required=False), accessor=Accessor(position=0, inner=None))
def test_projection_bucket_unary(bound_reference_str: BoundReference[str]) -> None:
assert BucketTransform(2).project("name", BoundNotNull(term=bound_reference_str)) == NotNull(term=Reference(name="name"))
def test_projection_bucket_literal(bound_reference_str: BoundReference[str]) -> None:
assert BucketTransform(2).project("name", BoundEqualTo(term=bound_reference_str, literal=literal("data"))) == EqualTo(
term="name", literal=1
)
def test_projection_bucket_set_same_bucket(bound_reference_str: BoundReference[str]) -> None:
assert BucketTransform(2).project(
"name", BoundIn(term=bound_reference_str, literals={literal("hello"), literal("world")})
) == EqualTo(term="name", literal=1)
def test_projection_bucket_set_in(bound_reference_str: BoundReference[str]) -> None:
assert BucketTransform(3).project(
"name", BoundIn(term=bound_reference_str, literals={literal("hello"), literal("world")})
) == In(term="name", literals={1, 2})
def test_projection_bucket_set_not_in(bound_reference_str: BoundReference[str]) -> None:
assert (
BucketTransform(3).project("name", BoundNotIn(term=bound_reference_str, literals={literal("hello"), literal("world")}))
is None
)
def test_projection_year_unary(bound_reference_date: BoundReference[int]) -> None:
assert YearTransform().project("name", BoundNotNull(term=bound_reference_date)) == NotNull(term="name")
def test_projection_year_literal(bound_reference_date: BoundReference[int]) -> None:
assert YearTransform().project("name", BoundEqualTo(term=bound_reference_date, literal=DateLiteral(1925))) == EqualTo(
term="name", literal=5
)
def test_projection_year_set_same_year(bound_reference_date: BoundReference[int]) -> None:
assert YearTransform().project(
"name", BoundIn(term=bound_reference_date, literals={DateLiteral(1925), DateLiteral(1926)})
) == EqualTo(term="name", literal=5)
def test_projection_year_set_in(bound_reference_date: BoundReference[int]) -> None:
assert YearTransform().project(
"name", BoundIn(term=bound_reference_date, literals={DateLiteral(1925), DateLiteral(2925)})
) == In(term="name", literals={8, 5})
def test_projection_year_set_not_in(bound_reference_date: BoundReference[int]) -> None:
assert (
YearTransform().project("name", BoundNotIn(term=bound_reference_date, literals={DateLiteral(1925), DateLiteral(2925)}))
is None
)
def test_projection_month_unary(bound_reference_date: BoundReference[int]) -> None:
assert MonthTransform().project("name", BoundNotNull(term=bound_reference_date)) == NotNull(term="name")
def test_projection_month_literal(bound_reference_date: BoundReference[int]) -> None:
assert MonthTransform().project("name", BoundEqualTo(term=bound_reference_date, literal=DateLiteral(1925))) == EqualTo(
term="name", literal=63
)
def test_projection_month_set_same_month(bound_reference_date: BoundReference[int]) -> None:
assert MonthTransform().project(
"name", BoundIn(term=bound_reference_date, literals={DateLiteral(1925), DateLiteral(1926)})
) == EqualTo(term="name", literal=63)
def test_projection_month_set_in(bound_reference_date: BoundReference[int]) -> None:
assert MonthTransform().project(
"name", BoundIn(term=bound_reference_date, literals={DateLiteral(1925), DateLiteral(2925)})
) == In(term="name", literals={96, 63})
def test_projection_day_month_not_in(bound_reference_date: BoundReference[int]) -> None:
assert (
MonthTransform().project("name", BoundNotIn(term=bound_reference_date, literals={DateLiteral(1925), DateLiteral(2925)}))
is None
)
def test_projection_day_unary(bound_reference_timestamp: BoundReference[int]) -> None:
assert DayTransform().project("name", BoundNotNull(term=bound_reference_timestamp)) == NotNull(term="name")
def test_projection_day_literal(bound_reference_timestamp: BoundReference[int]) -> None:
assert DayTransform().project(
"name", BoundEqualTo(term=bound_reference_timestamp, literal=TimestampLiteral(1667696874000))
) == EqualTo(term="name", literal=19)
def test_projection_day_set_same_day(bound_reference_timestamp: BoundReference[int]) -> None:
assert DayTransform().project(
"name",
BoundIn(term=bound_reference_timestamp, literals={TimestampLiteral(1667696874001), TimestampLiteral(1667696874000)}),
) == EqualTo(term="name", literal=19)
def test_projection_day_set_in(bound_reference_timestamp: BoundReference[int]) -> None:
assert DayTransform().project(
"name",
BoundIn(term=bound_reference_timestamp, literals={TimestampLiteral(1667696874001), TimestampLiteral(1567696874000)}),
) == In(term="name", literals={18, 19})
def test_projection_day_set_not_in(bound_reference_timestamp: BoundReference[int]) -> None:
assert (
DayTransform().project(
"name",
BoundNotIn(term=bound_reference_timestamp, literals={TimestampLiteral(1567696874), TimestampLiteral(1667696874)}),
)
is None
)
def test_projection_day_human(bound_reference_date: BoundReference[int]) -> None:
date_literal = DateLiteral(17532)
assert DayTransform().project("dt", BoundEqualTo(term=bound_reference_date, literal=date_literal)) == EqualTo(
term="dt", literal=17532
) # == 2018, 1, 1
assert DayTransform().project("dt", BoundLessThanOrEqual(term=bound_reference_date, literal=date_literal)) == LessThanOrEqual(
term="dt", literal=17532
) # <= 2018, 1, 1
assert DayTransform().project("dt", BoundLessThan(term=bound_reference_date, literal=date_literal)) == LessThanOrEqual(
term="dt", literal=17531
) # <= 2017, 12, 31
assert DayTransform().project(
"dt", BoundGreaterThanOrEqual(term=bound_reference_date, literal=date_literal)
) == GreaterThanOrEqual(term="dt", literal=17532) # >= 2018, 1, 1
assert DayTransform().project("dt", BoundGreaterThan(term=bound_reference_date, literal=date_literal)) == GreaterThanOrEqual(
term="dt", literal=17533
) # >= 2018, 1, 2
def test_projection_hour_unary(bound_reference_timestamp: BoundReference[int]) -> None:
assert HourTransform().project("name", BoundNotNull(term=bound_reference_timestamp)) == NotNull(term="name")
TIMESTAMP_EXAMPLE = 1667696874000000 # Sun Nov 06 2022 01:07:54
HOUR_IN_MICROSECONDS = 60 * 60 * 1000 * 1000
def test_projection_hour_literal(bound_reference_timestamp: BoundReference[int]) -> None:
assert HourTransform().project(
"name", BoundEqualTo(term=bound_reference_timestamp, literal=TimestampLiteral(TIMESTAMP_EXAMPLE))
) == EqualTo(term="name", literal=463249)
def test_projection_hour_set_same_hour(bound_reference_timestamp: BoundReference[int]) -> None:
assert HourTransform().project(
"name",
BoundIn(
term=bound_reference_timestamp,
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + 1), TimestampLiteral(TIMESTAMP_EXAMPLE)},
),
) == EqualTo(term="name", literal=463249)
def test_projection_hour_set_in(bound_reference_timestamp: BoundReference[int]) -> None:
assert HourTransform().project(
"name",
BoundIn(
term=bound_reference_timestamp,
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + HOUR_IN_MICROSECONDS), TimestampLiteral(TIMESTAMP_EXAMPLE)},
),
) == In(term="name", literals={463249, 463250})
def test_projection_hour_set_not_in(bound_reference_timestamp: BoundReference[int]) -> None:
assert (
HourTransform().project(
"name",
BoundNotIn(
term=bound_reference_timestamp,
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + HOUR_IN_MICROSECONDS), TimestampLiteral(TIMESTAMP_EXAMPLE)},
),
)
is None
)
def test_projection_identity_unary(bound_reference_timestamp: BoundReference[int]) -> None:
assert IdentityTransform().project("name", BoundNotNull(term=bound_reference_timestamp)) == NotNull(term="name")
def test_projection_identity_literal(bound_reference_timestamp: BoundReference[int]) -> None:
assert IdentityTransform().project(
"name", BoundEqualTo(term=bound_reference_timestamp, literal=TimestampLiteral(TIMESTAMP_EXAMPLE))
) == EqualTo(term="name", literal=TimestampLiteral(TIMESTAMP_EXAMPLE))
def test_projection_identity_set_in(bound_reference_timestamp: BoundReference[int]) -> None:
assert IdentityTransform().project(
"name",
BoundIn(
term=bound_reference_timestamp,
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + HOUR_IN_MICROSECONDS), TimestampLiteral(TIMESTAMP_EXAMPLE)},
),
) == In(
term="name",
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + HOUR_IN_MICROSECONDS), TimestampLiteral(TIMESTAMP_EXAMPLE)},
)
def test_projection_identity_set_not_in(bound_reference_timestamp: BoundReference[int]) -> None:
assert IdentityTransform().project(
"name",
BoundNotIn(
term=bound_reference_timestamp,
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + HOUR_IN_MICROSECONDS), TimestampLiteral(TIMESTAMP_EXAMPLE)},
),
) == NotIn(
term="name",
literals={TimestampLiteral(TIMESTAMP_EXAMPLE + HOUR_IN_MICROSECONDS), TimestampLiteral(TIMESTAMP_EXAMPLE)},
)
def test_projection_truncate_string_unary(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project("name", BoundNotNull(term=bound_reference_str)) == NotNull(term="name")
def test_projection_truncate_string_literal_eq(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project("name", BoundEqualTo(term=bound_reference_str, literal=literal("data"))) == EqualTo(
term="name", literal=literal("da")
)
def test_projection_truncate_string_literal_gt(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundGreaterThan(term=bound_reference_str, literal=literal("data"))
) == GreaterThanOrEqual(term="name", literal=literal("da"))
def test_projection_truncate_string_literal_gte(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundGreaterThanOrEqual(term=bound_reference_str, literal=literal("data"))
) == GreaterThanOrEqual(term="name", literal=literal("da"))
def test_projection_truncate_string_literal_lt(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundLessThan(term=bound_reference_str, literal=literal("data"))
) == LessThanOrEqual(term="name", literal=literal("da"))
def test_projection_truncate_string_literal_lte(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundLessThanOrEqual(term=bound_reference_str, literal=literal("data"))
) == LessThanOrEqual(term="name", literal=literal("da"))
def test_projection_truncate_string_set_same_result(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundIn(term=bound_reference_str, literals={literal("hello"), literal("helloworld")})
) == EqualTo(term="name", literal=literal("he"))
def test_projection_truncate_string_set_in(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(3).project(
"name", BoundIn(term=bound_reference_str, literals={literal("hello"), literal("world")})
) == In(term="name", literals={literal("hel"), literal("wor")})
def test_projection_truncate_string_set_not_in(bound_reference_str: BoundReference[str]) -> None:
assert (
TruncateTransform(3).project("name", BoundNotIn(term=bound_reference_str, literals={literal("hello"), literal("world")}))
is None
)
def test_projection_truncate_decimal_literal_eq(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundEqualTo(term=bound_reference_decimal, literal=DecimalLiteral(Decimal(19.25)))
) == EqualTo(term="name", literal=Decimal("19.24"))
def test_projection_truncate_decimal_literal_gt(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundGreaterThan(term=bound_reference_decimal, literal=DecimalLiteral(Decimal(19.25)))
) == GreaterThanOrEqual(term="name", literal=Decimal("19.26"))
def test_projection_truncate_decimal_literal_gte(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundGreaterThanOrEqual(term=bound_reference_decimal, literal=DecimalLiteral(Decimal(19.25)))
) == GreaterThanOrEqual(term="name", literal=Decimal("19.24"))
def test_projection_truncate_decimal_in(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundIn(term=bound_reference_decimal, literals={literal(Decimal(19.25)), literal(Decimal(18.15))})
) == In(
term="name",
literals={
Decimal("19.24"),
Decimal("18.14999999999999857891452847979962825775146484374"),
},
)
def test_projection_truncate_long_literal_eq(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundEqualTo(term=bound_reference_decimal, literal=DecimalLiteral(Decimal(19.25)))
) == EqualTo(term="name", literal=Decimal("19.24"))
def test_projection_truncate_long_literal_gt(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundGreaterThan(term=bound_reference_decimal, literal=DecimalLiteral(Decimal(19.25)))
) == GreaterThanOrEqual(term="name", literal=Decimal("19.26"))
def test_projection_truncate_long_literal_gte(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundGreaterThanOrEqual(term=bound_reference_decimal, literal=DecimalLiteral(Decimal(19.25)))
) == GreaterThanOrEqual(term="name", literal=Decimal("19.24"))
def test_projection_truncate_long_in(bound_reference_decimal: BoundReference[Decimal]) -> None:
assert TruncateTransform(2).project(
"name", BoundIn(term=bound_reference_decimal, literals={DecimalLiteral(Decimal(19.25)), DecimalLiteral(Decimal(18.15))})
) == In(
term="name",
literals={
Decimal("19.24"),
Decimal("18.14999999999999857891452847979962825775146484374"),
},
)
def test_projection_truncate_string_starts_with(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundStartsWith(term=bound_reference_str, literal=literal("hello"))
) == StartsWith(term="name", literal=literal("he"))
def test_projection_truncate_string_not_starts_with(bound_reference_str: BoundReference[str]) -> None:
assert TruncateTransform(2).project(
"name", BoundNotStartsWith(term=bound_reference_str, literal=literal("hello"))
) == NotStartsWith(term="name", literal=literal("he"))
def _test_projection(lhs: Optional[UnboundPredicate[L]], rhs: Optional[UnboundPredicate[L]]) -> None:
assert type(lhs) == type(lhs), f"Different classes: {type(lhs)} != {type(rhs)}"
if lhs is None and rhs is None:
# Both null
pass
elif isinstance(lhs, UnaryPredicate) and isinstance(rhs, UnaryPredicate):
# Nothing more to check
pass
elif isinstance(lhs, LiteralPredicate) and isinstance(rhs, LiteralPredicate):
assert lhs.literal == rhs.literal, f"Different literal: {lhs.literal} != {rhs.literal}"
elif isinstance(lhs, SetPredicate) and isinstance(rhs, SetPredicate):
assert lhs.literals == rhs.literals, f"Different literals: {lhs.literals} != {rhs.literals}"
else:
raise ValueError(f"Comparing unrelated: {lhs} <> {rhs}")
def test_month_projection_strict_epoch(bound_reference_date: BoundReference[int]) -> None:
date = literal("1970-01-01").to(DateType())
transform: Transform[Any, int] = MonthTransform()
_test_projection(
transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(0)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(0)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(0)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-1)), # In Java this is human string 1970-01
)
_test_projection(
transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(0)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("1969-12-31").to(DateType())
_test_projection(
transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={DateLiteral(-1), DateLiteral(0)}),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_month_projection_strict_lower_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("2017-01-01").to(DateType()) # == 564 months since epoch
transform: Transform[Any, int] = MonthTransform()
_test_projection(
transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(564)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(564)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(564)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(563)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(564)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("2017-12-02").to(DateType())
_test_projection(
transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(575), LongLiteral(564)}),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_negative_month_projection_strict_lower_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("1969-01-01").to(DateType()) # == 564 months since epoch
transform: Transform[Any, int] = MonthTransform()
_test_projection(
transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(-12)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(-12)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-12)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-13)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(-12)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("1969-12-31").to(DateType())
_test_projection(
transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(-1), LongLiteral(-12)}),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_month_projection_strict_upper_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("2017-12-31").to(DateType()) # == 575 months since epoch
transform: Transform[Any, int] = MonthTransform()
_test_projection(
transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(575)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(576)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(575)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(575)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(575)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("2017-01-01").to(DateType())
_test_projection(
transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(575), LongLiteral(564)}),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_negative_month_projection_strict_upper_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("1969-12-31").to(DateType()) # == -1 month since epoch
transform: Transform[Any, int] = MonthTransform()
_test_projection(
transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(-1)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(0)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(-1)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-1)),
)
_test_projection(
transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(-1)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("1969-11-01").to(DateType())
_test_projection(
transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(-1), LongLiteral(-2)}),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_day_strict(bound_reference_date: BoundReference[int]) -> None:
date = literal("2017-01-01").to(DateType())
_test_projection(
DayTransform().strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(17167)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(17168)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(17167)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(17166)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(17167)),
)
_test_projection(
lhs=DayTransform().strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("2017-12-31").to(DateType())
_test_projection(
DayTransform().strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(17531), LongLiteral(17167)}),
)
_test_projection(
lhs=DayTransform().strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_day_negative_strict(bound_reference_date: BoundReference[int]) -> None:
date = literal("1969-12-30").to(DateType())
_test_projection(
DayTransform().strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(-2)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(-1)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(-2)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-3)),
)
_test_projection(
DayTransform().strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(-2)),
)
_test_projection(
lhs=DayTransform().strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("1969-12-28").to(DateType())
_test_projection(
DayTransform().strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(-2), LongLiteral(-4)}),
)
_test_projection(
lhs=DayTransform().strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_year_strict_lower_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("2017-01-01").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(47)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(47)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(47)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(46)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(47)),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("2016-12-31").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(46), LongLiteral(47)}),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_negative_year_strict_lower_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("1970-01-01").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(0)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(0)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(0)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-1)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(0)),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("1969-12-31").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(-1), LongLiteral(0)}),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_year_strict_upper_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("2017-12-31").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(47)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(48)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(47)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(47)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(47)),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("2016-01-01").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(46), LongLiteral(47)}),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_negative_year_strict_upper_bound(bound_reference_date: BoundReference[int]) -> None:
date = literal("1969-12-31").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThan(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=DateLiteral(-1)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_date, literal=date)),
LessThan(term="name", literal=LongLiteral(0)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=DateLiteral(-1)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_date, literal=date)),
GreaterThan(term="name", literal=LongLiteral(-1)),
)
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_date, literal=date)),
NotEqualTo(term="name", literal=DateLiteral(-1)),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundEqualTo(term=bound_reference_date, literal=date)), rhs=None
)
another_date = literal("1970-01-01").to(DateType())
_test_projection(
YearTransform().strict_project(name="name", pred=BoundNotIn(term=bound_reference_date, literals={date, another_date})),
NotIn(term="name", literals={LongLiteral(-1), LongLiteral(0)}),
)
_test_projection(
lhs=YearTransform().strict_project(name="name", pred=BoundIn(term=bound_reference_date, literals={date, another_date})),
rhs=None,
)
def test_strict_bucket_integer(bound_reference_long: BoundReference[int]) -> None:
value = literal(100)
transform: Transform[Any, int] = BucketTransform(num_buckets=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_long, literal=value)),
rhs=LessThan(term="name", literal=literal(6)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_long, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_long, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_long, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_long, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_long, literal=value)),
rhs=None,
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundNotIn(term=bound_reference_long, literals={literal(100 - 1), value, literal(100 + 1)})
),
rhs=NotIn(term=Reference("name"), literals={6, 7, 8}),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundIn(term=bound_reference_long, literals={literal(100 - 1), value, literal(100 + 1)})
),
rhs=None,
)
def test_strict_bucket_decimal(bound_reference_decimal: BoundReference[int]) -> None:
value = literal(Decimal("100.00"))
transform: Transform[Any, int] = BucketTransform(num_buckets=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_decimal, literal=value)),
rhs=LessThan(term="name", literal=literal(2)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_decimal, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_decimal, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_decimal, literal=value)),
rhs=None,
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_decimal, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_decimal, literal=value)),
rhs=None,
)
_test_projection(
lhs=transform.strict_project(
name="name",
pred=BoundNotIn(
term=bound_reference_decimal, literals={literal(Decimal("99.00")), value, literal(Decimal("101.00"))}
),
),
rhs=NotIn(term=Reference("name"), literals={2, 6}),
)
_test_projection(
lhs=transform.strict_project(
name="name",
pred=BoundIn(term=bound_reference_decimal, literals={literal(Decimal("99.00")), value, literal(Decimal("101.00"))}),
),
rhs=None,
)
def test_strict_bucket_string(bound_reference_str: BoundReference[int]) -> None:
value = literal("abcdefg")
transform: Transform[Any, int] = BucketTransform(num_buckets=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_str, literal=value)),
rhs=LessThan(term="name", literal=literal(4)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_str, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_str, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_str, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_str, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_str, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundNotIn(term=bound_reference_str, literals={literal("abcdefg"), literal("abcdefgabc")})
),
rhs=NotIn(term=Reference("name"), literals={4, 9}),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundIn(term=bound_reference_str, literals={literal("abcdefg"), literal("abcdefgabc")})
),
rhs=None,
)
def test_strict_bucket_bytes(bound_reference_binary: BoundReference[int]) -> None:
value = literal(str.encode("abcdefg"))
transform: Transform[Any, int] = BucketTransform(num_buckets=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_binary, literal=value)),
rhs=LessThan(term="name", literal=literal(4)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_binary, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_binary, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_binary, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_binary, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_binary, literal=value)),
rhs=None,
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundNotIn(term=bound_reference_binary, literals={value, literal(str.encode("abcdehij"))})
),
rhs=NotIn(term=Reference("name"), literals={4, 6}),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundIn(term=bound_reference_binary, literals={value, literal(str.encode("abcdehij"))})
),
rhs=None,
)
def test_strict_bucket_uuid(bound_reference_uuid: BoundReference[int]) -> None:
value = literal(UUID("12345678123456781234567812345678"))
transform: Transform[Any, int] = BucketTransform(num_buckets=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotEqualTo(term=bound_reference_uuid, literal=value)),
rhs=LessThan(term="name", literal=literal(1)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundEqualTo(term=bound_reference_uuid, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_uuid, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_uuid, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_uuid, literal=value)), rhs=None
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_uuid, literal=value)),
rhs=None,
)
_test_projection(
lhs=transform.strict_project(
name="name",
pred=BoundNotIn(term=bound_reference_uuid, literals={value, literal(UUID("12345678123456781234567812345679"))}),
),
rhs=NotIn(term=Reference("name"), literals={1, 4}),
)
_test_projection(
lhs=transform.strict_project(
name="name",
pred=BoundIn(term=bound_reference_uuid, literals={value, literal(UUID("12345678123456781234567812345679"))}),
),
rhs=None,
)
def test_strict_identity_projection(bound_reference_long: BoundReference[int]) -> None:
transform: Transform[Any, Any] = IdentityTransform()
predicates = [
BoundNotNull(term=bound_reference_long),
BoundIsNull(term=bound_reference_long),
BoundLessThan(term=bound_reference_long, literal=literal(100)),
BoundLessThanOrEqual(term=bound_reference_long, literal=literal(101)),
BoundGreaterThan(term=bound_reference_long, literal=literal(102)),
BoundGreaterThanOrEqual(term=bound_reference_long, literal=literal(103)),
BoundEqualTo(term=bound_reference_long, literal=literal(104)),
BoundNotEqualTo(term=bound_reference_long, literal=literal(105)),
]
for predicate in predicates:
if isinstance(predicate, BoundLiteralPredicate):
_test_projection(
lhs=transform.strict_project(
name="name",
pred=predicate,
),
rhs=predicate.as_unbound(term=Reference("name"), literal=predicate.literal),
)
else:
_test_projection(
lhs=transform.strict_project(
name="name",
pred=predicate,
),
rhs=predicate.as_unbound(term=Reference("name")),
)
def test_truncate_strict_integer_lower_bound(bound_reference_long: BoundReference[int]) -> None:
value = literal(100)
transform: Transform[Any, Any] = TruncateTransform(width=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_long, literal=value)),
rhs=LessThan(term=Reference("name"), literal=LongLiteral(100)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_long, literal=value)),
rhs=LessThanOrEqual(term=Reference("name"), literal=LongLiteral(100)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_long, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=LongLiteral(100)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_long, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=LongLiteral(90)),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundNotIn(term=bound_reference_long, literals={literal(99), literal(100), literal(101)})
),
rhs=NotIn(term=Reference("name"), literals={literal(90), literal(100)}),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundIn(term=bound_reference_long, literals={literal(99), literal(100), literal(101)})
),
rhs=None,
)
def test_truncate_strict_integer_upper_bound(bound_reference_long: BoundReference[int]) -> None:
value = literal(99)
transform: Transform[Any, Any] = TruncateTransform(width=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_long, literal=value)),
rhs=LessThan(term=Reference("name"), literal=LongLiteral(90)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_long, literal=value)),
rhs=LessThan(term=Reference("name"), literal=LongLiteral(100)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_long, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=LongLiteral(90)),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_long, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=LongLiteral(90)),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundNotIn(term=bound_reference_long, literals={literal(99), literal(100), literal(101)})
),
rhs=NotIn(term=Reference("name"), literals={literal(90), literal(100)}),
)
_test_projection(
lhs=transform.strict_project(
name="name", pred=BoundIn(term=bound_reference_long, literals={literal(99), literal(100), literal(101)})
),
rhs=None,
)
def test_truncate_strict_decimal_lower_bound(bound_reference_decimal: BoundReference[Decimal]) -> None:
value = literal(Decimal("100.00"))
transform: Transform[Any, Any] = TruncateTransform(width=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_decimal, literal=value)),
rhs=LessThan(term=Reference("name"), literal=Decimal("100.00")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_decimal, literal=value)),
rhs=LessThanOrEqual(term=Reference("name"), literal=Decimal("100.00")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_decimal, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=Decimal("100.00")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_decimal, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=Decimal("99.90")),
)
set_of_literals = {literal(Decimal("99.00")), literal(Decimal("100.00")), literal(Decimal("101.00"))}
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_decimal, literals=set_of_literals)),
rhs=NotIn(term=Reference("name"), literals=set_of_literals),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_decimal, literals=set_of_literals)), rhs=None
)
def test_truncate_strict_decimal_upper_bound(bound_reference_decimal: BoundReference[Decimal]) -> None:
value = literal(Decimal("99.99"))
transform: Transform[Any, Any] = TruncateTransform(width=10)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_decimal, literal=value)),
rhs=LessThan(term=Reference("name"), literal=Decimal("99.90")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_decimal, literal=value)),
rhs=LessThan(term=Reference("name"), literal=Decimal("100.00")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_decimal, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=Decimal("99.90")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_decimal, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=Decimal("99.90")),
)
set_of_literals = {literal(Decimal("98.99")), literal(Decimal("99.99")), literal(Decimal("100.99"))}
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_decimal, literals=set_of_literals)),
rhs=NotIn(
term=Reference("name"), literals={literal(Decimal("98.90")), literal(Decimal("99.90")), literal(Decimal("100.90"))}
),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_decimal, literals=set_of_literals)), rhs=None
)
def test_string_strict(bound_reference_str: BoundReference[str]) -> None:
value = literal("abcdefg")
transform: Transform[Any, Any] = TruncateTransform(width=5)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_str, literal=value)),
rhs=LessThan(term=Reference("name"), literal=literal("abcde")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_str, literal=value)),
rhs=LessThan(term=Reference("name"), literal=literal("abcde")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_str, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=literal("abcde")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_str, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=literal("abcde")),
)
set_of_literals = {literal("abcde"), literal("abcdefg")}
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_str, literals=set_of_literals)),
rhs=NotEqualTo(term=Reference("name"), literal=literal("abcde")),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_str, literals=set_of_literals)), rhs=None
)
def test_strict_binary(bound_reference_binary: BoundReference[str]) -> None:
value = literal(b"abcdefg")
transform: Transform[Any, Any] = TruncateTransform(width=5)
abcde = literal(b"abcde")
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThan(term=bound_reference_binary, literal=value)),
rhs=LessThan(term=Reference("name"), literal=abcde),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundLessThanOrEqual(term=bound_reference_binary, literal=value)),
rhs=LessThan(term=Reference("name"), literal=abcde),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThan(term=bound_reference_binary, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=abcde),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundGreaterThanOrEqual(term=bound_reference_binary, literal=value)),
rhs=GreaterThan(term=Reference("name"), literal=abcde),
)
set_of_literals = {literal(b"abcde"), literal(b"abcdefg")}
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundNotIn(term=bound_reference_binary, literals=set_of_literals)),
rhs=NotEqualTo(term=Reference("name"), literal=abcde),
)
_test_projection(
lhs=transform.strict_project(name="name", pred=BoundIn(term=bound_reference_binary, literals=set_of_literals)), rhs=None
)
@pytest.mark.parametrize(
"transform",
[
pytest.param(YearTransform(), id="year_transform"),
pytest.param(MonthTransform(), id="month_transform"),
pytest.param(DayTransform(), id="day_transform"),
pytest.param(HourTransform(), id="hour_transform"),
],
)
@pytest.mark.parametrize(
"source_col, source_type", [("date", DateType()), ("timestamp", TimestampType()), ("timestamptz", TimestamptzType())]
)
def test_ymd_pyarrow_transforms(
arrow_table_date_timestamps: "pa.Table",
source_col: str,
source_type: PrimitiveType,
transform: Transform[Any, Any],
) -> None:
if transform.can_transform(source_type):
assert transform.pyarrow_transform(source_type)(arrow_table_date_timestamps[source_col]).to_pylist() == [
transform.transform(source_type)(_to_partition_representation(source_type, v))
for v in arrow_table_date_timestamps[source_col].to_pylist()
]
else:
with pytest.raises(ValueError):
transform.pyarrow_transform(DateType())(arrow_table_date_timestamps[source_col])