Introduce an Attribute object to handle the type casting dance

Depends on #15429 and includes the changes from that PR as well. There's a lot more that can be moved to these, but this felt like a good place to introduce the object. Plans are:

- Remove all knowledge of type casting from the columns, beyond a
  reference to the `cast_type`
- Move `type_cast_for_database` to these objects
- Potentially make them mutable, introduce a state machine, and have
  dirty checking handled here as well
- Move `attribute`, `decorate_attribute`, and anything else that
  modifies types to mess with this object, not the columns hash
- Introduce a collection object to manage these, and reduce allocations
I think is worth to benchmark. If it is only an optimisation we need to make clear because I imagine if I change it to use `||=` tests will not fail and since there is no information about this optimisation it will be lost.