Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions csharp/src/AdbcDrivers.BigQuery/BigQueryConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ public BigQueryConnection(IReadOnlyDictionary<string, string> properties) : base

internal BigQueryClient? Client { get; private set; }

internal BigQueryClient? ClientWithoutProject { get; private set; }

/// <summary>
/// The active BigQuery session ID when autocommit is disabled, or null when in autocommit mode.
/// Used by <see cref="BigQueryStatement"/> to attach queries to the active session/transaction.
Expand Down Expand Up @@ -470,7 +472,42 @@ internal BigQueryClient Open(string? projectId = null)
activity?.AddBigQueryTag("client.default_location", null);
}

GoogleCredential? credentialsForWithoutProjectClient = Credential?.CreateWithQuotaProject(null);

BigQueryClientBuilder bigQueryClientBuilderforWithoutProject = new BigQueryClientBuilder()
{
GoogleCredential = credentialsForWithoutProjectClient
};

bigQueryClientBuilderforWithoutProject.ProjectId = !string.IsNullOrEmpty(billingProjectId) ? billingProjectId : projectId;

if (this.properties.TryGetValue(BigQueryParameters.TestRestEndpoint, out string? testRestEndpoint1) &&
!string.IsNullOrEmpty(testRestEndpoint))
{
bigQueryClientBuilderforWithoutProject.BaseUri = $"http://{testRestEndpoint1}/bigquery/v2/";
}

if (!string.IsNullOrEmpty(DefaultClientLocation))
{
// If the user selects a public dataset (from a multi-region) but sets this
// value to a specific location like us-east4, then there is an error produced
// that the caller doesn't have permission to call to the public dataset.
// Example:
// Access Denied: Table bigquery-public-data:blockchain_analytics_ethereum_mainnet_us.accounts:
// User does not have permission to query table bigquery-public-data:blockchain_analytics_ethereum_mainnet_us.accounts,
// or perhaps it does not exist.'

bigQueryClientBuilderforWithoutProject.DefaultLocation = DefaultClientLocation;
activity?.AddBigQueryParameterTag(BigQueryParameters.DefaultClientLocation, DefaultClientLocation);
}
else
{
activity?.AddBigQueryTag("client.default_location", null);
}


BigQueryClient client = bigQueryClientBuilder.Build();
ClientWithoutProject = bigQueryClientBuilderforWithoutProject.Build();

if (clientTimeout.HasValue)
{
Expand Down
1 change: 1 addition & 0 deletions csharp/src/AdbcDrivers.BigQuery/BigQueryParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ internal class BigQueryParameters
public const string StatementType = "adbc.bigquery.multiple_statement.statement_type";
public const string UseLegacySQL = "adbc.bigquery.use_legacy_sql";
public const string IsMetadataCommand = "adbc.bigquery.statement.is_metadata_command";
public const string UseClientWithoutProjectForMetadata = "adbc.bigquery.use_client_without_project_for_metadata";

/// <summary>
/// Overrides the BigQuery REST API endpoint for testing (e.g. "localhost:1234").
Expand Down
29 changes: 29 additions & 0 deletions csharp/src/AdbcDrivers.BigQuery/BigQueryStatement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class BigQueryStatement : TracingStatement, ITokenProtectedResource, IDisposable
readonly CancellationRegistry cancellationRegistry;

bool isMetadataCommand = false;
bool useClientWithoutProjectForMetadata = false;
string? catalogName = null;
string? schemaName = null;
string? tableName = null;
Expand Down Expand Up @@ -107,6 +108,8 @@ public override void BindStream(IArrowArrayStream stream)

private BigQueryClient Client => this.bigQueryConnection.Client ?? throw new AdbcException("Client cannot be null");

private BigQueryClient ClientWithoutProject => this.bigQueryConnection.ClientWithoutProject ?? throw new AdbcException("ClientWithoutProject cannot be null");

private GoogleCredential Credential => this.bigQueryConnection.Credential ?? throw new AdbcException("Credential cannot be null");

private int MaxRetryAttempts => this.bigQueryConnection.MaxRetryAttempts;
Expand Down Expand Up @@ -358,6 +361,10 @@ protected Task<QueryResult> GetTables(Activity? activity)
StringArray.Builder tableTypeBuilder = new StringArray.Builder();
Func<Task<PagedEnumerable<TableList, BigQueryTable>?>> func = () => Task.Run(() =>
{
if (useClientWithoutProjectForMetadata)
{
return ClientWithoutProject?.ListTables(this.catalogName, this.schemaName);
}
return Client?.ListTables(this.catalogName, this.schemaName);
});
PagedEnumerable<TableList, BigQueryTable>? tables;
Expand Down Expand Up @@ -413,6 +420,10 @@ protected Task<QueryResult> GetPrimaryKeys(Activity? activity)

Func<Task<BigQueryTable?>> func = () => Task.Run(() =>
{
if (useClientWithoutProjectForMetadata)
{
return ClientWithoutProject?.GetTable(this.catalogName, this.schemaName, this.tableName);
}
return Client?.GetTable(this.catalogName, this.schemaName, this.tableName);
});

Expand Down Expand Up @@ -514,6 +525,10 @@ protected Task<QueryResult> GetTableSchema(Activity? activity)

Func<Task<BigQueryTable?>> func = () => Task.Run(() =>
{
if (useClientWithoutProjectForMetadata)
{
return ClientWithoutProject?.GetTable(this.catalogName, this.schemaName, this.tableName);
}
return Client?.GetTable(this.catalogName, this.schemaName, this.tableName);
});
BigQueryTable? table = ExecuteWithRetriesAsync<BigQueryTable?>(func, activity).GetAwaiter().GetResult();
Expand Down Expand Up @@ -691,7 +706,12 @@ protected Task<QueryResult> GetSchemas(Activity? activity)
Func<Task<PagedEnumerable<DatasetList, BigQueryDataset>?>> func = () => Task.Run(() =>
{
// stick with this call because PagedAsyncEnumerable has different behaviors for selecting items
if (useClientWithoutProjectForMetadata)
{
return ClientWithoutProject?.ListDatasets(this.catalogName);
}
return Client?.ListDatasets(this.catalogName);

});
PagedEnumerable<DatasetList, BigQueryDataset>? datasets;
datasets = ExecuteWithRetriesAsync<PagedEnumerable<DatasetList, BigQueryDataset>?>(func, activity).GetAwaiter().GetResult();
Expand Down Expand Up @@ -725,7 +745,12 @@ protected Task<QueryResult> GetCatalogs(Activity? activity)
Func<Task<PagedEnumerable<ProjectList, CloudProject>?>> func = () => Task.Run(() =>
{
// stick with this call because PagedAsyncEnumerable has different behaviors for selecting items
if (useClientWithoutProjectForMetadata)
{
return ClientWithoutProject?.ListProjects();
}
return Client?.ListProjects();

});
PagedEnumerable<ProjectList, CloudProject>? catalogs;
catalogs = ExecuteWithRetriesAsync<PagedEnumerable<ProjectList, CloudProject>?>(func, activity).GetAwaiter().GetResult();
Expand Down Expand Up @@ -1098,6 +1123,10 @@ private QueryOptions ValidateOptions(Activity? activity)
isMetadataCommand = keyValuePair.Value.Equals("true", StringComparison.OrdinalIgnoreCase);
activity?.AddBigQueryParameterTag(BigQueryParameters.IsMetadataCommand, isMetadataCommand);
break;
case BigQueryParameters.UseClientWithoutProjectForMetadata:
useClientWithoutProjectForMetadata = keyValuePair.Value.Equals("true", StringComparison.OrdinalIgnoreCase);
activity?.AddBigQueryParameterTag(BigQueryParameters.UseClientWithoutProjectForMetadata, useClientWithoutProjectForMetadata);
break;
case BigQueryParameters.CatalogName:
catalogName = keyValuePair.Value;
break;
Expand Down