[ 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)