#odbc #database #sql

odbc-api

Write ODBC Applications in (mostly) safe Rust

20 releases (9 breaking)

new 0.10.3 Nov 21, 2020
0.9.1 Nov 11, 2020

#253 in Database interfaces

Download history 11/week @ 2020-08-09 43/week @ 2020-08-16 19/week @ 2020-08-23 52/week @ 2020-08-30 76/week @ 2020-09-06 21/week @ 2020-09-13 45/week @ 2020-09-20 81/week @ 2020-09-27 52/week @ 2020-10-04 11/week @ 2020-10-11 49/week @ 2020-10-18 33/week @ 2020-10-25 53/week @ 2020-11-01 108/week @ 2020-11-08 92/week @ 2020-11-15

228 downloads per month
Used in 2 crates

MIT license

140KB
2K SLoC

ODBC-API

ODBC (Open Database Connectivity) bindings for Rust.

Docs MIT licensed Published

Usage

Check the guide for code examples and a tour of the features.

Features

  • Connect using either Data Source names (DSN) or connection strings
  • Provide nice erros and log diagnostic output.
  • Support for columnwise bulk inserts.
  • Support for columnwise bulk queries.
  • Support for rowise bulk inserts.
  • Support for rowise bulk queries.
  • Provide general purpose implementations of buffers to bind, which can be used in safe code without caveats.
  • Support prepared and 'one shot' queries.
  • Pass parameters to queries
  • Support for async
  • Support for Multithreading

Motivation

Supports writing ODBC Application in Rust. Prior work in this area has been done:

  • odbc-sys: Bare bindings to the ODBC C Library. Declares C-Function signatures and handles linking. All other libraries mentioned are based on this one.
  • odbc-safe: (Mostly) safe wrapper around odbc-sys. Apart from protecting against unsafe behaviour, this library also tries to prevent invalid use of the ODBC API by modelling state transitions.
  • odbc-rs: Higher level and more idiomatic bindings. Wraps odbc-safe.

So why odbc-api? This is a somewhat less ambitious and more opinionated rewrite of odbc-safe. odbc-safe aimed to model all the possible state transitions offered by odbc. This turned out to be both, incredibly challenging to implement and maintain, and cumbersome to use. ODBCs way of sharing mutable buffers is very much at odds with Rusts type system, introducing significant complexity in an unopinionated general purpose wrapper. This library leaves the low level odbc abstractions as unsafe as they are, but aims to provide idiomatic interfaces for the usual high level use cases.

Design decisions

Here are some of the tradeoffs I made in this library to make my life (and hopefully that of the users a bit easier).

Commiting to one version of the ODBC Api

The underlying odbc-sys crate does not limit you to a specific ODBC version. This crate however uses ODBC version 3.8 fixed.

Use of the Wide ODBC methods returning UTF-16

Idiomatic Rust uses UTF-8. Sadly the narrow C-Methods in ODBC do not always imply the use of UTF-8, which can cause some mess with encodings (think about a Windows system with a Japanese local). Although the use of the wide methods may require the additional encoding, decoding and allocation of strings it works consistently on all platforms and configuration. Also application performance does rarely depend on how fast we process the connection string. Correct handling of the buffers for the payload is far more important. That being said. This library is not a zero cost abstraction. In some setups you may very well be able to assume that you can directly use UTF-8 and this API does introduce some overhead on such systems.

Warnings are logged

ODBC calls produce a Result. If successful they may also produce any number of warnings. These are logged away using the log crate with the warn severity. Rust type systems would have been powerful enough to express the presence of warnings in the Return type, yet I did not want to loose out on simply using ?-operator for error propagation. Also I never wanted to do something with these warnings besides logging them. Some overhead is introduced, as the messages for these warnings are allocated, even if you do not register a backend for the log crate at all.

Dependencies

~0.7–1.2MB
~25K SLoC