Hi,

I have a kind of complex case, but I think I've found an instance where a necessary JOIN condition isn't being added to the query generated by Views. I've dug around for a few hours in the code, and while I couldn't find the place the necessary code is missing, I know what's wrong and have figured out how to fix it with a hook_views_query_alter(). Here's what I have:

I'm using the File Entity module (Drupal 7) to have fieldable files. My site includes a taxonomy vocabulary for primate taxa (family, subfamily, genus, species, etc.), where each primate taxon is a Drupal taxonomy term. I also have images of the primate taxa, but since each image needs to have its own fields (caption, photo contributor, other information), images are standalone File entities, each of which has a Taxonomy Term Reference field containing the primate taxon the image represents.

Here's what I needed to do: build a View that takes a file ID for an image as an argument, then retrieve the taxonomy term (primate species) for that image. Next, find all other images of that same primate species and display them as well.

My View uses File as its base field and takes File: File ID as an argument. I then added a Relationship for the field containing the taxonomy term (Field: Primate Taxa). I then added the relationship "Taxonomy Term: File Using Primate Taxa" and set it to use the taxonomy term relationship I mentioned in the last sentence. I then set to display the images from the file relationship. What I got, though, included a bunch of wrong images.

I'm using the "Primate Taxa" field for more than just image-taxonomy relationships; several types of nodes on my site use the field as well. What's happening is that the View isn't ensuring that items from the Field API table for the taxonomy term reference field have entity_type == 'file.' Instead, I'm getting random files that happen to have FIDs that are the same as NIDs stored in the same Field API table.

Here's how I fixed the problem via a hook_views_query_alter():


function MODULE_views_query_alter(&$view, &$query) {
      foreach($query->table_queue as $name => &$data){
		if (!empty($data['join']) && !empty($data['join']->table) && !empty($data['join']->field)
			&& !empty($data['join']->left_field)){
			
			if ($data['join']->table == 'file_managed' && $data['join']->field == 'fid' &&
				$data['join']->left_field == 'entity_id'){
				
				$table_alias = $data['join']->left_table;
				
				// Rough check: try to make sure the table is a Field API table.
				if (strpos($table_alias, 'field_data_') === FALSE){
					continue;
				}

				$join = &$query->table_queue[$table_alias]['join'];
				if (!isset($join->extra)){
					$join->extra = array();
				}
				$join->extra[] = array(
					'field' => 'entity_type',
					'value' => 'file',
				);
	
			}
		}
	}
}

Alternatively, instead of adding the "extra" to the Join object, it also works to just do

$query->add_where(0, "$table_alias.entity_type", 'file'); 

Please let me know if there's any more information I can provide - it looks like whatever is setting up the views_join objects for connecting Field API tables to the file_managed table is forgetting to add the condition to check for the entity_id.

Thanks for your help,
Nathan

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

Can you please attach the export and the generated sql as well?
Every minute we don't have to spent to reproduce the problem will probably be put into fixing the problem.
Additional you have to know that it's actual hard to reproduce such errors without doing something wrong.

dawehner’s picture

Status: Active » Postponed (maintainer needs more info)

.

nkschaefer’s picture

Status: Postponed (maintainer needs more info) » Active
FileSize
2.13 KB
76.09 KB

Okay - I've attached the exported View code and the SQL it generated. Unfortunately, this View is kind of complicated and probably dependent on a fair amount of customized stuff I have on my site - the gist of the problem, again, is that I'm joining these tables:

file_managed => taxonomy term reference field
=> taxonomy_term_data
=> the same taxonomy term reference field
=> file_managed
=> taxonomy_vocabulary

and whenever file_managed is joined to the taxonomy_term_reference field, there is no check that entity_type == 'file' on the taxonomy_term_reference field.

In the attached View code, the display causing the problem is called "Thumbnails;" that's the display for which I attached the SQL output.

nkschaefer’s picture

I also dug around more and found what I think is the problem, and created a patch against the 7.x.-3.x-dev branch.

The problem stems with the relationship handler "views_handler_relationship_entity_reverse" -- this patch adds conditions to the JOINs that handler creates to ensure that the field "entity_type" is consistent when joining Field API tables to base tables.

Please see the attached patch.

Thanks,
Nathan

dawehner’s picture

Status: Active » Needs review

Please always set the status to "needs review" unless you want your patch to be ignored :)

dawehner’s picture

Status: Needs review » Fixed

This patch looks fine! Committed to 7.x-3.x

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

Edit: changed "return" statement in code to "continue," which makes more sense.