[
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, [[email protected]]. 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)