From 9ba26aaa194bdc7af7d36e96a99755c30ef17412 Mon Sep 17 00:00:00 2001 From: Alvaro Viebrantz Date: Tue, 28 Jul 2026 20:30:33 +0000 Subject: [PATCH 1/4] docs(bigquery): improve Client and ClientBuilder docs --- src/bigquery/src/client.rs | 77 +++++++++++++++++++++++-- src/bigquery/src/client_builder.rs | 90 ++++++++++++++++++++++++++++-- 2 files changed, 157 insertions(+), 10 deletions(-) diff --git a/src/bigquery/src/client.rs b/src/bigquery/src/client.rs index 678e335994..88bacc5e5a 100644 --- a/src/bigquery/src/client.rs +++ b/src/bigquery/src/client.rs @@ -19,14 +19,59 @@ use google_cloud_bigquery_v2::client::JobService; use std::sync::Arc; /// A high-level BigQuery client for executing queries and managing jobs. +/// +/// # Configuration +/// +/// To construct a `BigQuery` client with custom configuration—such as non-default credentials, specific API endpoints, +/// or universe domain settings—use [`BigQuery::builder()`] to obtain a [`ClientBuilder`]. +/// +/// # Pooling and Cloning +/// +/// A `BigQuery` instance wraps an internal REST service stub behind an atomic reference counted pointer ([`Arc`](std::sync::Arc)). +/// Because the underlying connection pools and authorization state are maintained within this shared stub, **cloning a `BigQuery` client is cheap**. +/// +/// You do not need to wrap `BigQuery` in an additional `Arc` when passing it across threads or sharing it across asynchronous Tokio tasks. +/// +/// # Example: Basic Setup and Query Execution +/// +/// ``` +/// # use google_cloud_bigquery::client::BigQuery; +/// # async fn sample() -> anyhow::Result<()> { +/// let client = BigQuery::builder().build().await?; +/// let mut rows = client +/// .query("SELECT name, count FROM `bigquery-public-data.usa_names.usa_1910_2013` WHERE state = 'WA' ORDER BY count DESC LIMIT 5") +/// .with_project_id("my-project-id") +/// .run() +/// .await? +/// .until_done() +/// .await? +/// .read(); +/// +/// while let Some(row) = rows.next().await.transpose()? { +/// let name: String = row.get("name"); +/// let count: i64 = row.get("count"); +/// println!("{name}: {count}"); +/// } +/// # Ok(()) } +/// ``` #[derive(Clone, Debug)] pub struct BigQuery { - #[allow(dead_code)] - pub(crate) job_service: Arc, + job_service: Arc, } impl BigQuery { - /// Convenient entrypoint to return a fresh configuration builder. + /// Returns a new [`ClientBuilder`] for configuring and instantiating a [`BigQuery`] client. + /// + /// # Example + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// let client = BigQuery::builder() + /// .with_endpoint("https://bigquery.googleapis.com") + /// .build() + /// .await?; + /// # Ok(()) } + /// ``` pub fn builder() -> ClientBuilder { ClientBuilder::new() } @@ -58,9 +103,31 @@ impl BigQuery { Ok(BigQuery { job_service }) } - /// Execute a SQL query. + /// Creates a [`RunQuery`] request builder to configure and execute a SQL query. + /// + /// When you invoke `.run()` on the returned builder, the client automatically inspects your request configuration + /// to determine the most efficient execution path: + /// + /// - **Fast Query Path (`jobs.query`)**: If the query executes standard SQL with basic options, the client sends a synchronous + /// `jobs.query` request. If the query runs fast enough, the initial result rows are returned in the response. + /// - **Job Path (`jobs.insert`)**: If you configure execution options—such as custom destination tables, dry runs, + /// or legacy SQL syntax—the client automatically routes to `jobs.insert` to create a Query Job. + /// + /// In either case, execution returns a consistent handle that can be polled and read uniformly. + /// + /// # Example: Executing a Query /// - /// This builder internally routes to either `jobs.query` (fast path) or `jobs.insert` (job path) + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// let client = BigQuery::builder().build().await?; + /// let query_handle = client + /// .query("SELECT 1 AS num") + /// .with_project_id("my-project-id") + /// .run() + /// .await?; + /// # Ok(()) } + /// ``` pub fn query>(&self, sql: S) -> RunQuery { RunQuery::new(self.job_service.clone(), sql.into()) } diff --git a/src/bigquery/src/client_builder.rs b/src/bigquery/src/client_builder.rs index 8561f00207..e5c9f0ae7c 100644 --- a/src/bigquery/src/client_builder.rs +++ b/src/bigquery/src/client_builder.rs @@ -17,7 +17,19 @@ use gaxi::options::ClientConfig; use google_cloud_auth::credentials::Credentials; use google_cloud_gax::client_builder::Result; -/// A builder for creating and configuring a BigQuery client instance. +/// A builder for [`BigQuery`][crate::client::BigQuery]. +/// +/// # Example +/// ``` +/// # use google_cloud_bigquery::client::BigQuery; +/// # async fn sample() -> anyhow::Result<()> { +/// let builder = BigQuery::builder(); +/// let client = builder +/// .with_endpoint("https://bigquery.googleapis.com") +/// .build() +/// .await?; +/// # Ok(()) } +/// ``` #[derive(Clone, Debug)] pub struct ClientBuilder { pub(crate) config: ClientConfig, @@ -30,7 +42,7 @@ impl Default for ClientBuilder { } impl ClientBuilder { - /// Creates a new default `ClientBuilder`. + /// Creates a new default [`ClientBuilder`]. pub fn new() -> Self { Self { config: ClientConfig::default(), @@ -39,13 +51,46 @@ impl ClientBuilder { /// Sets the [BigQuery v2] API endpoint. /// + /// # Example + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// let client = BigQuery::builder() + /// .with_endpoint("https://private.googleapis.com") + /// .build() + /// .await?; + /// # Ok(()) } + /// ``` + /// /// [BigQuery v2]: https://docs.cloud.google.com/bigquery/docs/reference/rest pub fn with_endpoint>(mut self, v: V) -> Self { self.config.endpoint = Some(v.into()); self } - /// Sets custom credentials for the client. + /// Configure the authentication credentials. + /// + /// Most Google Cloud services require authentication, though some services + /// allow for anonymous access, and some services provide emulators where + /// no authentication is required. More information about valid credentials + /// types can be found in the [google-cloud-auth] crate documentation. + /// + /// # Example + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// use google_cloud_auth::credentials::mds; + /// let client = BigQuery::builder() + /// .with_credentials( + /// mds::Builder::default() + /// .with_scopes(["https://www.googleapis.com/auth/cloud-platform.read-only"]) + /// .build()?) + /// .build() + /// .await?; + /// # Ok(()) } + /// ``` + /// + /// [google-cloud-auth]: https://docs.rs/google-cloud-auth pub fn with_credentials>(mut self, credentials: V) -> Self { self.config.cred = Some(credentials.into()); self @@ -55,18 +100,53 @@ impl ClientBuilder { /// /// The universe domain is the default service domain for a given cloud universe. /// The default value is "googleapis.com". + /// + /// # Example + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// let client = BigQuery::builder() + /// .with_universe_domain("googleapis.com") + /// .build() + /// .await?; + /// # Ok(()) } + /// ``` pub fn with_universe_domain>(mut self, v: V) -> Self { self.config.universe_domain = Some(v.into()); self } - /// Enables observability signals for the client. + /// Enables tracing. + /// + /// The client libraries can be dynamically instrumented with the Tokio + /// [tracing] framework. Setting this flag enables this instrumentation. + /// + /// # Example + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// let client = BigQuery::builder() + /// .with_tracing() + /// .build() + /// .await?; + /// # Ok(()) } + /// ``` + /// + /// [tracing]: https://docs.rs/tracing/latest/tracing/ pub fn with_tracing(mut self) -> Self { self.config.tracing = true; self } - /// Builds the `BigQuery` client instance. + /// Creates a new client. + /// + /// # Example + /// ``` + /// # use google_cloud_bigquery::client::BigQuery; + /// # async fn sample() -> anyhow::Result<()> { + /// let client = BigQuery::builder().build().await?; + /// # Ok(()) } + /// ``` pub async fn build(self) -> Result { BigQuery::new(self).await } From dc5ce1800167b3333c3c61c2d714e781c8b6dd28 Mon Sep 17 00:00:00 2001 From: Alvaro Viebrantz Date: Tue, 28 Jul 2026 20:33:47 +0000 Subject: [PATCH 2/4] impl: add link to BigQuery client on build --- src/bigquery/src/client_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigquery/src/client_builder.rs b/src/bigquery/src/client_builder.rs index e5c9f0ae7c..a6378d8372 100644 --- a/src/bigquery/src/client_builder.rs +++ b/src/bigquery/src/client_builder.rs @@ -138,7 +138,7 @@ impl ClientBuilder { self } - /// Creates a new client. + /// Creates a new [`BigQuery`] client. /// /// # Example /// ``` From 2a7dd9aaf18dfcf382dc17297d6393ef83923181 Mon Sep 17 00:00:00 2001 From: Alvaro Viebrantz Date: Wed, 29 Jul 2026 13:58:37 +0000 Subject: [PATCH 3/4] docs: more improvements --- src/bigquery/src/client.rs | 61 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/bigquery/src/client.rs b/src/bigquery/src/client.rs index 88bacc5e5a..128ab1fda7 100644 --- a/src/bigquery/src/client.rs +++ b/src/bigquery/src/client.rs @@ -22,15 +22,20 @@ use std::sync::Arc; /// /// # Configuration /// -/// To construct a `BigQuery` client with custom configuration—such as non-default credentials, specific API endpoints, -/// or universe domain settings—use [`BigQuery::builder()`] to obtain a [`ClientBuilder`]. +/// To configure a `BigQuery` client, use the `with_*` methods on the [`ClientBuilder`][crate::builder::bigquery::ClientBuilder] returned +/// by [`BigQuery::builder()`]. The default configuration uses Application Default Credentials (ADC) +/// and connects to the global default endpoint, which works for most applications. /// -/// # Pooling and Cloning +/// Common configuration customizations include: +/// +/// - [`with_endpoint()`][crate::builder::bigquery::ClientBuilder::with_endpoint]: Overrides the default API endpoint (`https://bigquery.googleapis.com`). Useful when testing against mock servers or running in restricted network environments (for example, with VPC Service Controls). +/// - [`with_credentials()`][crate::builder::bigquery::ClientBuilder::with_credentials]: Overrides the default Application Default Credentials with explicit or custom authentication credentials. /// -/// A `BigQuery` instance wraps an internal REST service stub behind an atomic reference counted pointer ([`Arc`](std::sync::Arc)). -/// Because the underlying connection pools and authorization state are maintained within this shared stub, **cloning a `BigQuery` client is cheap**. +/// # Pooling and Cloning /// -/// You do not need to wrap `BigQuery` in an additional `Arc` when passing it across threads or sharing it across asynchronous Tokio tasks. +/// `BigQuery` holds an internal gRPC/HTTP client and connection pool wrapped in an [`Arc`]. +/// You should create a single `BigQuery` client instance upon application initialization and reuse it across multiple tasks or requests. +/// Cloning a `BigQuery` instance is cheap and does not duplicate underlying connections or thread pools, so you do not need to wrap `BigQuery` in an additional `Arc`. /// /// # Example: Basic Setup and Query Execution /// @@ -103,30 +108,46 @@ impl BigQuery { Ok(BigQuery { job_service }) } - /// Creates a [`RunQuery`] request builder to configure and execute a SQL query. + /// Creates a request builder to configure and execute a SQL query. /// - /// When you invoke `.run()` on the returned builder, the client automatically inspects your request configuration - /// to determine the most efficient execution path: + /// This method returns a [`RunQuery`] builder. You can chain additional configuration methods + /// (such as setting the project ID, positional or named parameters, query location, and maximum result buffer sizes) + /// before calling [`RunQuery::run()`]. /// - /// - **Fast Query Path (`jobs.query`)**: If the query executes standard SQL with basic options, the client sends a synchronous - /// `jobs.query` request. If the query runs fast enough, the initial result rows are returned in the response. - /// - **Job Path (`jobs.insert`)**: If you configure execution options—such as custom destination tables, dry runs, - /// or legacy SQL syntax—the client automatically routes to `jobs.insert` to create a Query Job. + /// The [`RunQuery`] builder automatically decides whether to route your request via the fast path ([`jobs.query`][jobs_query]) + /// or the background job creation path ([`jobs.insert`][jobs_insert]). If the query configuration uses only options supported + /// by the fast path, the client library uses [`jobs.query`][jobs_query] for lower latency. If advanced options (such as destination + /// tables or allowing large results) are configured, the client automatically falls back to creating an asynchronous job. /// - /// In either case, execution returns a consistent handle that can be polled and read uniformly. + /// [jobs_query]: https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query + /// [jobs_insert]: https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/insert /// - /// # Example: Executing a Query + /// # Example /// /// ``` - /// # use google_cloud_bigquery::client::BigQuery; /// # async fn sample() -> anyhow::Result<()> { + /// use google_cloud_bigquery::client::BigQuery; + /// /// let client = BigQuery::builder().build().await?; - /// let query_handle = client - /// .query("SELECT 1 AS num") + /// + /// // Execute a query and read the resulting rows. + /// let mut rows = client + /// .query("SELECT name, count FROM `my-project.my_dataset.stats` LIMIT 50") /// .with_project_id("my-project-id") + /// .set_location("US") /// .run() - /// .await?; - /// # Ok(()) } + /// .await? + /// .until_done() + /// .await? + /// .read(); + /// + /// while let Some(row) = rows.next().await.transpose()? { + /// let name: String = row.get("name"); + /// let count: i64 = row.get("count"); + /// println!("{name}: {count}"); + /// } + /// # Ok(()) + /// # } /// ``` pub fn query>(&self, sql: S) -> RunQuery { RunQuery::new(self.job_service.clone(), sql.into()) From 65bdca7f1178ad2ee72d9f9fe6f6801b7be3d233 Mon Sep 17 00:00:00 2001 From: Alvaro Viebrantz Date: Wed, 29 Jul 2026 14:19:24 +0000 Subject: [PATCH 4/4] fix: docs build --- src/bigquery/src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigquery/src/client.rs b/src/bigquery/src/client.rs index 128ab1fda7..8548a7280d 100644 --- a/src/bigquery/src/client.rs +++ b/src/bigquery/src/client.rs @@ -22,7 +22,7 @@ use std::sync::Arc; /// /// # Configuration /// -/// To configure a `BigQuery` client, use the `with_*` methods on the [`ClientBuilder`][crate::builder::bigquery::ClientBuilder] returned +/// To configure a `BigQuery` client, use the `with_*` methods on the [`ClientBuilder`] returned /// by [`BigQuery::builder()`]. The default configuration uses Application Default Credentials (ADC) /// and connects to the global default endpoint, which works for most applications. ///