Add unselect operator.

unselect removes columns from the dataset.
This is useful when columns are present merely
to provide a sort order, and should not be
present in the final graph.
diff --git a/render.js b/render.js
index 28dc211..f748c0e 100644
--- a/render.js
+++ b/render.js
@@ -1084,6 +1084,44 @@
   }
 
 
+  function unselectBy(ingrid, keys) {
+    var outgrid = {headers: [], data: [], types: []};
+    var keycols = {};
+    for (var keyi in keys) {
+      var key = keys[keyi];
+      var col = keyToColNum(ingrid, key);
+      keycols[col] = true;
+    }
+
+    for (var headi = 0; headi < ingrid.headers.length; headi++) {
+      if (!(headi in keycols)) {
+        outgrid.headers.push(ingrid.headers[headi]);
+        outgrid.types.push(ingrid.types[headi]);
+      }
+    }
+    for (var rowi = 0; rowi < ingrid.data.length; rowi++) {
+      var row = ingrid.data[rowi];
+      var newrow = [];
+      for (var coli = 0; coli < row.length; coli++) {
+        if (!(coli in keycols)) {
+          newrow.push(row[coli]);
+        }
+      }
+      outgrid.data.push(newrow);
+    }
+
+    return outgrid;
+  }
+
+
+  function doUnselectBy(grid, argval) {
+    console.debug('unselectBy:', argval);
+    grid = unselectBy(grid, argval.split(','));
+    console.debug('grid:', grid);
+    return grid;
+  }
+
+
   function orderBy(grid, keys) {
     var keycols = [];
     for (var keyi in keys) {
@@ -1341,6 +1379,8 @@
         transform(doLimit, argval);
       } else if (argkey == 'delta') {
         transform(doDeltaBy, argval);
+      } else if (argkey == 'unselect') {
+        transform(doUnselectBy, argval);
       } else if (argkey == 'order') {
         transform(doOrderBy, argval);
       } else if (argkey == 'extract_regexp') {
@@ -1741,6 +1781,7 @@
       filterBy: filterBy,
       queryBy: queryBy,
       deltaBy: deltaBy,
+      unselectBy: unselectBy,
       orderBy: orderBy,
       extractRegexp: extractRegexp,
       fillNullsWithZero: fillNullsWithZero,
diff --git a/t/trender.js b/t/trender.js
index e65ff81..bb01ede 100644
--- a/t/trender.js
+++ b/t/trender.js
@@ -138,6 +138,46 @@
 
 
 
+wvtest('unselect', function() {
+  var grid = {
+    headers: ['a', 'b', 'c'],
+    types: ['number', 'number', 'number'],
+    data: [
+      [1, 2, 3],
+      [4, 5, 6],
+      [7, 8, 9],
+      [10, 11, 12],
+      [13, 14, 15],
+    ]
+  };
+  var dt = afterquery.internal.unselectBy(grid, 'b');
+  dump(dt);
+  WVPASSEQ(dt.headers.length, 2);
+  WVPASSEQ(dt.headers[0], 'a');
+  WVPASSEQ(dt.headers[1], 'c');
+  WVPASSEQ(dt.types.length, 2);
+  WVPASSEQ(dt.types[0], 'number');
+  WVPASSEQ(dt.types[1], 'number');
+  WVPASSEQ(dt.data.length, 5);
+  WVPASSEQ(dt.data[0].length, 2);
+  WVPASSEQ(dt.data[0][0], 1);
+  WVPASSEQ(dt.data[0][1], 3);
+  WVPASSEQ(dt.data[1].length, 2);
+  WVPASSEQ(dt.data[1][0], 4);
+  WVPASSEQ(dt.data[1][1], 6);
+  WVPASSEQ(dt.data[2].length, 2);
+  WVPASSEQ(dt.data[2][0], 7);
+  WVPASSEQ(dt.data[2][1], 9);
+  WVPASSEQ(dt.data[3].length, 2);
+  WVPASSEQ(dt.data[3][0], 10);
+  WVPASSEQ(dt.data[3][1], 12);
+  WVPASSEQ(dt.data[4].length, 2);
+  WVPASSEQ(dt.data[4][0], 13);
+  WVPASSEQ(dt.data[4][1], 15);
+});
+
+
+
 wvtest('guessTypes', function() {
   var data1 = [['1999-01-01', '1999-02-02', 1, 2.5, false, 'foo']];
   var data2 = [['1999-01-01', '1999-02-02 12:34', 2, 'x', true, null]];