protected QB appendCanonicalizedAttributeToQuery(final QB queryBuilder, final String queryAttribute, final String dataAttribute, final List<Object> queryValues) {
        val canonicalizedQueryValues = canonicalizeAttribute(queryAttribute, queryValues, caseInsensitiveQueryAttributes);
        LOGGER.debug("Adding attribute [{}] with value [{}] to query builder [{}]", queryAttribute, queryValues, queryBuilder);
        return appendAttributeToQuery(queryBuilder, dataAttribute, canonicalizedQueryValues);
    }
Append the attribute and its canonicalized value/s to the
{@code queryBuilder}. Uses {@code queryAttribute} to determine whether or
not the value/s should be canonicalized. I.e. the behavior is controlled
by {@link #setCaseInsensitiveQueryAttributes(Map)}.

<p>This method is only concerned with canonicalizing the query attribute
value. It is still up to the subclass to canonicalize the data-layer
attribute value prior to comparison, if necessary. For example, if
the data layer is a case-sensitive relational database and attributes
therein are stored in mixed case, but comparison should be
case-insensitive, the relational column reference would need to be
wrapped in a {@code lower()} or {@code upper()} function. (This, of
course, needs to be handled with care, since it can lead to table
scanning if the store does not support function-based indexes.) Such
data-layer canonicalization would be unnecessary if the data layer is
case-insensitive or stores values in the same canonicalized form as has
been configured for the app-layer attribute.

@param queryBuilder   The sub-class specific query builder object
@param queryAttribute The full attribute name to append
@param dataAttribute  The full attribute name to append
@param queryValues    The values for the data attribute
@return An updated queryBuilder
core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/attribute/AbstractQueryPersonAttributeDao.java