google_cloud_bigquery/http/
bigquery_routine_client.rs1use 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 #[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 #[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 #[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 #[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 #[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}