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

James Taylor commented on PHOENIX-2631:
---------------------------------------

[~sergey.soldatov] - why would the extra 4 byte part need to be treated 
differently? Before we go back to the object/timestamp value, we need to 
re-invert the bytes (that's the case with all our types).  Sounds to me like 
there's a place in ExplainTable that is not doing the re-invert. Here's a quick 
test I wrote to confirm that timestamp ordering is ok:
{code}
    @Test
    public void testTimestamp() {
        long now = System.currentTimeMillis();
        Timestamp ts1 = DateUtil.getTimestamp(now,  1111);
        final byte[] bytes1 = PTimestamp.INSTANCE.toBytes(ts1);
        Timestamp ts2 = DateUtil.getTimestamp(now,  1112);
        final byte[] bytes2 = PTimestamp.INSTANCE.toBytes(ts2);
        assertTrue(Bytes.compareTo(bytes1, bytes2) < 0);
        
        final byte[] ibytes1 = SortOrder.invert(bytes1, 0, bytes1.length);
        final byte[] ibytes2 = SortOrder.invert(bytes2, 0, bytes2.length);
        assertTrue(Bytes.compareTo(ibytes1, ibytes2) > 0);

        Timestamp ts3 = new Timestamp(now+1);
        final byte[] bytes3 = PTimestamp.INSTANCE.toBytes(ts3);
        assertTrue(Bytes.compareTo(bytes3, bytes2) > 0);
        final byte[] ibytes3 = SortOrder.invert(bytes3, 0, bytes3.length);
        assertTrue(Bytes.compareTo(ibytes3, ibytes2) < 0);
        
        Timestamp ts4 = new Timestamp(now-1);
        byte[] bytes4 = PTimestamp.INSTANCE.toBytes(ts4);
        assertTrue(Bytes.compareTo(bytes4, bytes1) < 0);
        byte[] ibytes4 = SortOrder.invert(bytes4, 0, bytes4.length);
        assertTrue(Bytes.compareTo(ibytes4, ibytes1) > 0);
    }
{code}

As a side note, Timestamp.setNanos() has a *very* strange behavior. See 
DateUtilTest.testDemonstrateSetNanosOnTimestampLosingMillis() for a 
description, but it ends up truncating your millisecond part, so it can make 
your timestamp smaller than you'd expect.

I think the code to look at is here at 
appendPKColumnValue(ExplainTable.java:194). The if statement right before the 
call to appendPKColumnValue should be inverting the timestamp bytes back:
{code}
        if (sortOrder == SortOrder.DESC) {
            buf.append('~');
            ImmutableBytesWritable ptr = new ImmutableBytesWritable(range);
            type.coerceBytes(ptr, type, sortOrder, SortOrder.getDefault());
            range = ptr.get();
        }
        Format formatter = context.getConnection().getFormatter(type);
        buf.append(type.toStringLiteral(range, formatter));
{code}

Is that block being entered and if so why not?

> Exception when parsing boundary timestamp values
> ------------------------------------------------
>
>                 Key: PHOENIX-2631
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-2631
>             Project: Phoenix
>          Issue Type: Bug
>    Affects Versions: 4.6.0, 4.7.0
>            Reporter: Nick Dimiduk
>             Fix For: 4.7.0
>
>         Attachments: 2631-workaround.patch
>
>
> I get a stack trace when querying or explaining a query that contains a 
> timestamp value on the boundary of the day.
> {noformat}
> > CREATE TABLE FOO(
>   a VARCHAR NOT NULL,
>   b TIMESTAMP NOT NULL,
>   c VARCHAR,
>   CONSTRAINT pk PRIMARY KEY (a, b DESC ROW_TIMESTAMP, c)
> ) IMMUTABLE_ROWS=true,
>   SALT_BUCKETS=20
> ;
> No rows affected (1.532 seconds)
> > explain select * from foo where a = 'a' and b >= timestamp '2016-01-28 
> > 00:00:00' and b < timestamp '2016-01-29 00:00:00';
> Error: ERROR 201 (22000): Illegal data. (state=22000,code=201)
> java.sql.SQLException: ERROR 201 (22000): Illegal data.
>       at 
> org.apache.phoenix.exception.SQLExceptionCode$Factory$1.newException(SQLExceptionCode.java:419)
>       at 
> org.apache.phoenix.exception.SQLExceptionInfo.buildException(SQLExceptionInfo.java:145)
>       at 
> org.apache.phoenix.schema.types.PDataType.newIllegalDataException(PDataType.java:286)
>       at 
> org.apache.phoenix.schema.types.PUnsignedInt$UnsignedIntCodec.decodeInt(PUnsignedInt.java:165)
>       at 
> org.apache.phoenix.schema.types.PTimestamp.toObject(PTimestamp.java:108)
>       at 
> org.apache.phoenix.schema.types.PTimestamp.toObject(PTimestamp.java:32)
>       at 
> org.apache.phoenix.schema.types.PDataType.toObject(PDataType.java:968)
>       at 
> org.apache.phoenix.schema.types.PDataType.toObject(PDataType.java:972)
>       at 
> org.apache.phoenix.schema.types.PDataType.toObject(PDataType.java:1001)
>       at 
> org.apache.phoenix.schema.types.PDataType.toStringLiteral(PDataType.java:1074)
>       at 
> org.apache.phoenix.schema.types.PDataType.toStringLiteral(PDataType.java:1070)
>       at 
> org.apache.phoenix.iterate.ExplainTable.appendPKColumnValue(ExplainTable.java:194)
>       at 
> org.apache.phoenix.iterate.ExplainTable.appendScanRow(ExplainTable.java:270)
>       at 
> org.apache.phoenix.iterate.ExplainTable.appendKeyRanges(ExplainTable.java:282)
>       at 
> org.apache.phoenix.iterate.ExplainTable.explain(ExplainTable.java:125)
>       at 
> org.apache.phoenix.iterate.BaseResultIterators.explain(BaseResultIterators.java:830)
>       at 
> org.apache.phoenix.iterate.RoundRobinResultIterator.explain(RoundRobinResultIterator.java:153)
>       at 
> org.apache.phoenix.execute.BaseQueryPlan.getPlanSteps(BaseQueryPlan.java:468)
>       at 
> org.apache.phoenix.execute.BaseQueryPlan.iterator(BaseQueryPlan.java:322)
>       at 
> org.apache.phoenix.execute.BaseQueryPlan.iterator(BaseQueryPlan.java:193)
>       at 
> org.apache.phoenix.execute.BaseQueryPlan.getExplainPlan(BaseQueryPlan.java:463)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$ExecutableExplainStatement.compilePlan(PhoenixStatement.java:459)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$ExecutableExplainStatement.compilePlan(PhoenixStatement.java:438)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$1.call(PhoenixStatement.java:266)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement$1.call(PhoenixStatement.java:261)
>       at org.apache.phoenix.call.CallRunner.run(CallRunner.java:53)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement.executeQuery(PhoenixStatement.java:260)
>       at 
> org.apache.phoenix.jdbc.PhoenixStatement.execute(PhoenixStatement.java:1349)
>       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}
> In this case, down in {{PUnsignedInt$UnsignedIntCodec#decodeInt}}, I see the 
> parsed {{v}} is {{-1}}, and the if clause throws.



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

Reply via email to