Implement EXPLAIN for SQL++

- move some code from static methods in ResultUtils to a stateful
  ResultPrinter to facilitate reuse (we create one ResultWriter per request)
- tiny cleanup in LogicalOperatorPrettyPrintVisitor

Change-Id: I7b7028fb243d494150cac525c73b2d77b0068646
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1020
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <buyingyi@gmail.com>
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index afc970a..8f9a201 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -316,7 +316,8 @@
     | stmt = UpdateStatement()
     | stmt = FeedStatement()
     | stmt = CompactStatement()
-    | stmt = Query() <SEMICOLON>
+    | stmt = ExplainStatement()
+    | stmt = Query(false) <SEMICOLON>
     | stmt = RefreshExternalDatasetStatement()
     | stmt = RunStatement()
   )
@@ -925,7 +926,7 @@
   Query query;
 }
 {
-  <INSERT> <INTO> nameComponents = QualifiedName() query = Query()
+  <INSERT> <INTO> nameComponents = QualifiedName() query = Query(false)
     {
       query.setTopLevel(true);
       return new InsertStatement(nameComponents.first, nameComponents.second, query, getVarCounter());
@@ -1562,10 +1563,20 @@
     }
 }
 
-
-Query Query() throws ParseException:
+Query ExplainStatement() throws ParseException:
 {
-  Query query = new Query();
+  Query query;
+}
+{
+  "explain" query = Query(true)
+  {
+    return query;
+  }
+}
+
+Query Query(boolean explain) throws ParseException:
+{
+  Query query = new Query(explain);
   // we set the pointers to the dataverses and datasets lists to fill them with entities to be locked
   setDataverses(query.getDataverses());
   setDatasets(query.getDatasets());