The Toql API

Toql relies on backends to handle database differences. These backends implement the ToqlApi trait which serves as an entry point for any high level function. The backends internally then use the Toql library to do their job.

This chapter explains how to use the ToqlApi trait. Notice that you must derive your structs before you can load or modify them with the ToqlApi. See the derive chapter for details.

The common ToqlApi trait makes it also possible to write database independend code. This is described here.

Creating the backend

To use the ToqlApi functions you need a Toql backend for your database.

Currently the following backends are available

Database Backend Crate Driver Crate
MySQL toql_mysql_async mysql_async

For MySQL add this to your cargo.toml:

[dependency]
toql = "0.4"
toql_mysql_async = "0.4"

You must add toql together with the backend crate. The backend crate then depends on a suitable version of the driver crate. Normally there is no need to access the driver crate. However I you really must, the backend crate re-exports the driver crate. For toql_mysql_async the driver crate can be accessed through toql_mysql_async::mysql_async.

With these two dependencies you can get the backend in your code. Notice that the backend takes a database connection and a cache object to hold the database mapping.


# #![allow(unused_variables)]

#fn main() {
use toql::prelude::Cache;
use toql::mock_db::MockDb;

let cache = Cache::new();
let mut toql = MockDb::from(&cache);

// For MySQL
// use toql_mysql_async::{prelude::MySqlAsync, mysql_async};
//
// let database_url = "mysql://USER:PASS@localhost:3306/DATABASE";
// let pool = mysql_async::Pool::new(database_url);
// let mut conn = pool.get_conn().await.unwrap();
// let toql = MySqlAsync::from(&mut conn, &cache);


#}

In a bigger project you may want to feed configuration or authentication values into your SQL. This is done through so called auxiliary parameters (aux params).

There are three ways to feed in aux params:

  • You can put them in the context and they will be available as long as the backend object lives
  • You can also ship them with a query and they will be available only for that query
  • You can map aux params to a field. Used to configure field handlers.

Here how to put them in the context:


# #![allow(unused_variables)]
#fn main() {
use toql::prelude::{Cache, ContextBuilder};
use toql::mock_db::MockDb;
use std::collections::HashMap;

let mut p = HashMap::new();
p.insert("page_limit".into(), 200.into());

let context = ContextBuilder::new().with_aux_params(p).build();
let cache = Cache::new();
let mut toql = MockDb::with_context(&cache, context);

// For MySQL
// use toql_mysql_async::{prelude::MySqlAsync, mysql_async};
//
// let database_url = "mysql://USER:PASS@localhost:3306/DATABASE";
// let pool = mysql_async::Pool::new(database_url);
// let mut conn = pool.get_conn().await.unwrap();
// let toql = MySqlAsync::with_context(&mut conn, &cache, context);

#}

Beside aux params ContextBuilder allows you

  • to choose an alias format (user.id, us1.id, t1.id, ...)
  • set the roles for access control

# #![allow(unused_variables)]
#fn main() {
use toql::prelude::{ContextBuilder, AliasFormat};
use std::collections::HashSet;

let mut roles = HashSet::new();
roles.insert("teacher".to_string());
roles.insert("admin".to_string());

 let context = ContextBuilder::new()
   .with_alias_format(AliasFormat::TinyIndex)
   .with_roles(roles)
   .build();
#}