Problem/Motivation

When I add an exposed filter on a name field to my view, and set the operator to "Contains" in the UI, I get the following query output:

SELECT
  ...
FROM
  ...
WHERE 
  ...
  AND (LOWER(CONCAT(' ', COALESCE(crm_core_contact_field_data_field_activity_participants__field_data_contact_name.contact_name_title, ''), ' ', COALESCE(crm_core_contact_field_data_field_activity_participants__field_data_contact_name.contact_name_given, ''), ' ', COALESCE(crm_core_contact_field_data_field_activity_participants__field_data_contact_name.contact_name_middle, ''), ' ', COALESCE(crm_core_contact_field_data_field_activity_participants__field_data_contact_name.contact_name_family, ''), ' ', COALESCE(crm_core_contact_field_data_field_activity_participants__field_data_contact_name.contact_name_generational, ''), ' ', COALESCE(crm_core_contact_field_data_field_activity_participants__field_data_contact_name.contact_name_credentials, ''))) LIKE '% search_term%') ))
...

Note the extra space before search_term in that query.

Steps to reproduce

  1. Download a fresh copy of Drupal 7 core.
  2. Install Drupal using the minimal install profile: drush -y site-install minimal.
  3. Clone the Name module, version 7.x-1.x: git clone --branch 7.x-1.x http://git.drupal.org/project/name.git
  4. Install field_ui, name, views, and their dependencies: drush -y pm-enable --resolve-dependencies field_ui name views views_ui
  5. Add a content type (I called mine "Client contact"). Use the default settings.
  6. Add a name field (I called mine "Client contact's name") to the new content type. Use the default settings.
  7. Add a node of the new content type. Set the Title to "Test", and the Client contact's name field to:
    • Title = Dr.
    • Given = Joseph
    • Middle name(s) = Q
    • Family = Bloggs
    • Generational = III
    • Credentials = K.B.E.
  8. Go to /admin/structure/views/settings, and, under Live preview settings, set Show the SQL query = TRUE.
  9. Add a new view. (I called mine "Contacts", showing Content of type Client Contact sorted by Newest first. I chose to Create a page with the title "Contacts", path "contacts", Display format Table of fields, with 10 items to display, using a pager). Click "Continue & edit".
  10. Add a Filter criteria to the view:
    1. Select the filter Content: Client contact's name.
    2. Expose this filter to visitors, to allow them to change it = TRUE
    3. Filter type to expose = Single filter
    4. Required = FALSE
    5. Label = Client contact's name contains
    6. Leave Description empty.
    7. Operator = Contains
    8. Leave Value empty.
    9. Expose operator = FALSE
    10. Remember the last selection = FALSE
    11. Leave Administrative title empty.
    12. Leave Filter identifier at it's default value.
  11. Add a Filter criteria to the view:
    1. Select the filter Content: Title.
    2. Expose this filter to visitors, to allow them to change it = TRUE
    3. Filter type to expose = Single filter
    4. Required = FALSE
    5. Label = Title contains
    6. Leave Description empty.
    7. Operator = Contains
    8. Leave Value empty.
    9. Expose operator = FALSE
    10. Remember the last selection = FALSE
    11. Leave Administrative title empty.
    12. Leave Filter identifier at it's default value.
  12. Add a Field to the view. Select the field Content: Title. Use the default settings.
  13. Add a Field to the view. Select the field Content: Client contact's name. Use the default settings.
  14. Add a No results behavior to the view. Select the Global: Text area behavior. Enter No results found. for the text. Use the default settings for everything else.
  15. Save the view.
  16. Scroll to the preview area.
  17. In the Title contains field, enter es and click Apply. You see the row with the title "Test".
  18. In the Client contact's name field, enter osep and click Apply.

Expected result: I see the row with the Client contact's name "Dr. Joseph Q Bloggs III, K.B.E.".
Actual result: I see "No results found."

Note the query adds an extra space before "osep", i.e.: '% osep%'.

Proposed resolution

Remove the extra space in the LIKE query fragments in \name_handler_filter_name_fulltext::op_contains() and \name_handler_filter_name_fulltext::op_word() inside includes/name_handler_filter_name_fulltext.inc.

Remaining tasks

  1. Add steps to reproduce
  2. Write a patch
  3. Review and RTBC
  4. Commit

User interface changes

None.

API changes

None.

Data model changes

None.

Comments

mparker17’s picture

Issue summary: View changes

Added steps to reproduce.

Leaving assigned to myself so I can write a patch.

mparker17’s picture

Assigned: mparker17 » Unassigned
Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new1.62 KB

Patch attached. Reviews welcome.

alan d.’s picture

Seems to be a duplicate of #2090789: Fulltext Filter does not match surname. In general this query is poor, but haven't investigated anything better :/

This came up in https://drupal.org/node/1369618#comment-5542738 to ensure that search for cd didn't match abcd, but matched cdef.

SELECT CONCAT('"', (LOWER(CONCAT(' ', COALESCE(field_data_field_name_test.field_name_test_title, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_given, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_middle, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_family, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_generational, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_credentials, '')))), '"') FROM `field_data_field_name_test` 

produces " john doe ", so both '% doe%' and '%doe%' would match this string. Are you sure that you didn't have both first and second names in the search? ie: "%john doe%" != " john doe "

And was the comma from the markup / output? If so, then it wouldn't match (Dr. Joseph Q Bloggs III, K.B.E.)

mparker17’s picture

Seems to be a duplicate of #2090789: Fulltext Filter does not match surname.

Agreed; although this patch fixes the issue in both the "contains" and the "contains word" filters.

In general this query is poor, but haven't investigated anything better :/

For whatever it's worth, I don't see a better way of accomplishing the same goal :)

mparker17’s picture

Issue summary: View changes

SELECT CONCAT('"', (LOWER(CONCAT(' ', COALESCE(field_data_field_name_test.field_name_test_title, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_given, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_middle, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_family, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_generational, ''), ' ', COALESCE(field_data_field_name_test.field_name_test_credentials, '')))), '"') FROM `field_data_field_name_test`

produces " john doe ", so both '% doe%' and '%doe%' would match this string. Are you sure that you didn't have both first and second names in the search? ie: "%john doe%" != " john doe "

This is a good point... I chose a poor test case. I've updated the test case to use "osep" instead.

mparker17’s picture

Issue summary: View changes

This came up in https://drupal.org/node/1369618#comment-5542738 to ensure that search for cd didn't match abcd, but matched cdef.

I think I see what they were trying to do here; but I'd argue that they're proposing a "Starts with" filter. The filters I'm patching are currently labelled as a "Contains" and a "Contains word" filter, and are inconsistent with Views' "Contains" filter.

I've updated the steps to reproduce to add an exposed filter to the view for the Title field, set it's operator to "Contains", and test it, to demonstrate that the Name module's "Contains" filter behaviour differs from Views' "Contains" filter behaviour.

joelpittet’s picture

Priority: Normal » Major

If this is committed, please credit @webflo from #2090789: Fulltext Filter does not match surname

joelpittet’s picture

Status: Needs review » Closed (duplicate)

closing as a duplicate of #2090789: Fulltext Filter does not match surname, please move your patch to include the op_word as well.