Optional fields

A Toql query can select individual fields from a struct. However fields must be Option for this, otherwise they will always be selected in the SQL statement, regardless of the query.

Example:

#   #[tokio::main(flavor="current_thread")]
#   async fn main() {
use toql::prelude::{Toql, ToqlApi, query, Cache};
use toql::mock_db::MockDb;
  #[derive(Toql)]
    struct User {

        #[toql(key)]
        id: u32,			// Always selected in SQL (keys must not be optional)

        age: u8,			// Always selected in SQL

        firstname: Option<String>,	// Selectable field of non nullable column
        middlename: Option<Option<String>>,// Selectable field of nullable column

        #[toql(preselect)]	
        lastname: Option<String>	// Always selected in SQL, nullable column
  }
    let cache = Cache::default();
    let mut toql = MockDb::from(&cache);
  
    // Load preselected fields
    let q = query!(User, "id"); 
    let mut _users = toql.load_many(&q).await.unwrap(); 
    assert_eq!(toql.take_unsafe_sql(), 
            "SELECT user.id, user.age, user.lastname FROM User user");

#  }

You noticed it: Nullable columns that should always be selected must be annotated with preselect.

Preselection and joins

Preselected fields on joined structs are selected, if

  • A join itself is preselected
  • or at least one field on that join is selected

Preselection example

#   #[tokio::main(flavor="current_thread")]
#   async fn main() {
use toql::prelude::{Toql, ToqlApi, query, Cache};
use toql::mock_db::MockDb;
  #[derive(Toql)]
    struct User {

        #[toql(key)]
        id: u32,

        #[toql(join())]
        native_language: Language,	// Preselected inner join

        #[toql(join())]
        foreign_language: Option<Option<Language>>,
    }

    #[derive(Toql)]
    struct Language {
            #[toql(key)]
            id: u32,

            code: Option<String>
    }
    let cache = Cache::default();
    let mut toql = MockDb::from(&cache);
  
    // Load preselected fields
    let q = query!(User, "id"); 
    let mut _users = toql.load_many(&q).await.unwrap(); 
    assert_eq!(toql.take_unsafe_sql(), 
            "SELECT user.id, user_nativeLanguage.id \
            FROM User user \
            JOIN (Language user_nativeLanguage) \
            ON (user.native_language_id = user_nativeLanguage.id)");

#  }

Above id in User is always selected, because it's not Option. As native_language is a preselected (inner) join, its id will also always be selected. But on the contrary foreign_language is a selectable (left) join. id will only be selected if the query requests any other field from that join. For example with foreignLanguage_code.

Preselection on parent paths

One more thing: If a field on a related struct is selected, all preselected fields from the path line will be selected too.

Lets assume we have a user that has an address, which contains country information.

The query

address_country_code

would therefore

  • select code from the table Country
  • select all preseleted fields from table Country
  • select all preseleted fields from table Address
  • select all preseleted fields from table User