Clarify usage of Statement.setQueryTimestamp

Description

Updated description

For BATCH messages, only a global timestamp can be set with setQueryTimestamp, and will apply to all batch child statements. It’s not possible, per the protocol specs, to specify different timestamps per child statement this way – even if it is possible to achieve that effect using a different USING TIMESTAMP clause for each child query string.

As a consequence, if you call setQueryTimestamp on a child statement of a BatchStatement, it will be silently ignored.

This should be clarified in the javadocs.

Initial Description

When using Batch statements to delete rows and then re-add them, the DELETE queries must have a USING TIMESTAMP clause in the query, and the timestamp used must be earlier than the timestamp of the following INSERT statements to ensure that the DELETEs happen before the INSERTs. An example might be:

Timestamp.java

In the above example, the USING TIMESTAMP clause is part of the query string and works as expected. However, if we change the way the query is built and use setQueryTimestamp(long) on SimpleStatementBuilder:

SetQueryTimestamp.java

The query does not build the USING TIMESTAMP clause. The result, in the case of a BatchStatement with DELETE queries and INSERT queries, is that only the DELETE seems to happen.

Environment

None

Pull Requests

None

Activity

Show:
Erik Merkle
October 22, 2020, 6:55 PM

This seems to be an issue with BatchStatement. If you start with a a table like this:

And execute this:

the row is not deleted. Similarly, if you execute this:

the row is also not deleted.

If you then wrap the statement in a BatchSatetment where USING TIMESTAMP 0 is part of the query string:

again, the row is not deleted.

But, if you wrap a SimpleStaement that uses setQueryTimestamp() in a BatchStatement like this:

The row is deleted.

Now, if you wrap a SimpleStaement in a BatchStatement, but call setQueryTimeout on the BatchStatement (not on the wrapped SimpleStatement):

The row is not deleted.

The issues seems to be that calling setQueryTimestamp on a Statement is not honored if that Statement is wrapped in another Statement (like BatchStatement). Calling setQueryTimestamp does seem to be honored on the outer most Statement, however that does not work for the case where the outer statement is a BatchStatement and the batched statements include a DELETE and an INSERT with the same primary key. In this specific case, the INSERT needs to have a later timestamp than the DELETE, otherwise the result is only the DELETE being applied. Setting the timestamp on the BatchStatement seems to set the same value for all batched queries, so the INSERT would not have a newer/later timestamp than the DELETE.

The only workaround for this when using BatchStatement is to make sure the USING TIMESTAMP clause is part of the query string for the statements being batched.

Alexandre Dutra
6 days ago

setQueryTimestamp is not meant to modify the query string, it actually activates a protocol-level field holding the timestamp to use, which is a distinct field from the query string itself.

The timestamp can be set this way for:

  1. QUERY and EXECUTE messages: https://github.com/datastax/native-protocol/blob/53a2b8eb9ac704b69f153de3dc0c53982642a698/src/main/resources/native_protocol_v4.spec#L338

  2. BATCH messages: https://github.com/datastax/native-protocol/blob/53a2b8eb9ac704b69f153de3dc0c53982642a698/src/main/resources/native_protocol_v4.spec#L404

For BATCH messages, only a global timestamp can be set this way, and will apply to all batch child statements. It’s not possible, per the protocol specs, to specify different timestamps per child statement this way – even if it is possible to achieve that effect using a different USING TIMESTAMP clause for each child query string.

As a consequence, if you call setQueryTimestamp on a child statement of a BatchStatement, it will be silently ignored.

I will amend the javadocs to explicitly warn about that, but other than that, I don’t think there is a bug here.

Assignee

Alexandre Dutra

Reporter

Erik Merkle

Labels

None

PM Priority

None

Affects versions

Fix versions

Pull Request

None

Doc Impact

None

Size

None

External issue ID

None

External issue ID

None

Components

Priority

Minor
Configure