Pass Session to all Encoders/Decoders allowing UDT Encoding without local session varaible in contexts e.g. ZIO and others #2219
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
One significant limitation that Quill Encoders/Decoders have always had is that they have no access to the underlying session, only to the prepared statement. In many databases however, setting certain kinds of values on a prepared statement requires access to the session. For example, in Cassandra, creating a UDT requires access to the cluster:
For this reason, the method
udtValueOf
was defined onCassandraSession
which has access to theCluster
object.One important problem with the Cassandra contexts and UDTs however is that they rely on the method
udtValueOf
to exist directly on the Cassandra contexts (see theUdtEncodingMacro
which referencedq"$prefix.udtValueOf"
in several places, where '$prefix' is the surrounding Cassandra Context). Most of the contexts that extend CassandraSession e.g. CassandraAsyncContext, CassandraSyncContext, CassandraMonixContext etc... however this is not true of the CassandraZioContext implementations which do not store theCluster
object locally. Rather, they return a ZIO object which has a CassandraZioSession dependency (this is defined as theCIO[T]
type in CassandraZioContext). This means that for the ZIO contexts, the UDT functionality do not work (* unless a nasty workaround is employed, more on that later).Also note that this problem has always existed in the CassandraLagom contexts. Those have never been able to use UDT functionality in the first place.
Now if the quill encoders could actually access the session, the
UdtEncodingMacro
could then use the session varaible for the encoders directly. This macro essentially syntheizes the encoders with theencode
function therefore if the Session (i.e. the CassandraZioContext or others in our case) is available on that function, it could be used directly. Also note that some additional refactoring ofCassandraMapper
would be required for this to be possible for mapped for mapped UDTs as well.Note however that if we add the Session to the Encoders, if it is not added to the Decoders as well, then certain problems arise. In Cassandra for example we need to modify the
CassandraMapper
to carry the Session value but if is is only available on the Encoding side, some kind of optional value (or the infamousnull
) has to be used in it's place. One other possibility is to have a variation ofCassandraMapperWithUdt
but then all the different cassandra collection encoders need to be implemented with bothCassandraMapper
andCassandraMapperWithUdt
. Since the cassandra Map encoder takes aCassandraMapper
for both keys and values, you need to implement all four variations. More pressingly, theUdtEncodingMacro
itself would have to be implemented via bothCassandraMapper
andCassandraMapperWithUdt
. For this reason, in order to maintain symmetry, the session must be passed into both the encders and decoders from whence it can be propogated intoCassandraMapper
and other places.Note that this issue is hardly exclusive to Cassandra contexts or even ZIO. One problem that Quill has had is the inability to simply create a CLOB encoder because the CLOB must be created from the Session:
If a clob encoder were to be written, we would need to be able to create it from the underlying connection. However, since currently, encoders do not have access to the underlying connection, this cannot be done in any straightfoward way.
Now the answer to all of these issues is simple, change the BaseEncoder and BasedDecoder:
This requires changes to every single context's implementation of encdoers and decoders as well as all of the tests.
Additionally in order for the Contexts to have the Session available in the
execute___
methods, they need to have recieved it from the extractors and the prepares. That means that in Context.scala, they must be changedFurthermore, the identity encoders all need to change as well:
The net of all of these changes is truly a significant refactoring touching the entirely of Quill. However because of the reasons mentioned above, I believe it is the right thing to do for the library as a whole.
README.md
if applicable[WIP]
to the pull request title if it's work in progresssbt scalariformFormat test:scalariformFormat
to make sure that the source files are formatted@getquill/maintainers