PIG-5335: Error message from range projection completely misleading (knoguchi)


git-svn-id: https://svn.apache.org/repos/asf/pig/trunk@1831606 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGES.txt b/CHANGES.txt
index ac5eb44..006538c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -65,6 +65,9 @@
 OPTIMIZATIONS
  
 BUG FIXES
+
+PIG-5335: Error message from range projection completely misleading (knoguchi)
+
 PIG-5333: LoadCaster sometimes not set for complex type (knoguchi)
 
 PIG-5328: expressionOperator Divide.equalsZero(DataType.BIGDECIMAL) is invalid (michaelthoward via knoguchi)
diff --git a/src/org/apache/pig/newplan/logical/expression/ProjectExpression.java b/src/org/apache/pig/newplan/logical/expression/ProjectExpression.java
index 49f551f..d08af04 100644
--- a/src/org/apache/pig/newplan/logical/expression/ProjectExpression.java
+++ b/src/org/apache/pig/newplan/logical/expression/ProjectExpression.java
@@ -372,9 +372,20 @@
                         }
                     }
                 }
-                if (index==-1) {
-                    if (alias!=null) {
-                        index = schema.getFieldPosition(alias);
+                if (index==-1 && alias != null) {
+                    index = schema.getFieldPosition(alias);
+                    if( index == -1 ) {
+                        // Return a place holder for this invalid field reference.
+                        // If this relation is used, error will be caught in the
+                        // LogicalPlan.validate phase.
+                        // New uid is assigned to this fake field so that invalid script
+                        // like the one on
+                        // TestColumnAliasConversion.testInvalidNestedProjection
+                        // would not fail at LogicalPlanBuilder phase
+                        // but fail at LogicalPlan.validate phase.
+                        // (PIG-5335 for more details)
+                        return new LogicalSchema.LogicalFieldSchema(alias, null, DataType.BYTEARRAY,
+                                                                   LogicalExpression.getNextUid());
                     }
                 }
                 if (index==-1)
diff --git a/test/org/apache/pig/test/TestProjectRange.java b/test/org/apache/pig/test/TestProjectRange.java
index 515d5fa..a1568be 100644
--- a/test/org/apache/pig/test/TestProjectRange.java
+++ b/test/org/apache/pig/test/TestProjectRange.java
@@ -19,6 +19,7 @@
 package org.apache.pig.test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.io.IOException;
@@ -33,6 +34,7 @@
 import org.apache.pig.impl.logicalLayer.FrontendException;
 import org.apache.pig.impl.logicalLayer.schema.Schema;
 import org.apache.pig.impl.logicalLayer.schema.Schema.FieldSchema;
+import org.apache.pig.impl.plan.PlanValidationException;
 import org.apache.pig.impl.util.Utils;
 import org.apache.pig.newplan.logical.expression.LogicalExpressionPlan;
 import org.apache.pig.newplan.logical.relational.LOCogroup;
@@ -373,6 +375,37 @@
     }
 
     /**
+     * -ve test cases
+     * @throws IOException
+     * @throws ParserException
+     */
+    @Test
+    public void testNegativeForeachFollowedByRange() throws IOException, ParserException {
+        String query =
+            "A = load '" + INP_FILE_5FIELDS + "'  as (a0,a1,a2,a3,a4);"
+            + "B = FOREACH A GENERATE a0, b1, a2, a3, a4;"
+            + "C = FOREACH B GENERATE a0..a2;";
+
+        // In PIG-5335, above query was failing at parsing time
+        // and error message didn't even mention "b1".
+        // (below generateLogicalPlan was throwing ParserException)
+        LogicalPlan lp = generateLogicalPlan(query);
+
+        // After PIG-5335, we moved the error to be caught
+        // at validation phase AND have proper error message
+        // pointing to an invalid fieldname, b1.
+        boolean exceptionCaught = false;
+        try {
+            lp.validate(pigServer.getPigContext(), "test", false);
+        } catch (PlanValidationException ex) {
+            Util.checkMessageInException(ex,
+             "Projected field [b1] does not exist in schema: a0:bytearray,a1:bytearray,a2:bytearray,a3:bytearray,a4:bytearray");
+            exceptionCaught = true;
+        }
+        assertTrue("No exception was thrown from an invalid script", exceptionCaught);
+    }
+
+    /**
      * Test foreach without schema
      * @throws IOException
      * @throws ParserException