**Use case**

Comparison between DateTime64 and DateTime / Date types is allowed but the behavior is confusing (it looks like used numerical comparison):

* from one side for zero-precision it works as expected (values compared as datetime-based ones): 

```sql
SELECT toTypeName(dt64) AS dt64_typename, dt64 = dt
FROM 
(
    SELECT 
        toDateTime64(toStartOfInterval(now(), toIntervalSecond(1), 'UTC'), 0, 'UTC') AS dt64,
        toStartOfInterval(now(), toIntervalSecond(1), 'UTC') AS dt
)

/*
┌─dt64_typename────────┬─equals(dt64, dt)─┐
│ DateTime64(0, 'UTC') │                1 │
└──────────────────────┴──────────────────┘
*/
```
* from another side for non-zero-precision its behavior is unexpected if not used explicit type conversion:

```sql
SELECT 
    toTypeName(dt64) AS dt64_typename,
    dt64 = dt,
    toDateTime(dt64) = dt,
    dt64 = toDateTime64(dt, 1, 'UTC')
FROM 
(
    SELECT 
        toDateTime64(toStartOfInterval(now(), toIntervalSecond(1), 'UTC'), 1, 'UTC') AS dt64,
        toStartOfInterval(now(), toIntervalSecond(1), 'UTC') AS dt
)
/*
┌─dt64_typename────────┬─equals(dt64, dt)─┬─equals(toDateTime(dt64), dt)─┬─equals(dt64, toDateTime64(dt, 1, 'UTC'))─┐
│ DateTime64(1, 'UTC') │                0 │                            1 │                                        1 │
└──────────────────────┴──────────────────┴──────────────────────────────┴──────────────────────────────────────────┘
*/
```

**Describe the solution you'd like**
I think this comparison either:
- should be not allowed and throw an exception to ask for user uses explicit conversion
- or make valid implicit conversion relying on datetime/date essence of values

{
        assert(2 == types.size() && 2 == values.size());
        auto & b = static_cast<llvm::IRBuilder<> &>(builder);
        auto * x = values[0]();
        auto * y = values[1]();
        if (!types[0]->equals(*types[1]))
        {
            llvm::Type * common;
            if (x->getType()->isIntegerTy() && y->getType()->isIntegerTy())
                common = b.getIntNTy(std::max(
                    
                    
                    x->getType()->getIntegerBitWidth() + (!typeIsSigned(*types[0]) && typeIsSigned(*types[1])),
                    y->getType()->getIntegerBitWidth() + (!typeIsSigned(*types[1]) && typeIsSigned(*types[0]))));
            else
                
                common = b.getDoubleTy();
            x = nativeCast(b, types[0], x, common);
            y = nativeCast(b, types[1], y, common);
        }
        auto * result = CompileOp<Op>::compile(b, x, y, typeIsSigned(*types[0]) || typeIsSigned(*types[1]));
        return b.CreateSelect(result, b.getInt8(1), b.getInt8(0));
    }
#endif
};
}