diff --git a/src/sql/base/browser/ui/table/media/down-inverse.svg b/src/sql/base/browser/ui/table/media/down-inverse.svg
new file mode 100644
index 0000000000..f914c8bff1
--- /dev/null
+++ b/src/sql/base/browser/ui/table/media/down-inverse.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/sql/base/browser/ui/table/media/down.svg b/src/sql/base/browser/ui/table/media/down.svg
new file mode 100644
index 0000000000..dc21a6633d
--- /dev/null
+++ b/src/sql/base/browser/ui/table/media/down.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/sql/base/browser/ui/table/media/filter.svg b/src/sql/base/browser/ui/table/media/filter.svg
new file mode 100644
index 0000000000..32f914f54a
--- /dev/null
+++ b/src/sql/base/browser/ui/table/media/filter.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/sql/base/browser/ui/table/media/filter_inverse.svg b/src/sql/base/browser/ui/table/media/filter_inverse.svg
new file mode 100644
index 0000000000..60b90abd6d
--- /dev/null
+++ b/src/sql/base/browser/ui/table/media/filter_inverse.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/sql/base/browser/ui/table/media/table.css b/src/sql/base/browser/ui/table/media/table.css
index 99c7eeeba1..c010fd47ef 100644
--- a/src/sql/base/browser/ui/table/media/table.css
+++ b/src/sql/base/browser/ui/table/media/table.css
@@ -31,4 +31,117 @@
height: 5px;
margin-left: 4px;
margin-top: 6px;
+}
+
+.slick-header-menubutton {
+ background-position: center center;
+ background-repeat: no-repeat;
+ bottom: 0;
+ cursor: pointer;
+ display: inline-block;
+ position: absolute;
+ right: 10px;
+ top: 0;
+ width: 18px;
+ background-image: url('down.svg');
+}
+
+.vs-dark .slick-header-menubutton {
+ background-image: url('down-inverse.svg');
+}
+
+.slick-header-menubutton.filtered {
+ background-image: url('filter.svg');
+}
+
+.vs-dark .slick-header-menubutton.filtered {
+ background-image: url('filter_inverse.svg');
+}
+
+.slick-header-menu {
+ background: none repeat scroll 0 0 white;
+ border: 1px solid #BFBDBD;
+ min-width: 175px;
+ padding: 4px;
+ z-index: 100000;
+ cursor: default;
+ display: inline-block;
+ margin: 0;
+ position: absolute;
+}
+
+.vs-dark .slick-header-menu {
+ background: none repeat scroll 0 0 #333333;
+}
+
+.slick-header-menu a.monaco-button.monaco-text-button {
+ width: 60px;
+ margin: 6px 6px 6px 6px;
+ padding: 4px;
+}
+
+.slick-header-menu .filter
+{
+ border: 1px solid #BFBDBD;
+ font-size: 8pt;
+ height: 400px;
+ margin-top: 6px;
+ overflow: scroll;
+ padding: 4px;
+ white-space: nowrap;
+ width: 200px;
+}
+
+label {
+ display: block;
+ margin-bottom: 5px;
+}
+
+.slick-header-menuitem
+{
+ border: 1px solid transparent;
+ padding: 2px 4px;
+ cursor: pointer;
+ list-style: none outside none;
+ margin: 0;
+}
+
+.slick-header-menuicon
+{
+ display: inline-block;
+ height: 16px;
+ margin-right: 4px;
+ vertical-align: middle;
+ width: 16px;
+}
+
+.slick-header-menuicon.ascending {
+ background: url('sort-asc.gif');
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+
+.slick-header-menuicon.descending {
+ background: url('sort-desc.gif');
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+
+.slick-header-menucontent {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.slick-header-menuitem:hover {
+ border-color: #BFBDBD;
+}
+
+.header-overlay, .cell-overlay, .selection-cell-overlay {
+ display: block;
+ position: absolute;
+ z-index: 999;
+}
+
+.vs-dark .slick-header-menu > input.input {
+ color: #4a4a4a;
}
\ No newline at end of file
diff --git a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts
new file mode 100644
index 0000000000..720fc4d5bb
--- /dev/null
+++ b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts
@@ -0,0 +1,353 @@
+// Adopted and converted to typescript from https://github.com/danny-sg/slickgrid-spreadsheet-plugins/blob/master/ext.headerfilter.js
+// heavily modified
+import 'vs/css!sql/base/browser/ui/table/media/table';
+
+import { mixin } from 'vs/base/common/objects';
+import { SlickGrid } from 'angular2-slickgrid';
+import { Button } from '../../button/button';
+import { attachButtonStyler } from 'sql/common/theme/styler';
+import { IThemeService } from 'vs/platform/theme/common/themeService';
+
+export class HeaderFilter {
+
+ public onFilterApplied = new Slick.Event();
+ public onCommand = new Slick.Event();
+
+ private grid;
+ private handler = new Slick.EventHandler();
+ private defaults = {
+ filterImage: 'src/sql/media/icons/filter.svg',
+ sortAscImage: 'sort-asc.gif',
+ sortDescImage: 'sort-desc.gif'
+ };
+
+ private $menu;
+ private options: any;
+ private okButton: Button;
+ private clearButton: Button;
+ private cancelButton: Button;
+ private workingFilters: any;
+ private columnDef: any;
+
+ constructor(options: any, private _themeService: IThemeService) {
+ this.options = mixin(options, this.defaults, false);
+ }
+
+ public init(grid: Slick.Grid): void {
+ this.grid = grid;
+ this.handler.subscribe(this.grid.onHeaderCellRendered, (e, args) => this.handleHeaderCellRendered(e , args))
+ .subscribe(this.grid.onBeforeHeaderCellDestroy, (e, args) => this.handleBeforeHeaderCellDestroy(e, args))
+ .subscribe(this.grid.onClick, (e) => this.handleBodyMouseDown)
+ .subscribe(this.grid.onColumnsResized, () => this.columnsResized());
+
+ this.grid.setColumns(this.grid.getColumns());
+
+ $(document.body).bind('mousedown', this.handleBodyMouseDown);
+ }
+
+ public destroy() {
+ this.handler.unsubscribeAll();
+ $(document.body).unbind('mousedown', this.handleBodyMouseDown);
+ }
+
+ private handleBodyMouseDown = (e) => {
+ if (this.$menu && this.$menu[0] !== e.target && !$.contains(this.$menu[0], e.target)) {
+ this.hideMenu();
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+
+ private hideMenu() {
+ if (this.$menu) {
+ this.$menu.remove();
+ this.$menu = null;
+ }
+ }
+
+ private handleHeaderCellRendered(e, args) {
+ let column = args.column;
+ if (column.id === '_detail_selector') {
+ return;
+ }
+ let $el = $('')
+ .addClass('slick-header-menubutton')
+ .data('column', column);
+
+ $el.bind('click', (e) => this.showFilter(e)).appendTo(args.node);
+ }
+
+ private handleBeforeHeaderCellDestroy(e, args) {
+ $(args.node)
+ .find('.slick-header-menubutton')
+ .remove();
+ }
+
+ private addMenuItem(menu, columnDef, title, command, image) {
+ let $item = $('