@@ -684,32 +684,30 @@ Query make_diacritic_insensitive_constraint(NSPredicateOperatorType operatorType
684684 }
685685}
686686
687+ // static_assert is always evaluated even if it's inside a if constexpr
688+ // unless the value is derived from the template argument, in which case it's
689+ // only evaluated if that branch is active
690+ template <typename > struct AlwaysFalse : std::false_type {};
691+
687692template <typename C, typename T>
688- void QueryBuilder::do_add_diacritic_sensitive_string_constraint (NSPredicateOperatorType operatorType,
689- NSComparisonPredicateOptions predicateOptions,
690- C&& column, T&& value) {
691- bool caseSensitive = !(predicateOptions & NSCaseInsensitivePredicateOption);
693+ Query make_diacritic_sensitive_constraint (NSPredicateOperatorType operatorType,
694+ bool caseSensitive, C& column, T const & value)
695+ {
692696 switch (operatorType) {
693697 case NSBeginsWithPredicateOperatorType:
694- add_substring_constraint (value, column.begins_with (value, caseSensitive));
695- break ;
698+ return column.begins_with (value, caseSensitive);
696699 case NSEndsWithPredicateOperatorType:
697- add_substring_constraint (value, column.ends_with (value, caseSensitive));
698- break ;
700+ return column.ends_with (value, caseSensitive);
699701 case NSContainsPredicateOperatorType:
700- add_substring_constraint (value, column.contains (value, caseSensitive));
701- break ;
702+ return column.contains (value, caseSensitive);
702703 case NSEqualToPredicateOperatorType:
703- m_query.and_query (column.equal (value, caseSensitive));
704- break ;
704+ return column.equal (value, caseSensitive);
705705 case NSNotEqualToPredicateOperatorType:
706- m_query.and_query (column.not_equal (value, caseSensitive));
707- break ;
706+ return column.not_equal (value, caseSensitive);
708707 case NSLikePredicateOperatorType:
709- m_query.and_query (column.like (value, caseSensitive));
710- break ;
708+ return column.like (value, caseSensitive);
711709 default : {
712- if constexpr (is_any_v<C, Columns<String>, Columns<Lst<String>>, Columns<Set<String>>>) {
710+ if constexpr (is_any_v<C, Columns<String>, Columns<Lst<String>>, Columns<Set<String>>, ColumnDictionaryKeys >) {
713711 unsupportedOperator (RLMPropertyTypeString, operatorType);
714712 }
715713 else if constexpr (is_any_v<C, Columns<Binary>, Columns<Lst<Binary>>, Columns<Set<Binary>>>) {
@@ -726,10 +724,56 @@ Query make_diacritic_insensitive_constraint(NSPredicateOperatorType operatorType
726724 @" Operator '%@ ' not supported for string queries on Dictionary." ,
727725 operatorName (operatorType));
728726 }
727+ else {
728+ static_assert (AlwaysFalse<C>::value, " unsupported column type" );
729+ }
729730 }
730731 }
731732}
732733
734+ template <typename C, typename T>
735+ void QueryBuilder::do_add_diacritic_sensitive_string_constraint (NSPredicateOperatorType operatorType,
736+ NSComparisonPredicateOptions predicateOptions,
737+ C&& column, T&& value) {
738+ bool caseSensitive = !(predicateOptions & NSCaseInsensitivePredicateOption);
739+ Query condition = make_diacritic_sensitive_constraint (operatorType, caseSensitive, column, value);
740+
741+ // Queries on Mixed used to coerce Strings to Binary and vice-versa. Core
742+ // no longer does this, but we can maintain compatibility by doing the
743+ // coercion and checking both
744+ // NEXT-MAJOR: we should remove this and realign with core's behavior
745+ if constexpr (is_any_v<C, Columns<Mixed>, Columns<Lst<Mixed>>, Columns<Set<Mixed>>, Columns<Dictionary>>) {
746+ Mixed m = value;
747+ if (!m.is_null ()) {
748+ if (m.get_type () == type_String) {
749+ m = m.export_to_type <BinaryData>();
750+ }
751+ else {
752+ m = m.export_to_type <StringData>();
753+ }
754+
755+ // Equality and substring operations need (col == strValue OR col == binValue),
756+ // but not equals needs (col != strValue AND col != binValue)
757+ if (operatorType != NSNotEqualToPredicateOperatorType) {
758+ condition.Or ();
759+ }
760+
761+ condition.and_query (make_diacritic_sensitive_constraint (operatorType, caseSensitive, column, m));
762+ }
763+ }
764+ switch (operatorType) {
765+ case NSBeginsWithPredicateOperatorType:
766+ case NSEndsWithPredicateOperatorType:
767+ case NSContainsPredicateOperatorType:
768+ add_substring_constraint (value, std::move (condition));
769+ break ;
770+
771+ default :
772+ m_query.and_query (std::move (condition));
773+ break ;
774+ }
775+ }
776+
733777template <typename C, typename T>
734778void QueryBuilder::add_diacritic_sensitive_string_constraint (NSPredicateOperatorType operatorType,
735779 NSComparisonPredicateOptions predicateOptions,
@@ -1297,11 +1341,6 @@ KeyPath key_path_from_string(RLMSchema *schema, RLMObjectSchema *objectSchema, N
12971341
12981342#pragma mark Collection Operations
12991343
1300- // static_assert is always evaluated even if it's inside a if constexpr
1301- // unless the value is derived from the template argument, in which case it's
1302- // only evaluated if that branch is active
1303- template <CollectionOperation::Type> struct AlwaysFalse : std::false_type {};
1304-
13051344template <CollectionOperation::Type OperationType, typename Column>
13061345auto collection_operation_expr_2 (Column&& column) {
13071346 if constexpr (OperationType == CollectionOperation::Minimum) {
@@ -1317,7 +1356,8 @@ auto collection_operation_expr_2(Column&& column) {
13171356 return column.average ();
13181357 }
13191358 else {
1320- static_assert (AlwaysFalse<OperationType>::value, " invalid operation type" );
1359+ static_assert (AlwaysFalse<std::integral_constant<CollectionOperation::Type, OperationType>>::value,
1360+ " invalid operation type" );
13211361 }
13221362}
13231363
@@ -1660,7 +1700,7 @@ bool is_self_value_for_key_path_function_expression(NSExpression *expression)
16601700 ColumnReference collectionColumn = column_reference_from_key_path (key_path_from_string (m_schema, objectSchema, keyPath), true );
16611701 RLMPrecondition (collectionColumn.property ().dictionary , @" Invalid predicate" ,
16621702 @" Invalid keypath '%@ ': only dictionaries support subscript predicates." , functionExpression);
1663- add_mixed_constraint (operatorType, options, collectionColumn.resolve <Dictionary>().key (mapKey.UTF8String ), right.constantValue );
1703+ add_mixed_constraint (operatorType, options, std::move ( collectionColumn.resolve <Dictionary>().key (mapKey.UTF8String ) ), right.constantValue );
16641704}
16651705
16661706void QueryBuilder::apply_function_expression (RLMObjectSchema *objectSchema, NSExpression *functionExpression,
0 commit comments