gcp_bigquery_client/
routine.rs

1//! Manage BigQuery user-defined function or a stored procedure.
2use std::sync::Arc;
3
4use reqwest::Client;
5
6use crate::auth::Authenticator;
7use crate::error::BQError;
8use crate::model::list_routines_response::ListRoutinesResponse;
9use crate::model::routine::Routine;
10use crate::{process_response, urlencode, BIG_QUERY_V2_URL};
11
12/// A routine API handler.
13#[derive(Clone)]
14pub struct RoutineApi {
15    client: Client,
16    auth: Arc<dyn Authenticator>,
17    base_url: String,
18}
19
20impl RoutineApi {
21    pub(crate) fn new(client: Client, auth: Arc<dyn Authenticator>) -> Self {
22        Self {
23            client,
24            auth,
25            base_url: BIG_QUERY_V2_URL.to_string(),
26        }
27    }
28
29    pub(crate) fn with_base_url(&mut self, base_url: String) -> &mut Self {
30        self.base_url = base_url;
31        self
32    }
33
34    /// Creates a new routine in the dataset.
35    /// # Arguments
36    /// * `project_id` - Project ID of the new routine.
37    /// * `dataset_id` - Dataset ID of the new routine.
38    /// * `routine` - The request body contains an instance of Routine.
39    pub async fn insert(&self, project_id: &str, dataset_id: &str, routine: Routine) -> Result<Routine, BQError> {
40        let req_url = format!(
41            "{base_url}/projects/{project_id}/datasets/{dataset_id}/routines",
42            base_url = self.base_url,
43            project_id = urlencode(project_id),
44            dataset_id = urlencode(dataset_id),
45        );
46
47        let access_token = self.auth.access_token().await?;
48
49        let request = self
50            .client
51            .post(req_url.as_str())
52            .bearer_auth(access_token)
53            .json(&routine)
54            .build()?;
55
56        let resp = self.client.execute(request).await?;
57
58        process_response(resp).await
59    }
60
61    /// Lists all routines in the specified dataset. Requires the READER dataset role.
62    /// # Arguments
63    /// * `project_id` - Project ID of the routines to list.
64    /// * `dataset_id` - Dataset ID of the routines to list.
65    pub async fn list(
66        &self,
67        project_id: &str,
68        dataset_id: &str,
69        options: ListOptions,
70    ) -> Result<ListRoutinesResponse, BQError> {
71        let req_url = format!(
72            "{base_url}/projects/{project_id}/datasets/{dataset_id}/routines",
73            base_url = self.base_url,
74            project_id = urlencode(project_id),
75            dataset_id = urlencode(dataset_id),
76        );
77
78        let access_token = self.auth.access_token().await?;
79
80        let request = self
81            .client
82            .get(req_url.as_str())
83            .bearer_auth(access_token)
84            .query(&options)
85            .build()?;
86
87        let resp = self.client.execute(request).await?;
88
89        process_response(resp).await
90    }
91
92    /// Deletes the routine specified by routineId from the dataset.
93    /// # Arguments
94    /// * `project_id`- Project ID of the routine to delete
95    /// * `dataset_id` - Dataset ID of the routine to delete
96    /// * `routine_id` - Routine ID of the routine to delete
97    pub async fn delete(&self, project_id: &str, dataset_id: &str, routine_id: &str) -> Result<(), BQError> {
98        let req_url = &format!(
99            "{base_url}/projects/{project_id}/datasets/{dataset_id}/routines/{routine_id}",
100            base_url = self.base_url,
101            project_id = urlencode(project_id),
102            dataset_id = urlencode(dataset_id),
103            routine_id = urlencode(routine_id),
104        );
105
106        let access_token = self.auth.access_token().await?;
107
108        let request = self.client.delete(req_url).bearer_auth(access_token).build()?;
109        let response = self.client.execute(request).await?;
110
111        if response.status().is_success() {
112            Ok(())
113        } else {
114            Err(BQError::ResponseError {
115                error: response.json().await?,
116            })
117        }
118    }
119
120    /// Gets the specified routine resource by routine ID.
121    /// # Arguments
122    /// * `project_id`- Project ID of the requested routine
123    /// * `dataset_id` - Dataset ID of the requested routine
124    /// * `routine_id` - Routine ID of the requested routine
125    pub async fn get(&self, project_id: &str, dataset_id: &str, routine_id: &str) -> Result<Routine, BQError> {
126        let req_url = &format!(
127            "{base_url}/projects/{project_id}/datasets/{dataset_id}/routines/{routine_id}",
128            base_url = self.base_url,
129            project_id = urlencode(project_id),
130            dataset_id = urlencode(dataset_id),
131            routine_id = urlencode(routine_id),
132        );
133
134        let access_token = self.auth.access_token().await?;
135
136        let request = self.client.get(req_url).bearer_auth(access_token).build()?;
137        let response = self.client.execute(request).await?;
138
139        process_response(response).await
140    }
141
142    /// Updates information in an existing routine. The update method replaces the entire Routine
143    /// resource.
144    /// # Arguments
145    /// * `project_id`- Project ID of the routine to update
146    /// * `dataset_id` - Dataset ID of the routine to update
147    /// * `routine_id` - Routine ID of the routine to update
148    /// * `routine` - Routine to update
149    pub async fn update(
150        &self,
151        project_id: &str,
152        dataset_id: &str,
153        routine_id: &str,
154        routine: Routine,
155    ) -> Result<Routine, BQError> {
156        let req_url = &format!(
157            "{base_url}/projects/{project_id}/datasets/{dataset_id}/routines/{routine_id}",
158            base_url = self.base_url,
159            project_id = urlencode(project_id),
160            dataset_id = urlencode(dataset_id),
161            routine_id = urlencode(routine_id),
162        );
163
164        let access_token = self.auth.access_token().await?;
165
166        let request = self
167            .client
168            .put(req_url)
169            .bearer_auth(access_token)
170            .json(&routine)
171            .build()?;
172        let response = self.client.execute(request).await?;
173
174        process_response(response).await
175    }
176}
177
178#[derive(Debug, Serialize, Deserialize, Default)]
179#[serde(rename_all = "camelCase")]
180pub struct ListOptions {
181    max_results: Option<u64>,
182    page_token: Option<String>,
183    read_mask: Option<String>,
184    filter: Option<String>,
185}
186
187impl ListOptions {
188    /// The maximum number of results to return in a single response page. Leverage the page tokens
189    /// to iterate through the entire collection.
190    pub fn max_results(mut self, value: u64) -> Self {
191        self.max_results = Some(value);
192        self
193    }
194
195    /// Page token, returned by a previous call, to request the next page of results
196    pub fn page_token(mut self, value: String) -> Self {
197        self.page_token = Some(value);
198        self
199    }
200
201    /// If set, then only the Routine fields in the field mask, as well as projectId, datasetId and
202    /// routineId, are returned in the response. If unset, then the following Routine fields are
203    /// returned: etag, projectId, datasetId, routineId, routineType, creationTime,
204    /// lastModifiedTime, and language.
205    ///
206    /// A comma-separated list of fully qualified names of fields. Example: "user.displayName,photo".
207    pub fn read_mask(mut self, value: String) -> Self {
208        self.read_mask = Some(value);
209        self
210    }
211
212    /// If set, then only the Routines matching this filter are returned. The current supported form
213    /// is either "routineType:" or "routineType:", where is a RoutineType enum.
214    /// Example: "routineType:SCALAR_FUNCTION".
215    pub fn filter(mut self, value: String) -> Self {
216        self.filter = Some(value);
217        self
218    }
219}