gcloud_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!("SELECT * FROM `{project}.{dataset}.external_data` WHERE string_field_0 = x",),
145                arguments: Some(vec![Argument {
146                    name: Some("x".to_string()),
147                    argument_kind: Some(ArgumentKind::FixedType),
148                    mode: None,
149                    data_type: StandardSqlDataType {
150                        type_kind: TypeKind::String,
151                    },
152                }]),
153                ..Default::default()
154            })
155            .await
156            .unwrap();
157
158        let _f3 = client
159            .create(&Routine {
160                etag: "".to_string(),
161                routine_reference: RoutineReference {
162                    project_id: project.to_string(),
163                    dataset_id: dataset.to_string(),
164                    routine_id: format!("Procedure{}", OffsetDateTime::now_utc().unix_timestamp()),
165                },
166                routine_type: RoutineType::Procedure,
167                definition_body: format!(
168                    "
169            DECLARE id STRING;
170            SET id = GENERATE_UUID();
171            INSERT INTO `{project}.{dataset}.external_data` VALUES(id, name)
172            ",
173                ),
174                arguments: Some(vec![Argument {
175                    name: Some("name".to_string()),
176                    argument_kind: Some(ArgumentKind::FixedType),
177                    mode: None,
178                    data_type: StandardSqlDataType {
179                        type_kind: TypeKind::String,
180                    },
181                }]),
182                ..Default::default()
183            })
184            .await
185            .unwrap();
186
187        let all = client
188            .list(project.as_str(), &dataset, &ListRoutinesRequest::default())
189            .await
190            .unwrap();
191        for f in all {
192            let f = f.routine_reference;
193            let f = client
194                .get(f.project_id.as_str(), f.dataset_id.as_str(), f.routine_id.as_str())
195                .await
196                .unwrap()
197                .routine_reference;
198            client
199                .delete(f.project_id.as_str(), f.dataset_id.as_str(), f.routine_id.as_str())
200                .await
201                .unwrap();
202        }
203    }
204}