google_cloud_bigquery/http/
bigquery_routine_client.rs

1use std::sync::Arc;
2
3use crate::http::bigquery_client::BigqueryClient;
4use crate::http::error::Error;
5use crate::http::routine;
6use crate::http::routine::list::{ListRoutinesRequest, ListRoutinesResponse, RoutineOverview};
7use crate::http::routine::Routine;
8
9#[derive(Debug, Clone)]
10pub struct BigqueryRoutineClient {
11    inner: Arc<BigqueryClient>,
12}
13
14impl BigqueryRoutineClient {
15    pub fn new(inner: Arc<BigqueryClient>) -> Self {
16        Self { inner }
17    }
18
19    /// https://cloud.google.com/bigquery/docs/reference/rest/v2/routines/create
20    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
21    pub async fn create(&self, metadata: &Routine) -> Result<Routine, Error> {
22        let builder = routine::insert::build(self.inner.endpoint(), self.inner.http(), metadata);
23        self.inner.send(builder).await
24    }
25
26    /// https://cloud.google.com/bigquery/docs/reference/rest/v2/routines/update
27    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
28    pub async fn update(&self, metadata: &Routine) -> Result<Routine, Error> {
29        let builder = routine::update::build(self.inner.endpoint(), self.inner.http(), metadata);
30        self.inner.send(builder).await
31    }
32
33    /// https://cloud.google.com/bigquery/docs/reference/rest/v2/routines/delete
34    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
35    pub async fn delete(&self, project_id: &str, dataset_id: &str, routine_id: &str) -> Result<(), Error> {
36        let builder =
37            routine::delete::build(self.inner.endpoint(), self.inner.http(), project_id, dataset_id, routine_id);
38        self.inner.send_get_empty(builder).await
39    }
40
41    /// https://cloud.google.com/bigquery/docs/reference/rest/v2/routines/get
42    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
43    pub async fn get(&self, project_id: &str, dataset_id: &str, routine_id: &str) -> Result<Routine, Error> {
44        let builder = routine::get::build(self.inner.endpoint(), self.inner.http(), project_id, dataset_id, routine_id);
45        self.inner.send(builder).await
46    }
47
48    /// https://cloud.google.com/bigquery/docs/reference/rest/v2/routines/list
49    #[cfg_attr(feature = "trace", tracing::instrument(skip_all))]
50    pub async fn list(
51        &self,
52        project_id: &str,
53        dataset_id: &str,
54        req: &ListRoutinesRequest,
55    ) -> Result<Vec<RoutineOverview>, Error> {
56        let mut page_token: Option<String> = None;
57        let mut routines = vec![];
58        loop {
59            let builder = routine::list::build(
60                self.inner.endpoint(),
61                self.inner.http(),
62                project_id,
63                dataset_id,
64                req,
65                page_token,
66            );
67            let response: ListRoutinesResponse = self.inner.send(builder).await?;
68            routines.extend(response.routines);
69            if response.next_page_token.is_none() {
70                break;
71            }
72            page_token = response.next_page_token;
73        }
74        Ok(routines)
75    }
76}
77
78#[cfg(test)]
79mod test {
80    use std::sync::Arc;
81
82    use serial_test::serial;
83    use time::OffsetDateTime;
84
85    use crate::http::bigquery_client::test::{create_client, dataset_name};
86    use crate::http::bigquery_routine_client::BigqueryRoutineClient;
87    use crate::http::routine::list::ListRoutinesRequest;
88    use crate::http::routine::{Argument, ArgumentKind, Language, Routine, RoutineReference, RoutineType};
89    use crate::http::types::{StandardSqlDataType, TypeKind};
90
91    #[tokio::test]
92    #[serial]
93    pub async fn crud_routine() {
94        let dataset = dataset_name("job");
95        let (client, project) = create_client().await;
96        let client = BigqueryRoutineClient::new(Arc::new(client));
97        let _f1 = client
98            .create(&Routine {
99                etag: "".to_string(),
100                routine_reference: RoutineReference {
101                    project_id: project.to_string(),
102                    dataset_id: dataset.to_string(),
103                    routine_id: format!("AddFourAndDivide{}", OffsetDateTime::now_utc().unix_timestamp()),
104                },
105                routine_type: RoutineType::ScalarFunction,
106                language: Some(Language::Sql),
107                definition_body: "(x + 4) / y".to_string(),
108                return_type: Some(StandardSqlDataType {
109                    type_kind: TypeKind::Float64,
110                }),
111                arguments: Some(vec![
112                    Argument {
113                        name: Some("x".to_string()),
114                        argument_kind: Some(ArgumentKind::FixedType),
115                        mode: None,
116                        data_type: StandardSqlDataType {
117                            type_kind: TypeKind::Int64,
118                        },
119                    },
120                    Argument {
121                        name: Some("y".to_string()),
122                        argument_kind: Some(ArgumentKind::FixedType),
123                        mode: None,
124                        data_type: StandardSqlDataType {
125                            type_kind: TypeKind::Int64,
126                        },
127                    },
128                ]),
129                ..Default::default()
130            })
131            .await
132            .unwrap();
133
134        let _f2 = client
135            .create(&Routine {
136                etag: "".to_string(),
137                routine_reference: RoutineReference {
138                    project_id: project.to_string(),
139                    dataset_id: dataset.clone(),
140                    routine_id: format!("ExternalTable{}", OffsetDateTime::now_utc().unix_timestamp()),
141                },
142                routine_type: RoutineType::TableValuedFunction,
143                language: Some(Language::Sql),
144                definition_body: format!(
145                    "SELECT * FROM `{}.{}.external_data` WHERE string_field_0 = x",
146                    project, dataset,
147                ),
148                arguments: Some(vec![Argument {
149                    name: Some("x".to_string()),
150                    argument_kind: Some(ArgumentKind::FixedType),
151                    mode: None,
152                    data_type: StandardSqlDataType {
153                        type_kind: TypeKind::String,
154                    },
155                }]),
156                ..Default::default()
157            })
158            .await
159            .unwrap();
160
161        let _f3 = client
162            .create(&Routine {
163                etag: "".to_string(),
164                routine_reference: RoutineReference {
165                    project_id: project.to_string(),
166                    dataset_id: dataset.to_string(),
167                    routine_id: format!("Procedure{}", OffsetDateTime::now_utc().unix_timestamp()),
168                },
169                routine_type: RoutineType::Procedure,
170                definition_body: format!(
171                    "
172            DECLARE id STRING;
173            SET id = GENERATE_UUID();
174            INSERT INTO `{}.{}.external_data` VALUES(id, name)
175            ",
176                    project, dataset,
177                ),
178                arguments: Some(vec![Argument {
179                    name: Some("name".to_string()),
180                    argument_kind: Some(ArgumentKind::FixedType),
181                    mode: None,
182                    data_type: StandardSqlDataType {
183                        type_kind: TypeKind::String,
184                    },
185                }]),
186                ..Default::default()
187            })
188            .await
189            .unwrap();
190
191        let all = client
192            .list(project.as_str(), &dataset, &ListRoutinesRequest::default())
193            .await
194            .unwrap();
195        for f in all {
196            let f = f.routine_reference;
197            let f = client
198                .get(f.project_id.as_str(), f.dataset_id.as_str(), f.routine_id.as_str())
199                .await
200                .unwrap()
201                .routine_reference;
202            client
203                .delete(f.project_id.as_str(), f.dataset_id.as_str(), f.routine_id.as_str())
204                .await
205                .unwrap();
206        }
207    }
208}