[ 
https://issues.apache.org/jira/browse/PHOENIX-1001?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14013168#comment-14013168
 ] 

James Taylor commented on PHOENIX-1001:
---------------------------------------

Good catch, [~twdsi...@gmail.com]. Can you try the following in 
ExpressionCompiler.visitLeave(FunctionParseNode node, List<Expression> 
children) and let me know if it's better? If an expression is not 
deterministic, we shouldn't be rewriting it as a literal. There may be other 
occurrences of this in the code base as well.

{code}
    @Override
    /**
     * @param node a function expression node
     * @param children the child expression arguments to the function 
expression node.
     */
    public Expression visitLeave(FunctionParseNode node, List<Expression> 
children) throws SQLException {
        children = node.validate(children, context);
        Expression expression = node.create(children, context);
        ImmutableBytesWritable ptr = context.getTempPtr();
        if (expression.isStateless() && expression.isDeterministic()) {
            Object value = null;
            PDataType type = expression.getDataType();
            if (expression.evaluate(null, ptr)) {
                value = type.toObject(ptr);
            }
            return LiteralExpression.newConstant(value, type, 
expression.isDeterministic());
        }
        BuiltInFunctionInfo info = node.getInfo();
        for (int i = 0; i < info.getRequiredArgCount(); i++) { 
            // Optimization to catch cases where a required argument is null 
resulting in the function
            // returning null. We have to wait until after we create the 
function expression so that
            // we can get the proper type to use.
            if (node.evalToNullIfParamIsNull(context, i)) {
                Expression child = children.get(i);
                if (child.isStateless() && child.isDeterministic() && 
(!child.evaluate(null, ptr) || ptr.getLength() == 0)) {
                    return LiteralExpression.newConstant(null, 
expression.getDataType(), child.isDeterministic());
                }
            }
        }
        expression = addExpression(expression);
        expression = wrapGroupByExpression(expression);
        if (aggregateFunction == node) {
            aggregateFunction = null; // Turn back off on the way out
        }
        return expression;
    }
{code}

> Using NEXT VALUE FOR 'sequence' as an input to a function cause a NPE
> ---------------------------------------------------------------------
>
>                 Key: PHOENIX-1001
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-1001
>             Project: Phoenix
>          Issue Type: Bug
>            Reporter: Thomas D'Silva
>         Attachments: 1001.patch
>
>
> I get a NPE while trying to write a test that  uses NEXT VALUE of a sequence 
> as an input to a function.
>  
> For example 
> {code:sql}
> CREATE SEQUENCE foo.bar START WITH 0 INCREMENT BY 62
> SELECT INVERT(NEXT VALUE FOR foo.bar) FROM SYSTEM."SEQUENCE"
> {code}
> causes an exception
> java.lang.NullPointerException
>       at 
> org.apache.phoenix.compile.SequenceManager$SequenceValueExpression.evaluate(SequenceManager.java:189)
>       at 
> org.apache.phoenix.expression.function.InvertFunction.evaluate(InvertFunction.java:47)
>       at 
> org.apache.phoenix.compile.ExpressionCompiler.visitLeave(ExpressionCompiler.java:288)
>       at 
> org.apache.phoenix.compile.ProjectionCompiler$SelectClauseVisitor.visitLeave(ProjectionCompiler.java:560)
>       at 
> org.apache.phoenix.compile.ExpressionCompiler.visitLeave(ExpressionCompiler.java:1)
>       at 
> org.apache.phoenix.parse.FunctionParseNode.accept(FunctionParseNode.java:79)
>       at 
> org.apache.phoenix.compile.ProjectionCompiler.compile(ProjectionCompiler.java:325)
>       at 
> org.apache.phoenix.compile.QueryCompiler.compileSingleQuery(QueryCompiler.java:325)
>       at 
> org.apache.phoenix.compile.QueryCompiler.compile(QueryCompiler.java:130)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$ExecutableSelectStatement.compilePlan(PhoenixStatement.java:291)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$ExecutableSelectStatement.compilePlan(PhoenixStatement.java:1)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:206)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:1)
>       at 
> org.apache.phoenix.util.PhoenixContextExecutor.call(PhoenixContextExecutor.java:54)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement.executeQuery(PhoenixStatement.java:202)
>       at 
> org.apache.phoenix.jdbc.PhoenixPreparedStatement.executeQuery(PhoenixPreparedStatement.java:157)
>       at org.apache.phoenix.end2end.SequenceIT.test123(SequenceIT.java:596)
>       
>       
> I was able to fix this error by changing isStateless() to return false for 
> SequenceValueParseNode and SeuenceValueExpression, however this caused tests 
> to fail in SequenceIT when it tries to use NEXT VALUE in an UPSERT
> java.sql.SQLException: ERROR 204 (22008): Values in UPSERT must evaluate to a 
> constant.
>       at 
> org.apache.phoenix.exception.SQLExceptionCode$Factory$1.newException(SQLExceptionCode.java:309)
>       at 
> org.apache.phoenix.exception.SQLExceptionInfo.buildException(SQLExceptionInfo.java:133)
>       at 
> org.apache.phoenix.compile.UpsertCompiler.compile(UpsertCompiler.java:652)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$ExecutableUpsertStatement.compilePlan(PhoenixStatement.java:435)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$ExecutableUpsertStatement.compilePlan(PhoenixStatement.java:1)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$3.call(PhoenixStatement.java:244)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$3.call(PhoenixStatement.java:1)
>       at 
> org.apache.phoenix.util.PhoenixContextExecutor.call(PhoenixContextExecutor.java:54)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement.executeMutation(PhoenixStatement.java:235)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement.execute(PhoenixStatement.java:946)
>       at 
> org.apache.phoenix.end2end.SequenceIT.testInsertNextValueFor(SequenceIT.java:191)
>       



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to