Repository: realm/realm-swift
File: Realm/RLMQueryUtil.mm (Objective-C++)

Code before:
    firstIndex = RLMValidatedColumnIndex(desc, firstColumnName);
    RLMProperty *firstProp = desc[firstColumnName];

    // FIXME: when core support multiple levels of link queries, change == to >=
    //        and loop through the elements of arr to build up link query
    if ([arr count] == 2) {
        isLinkQuery = YES;
        if (firstProp.type != RLMPropertyTypeObject && firstProp.type != RLMPropertyTypeArray) {
            throw RLMPredicateException(@"Invalid value", [NSString stringWithFormat:@"column name '%@' is not a link", firstColumnName]);
        }
        TableRef secondTable = query.get_table()->get_link_target(size_t(firstIndex));
        RLMObjectSchema *secondDesc = [RLMObjectSchema schemaForTable:&(*secondTable) className:@"tmp"];
        secondColumnName = [arr objectAtIndex:1];
        secondIndex = RLMValidatedColumnIndex(secondDesc, secondColumnName);
        RLMProperty *secondProp = secondDesc[secondColumnName];
        secondType = secondProp.type;
    }


    BOOL betweenOperation = (operatorType == NSBetweenPredicateOperatorType);
    if (!isLinkQuery) {
        validate_value_for_query(value, firstProp, betweenOperation);
    }
    
    if (betweenOperation) {
        add_between_constraint_to_query(query, firstProp.type, firstIndex, value);
        return;
    }
    
    // finally cast to native types and add query clause
    RLMPropertyType type;
    if (isLinkQuery) {
        type = secondType;
    }
    else {
        type = firstProp.type;
    }
    switch (type) {
        case type_Bool:
            if (isLinkQuery) {
                add_bool_constraint_to_link_query(query, operatorType, firstIndex, secondIndex, bool([(NSNumber *)value boolValue]));
            }
            else {
                add_bool_constraint_to_query(query, operatorType, firstIndex,
                                             bool([(NSNumber *)value boolValue]));
            }
            break;
        case type_DateTime:
            if (isLinkQuery) {
                add_datetime_constraint_to_link_query(query, operatorType, firstIndex, secondIndex,
                                                      double([(NSDate *)value timeIntervalSince1970]));

Review comment (refactor):
Rather than inserting `if (!isLinkQuery)` for every statement for the rest of this method, perhaps we should split this into two methods/control flows and only do this conditional once. Would make it easier to read and less error prone.


Code after:
    BOOL isLinkQuery = NO;
    NSUInteger firstIndex, secondIndex = 0;
    RLMPropertyType secondType = RLMPropertyTypeAny;

    firstIndex = RLMValidatedColumnIndex(desc, firstColumnName);
    RLMProperty *firstProp = desc[firstColumnName];

    // FIXME: when core support multiple levels of link queries, change == to >=
    //        and loop through the elements of arr to build up link query
    if ([arr count] == 2) {
        isLinkQuery = YES;
        if (firstProp.type != RLMPropertyTypeObject && firstProp.type != RLMPropertyTypeArray) {
            throw RLMPredicateException(@"Invalid value", [NSString stringWithFormat:@"column name '%@' is not a link", firstColumnName]);
        }
        secondColumnName = [arr objectAtIndex:1];
        RLMProperty *secondProp = schema[firstProp.objectClassName][secondColumnName];
        secondType = secondProp.type;
        secondIndex = RLMValidatedColumnIndex(schema[firstProp.objectClassName], secondColumnName);
    }
    else if ([arr count] > 2) {
        @throw RLMPredicateException(@"Invalid predicate",
                                     [NSString stringWithFormat:@"Too many levels of relationships: %lu > 2", [arr count]]);
    }

    BOOL betweenOperation = (operatorType == NSBetweenPredicateOperatorType);
    if (!isLinkQuery) {
        validate_value_for_query(value, firstProp, betweenOperation);
    }
    
    if (betweenOperation) {
        add_between_constraint_to_query(query, firstProp.type, firstIndex, value);
        return;
    }
    
    // finally cast to native types and add query clause
    RLMPropertyType type;
    if (isLinkQuery) {
        type = secondType;
    }
    else {
        type = firstProp.type;
    }
    switch (type) {
        case type_Bool:
            if (isLinkQuery) {
                add_bool_constraint_to_link_query(query, operatorType, firstIndex, secondIndex, bool([(NSNumber *)value boolValue]));
            }
            else {
                add_bool_constraint_to_query(query, operatorType, firstIndex,
                                             bool([(NSNumber *)value boolValue]));
            }