diff --git a/Firestore/Swift/Source/ExpressionImplementation.swift b/Firestore/Swift/Source/ExpressionImplementation.swift index 836a571f07c..9beb9de42ae 100644 --- a/Firestore/Swift/Source/ExpressionImplementation.swift +++ b/Firestore/Swift/Source/ExpressionImplementation.swift @@ -604,14 +604,6 @@ public extension Expression { // --- Added Type Check Operations --- - func isNan() -> BooleanExpression { - return BooleanExpression(functionName: "is_nan", args: [self]) - } - - func isNil() -> BooleanExpression { - return BooleanExpression(functionName: "is_null", args: [self]) - } - func exists() -> BooleanExpression { return BooleanExpression(functionName: "exists", args: [self]) } @@ -624,14 +616,6 @@ public extension Expression { return BooleanExpression(functionName: "is_absent", args: [self]) } - func isNotNil() -> BooleanExpression { - return BooleanExpression(functionName: "is_not_null", args: [self]) - } - - func isNotNan() -> BooleanExpression { - return BooleanExpression(functionName: "is_not_nan", args: [self]) - } - // --- Added String Operations --- func join(delimiter: String) -> FunctionExpression { diff --git a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift index 97d5f3ef47e..b02fcd23604 100644 --- a/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift +++ b/Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift @@ -635,26 +635,6 @@ public protocol Expression: Sendable { /// boolean expressions. func notEqualAny(_ arrayExpression: Expression) -> BooleanExpression - /// Creates an expression that checks if this expression evaluates to "NaN" (Not a Number). - /// - /// ```swift - /// // Check if the result of a calculation is NaN - /// Field("value").divide(0).isNan() - /// ``` - /// - /// - Returns: A new `BooleanExpression` representing the "isNaN" check. - func isNan() -> BooleanExpression - - /// Creates an expression that checks if this expression evaluates to "Nil". - /// - /// ```swift - /// // Check if the "optionalField" is null - /// Field("optionalField").isNil() - /// ``` - /// - /// - Returns: A new `BooleanExpression` representing the "isNil" check. - func isNil() -> BooleanExpression - /// Creates an expression that checks if a field exists in the document. /// /// ```swift @@ -686,27 +666,6 @@ public protocol Expression: Sendable { /// - Returns: A new `BooleanExpression` representing the "isAbsent" check. func isAbsent() -> BooleanExpression - /// Creates an expression that checks if the result of this expression is not null. - /// - /// ```swift - /// // Check if the value of the "name" field is not null - /// Field("name").isNotNil() - /// ``` - /// - /// - Returns: A new `BooleanExpression` representing the "isNotNil" check. - func isNotNil() -> BooleanExpression - - /// Creates an expression that checks if the results of this expression is NOT "NaN" (Not a - /// Number). - /// - /// ```swift - /// // Check if the result of a calculation is NOT NaN - /// Field("value").divide(Field("count")).isNotNan() // Assuming count might be 0 - /// ``` - /// - /// - Returns: A new `BooleanExpr` representing the "isNotNaN" check. - func isNotNan() -> BooleanExpression - // MARK: String Operations /// Creates an expression that joins the elements of an array of strings with a given separator. diff --git a/Firestore/Swift/Tests/Integration/PipelineTests.swift b/Firestore/Swift/Tests/Integration/PipelineTests.swift index cb2b0ef96ac..7daae8f6938 100644 --- a/Firestore/Swift/Tests/Integration/PipelineTests.swift +++ b/Firestore/Swift/Tests/Integration/PipelineTests.swift @@ -2488,11 +2488,11 @@ class PipelineIntegrationTests: FSTIntegrationTestCase { .limit(1) .select( [ - Field("rating").isNil().as("ratingIsNull"), - Field("rating").isNan().as("ratingIsNaN"), + Field("rating").equal(Constant.nil).as("ratingIsNull"), + Field("rating").equal(Constant(Double.nan)).as("ratingIsNaN"), Field("foo").isAbsent().as("isAbsent"), - Field("title").isNotNil().as("titleIsNotNull"), - Field("cost").isNotNan().as("costIsNotNan"), + Field("title").notEqual(Constant.nil).as("titleIsNotNull"), + Field("cost").notEqual(Constant(Double.nan)).as("costIsNotNan"), Field("fooBarBaz").exists().as("fooBarBazExists"), Field("title").exists().as("titleExists"), ] diff --git a/Firestore/core/src/core/pipeline_util.cc b/Firestore/core/src/core/pipeline_util.cc index bc51be4fde6..11531845d32 100644 --- a/Firestore/core/src/core/pipeline_util.cc +++ b/Firestore/core/src/core/pipeline_util.cc @@ -554,87 +554,58 @@ std::shared_ptr ToPipelineBooleanExpr(const Filter& filter) { const google_firestore_v1_Value& value = field_filter.value(); FieldFilter::Operator op = field_filter.op(); - if (model::IsNaNValue(value)) { - auto is_nan_expr = std::make_shared( - "is_nan", std::vector>{api_field}); - if (op == FieldFilter::Operator::Equal) { - return std::make_shared( - "and", - std::vector>{exists_expr, is_nan_expr}); - } else { // Assuming NotEqual for IsNotNan - auto is_not_nan_expr = std::make_shared( - "not", std::vector>{is_nan_expr}); - return std::make_shared( - "and", std::vector>{exists_expr, - is_not_nan_expr}); + auto api_constant = + std::make_shared(model::DeepClone(value)); + std::shared_ptr comparison_expr; + std::string func_name; + + switch (op) { + case FieldFilter::Operator::LessThan: + func_name = "lt"; + break; + case FieldFilter::Operator::LessThanOrEqual: + func_name = "lte"; + break; + case FieldFilter::Operator::GreaterThan: + func_name = "gt"; + break; + case FieldFilter::Operator::GreaterThanOrEqual: + func_name = "gte"; + break; + case FieldFilter::Operator::Equal: + func_name = "eq"; + break; + case FieldFilter::Operator::NotEqual: + func_name = "neq"; + break; + case FieldFilter::Operator::ArrayContains: + func_name = "array_contains"; + break; + case FieldFilter::Operator::In: + case FieldFilter::Operator::NotIn: + case FieldFilter::Operator::ArrayContainsAny: { + HARD_ASSERT( + model::IsArray(value), + "Value for IN, NOT_IN, ARRAY_CONTAINS_ANY must be an array."); + + if (op == FieldFilter::Operator::In) + func_name = "eq_any"; + else if (op == FieldFilter::Operator::NotIn) + func_name = "not_eq_any"; + else if (op == FieldFilter::Operator::ArrayContainsAny) + func_name = "array_contains_any"; + break; } - } else if (model::IsNullValue(value)) { - auto is_null_expr = std::make_shared( - "is_null", std::vector>{api_field}); - if (op == FieldFilter::Operator::Equal) { - return std::make_shared( - "and", - std::vector>{exists_expr, is_null_expr}); - } else { // Assuming NotEqual for IsNotNull - auto is_not_null_expr = std::make_shared( - "not", std::vector>{is_null_expr}); - return std::make_shared( - "and", std::vector>{exists_expr, - is_not_null_expr}); - } - } else { - auto api_constant = - std::make_shared(model::DeepClone(value)); - std::shared_ptr comparison_expr; - std::string func_name; - - switch (op) { - case FieldFilter::Operator::LessThan: - func_name = "lt"; - break; - case FieldFilter::Operator::LessThanOrEqual: - func_name = "lte"; - break; - case FieldFilter::Operator::GreaterThan: - func_name = "gt"; - break; - case FieldFilter::Operator::GreaterThanOrEqual: - func_name = "gte"; - break; - case FieldFilter::Operator::Equal: - func_name = "eq"; - break; - case FieldFilter::Operator::NotEqual: - func_name = "neq"; - break; - case FieldFilter::Operator::ArrayContains: - func_name = "array_contains"; - break; - case FieldFilter::Operator::In: - case FieldFilter::Operator::NotIn: - case FieldFilter::Operator::ArrayContainsAny: { - HARD_ASSERT( - model::IsArray(value), - "Value for IN, NOT_IN, ARRAY_CONTAINS_ANY must be an array."); - - if (op == FieldFilter::Operator::In) - func_name = "eq_any"; - else if (op == FieldFilter::Operator::NotIn) - func_name = "not_eq_any"; - else if (op == FieldFilter::Operator::ArrayContainsAny) - func_name = "array_contains_any"; - break; - } - default: - HARD_FAIL("Unexpected FieldFilter operator."); - } - comparison_expr = std::make_shared( - func_name, - std::vector>{api_field, api_constant}); - return std::make_shared( - "and", std::vector>{exists_expr, - comparison_expr}); + default: + HARD_FAIL("Unexpected FieldFilter operator."); } + comparison_expr = std::make_shared( + func_name, + std::vector>{api_field, api_constant}); + return std::make_shared( + "and", + std::vector>{exists_expr, comparison_expr}); + } else if (filter.type() == FieldFilter::Type::kCompositeFilter) { const auto& composite_filter = static_cast(filter); std::vector> sub_exprs;