Index: wp-includes/taxonomy.php
===================================================================
--- wp-includes/taxonomy.php	(revision 16538)
+++ wp-includes/taxonomy.php	(working copy)
@@ -526,7 +526,17 @@
 	$join = '';
 	$where = '';
 	$i = 0;
+
+	if ( isset( $tax_query['relation'] ) && strtoupper( $tax_query['relation'] ) == 'OR' ) {
+		$relation = 'OR';
+	} else {
+		$relation = 'AND';
+	}
+
 	foreach ( $tax_query as $query ) {
+		if ( ! is_array( $query ) )
+			continue;
+
 		extract( wp_parse_args( $query, array(
 			'taxonomy' => array(),
 			'terms' => array(),
@@ -566,9 +576,14 @@
 		}
 
 		if ( 'IN' == $operator ) {
-			if ( empty( $terms ) )
-				return array( 'join' => '', 'where' => ' AND 0 = 1');
 
+			if ( empty( $terms ) ) {
+				if ( 'OR' == $relation )
+					continue;
+				else
+					return array( 'join' => '', 'where' => ' AND 0 = 1' );
+			}
+
 			$terms = implode( ',', $terms );
 
 			$alias = $i ? 'tt' . $i : $wpdb->term_relationships;
@@ -577,24 +592,33 @@
 			$join .= $i ? " AS $alias" : '';
 			$join .= " ON ($primary_table.$primary_id_column = $alias.object_id)";
 
-			$where .= " AND $alias.term_taxonomy_id $operator ($terms)";
+			if ( $i )
+				$where .= " $relation ";
 
-			$i++;
+			$where .= "$alias.term_taxonomy_id $operator ($terms)";
 		}
 		elseif ( 'NOT IN' == $operator ) {
+
 			if ( empty( $terms ) )
 				continue;
 
 			$terms = implode( ',', $terms );
 
-			$where .= " AND $primary_table.$primary_id_column NOT IN (
-				SELECT object_id 
-				FROM $wpdb->term_relationships 
+			if ( $i )
+				$where .= " $relation ";
+
+			$where .= "$primary_table.$primary_id_column NOT IN (
+				SELECT object_id
+				FROM $wpdb->term_relationships
 				WHERE term_taxonomy_id IN ($terms)
 			)";
 		}
+
+		$i++;
 	}
 
+	$where = ' AND ( ' . $where . ' )';
+
 	return compact( 'join', 'where' );
 }
 
