Module hdbconnect::code_examples
[−]
[src]
Here are some code examples for the usage of this database driver.
1. Get an authenticated database connection
Establish a physical connecton to the database server ...
let (host, port): (&str, &str) = ...; let mut connection = try!(Connection::new(host,port));
.. and authenticate to the database:
let (user, pw): (&str, &str) = ...; try!(connection.authenticate_user_password(user, pw));
2. Query the database
The most generic way to fire SQL statements without preparation is using
Connection::any_statement()
.
This generic method can handle all kinds of calls,
and thus has the most complex return type, HdbResponse
.
let my_statement = "..."; // some statement that doesn't need preparation let response: HdbResponse = try!(connection.any_statement(my_statement));
HdbResponse
is quite a complex nested enum which covers all possible
return values we can get from the database.
You thus have to analyze it to come to the
concrete response relevant for your call.
You can do this either explicitly using match
etc or with the
adequate short-cut method, e.g.:
let resultset: ResultSet = try!(response.as_resultset());
You can do the same of course with HdbResponse
s obtained from the execution
of prepared statements.
In many cases it will be more appropriate and convenient to use one of the specialized methods
query_statement()
-> ResultSetdml_statement()
-> usizeexec_statement()
-> ()which have the adequate simple result type you usually want:
let my_statement = "..."; // some statement that doesn't need preparation let resultset: ResultSet = try!(connection.query_statement(my_statement));
In many cases, you will need or want to use prepared statements. Then the code will look like this:
let stmt_str = "insert into TEST_PREPARE (F_STRING, F_INTEGER) values(?, ?)"; let mut stmt = try!(connection.prepare(stmt_str)); try!(stmt.add_batch(&("foo", 45_i32))); try!(stmt.add_batch(&("bar", 46_i32))); try!(stmt.execute_batch());
Or like this:
let stmt_str = "select NAME, CITY from TEST_TABLE where age > ?"; let mut stmt = try!(connection.prepare(stmt_str)); try!(stmt.add_batch(&(45_i32))); let resultset: ResultSet = try!(stmt.execute_batch());
3. Evaluate a resultset
Evaluating a resultset by traversing rows and columns should always be possible, of course, but there's again a more convenient alternative. Thanks to the usage of serde you can convert the resultset directly into a fitting rust structure.
Note that you need to specify the type of your target variable explicitly, so that
ResultSet::into_typed(self)
can derive the type it needs to serialize into.
Depending on the usecase, ResultSet::into_typed(self)
supports a variety of target data structures,
with the only strong limitation that no data loss is supported.
It depends on the dimension of the resultset what target data structures you can choose for deserialization:
You can always use a
Vec<MyRow>
, whereMyRow
is a struct or tuple that matches the fields of the resultset.#[derive(Deserialize)] struct MyRow { ... } let result: Vec<MyRow> = try!(resultset.into_typed());
If the resultset contains only a single line (e.g. because you specified TOP 1 in your select, or qualified the full primary key), then you can optionally choose to deserialize into a plain
MyRow
directly.#[derive(Deserialize)] struct MyRow { ... } let result: MyRow = try!(resultset.into_typed());
If the resultset contains only a single column, then you can optionally choose to deserialize into a
Vec<field>
, wherefield
is a type that matches the field of the resultset.let result: Vec<u32> = try!(resultset.into_typed());
If the resultset contains only a single value (one row with one column), then you can optionally choose to deserialize into a plain
MyRow
, or aVec<field>
, or afield
.let result: u32 = try!(resultset.into_typed());
Also the (de)serialization of the individual field values provides flexibility.
You can e.g. convert values from a nullable column into a plain field, provided that no NULL values are given in the resultset.
Vice versa, you always can use an Option
<field>
, even if the column is marked as NOT NULL.Similarly, integer types can differ, as long as the returned values can be assigned without loss.