Add an integer ordered list to dataset "Dataset" and "Index" optinally.

For the case the primary or secondary index key contains fields from the meta
record associated with a dataset record, we need an integer ordered
list to indicate which record a key field comes from.

Change-Id: I979c642ebd60e53213369f1e2070146b4c26e805
Reviewed-on: https://asterix-gerrit.ics.uci.edu/683
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: abdullah alamoudi <bamousaa@gmail.com>
Reviewed-by: Michael Blow <michael.blow@couchbase.com>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterix-lang-aql/src/main/javacc/AQL.html b/asterix-lang-aql/src/main/javacc/AQL.html
index 3da5e77..d3670d6 100644
--- a/asterix-lang-aql/src/main/javacc/AQL.html
+++ b/asterix-lang-aql/src/main/javacc/AQL.html
@@ -342,7 +342,7 @@
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod21">DatasetSpecification</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>( "external" &lt;DATASET&gt; <A HREF="#prod30">QualifiedName</A> &lt;LEFTPAREN&gt; <A HREF="#prod27">TypeName</A> &lt;RIGHTPAREN&gt; <A HREF="#prod28">IfNotExists</A> "using" <A HREF="#prod31">AdapterName</A> <A HREF="#prod32">Configuration</A> ( "on" <A HREF="#prod18">Identifier</A> )? ( "hints" <A HREF="#prod33">Properties</A> )? ( "using" "compaction" "policy" <A HREF="#prod34">CompactionPolicy</A> ( <A HREF="#prod32">Configuration</A> )? )? | ( "internal" | "temporary" )? &lt;DATASET&gt; <A HREF="#prod30">QualifiedName</A> &lt;LEFTPAREN&gt; <A HREF="#prod27">TypeName</A> ( &lt;COMMA&gt; <A HREF="#prod27">TypeName</A> )? &lt;RIGHTPAREN&gt; <A HREF="#prod28">IfNotExists</A> <A HREF="#prod35">PrimaryKey</A> ( "autogenerated" )? ( "on" <A HREF="#prod18">Identifier</A> )? ( "hints" <A HREF="#prod33">Properties</A> )? ( "using" "compaction" "policy" <A HREF="#prod34">CompactionPolicy</A> ( <A HREF="#prod32">Configuration</A> )? )? ( "with filter on" <A HREF="#prod36">NestedField</A> )? )</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( "external" &lt;DATASET&gt; <A HREF="#prod30">QualifiedName</A> &lt;LEFTPAREN&gt; <A HREF="#prod27">TypeName</A> &lt;RIGHTPAREN&gt; <A HREF="#prod28">IfNotExists</A> "using" <A HREF="#prod31">AdapterName</A> <A HREF="#prod32">Configuration</A> ( "on" <A HREF="#prod18">Identifier</A> )? ( "hints" <A HREF="#prod33">Properties</A> )? ( "using" "compaction" "policy" <A HREF="#prod34">CompactionPolicy</A> ( <A HREF="#prod32">Configuration</A> )? )? | ( "internal" | "temporary" )? &lt;DATASET&gt; <A HREF="#prod30">QualifiedName</A> &lt;LEFTPAREN&gt; <A HREF="#prod27">TypeName</A> &lt;RIGHTPAREN&gt; ( &lt;WITH&gt; <A HREF="#prod18">Identifier</A> &lt;LEFTPAREN&gt; <A HREF="#prod27">TypeName</A> &lt;RIGHTPAREN&gt; )? <A HREF="#prod28">IfNotExists</A> <A HREF="#prod35">PrimaryKey</A> ( "autogenerated" )? ( "on" <A HREF="#prod18">Identifier</A> )? ( "hints" <A HREF="#prod33">Properties</A> )? ( "using" "compaction" "policy" <A HREF="#prod34">CompactionPolicy</A> ( <A HREF="#prod32">Configuration</A> )? )? ( "with filter on" <A HREF="#prod36">NestedField</A> )? )</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod16">RefreshExternalDatasetStatement</A></TD>
@@ -562,7 +562,7 @@
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod36">NestedField</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>( "@" )? <A HREF="#prod18">Identifier</A> ( &lt;DOT&gt; <A HREF="#prod18">Identifier</A> )*</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod18">Identifier</A> ( &lt;LEFTPAREN&gt; &lt;RIGHTPAREN&gt; )? ( &lt;DOT&gt; <A HREF="#prod18">Identifier</A> )*</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod40">StringLiteral</A></TD>
diff --git a/asterix-lang-aql/src/main/javacc/AQL.jj b/asterix-lang-aql/src/main/javacc/AQL.jj
index ea95871..8205021 100644
--- a/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -408,14 +408,14 @@
   Map<String,String> properties = null;
   Map<String,String> compactionPolicyProperties = null;
   FunctionSignature appliedFunction = null;
-  List<List<String>> primaryKeyFields = null;
+  Pair<List<Integer>, List<List<String>>> primaryKeyFields = null;
   String nodeGroupName = null;
   Map<String,String> hints = new HashMap<String,String>();
   DatasetDecl dsetDecl = null;
   boolean autogenerated = false;
   String compactionPolicy = null;
   boolean temp = false;
-  List<String> filterField = null;
+  Pair<Integer, List<String>> filterField = null;
   Pair<Identifier,Identifier> metaTypeComponents = new Pair<Identifier, Identifier>(null, null);
 }
 {
@@ -471,9 +471,13 @@
     ( "using" "compaction" "policy" compactionPolicy = CompactionPolicy() (compactionPolicyProperties = Configuration())? )?
     ( "with filter on" filterField = NestedField() )?
       {
-        InternalDetailsDecl idd = new InternalDetailsDecl(primaryKeyFields,
+        if(filterField!=null && filterField.first!=0){
+          throw new ParseException("A filter field can only be a field in the main record of the dataset.");
+        }
+        InternalDetailsDecl idd = new InternalDetailsDecl(primaryKeyFields.second,
+                                                          primaryKeyFields.first,
                                                           autogenerated,
-                                                          filterField,
+                                                          filterField == null? null : filterField.second,
                                                           temp);
         dsetDecl = new DatasetDecl(nameComponents.first,
                                    nameComponents.second,
@@ -537,7 +541,7 @@
   String indexName = null;
   boolean ifNotExists = false;
   Pair<Identifier,Identifier> nameComponents = null;
-  Pair<List<String>, TypeExpression> fieldPair = null;
+  Pair<Integer, Pair<List<String>, TypeExpression>> fieldPair = null;
   IndexParams indexType = null;
   boolean enforced = false;
 }
@@ -547,11 +551,13 @@
   "on" nameComponents = QualifiedName()
   <LEFTPAREN> ( fieldPair = OpenField()
     {
-      cis.addFieldExprPair(fieldPair);
+       cis.addFieldExprPair(fieldPair.second);
+       cis.addFieldIndexIndicator(fieldPair.first);
     }
   ) (<COMMA> fieldPair = OpenField()
     {
-      cis.addFieldExprPair(fieldPair);
+       cis.addFieldExprPair(fieldPair.second);
+       cis.addFieldIndexIndicator(fieldPair.first);
     }
   )* <RIGHTPAREN> ( "type" indexType = IndexType() )? ( "enforced" { enforced = true; } )?
     {
@@ -817,23 +823,26 @@
     }
 }
 
-List<List<String>> PrimaryKey() throws ParseException:
+Pair<List<Integer>, List<List<String>>> PrimaryKey() throws ParseException:
 {
-  List<String> tmp = null;
-  List<List<String>> primaryKeyFields = new ArrayList<List<String>>();
+   Pair<Integer, List<String>> tmp = null;
+   List<Integer> keyFieldSourceIndicators = new ArrayList<Integer>();
+   List<List<String>> primaryKeyFields = new ArrayList<List<String>>();
 }
 {
   "primary" "key" tmp = NestedField()
     {
-      primaryKeyFields.add(tmp);
+      keyFieldSourceIndicators.add(tmp.first);
+      primaryKeyFields.add(tmp.second);
     }
   ( <COMMA> tmp = NestedField()
     {
-      primaryKeyFields.add(tmp);
+      keyFieldSourceIndicators.add(tmp.first);
+      primaryKeyFields.add(tmp.second);
     }
   )*
     {
-      return primaryKeyFields;
+      return new Pair<List<Integer>, List<List<String>>> (keyFieldSourceIndicators, primaryKeyFields);
     }
 }
 
@@ -1381,23 +1390,25 @@
   )
 }
 
-Pair<List<String>, TypeExpression> OpenField() throws ParseException:
+Pair<Integer, Pair<List<String>, TypeExpression>> OpenField() throws ParseException:
 {
   TypeExpression fieldType = null;
-  List<String> fieldList = null;
+  Pair<Integer, List<String>> fieldList = null;
 }
 {
   fieldList = NestedField()
   ( <COLON> fieldType =  IndexedTypeExpr() )?
   {
-    return new Pair<List<String>, TypeExpression>(fieldList, fieldType);
+    return new Pair<Integer, Pair<List<String>, TypeExpression>>
+           (fieldList.first, new Pair<List<String>, TypeExpression>(fieldList.second, fieldType));
   }
 }
 
-List<String> NestedField() throws ParseException:
+Pair<Integer, List<String>> NestedField() throws ParseException:
 {
   List<String> exprList = new ArrayList<String>();
   String lit = null;
+  int source = 0;
 }
 {
   lit = Identifier()
@@ -1405,14 +1416,14 @@
     boolean meetParens = false;
   }
   (
+    LOOKAHEAD(1)
     <LEFTPAREN><RIGHTPAREN>
     {
-        if(lit.equals("meta")){
-            exprList.add(lit+"()");
-        }else{
+        if(!lit.equals("meta")){
             throw new ParseException("The string before () has to be \"meta\".");
         }
         meetParens = true;
+        source = 1;
     }
   )?
   {
@@ -1427,7 +1438,7 @@
     }
   )*
   {
-    return exprList;
+    return new Pair<Integer, List<String>>(source, exprList);
   }
 }