gcp_bigquery_client/
lib.rs1#![allow(clippy::result_large_err)]
19
20#[macro_use]
21extern crate serde;
22extern crate serde_json;
23
24use std::env;
25use std::path::PathBuf;
26use std::sync::Arc;
27
28use client_builder::ClientBuilder;
29use reqwest::Response;
30use serde::Deserialize;
31use storage::StorageApi;
32use yup_oauth2::ServiceAccountKey;
33
34use crate::auth::Authenticator;
35use crate::dataset::DatasetApi;
36use crate::error::BQError;
37use crate::job::JobApi;
38use crate::model_api::ModelApi;
39use crate::project::ProjectApi;
40use crate::routine::RoutineApi;
41use crate::table::TableApi;
42use crate::tabledata::TableDataApi;
43
44pub use yup_oauth2;
49
50pub mod auth;
51pub mod client_builder;
52pub mod dataset;
53pub mod error;
54pub mod job;
55pub mod model;
56pub mod model_api;
57pub mod project;
58pub mod routine;
59pub mod storage;
60pub mod table;
61pub mod tabledata;
62
63const BIG_QUERY_V2_URL: &str = "https://bigquery.googleapis.com/bigquery/v2";
64const BIG_QUERY_AUTH_URL: &str = "https://www.googleapis.com/auth/bigquery";
65
66#[derive(Clone)]
68pub struct Client {
69 dataset_api: DatasetApi,
70 table_api: TableApi,
71 job_api: JobApi,
72 tabledata_api: TableDataApi,
73 routine_api: RoutineApi,
74 model_api: ModelApi,
75 project_api: ProjectApi,
76 storage_api: StorageApi,
77}
78
79impl Client {
80 pub async fn from_authenticator(auth: Arc<dyn Authenticator>) -> Result<Self, BQError> {
81 Self::from_authenticator_and_client(auth, Some(reqwest::Client::new())).await
82 }
83
84 pub async fn from_authenticator_and_client(
85 auth: Arc<dyn Authenticator>,
86 client: Option<reqwest::Client>,
87 ) -> Result<Self, BQError> {
88 let client = if let Some(client) = client {
89 client
90 } else {
91 reqwest::Client::new()
92 };
93 Ok(Self {
94 dataset_api: DatasetApi::new(client.clone(), Arc::clone(&auth)),
95 table_api: TableApi::new(client.clone(), Arc::clone(&auth)),
96 job_api: JobApi::new(client.clone(), Arc::clone(&auth)),
97 tabledata_api: TableDataApi::new(client.clone(), Arc::clone(&auth)),
98 routine_api: RoutineApi::new(client.clone(), Arc::clone(&auth)),
99 model_api: ModelApi::new(client.clone(), Arc::clone(&auth)),
100 project_api: ProjectApi::new(client, Arc::clone(&auth)),
101 storage_api: StorageApi::new(auth).await?,
102 })
103 }
104
105 pub async fn from_service_account_key_file(sa_key_file: &str) -> Result<Self, BQError> {
109 ClientBuilder::new()
110 .build_from_service_account_key_file(sa_key_file)
111 .await
112 }
113
114 pub async fn from_service_account_key(sa_key: ServiceAccountKey, readonly: bool) -> Result<Self, BQError> {
121 ClientBuilder::new()
122 .build_from_service_account_key(sa_key, readonly)
123 .await
124 }
125
126 pub async fn with_workload_identity(readonly: bool) -> Result<Self, BQError> {
127 ClientBuilder::new().build_with_workload_identity(readonly).await
128 }
129
130 pub(crate) fn v2_base_url(&mut self, base_url: String) -> &mut Self {
131 self.dataset_api.with_base_url(base_url.clone());
132 self.table_api.with_base_url(base_url.clone());
133 self.job_api.with_base_url(base_url.clone());
134 self.tabledata_api.with_base_url(base_url.clone());
135 self.routine_api.with_base_url(base_url.clone());
136 self.model_api.with_base_url(base_url.clone());
137 self.project_api.with_base_url(base_url.clone());
138 self.storage_api.with_base_url(base_url);
139 self
140 }
141
142 pub async fn from_installed_flow_authenticator<S: AsRef<[u8]>, P: Into<PathBuf>>(
143 secret: S,
144 persistant_file_path: P,
145 ) -> Result<Self, BQError> {
146 ClientBuilder::new()
147 .build_from_installed_flow_authenticator(secret, persistant_file_path)
148 .await
149 }
150
151 pub async fn from_installed_flow_authenticator_from_secret_file<P: Into<PathBuf>>(
152 secret_file: &str,
153 persistant_file_path: P,
154 ) -> Result<Self, BQError> {
155 Self::from_installed_flow_authenticator(
156 tokio::fs::read(secret_file)
157 .await
158 .expect("expecting a valid secret file."),
159 persistant_file_path,
160 )
161 .await
162 }
163
164 pub async fn from_application_default_credentials() -> Result<Self, BQError> {
165 ClientBuilder::new().build_from_application_default_credentials().await
166 }
167
168 pub async fn from_authorized_user_secret(secret: &str) -> Result<Self, BQError> {
169 ClientBuilder::new()
170 .build_from_authorized_user_authenticator(secret)
171 .await
172 }
173
174 pub fn dataset(&self) -> &DatasetApi {
176 &self.dataset_api
177 }
178
179 pub fn table(&self) -> &TableApi {
181 &self.table_api
182 }
183
184 pub fn job(&self) -> &JobApi {
186 &self.job_api
187 }
188
189 pub fn tabledata(&self) -> &TableDataApi {
191 &self.tabledata_api
192 }
193
194 pub fn routine(&self) -> &RoutineApi {
196 &self.routine_api
197 }
198
199 pub fn model(&self) -> &ModelApi {
201 &self.model_api
202 }
203
204 pub fn project(&self) -> &ProjectApi {
206 &self.project_api
207 }
208
209 pub fn storage(&self) -> &StorageApi {
211 &self.storage_api
212 }
213
214 pub fn storage_mut(&mut self) -> &mut StorageApi {
216 &mut self.storage_api
217 }
218}
219
220pub(crate) fn urlencode<T: AsRef<str>>(s: T) -> String {
221 url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
222}
223
224async fn process_response<T: for<'de> Deserialize<'de>>(resp: Response) -> Result<T, BQError> {
225 if resp.status().is_success() {
226 Ok(resp.json().await?)
227 } else {
228 Err(BQError::ResponseError {
229 error: resp.json().await?,
230 })
231 }
232}
233
234pub fn env_vars() -> (String, String, String, String) {
235 let project_id = env::var("PROJECT_ID").expect("Environment variable PROJECT_ID");
236 let dataset_id = env::var("DATASET_ID").expect("Environment variable DATASET_ID");
237 let table_id = env::var("TABLE_ID").expect("Environment variable TABLE_ID");
238 let gcp_sa_key =
239 env::var("GOOGLE_APPLICATION_CREDENTIALS").expect("Environment variable GOOGLE_APPLICATION_CREDENTIALS");
240
241 (project_id, dataset_id, table_id, gcp_sa_key)
242}
243
244pub mod google {
245 #![allow(clippy::all)]
246 #[path = "google.api.rs"]
247 pub mod api;
248
249 #[path = ""]
250 pub mod cloud {
251 #[path = ""]
252 pub mod bigquery {
253 #[path = ""]
254 pub mod storage {
255 #![allow(clippy::all)]
256 #[path = "google.cloud.bigquery.storage.v1.rs"]
257 pub mod v1;
258 }
259 }
260 }
261
262 #[path = "google.rpc.rs"]
263 pub mod rpc;
264}