diff --git a/search_api.theme.inc b/search_api.theme.inc
index 080aa02..53d29ec 100644
--- a/search_api.theme.inc
+++ b/search_api.theme.inc
@@ -296,7 +296,7 @@ function theme_search_api_index($variables) {
       // directly to the server.
       // @todo Add a cleaner way for doing this (i.e., skipping preprocessing).
       $query = $index->query();
-      $query->fields(array())->range(0, 0);
+      $query->range(0, 0);
       $response = $server->search($query);
 
       // Build the server index status translation variables.
diff --git a/search_api_db/src/Plugin/search_api/backend/Database.php b/search_api_db/src/Plugin/search_api/backend/Database.php
index cd28c5c..11565bb 100644
--- a/search_api_db/src/Plugin/search_api/backend/Database.php
+++ b/search_api_db/src/Plugin/search_api/backend/Database.php
@@ -1404,11 +1404,10 @@ class Database extends BackendPluginBase {
         );
       }
 
-      $fulltext_fields = $query->getFields();
+      $fulltext_fields = $this->getQueryFulltextFields($query);
       if ($fulltext_fields) {
-        $_fulltext_fields = $fulltext_fields;
-        $fulltext_fields = array();
-        foreach ($_fulltext_fields as $name) {
+        $fulltext_field_information = array();
+        foreach ($fulltext_fields as $name) {
           if (!isset($fields[$name])) {
             throw new SearchApiException(SafeMarkup::format('Unknown field @field specified as search target.', array('@field' => $name)));
           }
@@ -1417,10 +1416,10 @@ class Database extends BackendPluginBase {
             $type = $types[$fields[$name]['type']]['label'];
             throw new SearchApiException(SafeMarkup::format('Cannot perform fulltext search on field @field of type @type.', array('@field' => $name, '@type' => $type)));
           }
-          $fulltext_fields[$name] = $fields[$name];
+          $fulltext_field_information[$name] = $fields[$name];
         }
 
-        $db_query = $this->createKeysQuery($keys, $fulltext_fields, $fields, $query->getIndex());
+        $db_query = $this->createKeysQuery($keys, $fulltext_field_information, $fields, $query->getIndex());
       }
       else {
         $this->getLogger()->warning('Search keys are given but no fulltext fields are defined.');
@@ -2073,7 +2072,8 @@ class Database extends BackendPluginBase {
       // We need a list of all current results to match the suggestions against.
       // However, since MySQL doesn't allow using a temporary table multiple
       // times in one query, we regrettably have to do it this way.
-      if (count($query->getFields()) > 1) {
+      $fulltext_fields = $this->getQueryFulltextFields($query);
+      if (count($fulltext_fields) > 1) {
         $all_results = $db_query->execute()->fetchCol();
         // Compute the total number of results so we can later sort out matches
         // that occur too often.
@@ -2100,7 +2100,7 @@ class Database extends BackendPluginBase {
 
       /** @var \Drupal\Core\Database\Query\SelectInterface|null $word_query */
       $word_query = NULL;
-      foreach ($query->getFields() as $field) {
+      foreach ($fulltext_fields as $field) {
         if (!isset($fields[$field]) || !Utility::isTextType($fields[$field]['type'])) {
           continue;
         }
diff --git a/search_api_db/src/Tests/BackendTest.php b/search_api_db/src/Tests/BackendTest.php
index 4fd386f..85d691c 100644
--- a/search_api_db/src/Tests/BackendTest.php
+++ b/search_api_db/src/Tests/BackendTest.php
@@ -211,7 +211,7 @@ class BackendTest extends EntityUnitTestBase {
     if ($keys) {
       $query->keys($keys);
       if ($fields) {
-        $query->fields($fields);
+        $query->setFulltextFields($fields);
       }
     }
     foreach ($filters as $filter) {
diff --git a/src/Backend/BackendPluginBase.php b/src/Backend/BackendPluginBase.php
index dad1304..bb1e906 100644
--- a/src/Backend/BackendPluginBase.php
+++ b/src/Backend/BackendPluginBase.php
@@ -7,7 +7,9 @@
 
 namespace Drupal\search_api\Backend;
 
+use Drupal\Core\Annotation\Action;
 use Drupal\search_api\Entity\Server;
+use Drupal\search_api\Query\QueryInterface;
 use Drupal\search_api\SearchApiException;
 use Drupal\search_api\IndexInterface;
 use Drupal\search_api\Plugin\ConfigurablePluginBase;
@@ -180,4 +182,23 @@ abstract class BackendPluginBase extends ConfigurablePluginBase implements Backe
     }
   }
 
+  /**
+   * Retrieves the effective fulltext fields from the query.
+   *
+   * Automatically translates a NULL value in the query object to all fulltext
+   * fields in the search index.
+   *
+   * @param \Drupal\search_api\Query\QueryInterface $query
+   *   The search query.
+   *
+   * @return string[]
+   *   The fulltext fields in which to search for the search keys.
+   *
+   * @see \Drupal\search_api\Query\QueryInterface::getFulltextFields()
+   */
+  protected function getQueryFulltextFields(QueryInterface $query) {
+    $fulltext_fields = $query->getFulltextFields();
+    return $fulltext_fields === NULL ? $query->getIndex()->getFulltextFields() : $fulltext_fields;
+  }
+
 }
diff --git a/src/Plugin/views/argument/SearchApiFulltext.php b/src/Plugin/views/argument/SearchApiFulltext.php
index 443ed0f..e98b292 100644
--- a/src/Plugin/views/argument/SearchApiFulltext.php
+++ b/src/Plugin/views/argument/SearchApiFulltext.php
@@ -74,7 +74,7 @@ class SearchApiFulltext extends SearchApiArgument {
    */
   public function query($group_by = FALSE) {
     if ($this->options['fields']) {
-      $this->query->fields($this->options['fields']);
+      $this->query->setFulltextFields($this->options['fields']);
     }
     if ($this->options['conjunction'] != 'AND') {
       $this->query->setOption('conjunction', $this->options['conjunction']);
diff --git a/src/Plugin/views/filter/SearchApiFulltext.php b/src/Plugin/views/filter/SearchApiFulltext.php
index 57bda37..c00edb2 100644
--- a/src/Plugin/views/filter/SearchApiFulltext.php
+++ b/src/Plugin/views/filter/SearchApiFulltext.php
@@ -163,7 +163,7 @@ class SearchApiFulltext extends SearchApiFilterText {
     // back to mere filtering.
     $filter = $this->options['mode'] == 'filter';
     if (!$filter) {
-      $old = $this->query->getFields();
+      $old = $this->query->getFulltextFields();
       $filter = $old && (array_diff($old, $fields) || array_diff($fields, $old));
     }
 
@@ -183,7 +183,7 @@ class SearchApiFulltext extends SearchApiFilterText {
       $this->query->setOption('conjunction', 'OR');
     }
 
-    $this->query->fields($fields);
+    $this->query->setFulltextFields($fields);
     $old = $this->query->getKeys();
     $old_original = $this->query->getOriginalKeys();
     $this->query->keys($this->value);
diff --git a/src/Plugin/views/query/SearchApiQuery.php b/src/Plugin/views/query/SearchApiQuery.php
index afbdde4..d963786 100644
--- a/src/Plugin/views/query/SearchApiQuery.php
+++ b/src/Plugin/views/query/SearchApiQuery.php
@@ -566,12 +566,11 @@ class SearchApiQuery extends QueryPluginBase {
    * @throws \Drupal\search_api\SearchApiException
    *   Thrown if one of the fields isn't of type "text".
    *
-   * @see \Drupal\search_api\Query\QueryInterface::fields()
+   * @see \Drupal\search_api\Query\QueryInterface::setFulltextFields()
    */
-  // @todo Allow calling with NULL, and maybe rename to setFulltextFields().
-  public function fields(array $fields) {
+  public function setFulltextFields($fields = NULL) {
     if (!$this->shouldAbort()) {
-      $this->query->fields($fields);
+      $this->query->setFulltextFields($fields);
     }
     return $this;
   }
@@ -739,17 +738,16 @@ class SearchApiQuery extends QueryPluginBase {
   /**
    * Retrieves the fulltext fields that will be searched for the search keys.
    *
-   * @return array
+   * @return string[]|null
    *   An array containing the fields that should be searched for the search
    *   keys.
    *
-   * @see fields()
-   *
-   * @see \Drupal\search_api\Query\QueryInterface::getFields()
+   * @see setFulltextFields()
+   * @see \Drupal\search_api\Query\QueryInterface::getFulltextFields()
    */
-  public function &getFields() {
+  public function &getFulltextFields() {
     if (!$this->shouldAbort()) {
-      return $this->query->getFields();
+      return $this->query->getFulltextFields();
     }
     $ret = NULL;
     return $ret;
diff --git a/src/Query/Query.php b/src/Query/Query.php
index 265e130..14957dc 100644
--- a/src/Query/Query.php
+++ b/src/Query/Query.php
@@ -239,7 +239,7 @@ class Query implements QueryInterface {
   /**
    * {@inheritdoc}
    */
-  public function fields(array $fields) {
+  public function setFulltextFields(array $fields = NULL) {
     $fulltext_fields = $this->index->getFulltextFields();
     foreach (array_diff($fields, $fulltext_fields) as $field_id) {
       throw new SearchApiException(SafeMarkup::format('Trying to search on field @field which is no indexed fulltext field.', array('@field' => $field_id)));
@@ -319,11 +319,6 @@ class Query implements QueryInterface {
     if (!$this->preExecuteRan) {
       $this->preExecuteRan = TRUE;
 
-      // Add fulltext fields, unless set
-      if ($this->fields === NULL) {
-        $this->fields = $this->index->getFulltextFields();
-      }
-
       // Preprocess query.
       $this->index->preprocessSearchQuery($this);
 
@@ -370,7 +365,7 @@ class Query implements QueryInterface {
   /**
    * {@inheritdoc}
    */
-  public function &getFields() {
+  public function &getFulltextFields() {
     return $this->fields;
   }
 
diff --git a/src/Query/QueryInterface.php b/src/Query/QueryInterface.php
index 1446945..169c9ba 100644
--- a/src/Query/QueryInterface.php
+++ b/src/Query/QueryInterface.php
@@ -85,8 +85,7 @@ interface QueryInterface {
    * @throws \Drupal\search_api\SearchApiException
    *   Thrown if one of the fields isn't a fulltext field.
    */
-  // @todo Allow calling with NULL, and maybe rename to setFulltextFields().
-  public function fields(array $fields);
+  public function setFulltextFields(array $fields = NULL);
 
   /**
    * Adds a subfilter to this query's filter.
@@ -231,13 +230,13 @@ interface QueryInterface {
   /**
    * Retrieves the fulltext fields that will be searched for the search keys.
    *
-   * @return string[]
+   * @return string[]|null
    *   An array containing the fields that should be searched for the search
-   *   keys.
+   *   keys, or NULL if all indexed fulltext fields should be used.
    *
-   * @see fields()
+   * @see setFulltextFields()
    */
-  public function &getFields();
+  public function &getFulltextFields();
 
   /**
    * Retrieves the filter object associated with this search query.
