Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
allow users to specify bind type (jmoiron#520)
This is a thread-safe implementation of jmoiron#520, which adds a single function `sqlx.BindDriver(driverName string, bindType int)` that allows users of sqlx to specify the bind type for any driver. This allows rebinding, and therefore named queries, to work in a lot more cases: * a new driver is released but not yet catalogued in SQLX * users customize a driver and give it a new name To do this, a registry had to be created so that it could be updated at runtime. This represents a synchronization problem, as it would be written to and read from after compile time. I tried two approaches: * use `sync.Map` * use `atomic.Value` and load/store the registry Details within, but `sync.Map` ended up being 5x slower, and the `atomic.Value` approach was ~2.5x slower: ``` goos: linux goarch: amd64 pkg: github.com/jmoiron/sqlx original: BenchmarkBindSpeed/old-4 100000000 11.0 ns/op sync.Map: BenchmarkBindSpeed/new-4 24575726 50.8 ns/op atomic.Value BenchmarkBindSpeed/new-4 42535839 27.5 ns/op ``` Despite the slower showing, using `atomic.Value` in this way has a correctness tradeoff. Loads and Stores are guaranteed to be atomic, but using Load+Store means that in cases of simultaneous writes, a write could get lost. This would be a _very_ difficult bug to find, so I've opted for `sync.Map` despite the worse performance. I think this is an acceptable trade-off as this is really unlikely to be in any hot loops. If this performance degredation does become a problem, another option would be to hardcode the original registry in a switch as in the original implementation, and only fallback on the custom registry. I don't know of a use case where people would want to _change_ the bindtype of a driver whose bindtype is already known, but the flexibility seems worth it as the performance lost doesn't seem like it's important.
- Loading branch information