From a91ddf04a16f2be7f1c44c769316b9570c9c47cd Mon Sep 17 00:00:00 2001 From: Anshu6250 Date: Thu, 25 Sep 2025 17:12:51 +0530 Subject: [PATCH 1/2] fix(bq_driver): Prevent crash when listing datasets for invalid projects --- .../bq_driver/internal/odbc_sql_tables.cc | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc b/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc index 2737b22b0d..797c469127 100644 --- a/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc +++ b/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc @@ -195,6 +195,7 @@ StatusRecordOr ConstructQuery( } std::vector AppendAdditionalProjectsIfMissing( + ODBCBQClient& bq_client, SQLULEN metadata_id, std::vector base_projects, std::string const& additional_projects) { std::set existing_ids(base_projects.begin(), @@ -204,12 +205,29 @@ std::vector AppendAdditionalProjectsIfMissing( std::string project_id; while (std::getline(ss, project_id, ',')) { // Trim leading/trailing whitespace - project_id.erase(0, project_id.find_first_not_of(" \t")); - project_id.erase(project_id.find_last_not_of(" \t") + 1); + project_id.erase(0, project_id.find_first_not_of(" \t\n\r")); + project_id.erase(project_id.find_last_not_of(" \t\n\r") + 1); + + if (project_id.empty() || existing_ids.count(project_id)) { + continue; + } + auto validation_status = + GetFilteredDatasetIds(bq_client, project_id, "%", metadata_id); - if (!project_id.empty() && - existing_ids.find(project_id) == existing_ids.end()) { + if (validation_status.Ok()) { base_projects.push_back(project_id); + existing_ids.insert(project_id); + } else { + auto const& status_record = validation_status.GetStatusRecord(); + + if (status_record.native_error_code == 404) { + LOG(INFO) << "Additional project '" << project_id + << "' from DSN is not found or inaccessible. Skipping."; + } else { + LOG(ERROR) << "Validation of additional project '" << project_id + << "' failed with code " << status_record.native_error_code + << ": " << status_record.message; + } } } return base_projects; @@ -336,8 +354,8 @@ StatusRecordOr GetResultSetForProjects( std::vector project_list = *project_ids_status; if (!additional_projects.empty()) { - project_list = AppendAdditionalProjectsIfMissing(std::move(project_list), - additional_projects); + project_list = AppendAdditionalProjectsIfMissing( + bq_client, metadata_id, std::move(project_list), additional_projects); } return CreateResultSetForProjects(project_list); @@ -357,8 +375,8 @@ StatusRecordOr GetResultSetForDatasets( std::vector project_list = *project_ids_status; if (!additional_projects.empty()) { - project_list = AppendAdditionalProjectsIfMissing(std::move(project_list), - additional_projects); + project_list = AppendAdditionalProjectsIfMissing( + bq_client, metadata_id, std::move(project_list), additional_projects); } std::vector dataset_ids; @@ -395,7 +413,8 @@ StatusRecordOr GetResultSetForTables( ConnectionHandle& conn_handle = *(stmt_handle.GetConnectionHandle()); // Append additional projects if any project_list = AppendAdditionalProjectsIfMissing( - std::move(project_list), conn_handle.GetDsn().additional_projects); + bq_client, metadata_id, std::move(project_list), + conn_handle.GetDsn().additional_projects); // 1. Prepare the list of tasks (Project + Dataset combinations) struct TaskInput { From 427017edde36e67ed5b1a20c306f1522203c873b Mon Sep 17 00:00:00 2001 From: Anshu6250 Date: Mon, 10 Nov 2025 12:20:18 +0530 Subject: [PATCH 2/2] changes --- google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc b/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc index 797c469127..fccdc2b716 100644 --- a/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc +++ b/google/cloud/odbc/bq_driver/internal/odbc_sql_tables.cc @@ -204,8 +204,9 @@ std::vector AppendAdditionalProjectsIfMissing( std::stringstream ss(additional_projects); std::string project_id; while (std::getline(ss, project_id, ',')) { - // Trim leading/trailing whitespace + // Trim leading whitespace (spaces, tabs, newlines) project_id.erase(0, project_id.find_first_not_of(" \t\n\r")); + // Trim trailing whitespace (spaces, tabs, newlines) project_id.erase(project_id.find_last_not_of(" \t\n\r") + 1); if (project_id.empty() || existing_ids.count(project_id)) {