Closed jtaylor-sfdc closed 10 years ago
Am getting this when i try to execute this
com.salesforce.phoenix.exception.PhoenixParserException: ERROR 603 (42P00): Syntax error. Mismatched input. Expecting "FROM", got "[" at line 1, column 66.
at com.salesforce.phoenix.parse.SQLParser.parseStatement(SQLParser.java:116)
at com.salesforce.phoenix.jdbc.PhoenixStatement$PhoenixStatementParser.parseStatement(PhoenixStatement.java:868)
at com.salesforce.phoenix.jdbc.PhoenixStatement.parseStatement(PhoenixStatement.java:935)
at com.salesforce.phoenix.jdbc.PhoenixPreparedStatement.
But when the query is "SELECT CASE WHEN A_INTEGER = 1 THEN a_double_array[2] ELSE null END FROM table_with_array" it works fine. The testcase passes. Did u intend to add [2] after END and before FROM?
Try again, as my grammar change is checked in now (as is the above test, but with an @Ignore). The grammar change allows an array to be returned by an expression (i.e. remember how we were trying to allow array references to be expressions in the grammar?).
So the idea is that you can have an expression, like a CASE statement or a built-in function return an ARRAY type, like this:
SELECT CASE WHEN a=0 THEN a_array WHEN a=1 THEN b_array ELSE c_array END [the_index] FROM t
In this example, the CASE expression should evaluate to an array. It could have been written like this too:
SELECT ARRAY_ELEM(CASE WHEN a=0 THEN a_array WHEN a=1 THEN b_array ELSE c_array END, the_index) FROM t
But I'm getting a compile time error. Take a look at the following method in CaseExpression:
private static List<Expression> coerceIfNecessary(List<Expression> children) throws SQLException {
boolean isChildTypeUnknown = false;
PDataType returnType = children.get(0).getDataType();
...
The getDataType() should return an ARRAY PDataType, but my guess is that it's returning the element type instead.
Ok let me check this now.
This is what is happening, {code} boolean isChildTypeUnknown = false; PDataType returnType = children.get(0).getDataType(); {code} Here it is coming as array only. Since the ELSE condition says to make it null {code} if (isChildTypeUnknown && returnType.isCoercibleTo(PDataType.DECIMAL)) { returnType = PDataType.DECIMAL; } {code} And this is converting the expression to TO_DECIMAL(A_DOUBLE_ARRAY). The index position does not come into effect here. Now since TO_DECIMAL becomes an inbuilt function it now calls for isCoercible method where DECIMAL is checked with ARRAY which happens in FunctionParseNode.validate() method. This is where error is thrown. Checking out where could be the problem.
In syntaxes like this {code} SELECT CASE WHEN a=0 THEN a_array WHEN a=1 THEN b_array ELSE c_array END [the_index] FROM t {code} where b_array is double_array and c_array is string_array then {code} throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_CONVERT_TYPE) .setMessage("Case expressions must have common type: " + returnType + " cannot be coerced to " + childType) .build().buildException(); {code} I think this is valid, right?
I made this change {code} if (isChildTypeUnknown && returnType.isCoercibleTo(PDataType.DECIMAL)) { if (!returnType.isArrayType()) { returnType = PDataType.DECIMAL; } } {code} In CaseExpression.coerceIfNecessary, then it passes. Do let me know if this change is fine. I feel it is ok because with arrays we cannot convert it into TO_DECIMAL function. What do you think? I may be wrong here. Pls do correct me.
The check for returnType.isCoercibleTo(PDataType.DECIMAL) should fail when returnType is an array type. An array type should never be coercible to a primitive type. The isCoercibleTo check is asking "can I cast type1 to type2".
Hmm.. my bad.. I have given a fix in my new pull request.
Fixed now by @ramkrish86. Thanks for the contributions!
The following test in TestArray fails, but should succeed as the type returned by the CASE expression should be an ARRAY: