What about aborting the transaction / raising an exception if you try and do an 
incremental operator against a non-existent PK?

The reasonable inferred intent of the user is to change a value that's expected 
to be there, so if it's not there it's an error case right? Otherwise you'd 
append "IF EXISTS".

On Fri, Jun 21, 2024, at 1:56 AM, Caleb Rackliffe wrote:
> It does, but the primary reason it does is that it is setting a value, not 
> incrementing one. When we’re setting a value, we don’t care what was there 
> before. Incrementing a value is not possible in a non-transitional update, 
> hence this thread…
> 
>> On Jun 20, 2024, at 5:17 PM, Bernardo Botella <conta...@bernardobotella.com> 
>> wrote:
>> Doesn’t an UPDATE statement creates a row if the partition key does not 
>> exist? That’s also confirmed by the official Cassandra documentation here 
>> <https://cassandra.apache.org/doc/stable/cassandra/cql/dml.html#update-statement>:
>> 
>> ”Unlike in SQL, `UPDATE` does not check the prior existence of the row by 
>> default. The row is created if none existed before, and updated otherwise. 
>> Furthermore, there is no means of knowing which action occurred.”
>> 
>> That being the case, I think the second option you mention is what keeps 
>> consistency with the UPDATEs out of the transaction.
>> 
>> Kind regards,
>> Bernardo
>> 
>>> On Jun 20, 2024, at 1:54 PM, Caleb Rackliffe <calebrackli...@gmail.com> 
>>> wrote:
>>> 
>>> We had a bug report a while back from Luis E Fernandez and team in 
>>> CASSANDRA-18988 <https://issues.apache.org/jira/browse/CASSANDRA-18988> 
>>> around the behavior of increments/decrements on numeric fields for 
>>> non-existent rows. Consider the following, wich can be run on the 
>>> cep-15-accord branch:
>>> 
>>> CREATE KEYSPACE accord WITH replication = {'class': 'SimpleStrategy', 
>>> 'replication_factor': '1'} AND durable_writes = true
>>> 
>>> CREATE TABLE accord.accounts (
>>>     partition text,
>>>     account_id int,
>>>     balance int,
>>>     PRIMARY KEY (partition, account_id)
>>> ) WITH CLUSTERING ORDER BY (account_id ASC) AND transactional_mode='full'
>>> 
>>> BEGIN TRANSACTION
>>>     INSERT INTO accord.accounts (partition, account_id, balance) VALUES 
>>> ('default', 0, 100);
>>>     INSERT INTO accord.accounts (partition, account_id, balance) VALUES 
>>> ('default', 1, 100);
>>> COMMIT TRANSACTION
>>> 
>>> BEGIN TRANSACTION
>>>     UPDATE accord.accounts SET balance -= 10 WHERE partition = 'default' 
>>> AND account_id = 1;
>>>     UPDATE accord.accounts SET balance += 10 WHERE partition = 'default' 
>>> AND account_id = 3;
>>> COMMIT TRANSACTION
>>> 
>>> Reading the 'default' partition will produce the following result.
>>> 
>>>  partition | account_id | balance
>>> -----------+------------+---------
>>>    default |          0 |     100
>>>    default |          1 |      90
>>> 
>>> As you will notice, we have not implicitly inserted a row for account_id 3, 
>>> which does not exist when we request that its balance be incremented by 10. 
>>> This is by design, as null + 10 == null.
>>> 
>>> Before I close CASSANDRA-18988 
>>> <https://issues.apache.org/jira/browse/CASSANDRA-18988>, *I'd like to 
>>> confirm with everyone reading this that the behavior above is reasonable*. 
>>> The only other option I've seen proposed that would make sense is perhaps 
>>> producing a result like:
>>> 
>>>  partition | account_id | balance
>>> -----------+------------+---------
>>>    default |          0 |     100
>>>    default |          1 |      90
>>>    default |          3 |    null
>>> 
>>> Note however that this is exactly what we would produce if we had first 
>>> inserted a row w/ no value for balance:
>>> 
>>> INSERT INTO accord.accounts (partition, account_id) VALUES ('default', 3);

Reply via email to