diff --git a/google/cloud/odbc/bq_driver/odbc_driver_metadata.cc b/google/cloud/odbc/bq_driver/odbc_driver_metadata.cc index 3b6ae05f64..a82bbceacc 100644 --- a/google/cloud/odbc/bq_driver/odbc_driver_metadata.cc +++ b/google/cloud/odbc/bq_driver/odbc_driver_metadata.cc @@ -443,11 +443,6 @@ SQLRETURN SQLTablesInternal(SQLHSTMT stmt_handle, SQLCHAR* catalog_name, return LogAndReturnCode(handle, input_param_status); } - std::string project_filter = ToCharStr(catalog_name, kMatchAll); - std::string dataset_filter = ToCharStr(schema_name, kMatchAll); - std::string table_filter = ToCharStr(table_name, kMatchAll); - std::string table_type_filter = ToCharStr(table_type, kMatchAll); - if (handle.GetConnectionHandle() == nullptr) { LOG(ERROR) << "SQLTables:: Internal connection handle is null"; return LogAndReturnCode(handle, @@ -455,6 +450,25 @@ SQLRETURN SQLTablesInternal(SQLHSTMT stmt_handle, SQLCHAR* catalog_name, "Internal connection handle is null"}); } ConnectionHandle& conn_handle = *(handle.GetConnectionHandle()); + std::string catalog_str; + if (catalog_name == nullptr || catalog_name_len == 0) { + SQLINTEGER catalog_len = 0; + SQLCHAR current_catalog[256] = {0}; + conn_handle.GetAttribute(SQL_ATTR_CURRENT_CATALOG, current_catalog, + sizeof(current_catalog), &catalog_len); + + if (catalog_len > 0) { + catalog_str.assign(reinterpret_cast(current_catalog), catalog_len); + catalog_name = reinterpret_cast(catalog_str.data()); + catalog_name_len = static_cast(catalog_str.size()); + } + } + + std::string project_filter = ToCharStr(catalog_name, kMatchAll); + std::string dataset_filter = ToCharStr(schema_name, kMatchAll); + std::string table_filter = ToCharStr(table_name, kMatchAll); + std::string table_type_filter = ToCharStr(table_type, kMatchAll); + if (!metadata_id && dataset_filter == kMatchAll) { auto const dsn = conn_handle.GetDsn(); if (dsn.filter_tables_on_default_dataset && !dsn.default_dataset.empty()) { diff --git a/google/cloud/odbc/integration_tests/odbc_driver_tests/catalog_test.cc b/google/cloud/odbc/integration_tests/odbc_driver_tests/catalog_test.cc index a272f2f362..80a8bccdf7 100644 --- a/google/cloud/odbc/integration_tests/odbc_driver_tests/catalog_test.cc +++ b/google/cloud/odbc/integration_tests/odbc_driver_tests/catalog_test.cc @@ -2164,4 +2164,55 @@ TEST(SQLTables, Check_SQLTablesDescriptors) { EXPECT_EQ(Disconnect(conn), SQL_SUCCESS); } +TEST(CatalogTest, SQLTables_NullCatalogFiltersToCurrentProject) { + auto conn = std::make_shared(); + ASSERT_EQ(Connect(kDefaultConnectionString, conn), SQL_SUCCESS); + + SQLRETURN status = SQLSetStmtAttr(conn->hstmt, SQL_ATTR_METADATA_ID, + (SQLPOINTER)SQL_FALSE, 0); + CheckError(status, "SQLSetStmtAttr", conn); + + SQLCHAR current_catalog[256] = {0}; + SQLINTEGER catalog_len = 0; + SQLRETURN attr_status = + SQLGetConnectAttr(conn->hdbc, SQL_ATTR_CURRENT_CATALOG, current_catalog, + sizeof(current_catalog), &catalog_len); + + ASSERT_TRUE(SQL_SUCCEEDED(attr_status)) + << "Failed to get SQL_ATTR_CURRENT_CATALOG"; + std::string expected_catalog(reinterpret_cast(current_catalog)); + + SQLCHAR table_type[] = "TABLE,VIEW"; + SQLRETURN rc = SQLTables(conn->hstmt, NULL, 0, // Catalog (NULL) + NULL, 0, // Schema + NULL, 0, // Table name + table_type, SQL_NTS); // Table type + + ASSERT_TRUE(SQL_SUCCEEDED(rc)) << "SQLTables call failed."; + + SQLCHAR out_catalog[256] = {0}; + SQLLEN out_len = 0; + SQLBindCol(conn->hstmt, 1, SQL_C_CHAR, out_catalog, sizeof(out_catalog), + &out_len); + + int row_count = 0; + bool foreign_catalog_found = false; + + while (SQLFetch(conn->hstmt) == SQL_SUCCESS) { + row_count++; + std::string fetched_catalog(reinterpret_cast(out_catalog)); + + if (fetched_catalog != expected_catalog) { + foreign_catalog_found = true; + } + } + + EXPECT_FALSE(foreign_catalog_found) + << "SQLTables returned data for projects outside the configured DSN."; + EXPECT_GT(row_count, 0) + << "Expected to find at least one table/view in the default project."; + + EXPECT_EQ(Disconnect(conn), SQL_SUCCESS); +} + } // namespace google::cloud::odbc_tests