Repository: rcoh/angle-grinder (rust)

Issue:
Timeslice operator
See https://github.com/rcoh/angle-grinder/commit/274d34233bec9fd78ae680651efa58ad13b2a2e0 for a template
A non trivial undertaking. My suggested path:
- [ ] Add a `date` subtype to `data::Value` -- this will include the date rendering logic
- [ ] Add a parseDate expression that produces a `date` value from a string
- [ ] Create the timeslice operator that accepts an `Expression<Date>` as an argument and does the bucketing (nontrivial)
- [ ] Add an automatic `sort by _timeslice` automatically after groupingby `_timeslice`

Proposed query structure:
```* | parse "* * *" as level, date, message | timeslice(parseDate(level)) 5m | count by _timeslice```


Pull request description:
[lib] if _timeslice is used in an aggregate, include it in the sort keys
If the user is grouping by the slice, they probably want the
results displayed from earliest to latest.

(Hmm, it looks like sorting is not quite right since the direction
 is for the entire sort operator and not a per-key thing.)

Fixes #10

Patch:
diff --git a/src/lib.rs b/src/lib.rs
index 5556d93..e926ab5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -105,13 +105,26 @@ pub mod pipeline {
         }
 
         fn implicit_sort(multi_agg: &MultiAggregateOperator) -> SortOperator {
+            let timeslice_col = Expr::column("_timeslice");
+            let (opt_timeslice, direction) = if multi_agg.key_cols.contains(&timeslice_col) {
+                (Some(timeslice_col), SortMode::Ascending)
+            } else {
+                (None, SortMode::Descending)
+            };
+
+            let sort_cols: Vec<Expr> = opt_timeslice
+                .into_iter()
+                .chain(
+                    multi_agg
+                        .aggregate_functions
+                        .iter()
+                        .map(|&(ref k, _)| Expr::column(k)),
+                )
+                .collect();
+
             SortOperator {
-                sort_cols: multi_agg
-                    .aggregate_functions
-                    .iter()
-                    .map(|&(ref k, _)| Expr::column(k))
-                    .collect(),
-                direction: SortMode::Descending,
+                sort_cols,
+                direction,
             }
         }
 


Test patch:
diff --git a/tests/structured_tests/timeslice_1.toml b/tests/structured_tests/timeslice_1.toml
index 31818fd..d11a83c 100644
--- a/tests/structured_tests/timeslice_1.toml
+++ b/tests/structured_tests/timeslice_1.toml
@@ -17,8 +17,8 @@ input = """
 output = """
 _timeslice                     _count
 ---------------------------------------------
-2013-09-06 22:00:00 UTC        7
 2013-09-06 20:00:00 UTC        2
+2013-09-06 22:00:00 UTC        7
 2013-09-06 22:05:00 UTC        2
 2013-09-06 22:10:00 UTC        1
 2013-09-06 23:05:00 UTC        1