One complication of implementing this in Avatica brought up by Josh Elser is how to implement commit while preserving our "stateless client" approach. Specifically, say you're access a query server behind some "dumb" load balancer. You do some stuff, but before you call commit(), the server dies. How does the client handle this? When autocommit=off, do we buffer this in memory on the client and automatically replay the calls since the last commit()?
A similar issue might be if the same client connection ends up getting a different query server node due to the load balancer. How is the uncommitted state maintained across different query server nodes?
For transactional tables, one potential solution is that when a statement causes a transaction to start, we return back the transaction metadata as part of the response. The metadata would vary based on the implementation, but for Phoenix the state that would need to be captured is based on Tephra's Transaction object. The query server would need to ensure that the data for each statement was flushed to the cluster prior to returning (see
PHOENIX-2411 for more detail). With transactions, the data can essentially be written to HBase, but not yet considered committed. Ideally, a transaction implementation could give back a simple transaction ID which would capture this metadata
For non transactional tables, other than carrying around the uncommitted data on the client (which probably isn't such a scalable solution for a true thin driver), I can't think of another better solution.