kubo/rust-oracle

Design of `oracle::Statement` does not allow prepared statement cashing

weiznich opened this issue · 3 comments

The current design of oracle::Statement makes it hard to impossible to implement a efficient prepared statement mechanism on top of the oracle crate.

A common strategy to implement prepared statement caching is to bundle a connection and the associated statement cache into a common data structure. So any downstream crate that tries to provide a querybuilder + prepared statement caching will probably want to write code similar to this.

struct OracleConnection {
    inner: oracle::Connection,
    stmt_cache: StmtCache<oracle::Statement>,
}

Given that oracle::Statement<'a> has a lifetime 'a that is coupled to the connection type itself such a pattern is hardly possible, as rust does support self referential types poorly.

(Hit this while trying to provide a diesel connection implementation on top of this crate)

cjbj commented

Since the underlying Oracle libraries internally do statement caching, the need to write wrappers for manual caching may be lessened.

Since the underlying Oracle libraries internally do statement caching, the need to write wrappers for manual caching may be lessened.

The main problem with that internal statement caching is that it is based on heuristics. It uses the sql of the statement as cache key, which requires something like diesel to build the sql everytime a query is executed. In addition the underlying statement can change if certain types in the bind parameters change, which is not reflected just by using the sql string as cache key. Finally query builders like diesel can know in advance that certain statements should not be cached, because otherwise they can generate an unbound number of entries in the statement cache.

kubo commented

Sorry for too late reply.
I added stmt_with_lifetime feature in Cargo.toml.
When the feature is enabled, struct Statement<'conn> { ... } is declared as struct Statement { ... }.