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..fccdc2b716 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(), @@ -203,13 +204,31 @@ std::vector AppendAdditionalProjectsIfMissing( std::stringstream ss(additional_projects); 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); + // 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)) { + 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 +355,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 +376,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 +414,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 {