Author: knoguchi
Date: Wed Jan 18 22:53:46 2017
New Revision: 1779397

URL: http://svn.apache.org/viewvc?rev=1779397&view=rev
Log:
PIG-3938: Add LoadCaster to EvalFunc (knoguchi)

Modified:
    pig/trunk/CHANGES.txt
    pig/trunk/src/docs/src/documentation/content/xdocs/basic.xml
    pig/trunk/src/docs/src/documentation/content/xdocs/udf.xml
    pig/trunk/src/org/apache/pig/EvalFunc.java
    pig/trunk/src/org/apache/pig/LoadFunc.java
    pig/trunk/src/org/apache/pig/StreamToPig.java
    
pig/trunk/src/org/apache/pig/backend/hadoop/executionengine/physicalLayer/expressionOperators/POCast.java
    
pig/trunk/src/org/apache/pig/newplan/logical/visitor/LineageFindRelVisitor.java
    pig/trunk/test/e2e/pig/tests/negative.conf
    pig/trunk/test/org/apache/pig/test/TestEvalPipeline.java
    pig/trunk/test/org/apache/pig/test/TestLineageFindRelVisitor.java
    pig/trunk/test/org/apache/pig/test/TestTypeCheckingValidatorNewLP.java

Modified: pig/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/pig/trunk/CHANGES.txt?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/CHANGES.txt (original)
+++ pig/trunk/CHANGES.txt Wed Jan 18 22:53:46 2017
@@ -34,6 +34,8 @@ PIG-5067: Revisit union on numeric type
  
 IMPROVEMENTS
 
+PIG-3938: Add LoadCaster to EvalFunc (knoguchi)
+
 PIG-5105: Tez unit tests failing with "Argument list too long" (rohini)
 
 PIG-4901: To use Multistorage for each Group (szita via daijy)

Modified: pig/trunk/src/docs/src/documentation/content/xdocs/basic.xml
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/docs/src/documentation/content/xdocs/basic.xml?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/src/docs/src/documentation/content/xdocs/basic.xml (original)
+++ pig/trunk/src/docs/src/documentation/content/xdocs/basic.xml Wed Jan 18 
22:53:46 2017
@@ -8771,8 +8771,8 @@ DUMP U;
    </ul>
    
    
-   <section>
-   <title>About Input and Output</title>
+   <section id="pig-streaming-input-output">
+   <title>About Input and Output for Streaming</title>
    <p>Serialization is needed to convert data from tuples to a format that can 
be processed by the streaming application. Deserialization is needed to convert 
the output from the streaming application back into tuples. PigStreaming is the 
default serialization/deserialization function.</p>
    
 <p>Streaming uses the same default format as PigStorage to 
serialize/deserialize the data. If you want to explicitly specify a format, you 
can do it as show below (see more examples in the Examples: Input/Output 
section).  </p> 
@@ -8803,7 +8803,7 @@ interface StreamToPig {
     public Tuple deserialize(byte[]) throws IOException;
 
     /**
-     * This will be called on the front end during planning and not on the back
+     * This will be called on both the front end and the back
      * end during execution.
      *
      * @return the {@link LoadCaster} associated with this object.

Modified: pig/trunk/src/docs/src/documentation/content/xdocs/udf.xml
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/docs/src/documentation/content/xdocs/udf.xml?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/src/docs/src/documentation/content/xdocs/udf.xml (original)
+++ pig/trunk/src/docs/src/documentation/content/xdocs/udf.xml Wed Jan 18 
22:53:46 2017
@@ -976,6 +976,14 @@ public class CurrentTime extends EvalFun
 }
 </source>
 </section>
+<section id="udf-loadcaster">
+<title>Typecasting from bytearrays</title>
+<p>Just like <a href="#load-functions">Load Function</a> and <a 
href="basic.html#pig-streaming-input-output">Streaming</a>,
+Java UDF has a getLoadCaster() method that returns
+<a 
href="http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/LoadCaster.java?view=markup";>LoadCaster</a>
+to convert byte arrays to specific types. A UDf implementation should 
implement this if casts (implicit or explicit) from DataByteArray fields to 
other types need to be supported. Default implementation returns null and Pig 
will determine if all parameters passed to the UDF have identical loadcaster 
and use it when true. </p>
+</section>
+
 <section id="tez-jvm-reuse">
         <title>Clean up static variable in Tez</title>
         <p>In Tez, jvm could reuse for other tasks. It is important to cleanup 
static variable to make sure there is no side effect. Here is one example:</p>

Modified: pig/trunk/src/org/apache/pig/EvalFunc.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/EvalFunc.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/EvalFunc.java (original)
+++ pig/trunk/src/org/apache/pig/EvalFunc.java Wed Jan 18 22:53:46 2017
@@ -369,4 +369,17 @@ public abstract class EvalFunc<T>  {
 
     public void setEndOfAllInput(boolean endOfAllInput) {
     }
+
+    /**
+     * This will be called on both the front end and the back
+     * end during execution.
+     * @return the {@link LoadCaster} associated with this eval. Returning null
+     * indicates that casts from bytearray will pick the one associated with 
the
+     * parameters when they all come from the same loadcaster type.
+     * @throws IOException if there is an exception during LoadCaster
+     */
+    public LoadCaster getLoadCaster() throws IOException {
+        return null;
+    }
+
 }

Modified: pig/trunk/src/org/apache/pig/LoadFunc.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/LoadFunc.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/LoadFunc.java (original)
+++ pig/trunk/src/org/apache/pig/LoadFunc.java Wed Jan 18 22:53:46 2017
@@ -108,7 +108,7 @@ public abstract class LoadFunc {
     public abstract InputFormat getInputFormat() throws IOException;
 
     /**
-     * This will be called on the front end during planning and not on the 
back 
+     * This will be called on both the front end and the back
      * end during execution.
      * @return the {@link LoadCaster} associated with this loader. Returning 
null 
      * indicates that casts from byte array are not supported for this loader. 

Modified: pig/trunk/src/org/apache/pig/StreamToPig.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/StreamToPig.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/StreamToPig.java (original)
+++ pig/trunk/src/org/apache/pig/StreamToPig.java Wed Jan 18 22:53:46 2017
@@ -57,7 +57,7 @@ public interface StreamToPig {
     public Tuple deserialize(byte[] bytes) throws IOException;
 
     /**
-     * This will be called on the front end during planning and not on the back
+     * This will be called on both the front end and the back
      * end during execution.
      *
      * @return the {@link LoadCaster} associated with this object, or null if

Modified: 
pig/trunk/src/org/apache/pig/backend/hadoop/executionengine/physicalLayer/expressionOperators/POCast.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/backend/hadoop/executionengine/physicalLayer/expressionOperators/POCast.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- 
pig/trunk/src/org/apache/pig/backend/hadoop/executionengine/physicalLayer/expressionOperators/POCast.java
 (original)
+++ 
pig/trunk/src/org/apache/pig/backend/hadoop/executionengine/physicalLayer/expressionOperators/POCast.java
 Wed Jan 18 22:53:46 2017
@@ -28,6 +28,7 @@ import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.pig.EvalFunc;
 import org.apache.pig.FuncSpec;
 import org.apache.pig.LoadCaster;
 import org.apache.pig.LoadFunc;
@@ -89,6 +90,8 @@ public class POCast extends ExpressionOp
                 caster = ((LoadFunc)obj).getLoadCaster();
             } else if (obj instanceof StreamToPig) {
                 caster = ((StreamToPig)obj).getLoadCaster();
+            } else if (obj instanceof EvalFunc) {
+                caster = ((EvalFunc)obj).getLoadCaster();
             } else {
                 throw new IOException("Invalid class type "
                         + funcSpec.getClassName());

Modified: 
pig/trunk/src/org/apache/pig/newplan/logical/visitor/LineageFindRelVisitor.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/newplan/logical/visitor/LineageFindRelVisitor.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- 
pig/trunk/src/org/apache/pig/newplan/logical/visitor/LineageFindRelVisitor.java 
(original)
+++ 
pig/trunk/src/org/apache/pig/newplan/logical/visitor/LineageFindRelVisitor.java 
Wed Jan 18 22:53:46 2017
@@ -24,6 +24,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.pig.EvalFunc;
 import org.apache.pig.FuncSpec;
 import org.apache.pig.LoadCaster;
 import org.apache.pig.LoadFunc;
@@ -731,10 +732,39 @@ public class LineageFindRelVisitor exten
 
         @Override
         public void visit(UserFuncExpression op) throws FrontendException {
-            
if(op.getFuncSpec().getClassName().equals(IdentityColumn.class.getName())) {
-                // IdentityColumn only expects one arg
-                FuncSpec funcSpec = 
uid2LoadFuncMap.get(op.getArguments().get(0).getFieldSchema().uid);
+
+            if( op.getFieldSchema() == null ) {
+                return;
+            }
+
+            FuncSpec funcSpec = null;
+            Class loader = instantiateCaster(op.getFuncSpec());
+            List<LogicalExpression> arguments = op.getArguments();
+            if ( loader != null ) {
+                // if evalFunc.getLoadCaster() returns, simply use that.
+                funcSpec = op.getFuncSpec();
+            } else if (arguments.size() != 0 ) {
+                FuncSpec baseFuncSpec = null;
+                LogicalFieldSchema fs = arguments.get(0).getFieldSchema();
+                if ( fs != null ) {
+                    baseFuncSpec = uid2LoadFuncMap.get(fs.uid);
+                    if( baseFuncSpec != null ) {
+                        funcSpec = baseFuncSpec;
+                        for(int i = 1; i < arguments.size(); i++) {
+                            fs = arguments.get(i).getFieldSchema();
+                            if( fs == null || 
!haveIdenticalCasters(baseFuncSpec, uid2LoadFuncMap.get(fs.uid)) ) {
+                                funcSpec = null;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if( funcSpec != null ) {
                 addUidLoadFuncToMap(op.getFieldSchema().uid, funcSpec);
+                // in case schema is nested, set funcSpec for all
+                setLoadFuncForUids(op.getFieldSchema().schema, funcSpec);
             }
         }
 
@@ -779,6 +809,8 @@ public class LineageFindRelVisitor exten
                 caster = ((LoadFunc)obj).getLoadCaster();
             } else if (obj instanceof StreamToPig) {
                 caster = ((StreamToPig)obj).getLoadCaster();
+            } else if (obj instanceof EvalFunc) {
+                caster = ((EvalFunc)obj).getLoadCaster();
             } else {
                 throw new VisitorException("Invalid class type " + 
funcSpec.getClassName(),
                                            2270, PigException.BUG );

Modified: pig/trunk/test/e2e/pig/tests/negative.conf
URL: 
http://svn.apache.org/viewvc/pig/trunk/test/e2e/pig/tests/negative.conf?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/test/e2e/pig/tests/negative.conf (original)
+++ pig/trunk/test/e2e/pig/tests/negative.conf Wed Jan 18 22:53:46 2017
@@ -568,24 +568,7 @@ store D into ':OUTPATH:';\,
                         'expected_err_regex' => "Could not resolve 
StringStoreBad using imports",
                        },
                ]
-               },
-               {
-               'name' => 'LineageErrors',
-               'tests' => [
-                       {
-                       # UDF returns a bytearray that is cast to an integer
-                'num' => 1,
-                'pig' => q\register :FUNCPATH:/testudf.jar;
-a = load ':INPATH:/singlefile/studenttab10k' as (name, age, gpa);
-b = filter a by name lt 'b';
-c = foreach b generate 
org.apache.pig.test.udf.evalfunc.CreateMap((chararray)name, age);
-d = foreach c generate $0#'alice young' as field_bytearray;
-split d into e if field_bytearray < 42, f if field_bytearray >= 42;
-store e into ':OUTPATH:';\,
-                'expected_err_regex' => "Received a bytearray from the UDF or 
Union from two different Loaders. Cannot determine how to convert the bytearray 
to int for \\[field_bytearray\\[6,",
-            },
-        ]
-        }
+               }
     ]
 }
 ;

Modified: pig/trunk/test/org/apache/pig/test/TestEvalPipeline.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/test/org/apache/pig/test/TestEvalPipeline.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/test/org/apache/pig/test/TestEvalPipeline.java (original)
+++ pig/trunk/test/org/apache/pig/test/TestEvalPipeline.java Wed Jan 18 
22:53:46 2017
@@ -290,7 +290,7 @@ public class TestEvalPipeline {
             myMap.put("long", new Long(1));
             myMap.put("float", new Float(1.0));
             myMap.put("double", new Double(1.0));
-            myMap.put("dba", new DataByteArray(new 
String("bytes").getBytes()));
+            myMap.put("dba", new DataByteArray(new String("1234").getBytes()));
             myMap.put("map", mapInMap);
             myMap.put("tuple", tuple);
             myMap.put("bag", bag);
@@ -771,32 +771,31 @@ public class TestEvalPipeline {
     }
 
     @Test
-    public void testMapUDFfail() throws Exception{
+    public void testMapUDFWithImplicitTypeCast() throws Exception{
         int LOOP_COUNT = 2;
         File tmpFile = Util.createTempFileDelOnExit("test", "txt");
         PrintStream ps = new PrintStream(new FileOutputStream(tmpFile));
         for(int i = 0; i < LOOP_COUNT; i++) {
-            for(int j=0;j<LOOP_COUNT;j+=2){
-                ps.println(i+"\t"+j);
-                ps.println(i+"\t"+j);
-            }
+            ps.println(i);
         }
         ps.close();
 
         pigServer.registerQuery("A = LOAD '"
                 + Util.generateURI(tmpFile.toString(), pigContext) + "';");
         pigServer.registerQuery("B = foreach A generate " + 
MapUDF.class.getName() + "($0) as mymap;"); //the argument does not matter
-        String query = "C = foreach B {"
-        + "generate mymap#'dba' * 10;"
-        + "};";
+        String query = "C = foreach B generate mymap#'dba' * 10; ";
 
         pigServer.registerQuery(query);
-        try {
-            pigServer.openIterator("C");
-            Assert.fail("Error expected.");
-        } catch (Exception e) {
-            e.getMessage().contains("Cannot determine");
+
+        Iterator<Tuple> iter = pigServer.openIterator("C");
+        if(!iter.hasNext()) Assert.fail("No output found");
+        int numIdentity = 0;
+        while(iter.hasNext()){
+            Tuple t = iter.next();
+            Assert.assertEquals(new Integer(12340), (Integer)t.get(0));
+            ++numIdentity;
         }
+        Assert.assertEquals(LOOP_COUNT, numIdentity);
     }
 
     @Test

Modified: pig/trunk/test/org/apache/pig/test/TestLineageFindRelVisitor.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/test/org/apache/pig/test/TestLineageFindRelVisitor.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/test/org/apache/pig/test/TestLineageFindRelVisitor.java (original)
+++ pig/trunk/test/org/apache/pig/test/TestLineageFindRelVisitor.java Wed Jan 
18 22:53:46 2017
@@ -20,10 +20,14 @@ package org.apache.pig.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import junit.framework.Assert;
 
+import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.pig.FuncSpec;
@@ -35,6 +39,15 @@ import org.apache.pig.builtin.mock.Stora
 import org.apache.pig.data.DataByteArray;
 import org.apache.pig.data.Tuple;
 import org.apache.pig.impl.io.FileSpec;
+import org.apache.pig.impl.logicalLayer.FrontendException;
+import org.apache.pig.newplan.DependencyOrderWalker;
+import org.apache.pig.newplan.OperatorPlan;
+import org.apache.pig.newplan.PlanWalker;
+import org.apache.pig.newplan.ReverseDependencyOrderWalker;
+import org.apache.pig.newplan.logical.expression.CastExpression;
+import org.apache.pig.newplan.logical.expression.LogicalExpressionPlan;
+import org.apache.pig.newplan.logical.expression.LogicalExpressionVisitor;
+import org.apache.pig.newplan.logical.optimizer.AllExpressionVisitor;
 import org.apache.pig.newplan.logical.relational.LOLoad;
 import org.apache.pig.newplan.logical.relational.LogicalPlan;
 import org.apache.pig.newplan.logical.visitor.LineageFindRelVisitor;
@@ -49,7 +62,8 @@ public class TestLineageFindRelVisitor {
 
     private PigServer pig ;
 
-    public TestLineageFindRelVisitor() throws Throwable {
+    @Before
+    public void setUp() throws Exception{
         pig = new PigServer(Util.getLocalTestMode()) ;
     }
 
@@ -80,6 +94,13 @@ public class TestLineageFindRelVisitor {
         }
     }
 
+    public static class ToTupleWithCustomLoadCaster extends 
org.apache.pig.builtin.TOTUPLE {
+        @Override
+        public LoadCaster getLoadCaster() throws IOException {
+            return new SillyLoadCasterWithExtraConstructor("ignored");
+        }
+    }
+
     @Test
     public void testhaveIdenticalCasters() throws Exception {
         LogicalPlan lp = new LogicalPlan();
@@ -134,7 +155,7 @@ public class TestLineageFindRelVisitor {
                            (Boolean) testMethod.invoke(lineageFindRelVisitor,
                                      casterWithExtraConstuctorSpec, 
casterWithExtraConstuctorSpec) );
 
-        Assert.assertEquals("Loader should be instantiated at most once.", 
SillyLoaderWithLoadCasterWithExtraConstructor.counter, 1);
+        Assert.assertEquals("Loader should be instantiated at most once.", 1, 
SillyLoaderWithLoadCasterWithExtraConstructor.counter);
     }
 
     @Test
@@ -164,4 +185,139 @@ public class TestLineageFindRelVisitor {
                 new String[] {"('aaa', 'bbb')"});
         Util.checkQueryOutputs(actualResults.iterator(), expectedResults);
     }
+
+    @Test
+    public void testUDFForwardingLoadCaster() throws Exception {
+        Storage.Data data = Storage.resetData(pig);
+        data.set("input",
+                Storage.tuple(new DataByteArray("aaa")),
+                Storage.tuple(new DataByteArray("bbb")));
+        pig.setBatchOn();
+        String query = "A = load 'input' using mock.Storage() as 
(a1:bytearray);"
+            + "B = foreach A GENERATE TOTUPLE(a1) as tupleA;"
+            + "C = foreach B GENERATE (chararray) tupleA.a1;"  //using 
loadcaster
+            + "store C into 'output' using mock.Storage();";
+
+        LogicalPlan lp = Util.parse(query, pig.getPigContext());
+        Util.optimizeNewLP(lp);
+
+        CastFinder cf = new CastFinder(lp);
+        cf.visit();
+        Assert.assertEquals("There should be only one typecast expression.", 
1, cf.casts.size());
+        Assert.assertEquals("Loadcaster should be coming from the Load", 
"mock.Storage", cf.casts.get(0).getFuncSpec().getClassName());
+
+        pig.registerQuery(query);
+        pig.executeBatch();
+
+        List<Tuple> actualResults = data.get("output");
+        List<Tuple> expectedResults = Util.getTuplesFromConstantTupleStrings(
+                new String[] {"('aaa')", "('bbb')"});
+        Util.checkQueryOutputs(actualResults.iterator(), expectedResults);
+    }
+
+    @Test
+    public void testUDFgetLoadCaster() throws Exception {
+        Storage.Data data = Storage.resetData(pig);
+        data.set("input",
+                Storage.tuple(new DataByteArray("aaa")),
+                Storage.tuple(new DataByteArray("bbb")));
+        pig.setBatchOn();
+        String query = "A = load 'input' using mock.Storage() as 
(a1:bytearray);"
+            + "B = foreach A GENERATE 
org.apache.pig.test.TestLineageFindRelVisitor$ToTupleWithCustomLoadCaster(a1) 
as tupleA;"
+            + "C = foreach B GENERATE (chararray) tupleA.a1;" //using 
loadcaster
+            + "store C into 'output' using mock.Storage();";
+
+        pig.registerQuery(query);
+        pig.executeBatch();
+
+        LogicalPlan lp = Util.parse(query, pig.getPigContext());
+        Util.optimizeNewLP(lp);
+
+        CastFinder cf = new CastFinder(lp);
+        cf.visit();
+        Assert.assertEquals("There should be only one typecast expression.", 
1, cf.casts.size());
+        Assert.assertEquals("Loadcaster should be coming from the UDF", 
"org.apache.pig.test.TestLineageFindRelVisitor$ToTupleWithCustomLoadCaster", 
cf.casts.get(0).getFuncSpec().getClassName());
+
+        List<Tuple> actualResults = data.get("output");
+        List<Tuple> expectedResults = Util.getTuplesFromConstantTupleStrings(
+                new String[] {"('aaa')", "('bbb')"});
+        Util.checkQueryOutputs(actualResults.iterator(), expectedResults);
+    }
+
+    @Test
+    public void testUDFForwardingLoadCasterWithMultipleParams() throws 
Exception{
+        File inputfile = Util.createFile(new String[]{"123","456","789"});
+
+        pig.registerQuery("A = load '"
+                + inputfile.toString()
+                + "' using PigStorage() as (a1:bytearray);\n");
+        pig.registerQuery("B = load '"
+                + inputfile.toString()
+                + "' using PigStorage() as (b1:bytearray);\n");
+        pig.registerQuery("C = join A by a1, B by b1;\n");
+        pig.registerQuery("D = FOREACH C GENERATE TOTUPLE(a1,b1) as 
tupleD;\n");
+        pig.registerQuery("E = FOREACH D GENERATE (chararray) tupleD.a1;\n");
+        Iterator<Tuple> iter  = pig.openIterator("E");
+
+        Assert.assertEquals("123", iter.next().get(0));
+        Assert.assertEquals("456", iter.next().get(0));
+        Assert.assertEquals("789", iter.next().get(0));
+    }
+
+    @Test
+    public void testNegativeUDFForwardingLoadCasterWithMultipleParams() throws 
Exception {
+        File inputfile = Util.createFile(new String[]{"123","456","789"});
+
+        pig.registerQuery("A = load '"
+                + inputfile.toString()
+                + "' using PigStorage() as (a1:bytearray);\n");
+        pig.registerQuery("B = load '"
+                + inputfile.toString()
+                + "' using 
org.apache.pig.test.TestLineageFindRelVisitor$SillyLoaderWithLoadCasterWithExtraConstructor2()
 as (b1:bytearray);\n");
+        pig.registerQuery("C = join A by a1, B by b1;\n");
+        pig.registerQuery("D = FOREACH C GENERATE TOTUPLE(a1,b1) as 
tupleD;\n");
+        pig.registerQuery("E = FOREACH D GENERATE (chararray) tupleD.a1;\n");
+        try {
+            Iterator<Tuple> iter  = pig.openIterator("E");
+
+            // this should fail since above typecast cannot determine which
+            // loadcaster to use (one from PigStroage and another from
+            // SillyLoaderWithLoadCasterWithExtraConstructor2)
+            fail("Above typecast should fail since it cannot determine which 
loadcaster to use.");
+        } catch (IOException e) {
+            Assert.assertTrue(e.getMessage().contains("Unable to open iterator 
for alias E"));
+        }
+
+
+    }
+
+    /**
+     * Find all casts in the plan (Copied from 
TestTypeCheckingValidatorNewLP.java)
+     */
+    class CastFinder extends AllExpressionVisitor {
+        List<CastExpression> casts = new ArrayList<CastExpression>();
+
+        public CastFinder(OperatorPlan plan)
+                throws FrontendException {
+            super(plan, new DependencyOrderWalker(plan));
+        }
+
+        @Override
+        protected LogicalExpressionVisitor getVisitor(
+                LogicalExpressionPlan exprPlan) throws FrontendException {
+            return new CastExpFinder(exprPlan, new 
ReverseDependencyOrderWalker(exprPlan));
+        }
+
+        class CastExpFinder extends LogicalExpressionVisitor{
+            protected CastExpFinder(OperatorPlan p, PlanWalker walker)
+            throws FrontendException {
+                super(p, walker);
+            }
+
+            @Override
+            public void visit(CastExpression cExp){
+                casts.add(cExp);
+            }
+        }
+    }
 }

Modified: pig/trunk/test/org/apache/pig/test/TestTypeCheckingValidatorNewLP.java
URL: 
http://svn.apache.org/viewvc/pig/trunk/test/org/apache/pig/test/TestTypeCheckingValidatorNewLP.java?rev=1779397&r1=1779396&r2=1779397&view=diff
==============================================================================
--- pig/trunk/test/org/apache/pig/test/TestTypeCheckingValidatorNewLP.java 
(original)
+++ pig/trunk/test/org/apache/pig/test/TestTypeCheckingValidatorNewLP.java Wed 
Jan 18 22:53:46 2017
@@ -4067,12 +4067,12 @@ public class TestTypeCheckingValidatorNe
 
         @Test
         public void testUDFNoInnerSchema() throws FrontendException {
-            String query = "a= load '1.txt';"
+            String query = "a= load '1.txt' using PigStorage(':') ;"
                 + "b = foreach a generate 
"+TestUDFTupleNullInnerSchema.class.getName()+"($0);"
                 + "c = foreach b generate flatten($0);"
                 + "d = foreach c generate $0 + 1;";
 
-            checkLastForeachCastLoadFunc(query, null, 0);
+            checkLastForeachCastLoadFunc(query, "PigStorage(':')");
         }
 
         //see PIG-1990


Reply via email to