diff --git a/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php b/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php
index 12261b4..b8205c5 100644
--- a/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php
+++ b/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php
@@ -37,6 +37,10 @@ public function usesGroupBy() {
   /**
    * {@inheritdoc}
    */
+  public function isComputed() {
+    return TRUE;
+  }
+
   protected function defineOptions() {
     $options = parent::defineOptions();
 
@@ -150,9 +154,4 @@ public function render(ResultRow $values) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function query() { }
-
 }
diff --git a/core/modules/system/src/Plugin/views/field/BulkForm.php b/core/modules/system/src/Plugin/views/field/BulkForm.php
index 9d62e84..db3b740 100644
--- a/core/modules/system/src/Plugin/views/field/BulkForm.php
+++ b/core/modules/system/src/Plugin/views/field/BulkForm.php
@@ -432,6 +432,13 @@ public function clickSortable() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function isComputed() {
+    return TRUE;
+  }
+
+  /**
    * Wraps drupal_set_message().
    */
   protected function drupalSetMessage($message = NULL, $type = 'status', $repeat = FALSE) {
diff --git a/core/modules/views/src/Plugin/views/field/Counter.php b/core/modules/views/src/Plugin/views/field/Counter.php
index aba51d5..a715840 100644
--- a/core/modules/views/src/Plugin/views/field/Counter.php
+++ b/core/modules/views/src/Plugin/views/field/Counter.php
@@ -31,6 +31,10 @@ public function usesGroupBy() {
   /**
    * {@inheritdoc}
    */
+  public function isComputed() {
+    return TRUE;
+  }
+
   protected function defineOptions() {
     $options = parent::defineOptions();
     $options['counter_start'] = array('default' => 1);
@@ -55,13 +59,6 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
   /**
    * {@inheritdoc}
    */
-  public function query() {
-    // do nothing -- to override the parent query.
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function getValue(ResultRow $values, $field = NULL) {
     // Note:  1 is subtracted from the counter start value below because the
     // counter value is incremented by 1 at the end of this function.
diff --git a/core/modules/views/src/Plugin/views/field/Custom.php b/core/modules/views/src/Plugin/views/field/Custom.php
index 55f2353..fae6147 100644
--- a/core/modules/views/src/Plugin/views/field/Custom.php
+++ b/core/modules/views/src/Plugin/views/field/Custom.php
@@ -31,8 +31,8 @@ public function usesGroupBy() {
   /**
    * {@inheritdoc}
    */
-  public function query() {
-    // do nothing -- to override the parent query.
+  public function isComputed() {
+    return TRUE;
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/field/FieldHandlerInterface.php b/core/modules/views/src/Plugin/views/field/FieldHandlerInterface.php
index 6836c73..65433ea 100644
--- a/core/modules/views/src/Plugin/views/field/FieldHandlerInterface.php
+++ b/core/modules/views/src/Plugin/views/field/FieldHandlerInterface.php
@@ -33,6 +33,20 @@ public function clickSort($order);
   public function clickSortable();
 
   /**
+   * Determines if this field is computed or not.
+   *
+   * The default query behavior will not be invoked if this is FALSE.
+   *
+   * The base implementation of this method always returns FALSE and
+   * no property is provided to override it. This is because implementing
+   * a computed field always involves creating a subclass. Providing a
+   * 'computed' property was thought to be more dangerous than useful.
+   *
+   * @return bool
+   */
+  public function isComputed();
+
+  /**
    * Gets this field's label.
    */
   public function label();
diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
index e4058ef..9e47b96 100644
--- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
@@ -138,12 +138,15 @@ protected function allowAdvancedRender() {
    * Called to add the field to a query.
    */
   public function query() {
-    $this->ensureMyTable();
-    // Add the field.
-    $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
-    $this->field_alias = $this->query->addField($this->tableAlias, $this->realField, NULL, $params);
+    // Computed fields have no business with the query.
+    if (!$this->isComputed()) {
+      $this->ensureMyTable();
+      // Add the field.
+      $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
+      $this->field_alias = $this->query->addField($this->tableAlias, $this->realField, NULL, $params);
 
-    $this->addAdditionalFields();
+      $this->addAdditionalFields();
+    }
   }
 
   /**
@@ -225,6 +228,13 @@ public function clickSortable() {
   /**
    * {@inheritdoc}
    */
+  public function isComputed() {
+    return FALSE;
+  }
+
+  /**
+   * Get this field's label.
+   */
   public function label() {
     if (!isset($this->options['label'])) {
       return '';
diff --git a/core/modules/views/src/Plugin/views/field/LinkBase.php b/core/modules/views/src/Plugin/views/field/LinkBase.php
index 6ffc304..bef72c8 100644
--- a/core/modules/views/src/Plugin/views/field/LinkBase.php
+++ b/core/modules/views/src/Plugin/views/field/LinkBase.php
@@ -126,6 +126,13 @@ public function query() {
   /**
    * {@inheritdoc}
    */
+  public function isComputed() {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function render(ResultRow $row) {
     $access = $this->checkUrlAccess($row);
     $build = ['#markup' => $access->isAllowed() ? $this->renderLink($row) : ''];
diff --git a/core/modules/views/src/Plugin/views/field/Links.php b/core/modules/views/src/Plugin/views/field/Links.php
index 93c2081..312ab25 100644
--- a/core/modules/views/src/Plugin/views/field/Links.php
+++ b/core/modules/views/src/Plugin/views/field/Links.php
@@ -28,6 +28,13 @@ public function usesGroupBy() {
   /**
    * {@inheritdoc}
    */
+  public function isComputed() {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function defineOptions() {
     $options = parent::defineOptions();
 
@@ -95,11 +102,4 @@ protected function getLinks() {
 
     return $links;
   }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function query() {
-  }
-
 }
diff --git a/core/modules/views/src/Plugin/views/filter/Combine.php b/core/modules/views/src/Plugin/views/filter/Combine.php
index a0889c9..8d95eb8 100644
--- a/core/modules/views/src/Plugin/views/filter/Combine.php
+++ b/core/modules/views/src/Plugin/views/filter/Combine.php
@@ -38,9 +38,9 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     if ($this->view->style_plugin->usesFields()) {
       $options = array();
       foreach ($this->view->display_handler->getHandlers('field') as $name => $field) {
-        // Only allow clickSortable fields. Fields without clickSorting will
-        // probably break in the Combine filter.
-        if ($field->clickSortable()) {
+        // Don't allow computed fields. Computed fields will break the Combine
+        // filter.
+        if (!$field->isComputed()) {
           $options[$name] = $field->adminLabel(TRUE);
         }
       }
@@ -112,11 +112,8 @@ public function validate() {
         $errors[] = $this->t('Field %field set in %filter is not set in this display.', array('%field' => $id, '%filter' => $this->adminLabel()));
         break;
       }
-      elseif (!$fields[$id]->clickSortable()) {
-        // Combined field filter only works with simple fields. If the field is
-        // not click sortable we can assume it is not a simple field.
-        // @todo change this check to isComputed. See
-        // https://www.drupal.org/node/2349465
+      elseif ($fields[$id]->isComputed()) {
+        // Combined filter breaks with computed fields.
         $errors[] = $this->t('Field %field set in %filter is not usable for this filter type. Combined field filter only works for simple fields.', array('%field' => $fields[$id]->adminLabel(), '%filter' => $this->adminLabel()));
       }
     }
diff --git a/core/modules/views/src/Tests/Handler/FieldKernelTest.php b/core/modules/views/src/Tests/Handler/FieldKernelTest.php
index 815b1ec..9e3df60 100644
--- a/core/modules/views/src/Tests/Handler/FieldKernelTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldKernelTest.php
@@ -741,6 +741,19 @@ public function testClickSortable() {
   }
 
   /**
+   * Tests the isComputed method.
+   */
+  public function testIsComputed() {
+    // Test that isComputed is FALSE by default.
+    $item = array(
+      'table' => 'views_test_data',
+      'field' => 'name',
+    );
+    $plugin = $this->container->get('plugin.manager.views.field')->getHandler($item);
+    $this->assertFALSE($plugin->isComputed(), 'FALSE as a default value is correct.');
+  }
+
+  /**
    * Tests the trimText method.
    */
   public function testTrimText() {
