Rajeshbabu Chintaguntla created PHOENIX-2746:
------------------------------------------------

             Summary: Delete on the table with immutable rows may fail with 
INVALID_FILTER_ON_IMMUTABLE_ROWS error code.
                 Key: PHOENIX-2746
                 URL: https://issues.apache.org/jira/browse/PHOENIX-2746
             Project: Phoenix
          Issue Type: Bug
            Reporter: Rajeshbabu Chintaguntla
            Assignee: Rajeshbabu Chintaguntla
             Fix For: 4.8.0


Some times delete on table with immutable rows is failing with below error even 
all the indexes are having the column in where condition. If we have condition 
on primary key columns it's always failing.
{noformat}
0: jdbc:phoenix:localhost> delete from t2 where a='raj1';
Error: ERROR 1027 (42Y86): All columns referenced in a WHERE clause must be 
available in every index for a table with immutable rows. tableName=T2 
(state=42Y86,code=1027)
java.sql.SQLException: ERROR 1027 (42Y86): All columns referenced in a WHERE 
clause must be available in every index for a table with immutable rows. 
tableName=T2
        at 
org.apache.phoenix.exception.SQLExceptionCode$Factory$1.newException(SQLExceptionCode.java:386)
        at 
org.apache.phoenix.exception.SQLExceptionInfo.buildException(SQLExceptionInfo.java:145)
        at 
org.apache.phoenix.compile.DeleteCompiler.compile(DeleteCompiler.java:390)
        at 
org.apache.phoenix.jdbc.PhoenixStatement$ExecutableDeleteStatement.compilePlan(PhoenixStatement.java:546)
        at 
org.apache.phoenix.jdbc.PhoenixStatement$ExecutableDeleteStatement.compilePlan(PhoenixStatement.java:534)
        at 
org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:302)
        at 
org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:295)
        at org.apache.phoenix.call.CallRunner.run(CallRunner.java:53)
        at 
org.apache.phoenix.jdbc.PhoenixStatement.executeMutation(PhoenixStatement.java:293)
        at 
org.apache.phoenix.jdbc.PhoenixStatement.execute(PhoenixStatement.java:1247)
        at sqlline.Commands.execute(Commands.java:822)
        at sqlline.Commands.sql(Commands.java:732)
        at sqlline.SqlLine.dispatch(SqlLine.java:808)
        at sqlline.SqlLine.begin(SqlLine.java:681)
        at sqlline.SqlLine.start(SqlLine.java:398)
        at sqlline.SqlLine.main(SqlLine.java:292
{noformat}

The reason is we are collecting nondisable indexes and adding to list. 
1) Once after resolving the table data table.
2) One after running select with where condition from delete. 
So the references of index table objects will be different two times if cache 
updated again 2nd time.
{noformat}
                immutableIndex = getNonDisabledImmutableIndexes(tableRefToBe);
{noformat}

So here when remove a table from immutableIndex list we should compare 
references because PTable doesn't have equal or hashCode implementations which 
will not remove any index from the list and we throw SQLException.
{noformat}
            while (plans.hasNext()) {
                QueryPlan plan = plans.next();
                PTable table = plan.getTableRef().getTable();
                if (table.getType() == PTableType.INDEX) { // index plans
                    tableRefs[i++] = plan.getTableRef();
                    immutableIndex.remove(table);
                } else { // data plan
                    /*
                     * If we have immutable indexes that we need to maintain, 
don't execute the data plan
                     * as we can save a query by piggy-backing on any of the 
other index queries, since the
                     * PK columns that we need are always in each index row.
                     */
                    plans.remove();
                }
{noformat}

If the where condition is PK column then the plans returned by compiler is only 
one because we are passing USE_DATA_OVER_INDEX_TABLE hint. Then also the 
immutableIndex list is not empty. Then also we through exception.

{noformat}
                noQueryReqd = !hasLimit;
                // Can't run on same server for transactional data, as we need 
the row keys for the data
                // that is being upserted for conflict detection purposes.
                runOnServer = isAutoCommit && noQueryReqd && 
!table.isTransactional();
                HintNode hint = delete.getHint();
                if (runOnServer && 
!delete.getHint().hasHint(Hint.USE_INDEX_OVER_DATA_TABLE)) {
                    hint = HintNode.create(hint, 
Hint.USE_DATA_OVER_INDEX_TABLE);
                }
{noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to