via Benedict, here is a 4th option:

4.) Similar to #2, but don't rely on the key element being NULL.

If the read returns no result, x effectively becomes NULL. Otherwise, it
remains true/NOT NULL.

BEGIN TRANSACTION
  LET x = true FROM ks.tbl WHERE k=0 AND c=0;
  LET row2_v = v FROM ks.tbl WHERE k=1 AND c=0;
  SELECT x, row2_v
  IF x IS NULL AND row2_v = 3 THEN
    INSERT INTO ks.tbl (k, c, v) VALUES (0, 0, 1);
  END IF
COMMIT TRANSACTION

On Thu, Aug 11, 2022 at 12:12 PM Caleb Rackliffe <calebrackli...@gmail.com>
wrote:

> Hello again everyone!
>
> I've been working on a prototype
> <https://issues.apache.org/jira/browse/CASSANDRA-17719> in
> CASSANDRA-17719 for a grammar that roughly corresponds to what we've agreed
> on in this thread. One thing that isn't immediately obvious to me is how
> the LET syntax handles cases where we want to check for the plain existence
> of a row in IF. For example, in this hybrid of the originally proposed
> syntax and something more like what we've agreed on (and the RETURNING just
> to distinguish between that and SELECT), this could be pretty
> straightforward:
>
> BEGIN TRANSACTION
>   SELECT v FROM ks.tbl WHERE k=0 AND c=0 AS row1;
>   SELECT v FROM ks.tbl WHERE k=1 AND c=0 AS row2;
>   RETURNING row1.v, row2.v
>   IF row1 NOT EXISTS AND row2.v = 3 THEN
>     INSERT INTO ks.tbl (k, c, v) VALUES (0, 0, 1);
>   END IF
> COMMIT TRANSACTION
>
> The NOT EXISTS operator has row1 to work with. One the other hand, w/ the
> LET syntax and no naming of reads, it's not clear what the best solution
> would be. Here are a few possibilities:
>
> 1.) Provide a few built-in functions that operate on a whole result row.
> If we assume a SQL style IS NULL and IS NOT NULL (see my last post here)
> for operations on particular columns, this probably eliminates the need for
> EXISTS/NOT EXISTS as well.
>
> BEGIN TRANSACTION
>   LET row1_missing = notExists() FROM ks.tbl WHERE k=0 AND c=0;
>   LET row2_v = v FROM ks.tbl WHERE k=1 AND c=0;
>   SELECT row1_missing, row2_v
>   IF row1_missing AND row2_v = 3 THEN
>     INSERT INTO ks.tbl (k, c, v) VALUES (0, 0, 1);
>   END IF
> COMMIT TRANSACTION
>
> 2.) Assign and check the first primary key element to determine whether
> the row exists.
>
> BEGIN TRANSACTION
>   LET row1_k = k FROM ks.tbl WHERE k=0 AND c=0;
>   LET row2_v = v FROM ks.tbl WHERE k=1 AND c=0;
>   SELECT row1_k, row2_v
>   IF row1_k IS NULL AND row2_v = 3 THEN
>     INSERT INTO ks.tbl (k, c, v) VALUES (0, 0, 1);
>   END IF
> COMMIT TRANSACTION
>
> 3.) Reconsider the LET concept toward something that allows us to
> explicitly name our reads again.
>
> BEGIN TRANSACTION
>   WITH (SELECT v FROM ks.tbl WHERE k=0 AND c=0) AS row1;
>   WITH (SELECT v FROM ks.tbl WHERE k=1 AND c=0) AS row2;
>   SELECT row1.v, row2.v
>   IF row1 NOT EXISTS AND row2.v = 3 THEN
>     INSERT INTO ks.tbl (k, c, v) VALUES (0, 0, 1);
>   END IF
> COMMIT TRANSACTION
>
> I don't have a strong affinity for any of these, although #1 seems the
> most awkward.
>
> Does anyone have any other alternatives? Preference for one of the above
> options?
>
> Thanks!
>
> On Fri, Jul 22, 2022 at 11:21 AM Caleb Rackliffe <calebrackli...@gmail.com>
> wrote:
>
>> Avi brought up an interesting point around NULLness checking in
>> CASSANDRA-17762 <https://issues.apache.org/jira/browse/CASSANDRA-17762>
>> ...
>>
>> In SQL, any comparison with NULL is NULL, which is interpreted as FALSE
>>> in a condition. To test for NULLness, you use IS NULL or IS NOT NULL. But
>>> LWT uses IF col = NULL as a NULLness test. This is likely to confuse people
>>> coming from SQL and hamper attempts to extend the dialect.
>>
>>
>> We can leave that Jira open to address what to do in the legacy LWT case,
>> but I'd support a SQL-congruent syntax here (IS NULL or IS NOT NULL),
>> where we have something closer to a blank slate.
>>
>> Thoughts?
>>
>> On Thu, Jun 30, 2022 at 6:25 PM Abe Ratnofsky <a...@aber.io> wrote:
>>
>>> The new syntax looks great, and I’m really excited to see this coming
>>> together.
>>>
>>> One piece of feedback on the proposed syntax is around the use of “=“ as
>>> a declaration in addition to its current use as an equality operator in a
>>> WHERE clause and an assignment operator in an UPDATE:
>>>
>>> BEGIN TRANSACTION
>>>   LET car_miles = miles_driven, car_is_running = is_running FROM cars
>>> WHERE model=’pinto’
>>>   LET user_miles = miles_driven FROM users WHERE name=’blake’
>>>   SELECT something else from some other table
>>>   IF NOT car_is_running THEN ABORT
>>>   UPDATE users SET miles_driven = user_miles + 30 WHERE name='blake';
>>>   UPDATE cars SET miles_driven = car_miles + 30 WHERE model='pinto';
>>> COMMIT TRANSACTION
>>>
>>> This is supported in languages like PL/pgSQL, but in a normal SQL query
>>> kind of local declaration is often expressed as an alias (SELECT col AS
>>> new_col), subquery alias (SELECT col) t, or common table expression (WITH t
>>> AS (SELECT col)).
>>>
>>> Here’s an example of an alternative to the proposed syntax that I’d find
>>> more readable:
>>>
>>> BEGIN TRANSACTION
>>>   WITH car_miles, car_is_running AS (SELECT miles_driven, is_running
>>> FROM cars WHERE model=’pinto’),
>>>   user_miles AS (SELECT miles_driven FROM users WHERE name=’blake’)
>>>   IF NOT car_is_running THEN ABORT
>>>   UPDATE users SET miles_driven = user_miles + 30 WHERE name='blake';
>>>   UPDATE cars SET miles_driven = car_miles + 30 WHERE model='pinto';
>>> COMMIT TRANSACTION
>>>
>>> There’s also the option of naming the transaction like a subquery, and
>>> supporting LET via AS (this one I’m less sure about but wanted to propose
>>> anyway):
>>>
>>> BEGIN TRANSACTION t1
>>>   SELECT miles_driven AS t1.car_miles, is_running AS t1.car_is_running
>>> FROM cars WHERE model=’pinto’;
>>>   SELECT miles_driven AS t1.user_miles FROM users WHERE name=’blake’;
>>>   IF NOT car_is_running THEN ABORT
>>>   UPDATE users SET miles_driven = user_miles + 30 WHERE name='blake';
>>>   UPDATE cars SET miles_driven = car_miles + 30 WHERE model='pinto';
>>> COMMIT TRANSACTION
>>>
>>> This also has the benefit of resolving ambiguity in case of naming
>>> conflicts with existing (or future) column names.
>>>
>>> --
>>> Abe
>>>
>>

Reply via email to