#[query]Expand description
Register a query call entry point.
This attribute macro will export a function with name canister_query <name>
in the canister module.
§Examples
§Basic Usage
#[query]
fn query_function() {
// ...
}§Custom Export Name
You can customize the name of the exported function.
#[query(name = "some_name")]
fn query_function() {
// ...
}§Hide From Candid Generation
If you want to hide this method in the Candid generated by export_candid!,
you will need to set hidden to true. The entry point still exists in the canister.
#[query(hidden = true)]
fn query_function() {
// ...
}§Guard Functions
You can specify one or more guard functions to be executed before the query function.
Each guard function must return a Result<(), String>.
If any guard function returns an error, the query function will not proceed.
fn guard1() -> Result<(), String> {
// ...
}
fn guard2() -> Result<(), String> {
// ...
}
#[query(guard = "guard1", guard = "guard2")]
fn query_function() {
// ...
}§Custom Argument Decoding
You can specify a custom function to decode the arguments.
The function must take a Vec<u8> as an argument and return the same type as the query arguments.
fn decode_args(arg_bytes: Vec<u8>) -> (u32, u32) {
// ...
}
#[query(decode_with = "decode_args")]
fn query_function(a: u32, b: u32) {
// ...
}§Custom Return Value Encoding
You can specify a custom function to encode the return value.
The function must take the query return value as argument and return a Vec<u8>.
fn encode_result(result: (u32, u32)) -> Vec<u8> {
// ...
}
#[query(encode_with = "encode_result")]
fn query_function() -> (u32, u32) {
// ...
}§Composite Queries
To be able to make inter-canister calls from a query call, it must be a composite query (which cannot be executed in replicated mode).
#[query(composite = true)]
async fn composite_query_function() {
let (wallet_name,): (Option<String>,) = ic_cdk::call(wallet_canister_principal(), "name", ()).await.unwrap();
}§Manual Reply
The query macro defaults to invoke msg_reply() after the function execution.
If you want to execute other code after msg_reply(), you can:
- set
manual_replytotruein macro attribute; - set the return type to
PhantomData<T>whereTis the return type of the update method; - call the
msg_reply()function explicitly; - do other stuff;
- return
PhantomData;
#[query(manual_reply = true)]
fn query_function() -> PhantomData<MyResult> {
let result = calculate_result();
let reply_bytes = candid::encode_one(result).unwrap();
ic_cdk::api::msg_reply(reply_bytes);
PhantomData
}