superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From johnbod...@apache.org
Subject [incubator-superset] branch master updated: [adhoc-filters] Adding adhoc-filters to all viz types (#5206)
Date Mon, 18 Jun 2018 22:43:20 GMT
This is an automated email from the ASF dual-hosted git repository.

johnbodley pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new d483ed1  [adhoc-filters] Adding adhoc-filters to all viz types (#5206)
d483ed1 is described below

commit d483ed121ca0fc5b90eac65f5e39cd6cc9359331
Author: John Bodley <4567245+john-bodley@users.noreply.github.com>
AuthorDate: Mon Jun 18 15:43:18 2018 -0700

    [adhoc-filters] Adding adhoc-filters to all viz types (#5206)
---
 babel-node                                         |   0
 package-lock.json                                  | 743 +++++++++++++++++++++
 superset/assets/backendSync.json                   |  24 -
 .../components/AlteredSliceTag_spec.jsx            |  80 ++-
 .../explore/components/AdhocFilterControl_spec.jsx |  52 --
 .../components/ControlPanelsContainer_spec.jsx     |   2 +-
 .../explore/components/FilterControl_spec.jsx      | 248 -------
 .../javascripts/explore/components/Filter_spec.jsx | 115 ----
 superset/assets/src/components/AlteredSliceTag.jsx |  12 +-
 .../components/controls/AdhocFilterControl.jsx     |  78 +--
 .../src/explore/components/controls/Filter.jsx     | 187 ------
 .../explore/components/controls/FilterControl.jsx  | 155 -----
 .../src/explore/components/controls/index.js       |   2 -
 superset/assets/src/explore/controls.jsx           |  50 --
 superset/assets/src/explore/store.js               |   8 -
 superset/assets/src/explore/visTypes.js            | 128 ++--
 .../versions/bddc498dd179_adhoc_filters.py         |  97 +++
 superset/translations/de/LC_MESSAGES/messages.po   |   1 -
 superset/translations/en/LC_MESSAGES/messages.po   |   1 -
 superset/translations/es/LC_MESSAGES/messages.po   |   1 -
 superset/translations/fr/LC_MESSAGES/messages.po   |   1 -
 superset/translations/it/LC_MESSAGES/messages.po   |   1 -
 superset/translations/ja/LC_MESSAGES/messages.po   |   1 -
 superset/translations/messages.pot                 |   1 -
 .../translations/pt_BR/LC_MESSAGES/messages.po     |   1 -
 superset/translations/ru/LC_MESSAGES/messages.po   |   1 -
 superset/translations/zh/LC_MESSAGES/messages.po   |   1 -
 superset/utils.py                                  |   1 -
 28 files changed, 1012 insertions(+), 980 deletions(-)

diff --git a/babel-node b/babel-node
new file mode 100644
index 0000000..e69de29
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..dea4bad
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,743 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+    },
+    "ansi-styles": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+    },
+    "babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "requires": {
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
+      }
+    },
+    "babel-helper-builder-binary-assignment-operator-visitor": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+      "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+      "dev": true,
+      "requires": {
+        "babel-helper-explode-assignable-expression": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-call-delegate": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+      "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+      "requires": {
+        "babel-helper-hoist-variables": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-define-map": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+      "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+      "requires": {
+        "babel-helper-function-name": "^6.24.1",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-helper-explode-assignable-expression": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+      "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+      "dev": true,
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-function-name": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+      "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+      "requires": {
+        "babel-helper-get-function-arity": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-get-function-arity": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+      "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-hoist-variables": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+      "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-optimise-call-expression": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+      "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-regex": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+      "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-helper-remap-async-to-generator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
+      "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
+      "dev": true,
+      "requires": {
+        "babel-helper-function-name": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-helper-replace-supers": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+      "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+      "requires": {
+        "babel-helper-optimise-call-expression": "^6.24.1",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-messages": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-check-es2015-constants": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+      "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-dynamic-import-node": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-1.2.0.tgz",
+      "integrity": "sha512-yeDwKaLgGdTpXL7RgGt5r6T4LmnTza/hUn5Ul8uZSGGMtEjYo13Nxai7SQaGCTEzUtg9Zq9qJn0EjEr7SeSlTQ==",
+      "requires": {
+        "babel-plugin-syntax-dynamic-import": "^6.18.0"
+      }
+    },
+    "babel-plugin-syntax-async-functions": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+      "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
+      "dev": true
+    },
+    "babel-plugin-syntax-dynamic-import": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+      "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo="
+    },
+    "babel-plugin-syntax-exponentiation-operator": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+      "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
+      "dev": true
+    },
+    "babel-plugin-syntax-trailing-function-commas": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
+      "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
+      "dev": true
+    },
+    "babel-plugin-transform-async-to-generator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
+      "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
+      "dev": true,
+      "requires": {
+        "babel-helper-remap-async-to-generator": "^6.24.1",
+        "babel-plugin-syntax-async-functions": "^6.8.0",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-arrow-functions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+      "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoped-functions": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+      "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoping": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+      "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-template": "^6.26.0",
+        "babel-traverse": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-plugin-transform-es2015-classes": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+      "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+      "requires": {
+        "babel-helper-define-map": "^6.24.1",
+        "babel-helper-function-name": "^6.24.1",
+        "babel-helper-optimise-call-expression": "^6.24.1",
+        "babel-helper-replace-supers": "^6.24.1",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-computed-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+      "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-destructuring": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+      "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-duplicate-keys": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+      "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-for-of": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+      "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-function-name": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+      "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+      "requires": {
+        "babel-helper-function-name": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-literals": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+      "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-amd": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+      "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+      "requires": {
+        "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-commonjs": {
+      "version": "6.26.2",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
+      "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==",
+      "requires": {
+        "babel-plugin-transform-strict-mode": "^6.24.1",
+        "babel-runtime": "^6.26.0",
+        "babel-template": "^6.26.0",
+        "babel-types": "^6.26.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-systemjs": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+      "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+      "requires": {
+        "babel-helper-hoist-variables": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-umd": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+      "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+      "requires": {
+        "babel-plugin-transform-es2015-modules-amd": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-object-super": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+      "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+      "requires": {
+        "babel-helper-replace-supers": "^6.24.1",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-parameters": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+      "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+      "requires": {
+        "babel-helper-call-delegate": "^6.24.1",
+        "babel-helper-get-function-arity": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-template": "^6.24.1",
+        "babel-traverse": "^6.24.1",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-shorthand-properties": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+      "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-spread": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+      "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-sticky-regex": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+      "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+      "requires": {
+        "babel-helper-regex": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-plugin-transform-es2015-template-literals": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+      "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-typeof-symbol": {
+      "version": "6.23.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+      "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-es2015-unicode-regex": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+      "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+      "requires": {
+        "babel-helper-regex": "^6.24.1",
+        "babel-runtime": "^6.22.0",
+        "regexpu-core": "^2.0.0"
+      }
+    },
+    "babel-plugin-transform-exponentiation-operator": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+      "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+      "dev": true,
+      "requires": {
+        "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1",
+        "babel-plugin-syntax-exponentiation-operator": "^6.8.0",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-regenerator": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+      "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+      "requires": {
+        "regenerator-transform": "^0.10.0"
+      }
+    },
+    "babel-plugin-transform-strict-mode": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+      "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+      "requires": {
+        "babel-runtime": "^6.22.0",
+        "babel-types": "^6.24.1"
+      }
+    },
+    "babel-preset-env": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
+      "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==",
+      "dev": true,
+      "requires": {
+        "babel-plugin-check-es2015-constants": "^6.22.0",
+        "babel-plugin-syntax-trailing-function-commas": "^6.22.0",
+        "babel-plugin-transform-async-to-generator": "^6.22.0",
+        "babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
+        "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
+        "babel-plugin-transform-es2015-block-scoping": "^6.23.0",
+        "babel-plugin-transform-es2015-classes": "^6.23.0",
+        "babel-plugin-transform-es2015-computed-properties": "^6.22.0",
+        "babel-plugin-transform-es2015-destructuring": "^6.23.0",
+        "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0",
+        "babel-plugin-transform-es2015-for-of": "^6.23.0",
+        "babel-plugin-transform-es2015-function-name": "^6.22.0",
+        "babel-plugin-transform-es2015-literals": "^6.22.0",
+        "babel-plugin-transform-es2015-modules-amd": "^6.22.0",
+        "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0",
+        "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0",
+        "babel-plugin-transform-es2015-modules-umd": "^6.23.0",
+        "babel-plugin-transform-es2015-object-super": "^6.22.0",
+        "babel-plugin-transform-es2015-parameters": "^6.23.0",
+        "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0",
+        "babel-plugin-transform-es2015-spread": "^6.22.0",
+        "babel-plugin-transform-es2015-sticky-regex": "^6.22.0",
+        "babel-plugin-transform-es2015-template-literals": "^6.22.0",
+        "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0",
+        "babel-plugin-transform-es2015-unicode-regex": "^6.22.0",
+        "babel-plugin-transform-exponentiation-operator": "^6.22.0",
+        "babel-plugin-transform-regenerator": "^6.22.0",
+        "browserslist": "^3.2.6",
+        "invariant": "^2.2.2",
+        "semver": "^5.3.0"
+      }
+    },
+    "babel-preset-es2015": {
+      "version": "6.24.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+      "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+      "requires": {
+        "babel-plugin-check-es2015-constants": "^6.22.0",
+        "babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
+        "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
+        "babel-plugin-transform-es2015-block-scoping": "^6.24.1",
+        "babel-plugin-transform-es2015-classes": "^6.24.1",
+        "babel-plugin-transform-es2015-computed-properties": "^6.24.1",
+        "babel-plugin-transform-es2015-destructuring": "^6.22.0",
+        "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1",
+        "babel-plugin-transform-es2015-for-of": "^6.22.0",
+        "babel-plugin-transform-es2015-function-name": "^6.24.1",
+        "babel-plugin-transform-es2015-literals": "^6.22.0",
+        "babel-plugin-transform-es2015-modules-amd": "^6.24.1",
+        "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
+        "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1",
+        "babel-plugin-transform-es2015-modules-umd": "^6.24.1",
+        "babel-plugin-transform-es2015-object-super": "^6.24.1",
+        "babel-plugin-transform-es2015-parameters": "^6.24.1",
+        "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
+        "babel-plugin-transform-es2015-spread": "^6.22.0",
+        "babel-plugin-transform-es2015-sticky-regex": "^6.24.1",
+        "babel-plugin-transform-es2015-template-literals": "^6.22.0",
+        "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0",
+        "babel-plugin-transform-es2015-unicode-regex": "^6.24.1",
+        "babel-plugin-transform-regenerator": "^6.24.1"
+      }
+    },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "babel-template": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "babel-traverse": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-traverse": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+      "requires": {
+        "babel-code-frame": "^6.26.0",
+        "babel-messages": "^6.23.0",
+        "babel-runtime": "^6.26.0",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0",
+        "debug": "^2.6.8",
+        "globals": "^9.18.0",
+        "invariant": "^2.2.2",
+        "lodash": "^4.17.4"
+      }
+    },
+    "babel-types": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+      "requires": {
+        "babel-runtime": "^6.26.0",
+        "esutils": "^2.0.2",
+        "lodash": "^4.17.4",
+        "to-fast-properties": "^1.0.3"
+      }
+    },
+    "babylon": {
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+      "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
+    },
+    "browserslist": {
+      "version": "3.2.8",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
+      "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
+      "dev": true,
+      "requires": {
+        "caniuse-lite": "^1.0.30000844",
+        "electron-to-chromium": "^1.3.47"
+      }
+    },
+    "caniuse-lite": {
+      "version": "1.0.30000856",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000856.tgz",
+      "integrity": "sha512-x3mYcApHMQemyaHuH/RyqtKCGIYTgEA63fdi+VBvDz8xUSmRiVWTLeyKcoGQCGG6UPR9/+4qG4OKrTa6aSQRKg==",
+      "dev": true
+    },
+    "chalk": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+      "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+      "requires": {
+        "ansi-styles": "^2.2.1",
+        "escape-string-regexp": "^1.0.2",
+        "has-ansi": "^2.0.0",
+        "strip-ansi": "^3.0.0",
+        "supports-color": "^2.0.0"
+      }
+    },
+    "core-js": {
+      "version": "2.5.7",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
+      "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "electron-to-chromium": {
+      "version": "1.3.48",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz",
+      "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+    },
+    "globals": {
+      "version": "9.18.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "js-tokens": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+    },
+    "jsesc": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+      "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+    },
+    "lodash": {
+      "version": "4.17.10",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
+      "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
+    },
+    "loose-envify": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+      "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
+      "requires": {
+        "js-tokens": "^3.0.0"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "private": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+      "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+    },
+    "regenerate": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+      "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
+    },
+    "regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+    },
+    "regenerator-transform": {
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+      "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+      "requires": {
+        "babel-runtime": "^6.18.0",
+        "babel-types": "^6.19.0",
+        "private": "^0.1.6"
+      }
+    },
+    "regexpu-core": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+      "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+      "requires": {
+        "regenerate": "^1.2.1",
+        "regjsgen": "^0.2.0",
+        "regjsparser": "^0.1.4"
+      }
+    },
+    "regjsgen": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="
+    },
+    "regjsparser": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+      "requires": {
+        "jsesc": "~0.5.0"
+      }
+    },
+    "semver": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+      "dev": true
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "requires": {
+        "ansi-regex": "^2.0.0"
+      }
+    },
+    "supports-color": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+      "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+    },
+    "to-fast-properties": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+      "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
+    }
+  }
+}
diff --git a/superset/assets/backendSync.json b/superset/assets/backendSync.json
index 9145cc9..9b82552 100644
--- a/superset/assets/backendSync.json
+++ b/superset/assets/backendSync.json
@@ -1683,18 +1683,6 @@
       "renderTrigger": true,
       "default": ""
     },
-    "where": {
-      "type": "TextControl",
-      "label": "Custom WHERE clause",
-      "default": "",
-      "description": "The text in this box gets included in your query's WHERE clause, as an AND to other criteria. You can include complex expression, parenthesis and anything else supported by the backend it is directed towards."
-    },
-    "having": {
-      "type": "TextControl",
-      "label": "Custom HAVING clause",
-      "default": "",
-      "description": "The text in this box gets included in your query's HAVING clause, as an AND to other criteria. You can include complex expression, parenthesis and anything else supported by the backend it is directed towards."
-    },
     "compare_lag": {
       "type": "TextControl",
       "label": "Comparison Period Lag",
@@ -2628,12 +2616,6 @@
       "default": "",
       "description": "Labels for the marker lines"
     },
-    "filters": {
-      "type": "FilterControl",
-      "label": "",
-      "default": [],
-      "description": ""
-    },
     "annotation_layers": {
       "type": "AnnotationLayerControl",
       "label": "",
@@ -2641,12 +2623,6 @@
       "description": "Annotation Layers",
       "renderTrigger": true
     },
-    "having_filters": {
-      "type": "FilterControl",
-      "label": "",
-      "default": [],
-      "description": ""
-    },
     "slice_id": {
       "type": "HiddenControl",
       "label": "Slice ID",
diff --git a/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx b/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx
index 7994720..8670069 100644
--- a/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx
+++ b/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx
@@ -11,7 +11,15 @@ import TooltipWrapper from '../../../src/components/TooltipWrapper';
 
 const defaultProps = {
   origFormData: {
-    filters: [{ col: 'a', op: '==', val: 'hello' }],
+    adhoc_filters: [
+      {
+        clause: 'WHERE',
+        comparator: 'hello',
+        expressionType: 'SIMPLE',
+        operator: '==',
+        subject: 'a',
+      },
+    ],
     y_axis_bounds: [10, 20],
     column_collection: [{ 1: 'a', b: ['6', 'g'] }],
     bool: false,
@@ -21,7 +29,15 @@ const defaultProps = {
     ever: { a: 'b', c: 'd' },
   },
   currentFormData: {
-    filters: [{ col: 'b', op: 'in', val: ['hello', 'my', 'name'] }],
+    adhoc_filters: [
+      {
+        clause: 'WHERE',
+        comparator: ['hello', 'my', 'name'],
+        expressionType: 'SIMPLE',
+        operator: 'in',
+        subject: 'b',
+      },
+    ],
     y_axis_bounds: [15, 16],
     column_collection: [{ 1: 'a', b: [9, '15'], t: 'gggg' }],
     bool: true,
@@ -33,9 +49,25 @@ const defaultProps = {
 };
 
 const expectedDiffs = {
-  filters: {
-    before: [{ col: 'a', op: '==', val: 'hello' }],
-    after: [{ col: 'b', op: 'in', val: ['hello', 'my', 'name'] }],
+  adhoc_filters: {
+    before: [
+      {
+        clause: 'WHERE',
+        comparator: 'hello',
+        expressionType: 'SIMPLE',
+        operator: '==',
+        subject: 'a',
+      },
+    ],
+    after: [
+      {
+        clause: 'WHERE',
+        comparator: ['hello', 'my', 'name'],
+        expressionType: 'SIMPLE',
+        operator: 'in',
+        subject: 'b',
+      },
+    ],
   },
   y_axis_bounds: {
     before: [10, 20],
@@ -211,25 +243,49 @@ describe('AlteredSliceTag', () => {
     });
 
     it('returns "[]" for empty filters', () => {
-      expect(wrapper.instance().formatValue([], 'filters')).to.equal('[]');
+      expect(wrapper.instance().formatValue([], 'adhoc_filters')).to.equal('[]');
     });
 
     it('correctly formats filters with array values', () => {
       const filters = [
-        { col: 'a', op: 'in', val: ['1', 'g', '7', 'ho'] },
-        { col: 'b', op: 'not in', val: ['hu', 'ho', 'ha'] },
+        {
+          clause: 'WHERE',
+          comparator: ['1', 'g', '7', 'ho'],
+          expressionType: 'SIMPLE',
+          operator: 'in',
+          subject: 'a',
+        },
+        {
+          clause: 'WHERE',
+          comparator: ['hu', 'ho', 'ha'],
+          expressionType: 'SIMPLE',
+          operator: 'not in',
+          subject: 'b',
+        },
       ];
       const expected = 'a in [1, g, 7, ho], b not in [hu, ho, ha]';
-      expect(wrapper.instance().formatValue(filters, 'filters')).to.equal(expected);
+      expect(wrapper.instance().formatValue(filters, 'adhoc_filters')).to.equal(expected);
     });
 
     it('correctly formats filters with string values', () => {
       const filters = [
-        { col: 'a', op: '==', val: 'gucci' },
-        { col: 'b', op: 'LIKE', val: 'moshi moshi' },
+        {
+          clause: 'WHERE',
+          comparator: 'gucci',
+          expressionType: 'SIMPLE',
+          operator: '==',
+          subject: 'a',
+        },
+        {
+          clause: 'WHERE',
+          comparator: 'moshi moshi',
+          expressionType: 'SIMPLE',
+          operator: 'LIKE',
+          subject: 'b',
+        },
       ];
       const expected = 'a == gucci, b LIKE moshi moshi';
-      expect(wrapper.instance().formatValue(filters, 'filters')).to.equal(expected);
+      expect(wrapper.instance().formatValue(filters, 'adhoc_filters')).to.equal(expected);
     });
   });
 });
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx
index 4be8a2e..2123ed7 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx
@@ -33,18 +33,9 @@ const columns = [
   { type: 'DOUBLE', column_name: 'value' },
 ];
 
-const legacyFilter = { col: 'value', op: '>', val: '5' };
-const legacyHavingFilter = { col: 'SUM(value)', op: '>', val: '10' };
-const whereFilterText = 'target in (\'alpha\')';
-const havingFilterText = 'SUM(value) < 20';
-
 const formData = {
-  filters: [legacyFilter],
-  having: havingFilterText,
-  having_filters: [legacyHavingFilter],
   metric: undefined,
   metrics: [sumValueAdhocMetric, savedMetric.saved_metric_name],
-  where: whereFilterText,
 };
 
 function setup(overrides) {
@@ -68,49 +59,6 @@ describe('AdhocFilterControl', () => {
     expect(wrapper.find(OnPasteSelect)).to.have.lengthOf(1);
   });
 
-  it('will translate legacy filters into adhoc filters if no adhoc filters are present', () => {
-    const { wrapper } = setup({ value: undefined });
-    expect(wrapper.state('values')).to.have.lengthOf(4);
-    expect(wrapper.state('values')[0].equals((
-      new AdhocFilter({
-        expressionType: EXPRESSION_TYPES.SIMPLE,
-        subject: 'value',
-        operator: '>',
-        comparator: '5',
-        clause: CLAUSES.WHERE,
-      })
-    ))).to.be.true;
-    expect(wrapper.state('values')[1].equals((
-      new AdhocFilter({
-        expressionType: EXPRESSION_TYPES.SIMPLE,
-        subject: 'SUM(value)',
-        operator: '>',
-        comparator: '10',
-        clause: CLAUSES.HAVING,
-      })
-    ))).to.be.true;
-    expect(wrapper.state('values')[2].equals((
-      new AdhocFilter({
-        expressionType: EXPRESSION_TYPES.SQL,
-        sqlExpression: 'target in (\'alpha\')',
-        clause: CLAUSES.WHERE,
-      })
-    ))).to.be.true;
-    expect(wrapper.state('values')[3].equals((
-      new AdhocFilter({
-        expressionType: EXPRESSION_TYPES.SQL,
-        sqlExpression: 'SUM(value) < 20',
-        clause: CLAUSES.HAVING,
-      })
-    ))).to.be.true;
-  });
-
-  it('will ignore legacy filters if adhoc filters are present', () => {
-    const { wrapper } = setup();
-    expect(wrapper.state('values')).to.have.lengthOf(1);
-    expect(wrapper.state('values')[0]).to.equal(simpleAdhocFilter);
-  });
-
   it('handles saved metrics being selected to filter on', () => {
     const { wrapper, onChange } = setup({ value: [] });
     const select = wrapper.find(OnPasteSelect);
diff --git a/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx b/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
index fb1ea61..64a657e 100644
--- a/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
@@ -26,6 +26,6 @@ describe('ControlPanelsContainer', () => {
   });
 
   it('renders ControlPanelSections', () => {
-    expect(wrapper.find(ControlPanelSection)).to.have.lengthOf(7);
+    expect(wrapper.find(ControlPanelSection)).to.have.lengthOf(6);
   });
 });
diff --git a/superset/assets/spec/javascripts/explore/components/FilterControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/FilterControl_spec.jsx
deleted file mode 100644
index 2b83fff..0000000
--- a/superset/assets/spec/javascripts/explore/components/FilterControl_spec.jsx
+++ /dev/null
@@ -1,248 +0,0 @@
-/* eslint-disable no-unused-expressions */
-import React from 'react';
-import { Button } from 'react-bootstrap';
-import sinon from 'sinon';
-import { expect } from 'chai';
-import { describe, it, beforeEach } from 'mocha';
-import { shallow } from 'enzyme';
-import FilterControl from '../../../../src/explore/components/controls/FilterControl';
-import Filter from '../../../../src/explore/components/controls/Filter';
-
-const $ = window.$ = require('jquery');
-
-const defaultProps = {
-  name: 'not_having_filters',
-  onChange: sinon.spy(),
-  value: [
-    {
-      col: 'col1',
-      op: 'in',
-      val: ['a', 'b', 'd'],
-    },
-    {
-      col: 'col2',
-      op: '==',
-      val: 'Z',
-    },
-  ],
-  datasource: {
-    id: 1,
-    type: 'qtable',
-    filter_select: true,
-    filterable_cols: [['col1', 'col2']],
-    metrics_combo: [
-      ['m1', 'v1'],
-      ['m2', 'v2'],
-    ],
-  },
-};
-
-describe('FilterControl', () => {
-  let wrapper;
-
-  beforeEach(() => {
-    wrapper = shallow(<FilterControl {...defaultProps} />);
-    wrapper.setState({
-      filters: [
-        {
-          valuesLoading: false,
-          valueChoices: ['a', 'b', 'c', 'd', 'e', 'f'],
-        },
-        {
-          valuesLoading: false,
-          valueChoices: ['X', 'Y', 'Z'],
-        },
-        // Need a duplicate since onChange calls are not changing props
-        {
-          valuesLoading: false,
-          valueChoices: ['X', 'Y', 'Z'],
-        },
-      ],
-    });
-  });
-
-  it('renders Filters', () => {
-    expect(
-      React.isValidElement(<FilterControl {...defaultProps} />),
-    ).to.equal(true);
-  });
-
-  it('renders one button and two filters', () => {
-    expect(wrapper.find(Filter)).to.have.lengthOf(2);
-    expect(wrapper.find(Button)).to.have.lengthOf(1);
-  });
-
-  it('adds filter when clicking Add Filter', () => {
-    const addButton = wrapper.find('#add-button');
-    expect(addButton).to.have.lengthOf(1);
-    addButton.simulate('click');
-    expect(defaultProps.onChange).to.have.property('callCount', 1);
-    expect(defaultProps.onChange.getCall(0).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: 'in',
-        val: ['a', 'b', 'd'],
-      },
-      {
-        col: 'col2',
-        op: '==',
-        val: 'Z',
-      },
-      {
-        col: 'col1',
-        op: 'in',
-        val: [],
-      },
-    ]);
-  });
-
-  it('removes a the second filter when its delete button is clicked', () => {
-    expect(wrapper.find(Filter)).to.have.lengthOf(2);
-    wrapper.instance().removeFilter(1);
-    expect(defaultProps.onChange).to.have.property('callCount', 2);
-    expect(defaultProps.onChange.getCall(1).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: 'in',
-        val: ['a', 'b', 'd'],
-      },
-    ]);
-  });
-
-  before(() => {
-    sinon.stub($, 'ajax');
-  });
-
-  after(() => {
-    $.ajax.restore();
-  });
-
-  it('makes a GET request to retrieve value choices', () => {
-    wrapper.instance().fetchFilterValues(0, 'col1');
-    expect($.ajax.getCall(0).args[0].type).to.deep.equal('GET');
-    expect($.ajax.getCall(0).args[0].url).to.deep.equal('/superset/filter/qtable/1/col1/');
-  });
-
-  it('changes filter values when one is removed', () => {
-    wrapper.instance().changeFilter(0, 'val', ['a', 'b']);
-    expect(defaultProps.onChange).to.have.property('callCount', 3);
-    expect(defaultProps.onChange.getCall(2).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: 'in',
-        val: ['a', 'b'],
-      },
-      {
-        col: 'col2',
-        op: '==',
-        val: 'Z',
-      },
-    ]);
-  });
-
-  it('changes filter values when one is added', () => {
-    wrapper.instance().changeFilter(0, 'val', ['a', 'b', 'd', 'e']);
-    expect(defaultProps.onChange).to.have.property('callCount', 4);
-    expect(defaultProps.onChange.getCall(3).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: 'in',
-        val: ['a', 'b', 'd', 'e'],
-      },
-      {
-        col: 'col2',
-        op: '==',
-        val: 'Z',
-      },
-    ]);
-  });
-
-  it('changes op and transforms values', () => {
-    wrapper.instance().changeFilter(0, ['val', 'op'], ['a', '==']);
-    wrapper.instance().changeFilter(1, ['val', 'op'], [['Z'], 'in']);
-    expect(defaultProps.onChange).to.have.property('callCount', 6);
-    expect(defaultProps.onChange.getCall(4).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: '==',
-        val: 'a',
-      },
-      {
-        col: 'col2',
-        op: '==',
-        val: 'Z',
-      },
-    ]);
-    expect(defaultProps.onChange.getCall(5).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: 'in',
-        val: ['a', 'b', 'd'],
-      },
-      {
-        col: 'col2',
-        op: 'in',
-        val: ['Z'],
-      },
-    ]);
-  });
-
-  it('changes column and clears invalid values', () => {
-    wrapper.instance().changeFilter(0, 'col', 'col2');
-    expect(defaultProps.onChange).to.have.property('callCount', 7);
-    expect(defaultProps.onChange.getCall(6).args[0]).to.deep.equal([
-      {
-        col: 'col2',
-        op: 'in',
-        val: [],
-      },
-      {
-        col: 'col2',
-        op: '==',
-        val: 'Z',
-      },
-    ]);
-    wrapper.instance().changeFilter(1, 'col', 'col1');
-    expect(defaultProps.onChange).to.have.property('callCount', 8);
-    expect(defaultProps.onChange.getCall(7).args[0]).to.deep.equal([
-      {
-        col: 'col1',
-        op: 'in',
-        val: ['a', 'b', 'd'],
-      },
-      {
-        col: 'col1',
-        op: '==',
-        val: '',
-      },
-    ]);
-  });
-
-  it('tracks an active filter select ajax request', () => {
-    const spyReq = sinon.spy();
-    $.ajax.reset();
-    $.ajax.onFirstCall().returns(spyReq);
-    wrapper.instance().fetchFilterValues(0, 'col1');
-    expect(wrapper.state().activeRequest).to.equal(spyReq);
-    // Sets active to null after success
-    $.ajax.getCall(0).args[0].success(['opt1', 'opt2', null, '']);
-    expect(wrapper.state().filters[0].valuesLoading).to.equal(false);
-    expect(wrapper.state().filters[0].valueChoices).to.deep.equal(['opt1', 'opt2', null, '']);
-    expect(wrapper.state().activeRequest).to.equal(null);
-  });
-
-
-  it('cancels active request if another is submitted', () => {
-    const spyReq = sinon.spy();
-    spyReq.abort = sinon.spy();
-    $.ajax.reset();
-    $.ajax.onFirstCall().returns(spyReq);
-    wrapper.instance().fetchFilterValues(0, 'col1');
-    expect(wrapper.state().activeRequest).to.equal(spyReq);
-    const spyReq1 = sinon.spy();
-    $.ajax.onSecondCall().returns(spyReq1);
-    wrapper.instance().fetchFilterValues(1, 'col2');
-    expect(spyReq.abort.called).to.equal(true);
-    expect(wrapper.state().activeRequest).to.equal(spyReq1);
-  });
-});
diff --git a/superset/assets/spec/javascripts/explore/components/Filter_spec.jsx b/superset/assets/spec/javascripts/explore/components/Filter_spec.jsx
deleted file mode 100644
index 27425de..0000000
--- a/superset/assets/spec/javascripts/explore/components/Filter_spec.jsx
+++ /dev/null
@@ -1,115 +0,0 @@
-/* eslint-disable no-unused-expressions */
-import React from 'react';
-import Select from 'react-select';
-import { Button } from 'react-bootstrap';
-import sinon from 'sinon';
-import { expect } from 'chai';
-import { describe, it, beforeEach } from 'mocha';
-import { shallow } from 'enzyme';
-import Filter from '../../../../src/explore/components/controls/Filter';
-import SelectControl from '../../../../src/explore/components/controls/SelectControl';
-
-const defaultProps = {
-  changeFilter: sinon.spy(),
-  removeFilter: () => {},
-  filter: {
-    col: null,
-    op: 'in',
-    value: ['val'],
-  },
-  datasource: {
-    id: 1,
-    type: 'qtable',
-    filter_select: false,
-    filterable_cols: ['col1', 'col2'],
-    metrics_combo: [
-      ['m1', 'v1'],
-      ['m2', 'v2'],
-    ],
-  },
-};
-
-describe('Filter', () => {
-  let wrapper;
-
-  beforeEach(() => {
-    wrapper = shallow(<Filter {...defaultProps} />);
-  });
-
-  it('renders Filters', () => {
-    expect(
-      React.isValidElement(<Filter {...defaultProps} />),
-    ).to.equal(true);
-  });
-
-  it('renders two selects, one button and one input', () => {
-    expect(wrapper.find(Select)).to.have.lengthOf(2);
-    expect(wrapper.find(Button)).to.have.lengthOf(1);
-    expect(wrapper.find(SelectControl)).to.have.lengthOf(1);
-    expect(wrapper.find('#select-op').prop('options')).to.have.lengthOf(10);
-  });
-
-  it('renders five op choices for table datasource', () => {
-    const props = Object.assign({}, defaultProps);
-    props.datasource = {
-      id: 1,
-      type: 'druid',
-      filter_select: false,
-      filterable_cols: ['country_name'],
-    };
-    const druidWrapper = shallow(<Filter {...props} />);
-    expect(druidWrapper.find('#select-op').prop('options')).to.have.lengthOf(11);
-  });
-
-  it('renders six op choices for having filter', () => {
-    const props = Object.assign({}, defaultProps);
-    props.having = true;
-    const havingWrapper = shallow(<Filter {...props} />);
-    expect(havingWrapper.find('#select-op').prop('options')).to.have.lengthOf(6);
-  });
-
-  it('calls changeFilter when select is changed', () => {
-    const selectCol = wrapper.find('#select-col');
-    selectCol.simulate('change', { value: 'col' });
-    const selectOp = wrapper.find('#select-op');
-    selectOp.simulate('change', { value: 'in' });
-    const selectVal = wrapper.find(SelectControl);
-    selectVal.simulate('change', { value: 'x' });
-    expect(defaultProps.changeFilter).to.have.property('callCount', 3);
-  });
-
-  it('renders input for regex filters', () => {
-    const props = Object.assign({}, defaultProps);
-    props.filter = {
-      col: null,
-      op: 'regex',
-      value: 'val',
-    };
-    const regexWrapper = shallow(<Filter {...props} />);
-    expect(regexWrapper.find('input')).to.have.lengthOf(1);
-  });
-
-  it('renders `input` for text filters', () => {
-    const props = Object.assign({}, defaultProps);
-    ['>=', '>', '<=', '<'].forEach((op) => {
-      props.filter = {
-        col: 'col1',
-        op,
-        value: 'val',
-      };
-      wrapper = shallow(<Filter {...props} />);
-      expect(wrapper.find('input')).to.have.lengthOf(1);
-    });
-  });
-
-  it('replaces null filter values with empty string in `input`', () => {
-    const props = Object.assign({}, defaultProps);
-    props.filter = {
-      col: 'col1',
-      op: '>=',
-      value: null,
-    };
-    wrapper = shallow(<Filter {...props} />);
-    expect(wrapper.find('input').props().value).to.equal('');
-  });
-});
diff --git a/superset/assets/src/components/AlteredSliceTag.jsx b/superset/assets/src/components/AlteredSliceTag.jsx
index 209e4a9..a317a04 100644
--- a/superset/assets/src/components/AlteredSliceTag.jsx
+++ b/superset/assets/src/components/AlteredSliceTag.jsx
@@ -42,6 +42,10 @@ export default class AlteredSliceTag extends React.Component {
       if (!ofd[fdKey] && !cfd[fdKey]) {
         continue;
       }
+      // Ignore obsolete legacy filters
+      if (['filters', 'having', 'having_filters', 'where'].includes(fdKey)) {
+        continue;
+      }
       if (!isEqual(ofd[fdKey], cfd[fdKey])) {
         diffs[fdKey] = { before: ofd[fdKey], after: cfd[fdKey] };
       }
@@ -56,13 +60,15 @@ export default class AlteredSliceTag extends React.Component {
       return 'N/A';
     } else if (value === null) {
       return 'null';
-    } else if (controls[key] && controls[key].type === 'FilterControl') {
+    } else if (controls[key] && controls[key].type === 'AdhocFilterControl') {
       if (!value.length) {
         return '[]';
       }
       return value.map((v) => {
-        const filterVal = v.val && v.val.constructor === Array ? `[${v.val.join(', ')}]` : v.val;
-        return `${v.col} ${v.op} ${filterVal}`;
+        const filterVal = v.comparator && v.comparator.constructor === Array ?
+          `[${v.comparator.join(', ')}]` :
+          v.comparator;
+        return `${v.subject} ${v.operator} ${filterVal}`;
       }).join(', ');
     } else if (controls[key] && controls[key].type === 'BoundsControl') {
       return `Min: ${value[0]}, Max: ${value[1]}`;
diff --git a/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx b/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
index 3a12c2a..ca0d501 100644
--- a/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
+++ b/superset/assets/src/explore/components/controls/AdhocFilterControl.jsx
@@ -16,12 +16,6 @@ import OnPasteSelect from '../../../components/OnPasteSelect';
 import AdhocFilterOption from '../AdhocFilterOption';
 import FilterDefinitionOption from '../FilterDefinitionOption';
 
-const legacyFilterShape = PropTypes.shape({
-  col: PropTypes.string,
-  op: PropTypes.string,
-  val: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
-});
-
 const propTypes = {
   name: PropTypes.string,
   onChange: PropTypes.func,
@@ -30,12 +24,8 @@ const propTypes = {
   columns: PropTypes.arrayOf(columnType),
   savedMetrics: PropTypes.arrayOf(savedMetricType),
   formData: PropTypes.shape({
-    filters: PropTypes.arrayOf(legacyFilterShape),
-    having: PropTypes.string,
-    having_filters: PropTypes.arrayOf(legacyFilterShape),
     metric: PropTypes.oneOfType([PropTypes.string, adhocMetricType]),
     metrics: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, adhocMetricType])),
-    where: PropTypes.string,
   }),
 };
 
@@ -55,13 +45,15 @@ export default class AdhocFilterControl extends React.Component {
 
   constructor(props) {
     super(props);
-    this.coerceAdhocFilters = this.coerceAdhocFilters.bind(this);
     this.optionsForSelect = this.optionsForSelect.bind(this);
     this.onFilterEdit = this.onFilterEdit.bind(this);
     this.onChange = this.onChange.bind(this);
     this.getMetricExpression = this.getMetricExpression.bind(this);
 
-    const filters = this.coerceAdhocFilters(this.props.value, this.props.formData);
+    const filters = (this.props.value || []).map(filter => (
+      isDictionaryForAdhocFilter(filter) ? new AdhocFilter(filter) : filter
+    ));
+
     this.optionRenderer = VirtualizedRendererWrap(option => (
       <FilterDefinitionOption option={option} />
     ));
@@ -87,7 +79,11 @@ export default class AdhocFilterControl extends React.Component {
       this.setState({ options: this.optionsForSelect(nextProps) });
     }
     if (this.props.value !== nextProps.value) {
-      this.setState({ values: this.coerceAdhocFilters(nextProps.value, nextProps.formData) });
+      this.setState({
+        values: (nextProps.value || []).map(
+          filter => (isDictionaryForAdhocFilter(filter) ? new AdhocFilter(filter) : filter
+        )),
+      });
     }
   }
 
@@ -147,62 +143,6 @@ export default class AdhocFilterControl extends React.Component {
     )).expression;
   }
 
-  coerceAdhocFilters(propsValues, formData) {
-    // this converts filters from the four legacy filter controls into adhoc filters in the case
-    // someone loads an old slice in the explore view
-    if (propsValues) {
-      return propsValues.map(filter => (
-        isDictionaryForAdhocFilter(filter) ? new AdhocFilter(filter) : filter
-      ));
-    }
-    return [
-      ...(formData.filters || []).map(filter => (
-        new AdhocFilter({
-          subject: filter.col,
-          operator: filter.op,
-          comparator: filter.val,
-          clause: CLAUSES.WHERE,
-          expressionType: EXPRESSION_TYPES.SIMPLE,
-          filterOptionName: this.generateConvertedFilterOptionName(),
-        })
-      )),
-      ...(formData.having_filters || []).map(filter => (
-        new AdhocFilter({
-          subject: filter.col,
-          operator: filter.op,
-          comparator: filter.val,
-          clause: CLAUSES.HAVING,
-          expressionType: EXPRESSION_TYPES.SIMPLE,
-          filterOptionName: this.generateConvertedFilterOptionName(),
-        })
-      )),
-      ...[
-        formData.where ?
-        new AdhocFilter({
-          sqlExpression: formData.where,
-          clause: CLAUSES.WHERE,
-          expressionType: EXPRESSION_TYPES.SQL,
-          filterOptionName: this.generateConvertedFilterOptionName(),
-        }) :
-        null,
-      ],
-      ...[
-        formData.having ?
-        new AdhocFilter({
-          sqlExpression: formData.having,
-          clause: CLAUSES.HAVING,
-          expressionType: EXPRESSION_TYPES.SQL,
-          filterOptionName: this.generateConvertedFilterOptionName(),
-        }) :
-        null,
-      ],
-    ].filter(option => option);
-  }
-
-  generateConvertedFilterOptionName() {
-      return `form_filter_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
-  }
-
   optionsForSelect(props) {
     const options = [
       ...props.columns,
diff --git a/superset/assets/src/explore/components/controls/Filter.jsx b/superset/assets/src/explore/components/controls/Filter.jsx
deleted file mode 100644
index 539a413..0000000
--- a/superset/assets/src/explore/components/controls/Filter.jsx
+++ /dev/null
@@ -1,187 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import Select from 'react-select';
-import { Button, Row, Col } from 'react-bootstrap';
-import { t } from '../../../locales';
-import SelectControl from './SelectControl';
-
-const operatorsArr = [
-  { val: 'in', type: 'array', useSelect: true, multi: true },
-  { val: 'not in', type: 'array', useSelect: true, multi: true },
-  { val: '==', type: 'string', useSelect: true, multi: false, havingOnly: true },
-  { val: '!=', type: 'string', useSelect: true, multi: false, havingOnly: true },
-  { val: '>=', type: 'string', havingOnly: true },
-  { val: '<=', type: 'string', havingOnly: true },
-  { val: '>', type: 'string', havingOnly: true },
-  { val: '<', type: 'string', havingOnly: true },
-  { val: 'regex', type: 'string', datasourceTypes: ['druid'] },
-  { val: 'LIKE', type: 'string', datasourceTypes: ['table'] },
-  { val: 'IS NULL', type: null },
-  { val: 'IS NOT NULL', type: null },
-];
-const operators = {};
-operatorsArr.forEach((op) => {
-  operators[op.val] = op;
-});
-
-const propTypes = {
-  changeFilter: PropTypes.func,
-  removeFilter: PropTypes.func,
-  filter: PropTypes.object.isRequired,
-  datasource: PropTypes.object,
-  having: PropTypes.bool,
-  valuesLoading: PropTypes.bool,
-  valueChoices: PropTypes.array,
-};
-
-const defaultProps = {
-  changeFilter: () => {},
-  removeFilter: () => {},
-  datasource: null,
-  having: false,
-  valuesLoading: false,
-  valueChoices: [],
-};
-
-export default class Filter extends React.Component {
-
-  switchFilterValue(prevOp, nextOp) {
-    if (operators[prevOp].type !== operators[nextOp].type) {
-      // Switch from array to string or vice versa
-      const val = this.props.filter.val;
-      let newVal;
-      if (operators[nextOp].type === 'string') {
-        if (!val || !val.length) {
-          newVal = '';
-        } else {
-          newVal = val[0];
-        }
-      } else if (operators[nextOp].type === 'array') {
-        if (!val || !val.length) {
-          newVal = [];
-        } else {
-          newVal = [val];
-        }
-      }
-      this.props.changeFilter(['val', 'op'], [newVal, nextOp]);
-    } else {
-      // No value type change
-      this.props.changeFilter('op', nextOp);
-    }
-  }
-
-  changeText(event) {
-    this.props.changeFilter('val', event.target.value);
-  }
-
-  changeSelect(value) {
-    this.props.changeFilter('val', value);
-  }
-
-  changeColumn(event) {
-    this.props.changeFilter('col', event.value);
-  }
-
-  changeOp(event) {
-    this.switchFilterValue(this.props.filter.op, event.value);
-  }
-
-  removeFilter(filter) {
-    this.props.removeFilter(filter);
-  }
-
-  renderFilterFormControl(filter) {
-    const operator = operators[filter.op];
-    if (operator.type === null) {
-      // IS NULL or IS NOT NULL
-      return null;
-    }
-    if (operator.useSelect && !this.props.having) {
-      // TODO should use a simple Select, not a control here...
-      return (
-        <SelectControl
-          multi={operator.multi}
-          freeForm
-          name="filter-value"
-          value={filter.val}
-          isLoading={this.props.valuesLoading}
-          choices={this.props.valueChoices}
-          onChange={this.changeSelect.bind(this)}
-          showHeader={false}
-        />
-      );
-    }
-    return (
-      <input
-        type="text"
-        onChange={this.changeText.bind(this)}
-        value={filter.val || ''}
-        className="form-control input-sm"
-        placeholder={t('Filter value')}
-      />
-    );
-  }
-  render() {
-    const datasource = this.props.datasource;
-    const filter = this.props.filter;
-    const opsChoices = operatorsArr
-    .filter((o) => {
-      if (this.props.having) {
-        return !!o.havingOnly;
-      }
-      return (!o.datasourceTypes || o.datasourceTypes.indexOf(datasource.type) >= 0);
-    })
-    .map(o => ({ value: o.val, label: o.val }));
-    let colChoices;
-    if (datasource) {
-      if (this.props.having) {
-        colChoices = datasource.metrics_combo.map(c => ({ value: c[0], label: c[1] }));
-      } else {
-        colChoices = datasource.filterable_cols.map(c => ({ value: c[0], label: c[1] }));
-      }
-    }
-    return (
-      <div>
-        <Row className="space-1">
-          <Col md={12}>
-            <Select
-              id="select-col"
-              placeholder={this.props.having ? t('Select metric') : t('Select column')}
-              clearable={false}
-              options={colChoices}
-              value={filter.col}
-              onChange={this.changeColumn.bind(this)}
-            />
-          </Col>
-        </Row>
-        <Row className="space-1">
-          <Col md={3}>
-            <Select
-              id="select-op"
-              placeholder={t('Select operator')}
-              options={opsChoices}
-              clearable={false}
-              value={filter.op}
-              onChange={this.changeOp.bind(this)}
-            />
-          </Col>
-          <Col md={7}>
-            {this.renderFilterFormControl(filter)}
-          </Col>
-          <Col md={2}>
-            <Button
-              id="remove-button"
-              bsSize="small"
-              onClick={this.removeFilter.bind(this)}
-            >
-              <i className="fa fa-minus" />
-            </Button>
-          </Col>
-        </Row>
-      </div>
-    );
-  }
-}
-
-Filter.propTypes = propTypes;
-Filter.defaultProps = defaultProps;
diff --git a/superset/assets/src/explore/components/controls/FilterControl.jsx b/superset/assets/src/explore/components/controls/FilterControl.jsx
deleted file mode 100644
index 041dd6f..0000000
--- a/superset/assets/src/explore/components/controls/FilterControl.jsx
+++ /dev/null
@@ -1,155 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Button, Row, Col } from 'react-bootstrap';
-import Filter from './Filter';
-import { t } from '../../../locales';
-
-const $ = window.$ = require('jquery');
-
-const propTypes = {
-  name: PropTypes.string,
-  onChange: PropTypes.func,
-  value: PropTypes.array,
-  datasource: PropTypes.object,
-};
-
-const defaultProps = {
-  onChange: () => {},
-  value: [],
-};
-
-export default class FilterControl extends React.Component {
-
-  constructor(props) {
-    super(props);
-    const initialFilters = props.value.map(() => ({
-      valuesLoading: false,
-      valueChoices: [],
-    }));
-    this.state = {
-      filters: initialFilters,
-      activeRequest: null,
-    };
-  }
-
-  componentDidMount() {
-    this.state.filters.forEach((filter, index) => this.fetchFilterValues(index));
-  }
-
-  fetchFilterValues(index, column) {
-    const datasource = this.props.datasource;
-    const col = column || this.props.value[index].col;
-    const having = this.props.name === 'having_filters';
-    if (col && this.props.datasource && this.props.datasource.filter_select && !having) {
-      this.setState((prevState) => {
-        const newStateFilters = Object.assign([], prevState.filters);
-        newStateFilters[index].valuesLoading = true;
-        return { filters: newStateFilters };
-      });
-      // if there is an outstanding request to fetch values, cancel it.
-      if (this.state.activeRequest) {
-        this.state.activeRequest.abort();
-      }
-      this.setState({
-        activeRequest: $.ajax({
-          type: 'GET',
-          url: `/superset/filter/${datasource.type}/${datasource.id}/${col}/`,
-          success: (data) => {
-            this.setState((prevState) => {
-              const newStateFilters = Object.assign([], prevState.filters);
-              newStateFilters[index] = { valuesLoading: false, valueChoices: data };
-              return { filters: newStateFilters, activeRequest: null };
-            });
-          },
-        }),
-      });
-    }
-  }
-
-  addFilter() {
-    const newFilters = Object.assign([], this.props.value);
-    const col = this.props.datasource && this.props.datasource.filterable_cols.length > 0 ?
-      this.props.datasource.filterable_cols[0][0] :
-      null;
-    newFilters.push({
-      col,
-      op: 'in',
-      val: this.props.datasource.filter_select ? [] : '',
-    });
-    this.props.onChange(newFilters);
-    const nextIndex = this.state.filters.length;
-    this.setState((prevState) => {
-      const newStateFilters = Object.assign([], prevState.filters);
-      newStateFilters.push({ valuesLoading: false, valueChoices: [] });
-      return { filters: newStateFilters };
-    });
-    this.fetchFilterValues(nextIndex, col);
-  }
-
-  changeFilter(index, control, value) {
-    const newFilters = Object.assign([], this.props.value);
-    const modifiedFilter = Object.assign({}, newFilters[index]);
-    if (typeof control === 'string') {
-      modifiedFilter[control] = value;
-    } else {
-      control.forEach((c, i) => {
-        modifiedFilter[c] = value[i];
-      });
-    }
-    // Clear selected values and refresh upon column change
-    if (control === 'col') {
-      if (modifiedFilter.val.constructor === Array) {
-        modifiedFilter.val = [];
-      } else if (typeof modifiedFilter.val === 'string') {
-        modifiedFilter.val = '';
-      }
-      this.fetchFilterValues(index, value);
-    }
-    newFilters.splice(index, 1, modifiedFilter);
-    this.props.onChange(newFilters);
-  }
-
-  removeFilter(index) {
-    this.props.onChange(this.props.value.filter((f, i) => i !== index));
-    this.setState((prevState) => {
-      const newStateFilters = Object.assign([], prevState.filters);
-      newStateFilters.splice(index, 1);
-      return { filters: newStateFilters };
-    });
-  }
-
-  render() {
-    const filters = this.props.value.map((filter, i) => (
-      <div key={i}>
-        <Filter
-          having={this.props.name === 'having_filters'}
-          filter={filter}
-          datasource={this.props.datasource}
-          removeFilter={this.removeFilter.bind(this, i)}
-          changeFilter={this.changeFilter.bind(this, i)}
-          valuesLoading={this.state.filters[i].valuesLoading}
-          valueChoices={this.state.filters[i].valueChoices}
-        />
-      </div>
-    ));
-    return (
-      <div>
-        {filters}
-        <Row className="space-2">
-          <Col md={2}>
-            <Button
-              id="add-button"
-              bsSize="sm"
-              onClick={this.addFilter.bind(this)}
-            >
-              <i className="fa fa-plus" /> &nbsp; {t('Add Filter')}
-            </Button>
-          </Col>
-        </Row>
-      </div>
-    );
-  }
-}
-
-FilterControl.propTypes = propTypes;
-FilterControl.defaultProps = defaultProps;
diff --git a/superset/assets/src/explore/components/controls/index.js b/superset/assets/src/explore/components/controls/index.js
index 8199127..4a2df42 100644
--- a/superset/assets/src/explore/components/controls/index.js
+++ b/superset/assets/src/explore/components/controls/index.js
@@ -6,7 +6,6 @@ import ColorPickerControl from './ColorPickerControl';
 import ColorSchemeControl from './ColorSchemeControl';
 import DatasourceControl from './DatasourceControl';
 import DateFilterControl from './DateFilterControl';
-import FilterControl from './FilterControl';
 import FixedOrMetricControl from './FixedOrMetricControl';
 import HiddenControl from './HiddenControl';
 import SelectAsyncControl from './SelectAsyncControl';
@@ -29,7 +28,6 @@ const controlMap = {
   ColorSchemeControl,
   DatasourceControl,
   DateFilterControl,
-  FilterControl,
   FixedOrMetricControl,
   HiddenControl,
   SelectAsyncControl,
diff --git a/superset/assets/src/explore/controls.jsx b/superset/assets/src/explore/controls.jsx
index b2382c1..0281fe1 100644
--- a/superset/assets/src/explore/controls.jsx
+++ b/superset/assets/src/explore/controls.jsx
@@ -1132,34 +1132,6 @@ export const controls = {
     default: '',
   },
 
-  where: {
-    type: 'TextAreaControl',
-    label: t('Custom WHERE clause'),
-    default: '',
-    language: 'sql',
-    minLines: 2,
-    maxLines: 10,
-    offerEditInModal: false,
-    description: t('The text in this box gets included in your query\'s WHERE ' +
-    'clause, as an AND to other criteria. You can include ' +
-    'complex expression, parenthesis and anything else ' +
-    'supported by the backend it is directed towards.'),
-  },
-
-  having: {
-    type: 'TextAreaControl',
-    label: t('Custom HAVING clause'),
-    default: '',
-    language: 'sql',
-    minLines: 2,
-    maxLines: 10,
-    offerEditInModal: false,
-    description: t('The text in this box gets included in your query\'s HAVING ' +
-    'clause, as an AND to other criteria. You can include ' +
-    'complex expression, parenthesis and anything else ' +
-    'supported by the backend it is directed towards.'),
-  },
-
   compare_lag: {
     type: 'TextControl',
     label: t('Comparison Period Lag'),
@@ -1822,16 +1794,6 @@ export const controls = {
     description: t('Labels for the marker lines'),
   },
 
-  filters: {
-    type: 'FilterControl',
-    label: '',
-    default: [],
-    description: '',
-    mapStateToProps: state => ({
-      datasource: state.datasource,
-    }),
-  },
-
   annotation_layers: {
     type: 'AnnotationLayerControl',
     label: '',
@@ -1854,18 +1816,6 @@ export const controls = {
     provideFormDataToProps: true,
   },
 
-  having_filters: {
-    type: 'FilterControl',
-    label: '',
-    default: [],
-    description: '',
-    mapStateToProps: state => ({
-      choices: (state.datasource) ? state.datasource.metrics_combo
-        .concat(state.datasource.filterable_cols) : [],
-      datasource: state.datasource,
-    }),
-  },
-
   slice_id: {
     type: 'HiddenControl',
     label: t('Chart ID'),
diff --git a/superset/assets/src/explore/store.js b/superset/assets/src/explore/store.js
index 32c132f..48a24df 100644
--- a/superset/assets/src/explore/store.js
+++ b/superset/assets/src/explore/store.js
@@ -68,14 +68,6 @@ export function getControlsState(state, form_data) {
         delete formData[k];
       }
     }
-    // Removing invalid filters that point to a now inexisting column
-    if (control.type === 'FilterControl' && control.choices) {
-      if (!formData[k]) {
-        formData[k] = [];
-      }
-      const choiceValues = control.choices.map(c => c[0]);
-      formData[k] = formData[k].filter(flt => choiceValues.indexOf(flt.col) >= 0);
-    }
 
     if (typeof control.default === 'function') {
       control.default = control.default(control);
diff --git a/superset/assets/src/explore/visTypes.js b/superset/assets/src/explore/visTypes.js
index f771c38..b0037ec 100644
--- a/superset/assets/src/explore/visTypes.js
+++ b/superset/assets/src/explore/visTypes.js
@@ -40,14 +40,6 @@ export const sections = {
       ['since', 'until'],
     ],
   },
-  sqlClause: {
-    label: t('SQL'),
-    controlSetRows: [
-      ['where'],
-      ['having'],
-    ],
-    description: t('This section exposes ways to include snippets of SQL in your query'),
-  },
   annotations: {
     label: t('Annotations and Layers'),
     expanded: true,
@@ -80,20 +72,6 @@ export const sections = {
       ],
     },
   ],
-  filters: [
-    {
-      label: t('Filters'),
-      expanded: true,
-      controlSetRows: [['filters']],
-    },
-    {
-      label: t('Result Filters'),
-      expanded: true,
-      description: t('The filters to apply after post-aggregation.' +
-      'Leave the value control empty to filter empty strings or nulls'),
-      controlSetRows: [['having_filters']],
-    },
-  ],
 };
 
 const timeGrainSqlaAnimationOverrides = {
@@ -263,6 +241,13 @@ export const visTypes = {
           ['line_charts_2', 'y_axis_2_format'],
         ],
       },
+      {
+        label: t('Query'),
+        expanded: true,
+        controlSetRows: [
+          ['adhoc_filters'],
+        ],
+      },
       sections.annotations,
     ],
     controlOverrides: {
@@ -279,8 +264,6 @@ export const visTypes = {
       },
     },
     sectionOverrides: {
-      sqlClause: [],
-      filters: [[]],
       datasourceAndVizType: {
         label: t('Chart Type'),
         controlSetRows: [
@@ -310,7 +293,9 @@ export const visTypes = {
         label: t('Query'),
         expanded: true,
         controlSetRows: [
-          ['metric', 'freq'],
+          ['metric'],
+          ['adhoc_filters'],
+          ['freq'],
         ],
       },
       {
@@ -373,6 +358,13 @@ export const visTypes = {
           ['metric_2', 'y_axis_2_format'],
         ],
       },
+      {
+        label: t('Query'),
+        expanded: true,
+        controlSetRows: [
+          ['adhoc_filters'],
+        ],
+      },
       sections.annotations,
     ],
     controlOverrides: {
@@ -489,6 +481,13 @@ export const visTypes = {
           ['deck_slices', null],
         ],
       },
+      {
+        label: t('Query'),
+        expanded: true,
+        controlSetRows: [
+          ['adhoc_filters'],
+        ],
+      },
     ],
   },
 
@@ -502,6 +501,7 @@ export const visTypes = {
         controlSetRows: [
           ['spatial', 'size'],
           ['row_limit', null],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -540,6 +540,7 @@ export const visTypes = {
         controlSetRows: [
           ['spatial', 'size'],
           ['row_limit', null],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -579,6 +580,7 @@ export const visTypes = {
         controlSetRows: [
           ['line_column', 'line_type'],
           ['row_limit', null],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -612,6 +614,7 @@ export const visTypes = {
         controlSetRows: [
           ['spatial', 'size'],
           ['row_limit', null],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -656,6 +659,7 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['geojson', 'row_limit'],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -696,6 +700,7 @@ export const visTypes = {
         controlSetRows: [
           ['line_column', 'line_type'],
           ['row_limit', null],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -736,6 +741,7 @@ export const visTypes = {
         controlSetRows: [
           ['start_spatial', 'end_spatial'],
           ['row_limit', null],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -784,6 +790,7 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['spatial', 'row_limit'],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -902,6 +909,13 @@ export const visTypes = {
         ],
       },
       {
+        label: t('Query'),
+        expanded: true,
+        controlSetRows: [
+          ['adhoc_filters'],
+        ],
+      },
+      {
         label: t('Options'),
         expanded: true,
         controlSetRows: [
@@ -929,7 +943,9 @@ export const visTypes = {
         label: t('Query'),
         expanded: true,
         controlSetRows: [
-          ['groupby', 'metrics'],
+          ['metrics'],
+          ['adhoc_filters'],
+          ['groupby'],
           ['limit'],
           ['column_collection'],
           ['url'],
@@ -969,8 +985,10 @@ export const visTypes = {
         label: t('Query'),
         expanded: true,
         controlSetRows: [
-          ['groupby', 'columns'],
           ['metrics'],
+          ['adhoc_filters'],
+          ['groupby'],
+          ['columns'],
           ['row_limit', null],
         ],
       },
@@ -1017,7 +1035,9 @@ export const visTypes = {
         label: t('Query'),
         expanded: true,
         controlSetRows: [
-          ['series', 'metric'],
+          ['metric'],
+          ['adhoc_filters'],
+          ['series'],
           ['row_limit', null],
         ],
       },
@@ -1040,6 +1060,7 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['metrics'],
+          ['adhoc_filters'],
           ['groupby'],
         ],
       },
@@ -1070,6 +1091,7 @@ export const visTypes = {
         controlSetRows: [
           ['domain_granularity', 'subdomain_granularity'],
           ['metrics'],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -1106,7 +1128,9 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['metrics'],
-          ['groupby', 'limit'],
+          ['adhoc_filters'],
+          ['groupby'],
+          ['limit'],
         ],
       },
       {
@@ -1128,8 +1152,11 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['series', 'entity'],
-          ['x', 'y'],
-          ['size', 'max_bubble_size'],
+          ['x'],
+          ['y'],
+          ['adhoc_filters'],
+          ['size'],
+          ['max_bubble_size'],
           ['limit', null],
         ],
       },
@@ -1179,6 +1206,7 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['metric'],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -1256,6 +1284,7 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['all_columns_x'],
+          ['adhoc_filters'],
           ['row_limit'],
           ['groupby'],
         ],
@@ -1298,7 +1327,9 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['groupby'],
-          ['metric', 'secondary_metric'],
+          ['metric'],
+          ['secondary_metric'],
+          ['adhoc_filters'],
           ['row_limit'],
         ],
       },
@@ -1338,6 +1369,7 @@ export const visTypes = {
         controlSetRows: [
           ['groupby'],
           ['metric'],
+          ['adhoc_filters'],
           ['row_limit'],
         ],
       },
@@ -1366,6 +1398,7 @@ export const visTypes = {
         controlSetRows: [
           ['groupby'],
           ['metric'],
+          ['adhoc_filters'],
           ['row_limit'],
         ],
       },
@@ -1391,8 +1424,11 @@ export const visTypes = {
         label: t('Query'),
         expanded: true,
         controlSetRows: [
-          ['groupby', 'columns'],
-          ['metric', 'row_limit'],
+          ['groupby'],
+          ['columns'],
+          ['metric'],
+          ['adhoc_filters'],
+          ['row_limit'],
         ],
       },
       {
@@ -1432,6 +1468,7 @@ export const visTypes = {
         controlSetRows: [
           ['entity'],
           ['metric'],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -1467,6 +1504,7 @@ export const visTypes = {
           ['entity'],
           ['country_fieldtype'],
           ['metric'],
+          ['adhoc_filters'],
         ],
       },
       {
@@ -1503,6 +1541,7 @@ export const visTypes = {
         controlSetRows: [
           ['groupby'],
           ['metric'],
+          ['adhoc_filters'],
           ['date_filter', 'instant_filtering'],
           ['show_sqla_time_granularity', 'show_sqla_time_column'],
           ['show_druid_time_granularity', 'show_druid_time_origin'],
@@ -1544,6 +1583,7 @@ export const visTypes = {
           ['series'],
           ['metrics'],
           ['secondary_metric'],
+          ['adhoc_filters'],
           ['limit'],
         ],
       },
@@ -1564,7 +1604,9 @@ export const visTypes = {
         expanded: true,
         controlSetRows: [
           ['all_columns_x', 'all_columns_y'],
-          ['metric', 'row_limit'],
+          ['metric'],
+          ['adhoc_filters'],
+          ['row_limit'],
         ],
       },
       {
@@ -1627,6 +1669,7 @@ export const visTypes = {
           ['all_columns_x', 'all_columns_y'],
           ['clustering_radius'],
           ['row_limit'],
+          ['adhoc_filters'],
           ['groupby'],
         ],
       },
@@ -1702,6 +1745,13 @@ export const visTypes = {
         ],
       },
       {
+        label: t('Query'),
+        expanded: true,
+        controlSetRows: [
+          ['adhoc_filters'],
+        ],
+      },
+      {
         label: t('Additional meta data'),
         controlSetRows: [
           ['all_columns'],
@@ -1799,12 +1849,6 @@ export const visTypes = {
 
 export default visTypes;
 
-function adhocFilterEnabled(viz) {
-  return viz.controlPanelSections.find((
-    section => section.controlSetRows.find(row => row.find(control => control === 'adhoc_filters'))
-  ));
-}
-
 export function sectionsToRender(vizType, datasourceType) {
   const viz = visTypes[vizType];
 
@@ -1826,7 +1870,5 @@ export function sectionsToRender(vizType, datasourceType) {
     sectionsCopy.datasourceAndVizType,
     datasourceType === 'table' ? sectionsCopy.sqlaTimeSeries : sectionsCopy.druidTimeSeries,
     viz.controlPanelSections,
-    !adhocFilterEnabled(viz) && (datasourceType === 'table' ? sectionsCopy.sqlClause : []),
-    !adhocFilterEnabled(viz) && (datasourceType === 'table' ? sectionsCopy.filters[0] : sectionsCopy.filters),
   ).filter(section => section);
 }
diff --git a/superset/migrations/versions/bddc498dd179_adhoc_filters.py b/superset/migrations/versions/bddc498dd179_adhoc_filters.py
new file mode 100644
index 0000000..55503f0
--- /dev/null
+++ b/superset/migrations/versions/bddc498dd179_adhoc_filters.py
@@ -0,0 +1,97 @@
+"""adhoc filters
+
+Revision ID: bddc498dd179
+Revises: afb7730f6a9c
+Create Date: 2018-06-13 14:54:47.086507
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'bddc498dd179'
+down_revision = '80a67c5192fa'
+
+
+from collections import defaultdict
+import json
+import uuid
+
+from alembic import op
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column, Integer, Text
+
+from superset import db
+from superset import utils
+
+
+Base = declarative_base()
+
+
+class Slice(Base):
+    __tablename__ = 'slices'
+
+    id = Column(Integer, primary_key=True)
+    params = Column(Text)
+
+
+def upgrade():
+    bind = op.get_bind()
+    session = db.Session(bind=bind)
+    mapping = {'having': 'having_filters', 'where': 'filters'}
+
+    for slc in session.query(Slice).all():
+        try:
+            params = json.loads(slc.params)
+
+            if not 'adhoc_filters' in params:
+                params['adhoc_filters'] = []
+
+                for clause, filters in mapping.items():
+                    if clause in params and params[clause] != '':
+                        params['adhoc_filters'].append({
+                            'clause': clause.upper(),
+                            'expressionType': 'SQL',
+                            'filterOptionName': str(uuid.uuid4()),
+                            'sqlExpression': params[clause],
+                        })
+
+                    if filters in params:
+                        for filt in params[filters]:
+                            params['adhoc_filters'].append({
+                                'clause': clause.upper(),
+                                'comparator': filt['val'],
+                                'expressionType': 'SIMPLE',
+                                'filterOptionName': str(uuid.uuid4()),
+                                'operator': filt['op'],
+                                'subject': filt['col'],
+                            })
+
+            for key in ('filters', 'having', 'having_filters', 'where'):
+                if key in params:
+                    del params[key]
+
+            slc.params = json.dumps(params, sort_keys=True)
+        except Exception:
+            pass
+
+    session.commit()
+    session.close()
+
+
+def downgrade():
+    bind = op.get_bind()
+    session = db.Session(bind=bind)
+
+    for slc in session.query(Slice).all():
+        try:
+            params = json.loads(slc.params)
+            utils.split_adhoc_filters_into_base_filters(params)
+
+            if 'adhoc_filters' in params:
+                del params['adhoc_filters']
+
+            slc.params = json.dumps(params, sort_keys=True)
+        except Exception:
+            pass
+
+    session.commit()
+    session.close()
diff --git a/superset/translations/de/LC_MESSAGES/messages.po b/superset/translations/de/LC_MESSAGES/messages.po
index 7db79cd..59077e2 100644
--- a/superset/translations/de/LC_MESSAGES/messages.po
+++ b/superset/translations/de/LC_MESSAGES/messages.po
@@ -1193,7 +1193,6 @@ msgstr ""
 msgid "Select operator"
 msgstr ""
 
-#: superset/assets/javascripts/explore/components/controls/FilterControl.jsx:138
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr ""
diff --git a/superset/translations/en/LC_MESSAGES/messages.po b/superset/translations/en/LC_MESSAGES/messages.po
index 3d5e245..a861350 100644
--- a/superset/translations/en/LC_MESSAGES/messages.po
+++ b/superset/translations/en/LC_MESSAGES/messages.po
@@ -3815,7 +3815,6 @@ msgstr ""
 msgid "Select operator"
 msgstr ""
 
-#: superset/assets/src/explore/components/controls/FilterControl.jsx:145
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr ""
diff --git a/superset/translations/es/LC_MESSAGES/messages.po b/superset/translations/es/LC_MESSAGES/messages.po
index 4742f76..1dbd464 100644
--- a/superset/translations/es/LC_MESSAGES/messages.po
+++ b/superset/translations/es/LC_MESSAGES/messages.po
@@ -1250,7 +1250,6 @@ msgstr "Selecciona la columna"
 msgid "Select operator"
 msgstr "Selecciona el operador"
 
-#: superset/assets/javascripts/explore/components/controls/FilterControl.jsx:138
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "Añadir Filtro"
diff --git a/superset/translations/fr/LC_MESSAGES/messages.po b/superset/translations/fr/LC_MESSAGES/messages.po
index f3914a4..16245c3 100644
--- a/superset/translations/fr/LC_MESSAGES/messages.po
+++ b/superset/translations/fr/LC_MESSAGES/messages.po
@@ -3819,7 +3819,6 @@ msgstr ""
 msgid "Select operator"
 msgstr ""
 
-#: superset/assets/src/explore/components/controls/FilterControl.jsx:145
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "Ajouter un filtre"
diff --git a/superset/translations/it/LC_MESSAGES/messages.po b/superset/translations/it/LC_MESSAGES/messages.po
index 5ef5b4b..f383e14 100644
--- a/superset/translations/it/LC_MESSAGES/messages.po
+++ b/superset/translations/it/LC_MESSAGES/messages.po
@@ -1598,7 +1598,6 @@ msgstr "Seleziona una colonna"
 msgid "Select operator"
 msgstr "Seleziona operatore"
 
-#: superset/assets/javascripts/explore/components/controls/FilterControl.jsx:145
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "Aggiungi filtro"
diff --git a/superset/translations/ja/LC_MESSAGES/messages.po b/superset/translations/ja/LC_MESSAGES/messages.po
index 5f6b714..df16185 100644
--- a/superset/translations/ja/LC_MESSAGES/messages.po
+++ b/superset/translations/ja/LC_MESSAGES/messages.po
@@ -1202,7 +1202,6 @@ msgstr "列を選択"
 msgid "Select operator"
 msgstr "オペレータを選択"
 
-#: superset/assets/javascripts/explore/components/controls/FilterControl.jsx:138
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "フィルターを追加"
diff --git a/superset/translations/messages.pot b/superset/translations/messages.pot
index 23d2cb4..09c3e36 100644
--- a/superset/translations/messages.pot
+++ b/superset/translations/messages.pot
@@ -3814,7 +3814,6 @@ msgstr ""
 msgid "Select operator"
 msgstr ""
 
-#: superset/assets/src/explore/components/controls/FilterControl.jsx:145
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr ""
diff --git a/superset/translations/pt_BR/LC_MESSAGES/messages.po b/superset/translations/pt_BR/LC_MESSAGES/messages.po
index b2a5b34..8710021 100644
--- a/superset/translations/pt_BR/LC_MESSAGES/messages.po
+++ b/superset/translations/pt_BR/LC_MESSAGES/messages.po
@@ -1256,7 +1256,6 @@ msgstr "Selecione a coluna"
 msgid "Select operator"
 msgstr "Selecione o operador"
 
-#: superset/assets/javascripts/explore/components/controls/FilterControl.jsx:138
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "Adicionar filtro"
diff --git a/superset/translations/ru/LC_MESSAGES/messages.po b/superset/translations/ru/LC_MESSAGES/messages.po
index 79e5713..5ea2cc1 100644
--- a/superset/translations/ru/LC_MESSAGES/messages.po
+++ b/superset/translations/ru/LC_MESSAGES/messages.po
@@ -1599,7 +1599,6 @@ msgstr "Выбрать столбец"
 msgid "Select operator"
 msgstr "Выбрать оператор"
 
-#: superset/assets/javascripts/explore/components/controls/FilterControl.jsx:145
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "Добавить фильтр"
diff --git a/superset/translations/zh/LC_MESSAGES/messages.po b/superset/translations/zh/LC_MESSAGES/messages.po
index 0a9cc2f..4cd37c9 100644
--- a/superset/translations/zh/LC_MESSAGES/messages.po
+++ b/superset/translations/zh/LC_MESSAGES/messages.po
@@ -3820,7 +3820,6 @@ msgstr "选择列"
 msgid "Select operator"
 msgstr "选择运算符"
 
-#: superset/assets/src/explore/components/controls/FilterControl.jsx:145
 #: superset/templates/appbuilder/general/widgets/search.html:6
 msgid "Add Filter"
 msgstr "增加过滤条件"
diff --git a/superset/utils.py b/superset/utils.py
index 08ce0d2..eec2530 100644
--- a/superset/utils.py
+++ b/superset/utils.py
@@ -881,4 +881,3 @@ def split_adhoc_filters_into_base_filters(fd):
         fd['having'] = ' AND '.join(['({})'.format(sql) for sql in sql_having_filters])
         fd['having_filters'] = simple_having_filters
         fd['filters'] = simple_where_filters
-        del fd['adhoc_filters']


Mime
View raw message