Fix some longstanding bugs in pivot=, and add unit tests for it.

In particular, when a T_DATE ended up as a column heading, it was being
rendered in the (totally ugly) default javascript notation instead of using
our prettier string representation.

It also didn't work to use the same column name in two different aggregates,
for example, pivot=a;b;min(c),max(c).  They would both end up showing the
value of min(c).
diff --git a/render.js b/render.js
index ecc45c5..abc52bd 100644
--- a/render.js
+++ b/render.js
@@ -560,7 +560,7 @@
         var colkey = [];
         for (var coli in colkey_incols) {
           var colnum = colkey_incols[coli];
-          colkey.push(row[colnum]);
+          colkey.push(stringifiedCol(row[colnum], ingrid.types[colnum]));
         }
         for (var coli in valkeys) {
           var xcolkey = colkey.concat([valkeys[coli]]);
@@ -570,7 +570,7 @@
             // just clutter.
             var name = valkeys.length > 1 ?
                 xcolkey.join(' ') : colkey.join(' ');
-            var colnum = keyToColNum(ingrid, valkeys[coli]);
+            var colnum = rowkeys.length + colkeys.length + parseInt(coli);
             colkey_outcols[xcolkey] = outgrid.headers.length;
             valuecols[xcolkey] = colnum;
             outgrid.headers.push(name);
@@ -590,7 +590,7 @@
       var colkey = [];
       for (var coli in colkey_incols) {
         var colnum = colkey_incols[coli];
-        colkey.push(row[colnum]);
+        colkey.push(stringifiedCol(row[colnum], ingrid.types[colnum]));
       }
       for (var coli in valkeys) {
         var xcolkey = colkey.concat([valkeys[coli]]);
@@ -1443,7 +1443,7 @@
           $(el).height(window.innerHeight);
           options.height = window.innerHeight;
           t.draw(datatable, options);
-        }
+        };
         doRender();
         $(window).resize(function() {
           clearTimeout(resizeTimer);
@@ -1706,6 +1706,7 @@
       trySplitOne: trySplitOne,
       dataToGvizTable: dataToGvizTable,
       guessTypes: guessTypes,
+      myParseDate: myParseDate,
       groupBy: groupBy,
       pivotBy: pivotBy,
       stringifiedCols: stringifiedCols,
@@ -1722,6 +1723,11 @@
       runqueue: runqueue,
       gridFromData: gridFromData
     },
+    T_NUM: T_NUM,
+    T_DATE: T_DATE,
+    T_DATETIME: T_DATETIME,
+    T_BOOL: T_BOOL,
+    T_STRING: T_STRING,
     parseArgs: parseArgs,
     exec: exec,
     render: wrap(render)
diff --git a/t/trender.js b/t/trender.js
index ba09458..0340a40 100644
--- a/t/trender.js
+++ b/t/trender.js
@@ -239,3 +239,71 @@
     WVPASSEQ(grid.data, [[1, 1, 2]]);
   });
 });
+
+wvtest('pivot', function() {
+  var rawdata = [
+    ['a', 'b', 'c'],
+    ['fred', 9, '2013/01/02'],
+    ['bob', 7, '2013/01/01'],
+    ['fred', 11, '2013/02/03']
+  ];
+  var mpd = afterquery.internal.myParseDate;
+  afterquery.exec('group=a,b;only(c),count(c)', rawdata, function(grid) {
+    WVPASSEQ(grid.headers, ['a', 'b', 'c', 'c']);
+    WVPASSEQ(grid.data, [
+      ['fred', 9, mpd('2013/01/02'), 1],
+      ['bob', 7, mpd('2013/01/01'), 1],
+      ['fred', 11, mpd('2013/02/03'), 1]
+    ]);
+  });
+  afterquery.exec('pivot=a;b;only(c)', rawdata, function(grid) {
+    WVPASSEQ(grid.headers, ['a', 9, 7, 11]);
+    WVPASSEQ(grid.types, [
+      afterquery.T_STRING,
+      afterquery.T_DATE,
+      afterquery.T_DATE,
+      afterquery.T_DATE
+    ]);
+    WVPASSEQ(grid.data, [
+      ['fred', mpd('2013/01/02'), null, mpd('2013/02/03')],
+      ['bob', null, mpd('2013/01/01'), null]
+    ]);
+  });
+  afterquery.exec('pivot=a;b;c', rawdata, function(grid) {
+    WVPASSEQ(grid.headers, ['a', 9, 7, 11]);
+    WVPASSEQ(grid.types, [
+      afterquery.T_STRING,
+      afterquery.T_NUM,
+      afterquery.T_NUM,
+      afterquery.T_NUM
+    ]);
+    WVPASSEQ(grid.data, [
+      ['fred', 1, null, 1],
+      ['bob', null, 1, null]
+    ]);
+  });
+  afterquery.exec('pivot=a;b;only(c),count(c)', rawdata, function(grid) {
+    WVPASSEQ(grid.headers, [
+      'a',
+      '9 only(c)', '9 count(c)',
+      '7 only(c)', '7 count(c)',
+      '11 only(c)', '11 count(c)'
+    ]);
+    WVPASSEQ(grid.data, [
+      ['fred', mpd('2013/01/02'), 1, null, null, mpd('2013/02/03'), 1],
+      ['bob', null, null, mpd('2013/01/01'), 1, null, null]
+    ]);
+  });
+  afterquery.exec('pivot=a;b,c;count(*)', rawdata, function(grid) {
+    WVPASSEQ(grid.headers, [
+      'a',
+      '9 2013-01-02',
+      '7 2013-01-01',
+      '11 2013-02-03'
+    ]);
+    WVPASSEQ(grid.data, [
+      ['fred', 1, null, 1],
+      ['bob', null, 1, null]
+    ]);
+  });
+});