In fuzz testing I have found some differences between `WHERE` and `IF` clauses 
that want to get feedback from the broader community.

If you try to query with a `null` we will reject it

```
@Test  
public void test() throws IOException  
{  
    try (Cluster cluster = Cluster.build(1).start())  
    {  
        init(cluster);  
        cluster.schemaChange(withKeyspace("CREATE TABLE %s.tbl(pk int, ck int, 
v0 int, v1 int, primary key(pk, ck))"));  
        var inst = cluster.coordinator(1);  
  
        inst.execute(withKeyspace("INSERT INTO %s.tbl (pk, ck, v0) VALUES (?, 
?, ?)"), ConsistencyLevel.ALL, 0, 0, 0);  
        AssertUtils.assertRows(inst.execute(withKeyspace("SELECT * FROM %s.tbl 
WHERE pk=? AND ck=? and v1=? ALLOW FILTERING"), ConsistencyLevel.ALL, 0, 0, 
null),  
                               rows());  
    }  
}
```

This fails as follows

```
org.apache.cassandra.exceptions.InvalidRequestException: Invalid null value for 
column v1
```

But if you do this in the `IF` clause it is accepted

```
@Test  
public void test() throws IOException  
{  
    try (Cluster cluster = Cluster.build(1).start())  
    {  
        init(cluster);  
        cluster.schemaChange(withKeyspace("CREATE TABLE %s.tbl(pk int, ck int, 
v0 int, v1 int, primary key(pk, ck))"));  
        var inst = cluster.coordinator(1);  
  
  
        inst.execute(withKeyspace("UPDATE %s.tbl SET v1=0 WHERE pk=0 AND ck=0 
IF v0=?"), ConsistencyLevel.QUORUM, new Object[]{null});  
        AssertUtils.assertRows(inst.execute(withKeyspace("SELECT * FROM %s.tbl 
WHERE pk=? AND ck=?"), ConsistencyLevel.SERIAL, 0, 0, null),  
                               rows());  
    }  
}
```

CAS accepts this and will apply the `UPDATE` (the row doesn't exist, so `null = 
null => true`; this behavior isn't consistent).

Most of the project treats `null` as something that won't ever match, which is 
consistent with other DBs

```
sqlite> select * from employees;
sqlite> insert into employees (id, name, age, department) values (0, "name", 
42, "cassandra");
sqlite> insert into employees (id, name, age) values (1, "name2", 42);
sqlite> select * from employees where department = null;
sqlite> sqlite> select * from employees where department is null;
        id = 1
      name = name2
       age = 42
department = NULL
sqlite>
```

```
postgres=# select * from employees where department = null;
 id | name | age | department
----+------+-----+------------
(0 rows)
postgres=# select * from employees where department is null;
 id | name  | age | department
----+-------+-----+------------
  1 | name2 |  42 |
(1 row)
```

So I guess my main question; is this a bug or a feature?

Reply via email to