diff --git a/src/aws.cpp b/src/aws.cpp index 4f2cf3e0..12ba1a89 100644 --- a/src/aws.cpp +++ b/src/aws.cpp @@ -158,6 +158,10 @@ unique_ptr AWSInput::ExecuteRequest(ClientContext &context, Aws::H return result; } +unique_ptr AWSInput::HeadRequest(ClientContext &context) { + return ExecuteRequest(context, Aws::Http::HttpMethod::HTTP_HEAD); +} + unique_ptr AWSInput::GetRequest(ClientContext &context) { return ExecuteRequest(context, Aws::Http::HttpMethod::HTTP_GET); } diff --git a/src/catalog_api.cpp b/src/catalog_api.cpp index 87979931..d6dd0aae 100644 --- a/src/catalog_api.cpp +++ b/src/catalog_api.cpp @@ -17,7 +17,7 @@ using namespace duckdb_yyjson; namespace duckdb { -vector IRCAPI::ParseSchemaName(string &namespace_name) { +vector IRCAPI::ParseSchemaName(const string &namespace_name) { idx_t start = 0; idx_t end = namespace_name.find(".", start); vector ret; @@ -40,6 +40,7 @@ string IRCAPI::GetSchemaName(const vector &items) { //! Used for the path parameters string IRCAPI::GetEncodedSchemaName(const vector &items) { + D_ASSERT(!items.empty()); static const string unit_separator = "%1F"; return StringUtil::Join(items, unit_separator); } @@ -63,6 +64,47 @@ string IRCAPI::GetEncodedSchemaName(const vector &items) { int(response.status)); } +bool IRCAPI::VerifySchemaExistence(ClientContext &context, IRCatalog &catalog, const string &schema) { + auto namespace_items = ParseSchemaName(schema); + auto schema_name = GetEncodedSchemaName(namespace_items); + + auto url_builder = catalog.GetBaseUrl(); + url_builder.AddPathComponent(catalog.prefix); + url_builder.AddPathComponent("namespaces"); + url_builder.AddPathComponent(schema_name); + + auto url = url_builder.GetURL(); + try { + auto response = catalog.auth_handler->HeadRequest(context, url_builder); + if (response->Success() || response->status == HTTPStatusCode::NoContent_204) { + return true; + } + return false; + } catch (std::exception &ex) { + //! For some reason this API likes to throw, instead of just returning a response with an error + return false; + } +} + +bool IRCAPI::VerifyTableExistence(ClientContext &context, IRCatalog &catalog, const IRCSchemaEntry &schema, + const string &table) { + auto schema_name = GetEncodedSchemaName(schema.namespace_items); + + auto url_builder = catalog.GetBaseUrl(); + url_builder.AddPathComponent(catalog.prefix); + url_builder.AddPathComponent("namespaces"); + url_builder.AddPathComponent(schema_name); + url_builder.AddPathComponent("tables"); + url_builder.AddPathComponent(table); + + auto url = url_builder.GetURL(); + auto response = catalog.auth_handler->HeadRequest(context, url_builder); + if (response->Success() || response->status == HTTPStatusCode::NoContent_204) { + return true; + } + return false; +} + static string GetTableMetadata(ClientContext &context, IRCatalog &catalog, const IRCSchemaEntry &schema, const string &table) { auto schema_name = IRCAPI::GetEncodedSchemaName(schema.namespace_items); @@ -80,21 +122,15 @@ static string GetTableMetadata(ClientContext &context, IRCatalog &catalog, const ThrowException(url, *response, "GET"); } - const auto &api_result = response->body; - std::unique_ptr doc(ICUtils::api_result_to_doc(api_result)); - auto *root = yyjson_doc_get_root(doc.get()); - auto load_table_result = rest_api_objects::LoadTableResult::FromJSON(root); - catalog.SetCachedValue(url, api_result, load_table_result); - return api_result; + return response->body; } rest_api_objects::LoadTableResult IRCAPI::GetTable(ClientContext &context, IRCatalog &catalog, const IRCSchemaEntry &schema, const string &table_name) { - string result = GetTableMetadata(context, catalog, schema, table_name); + auto result = GetTableMetadata(context, catalog, schema, table_name); std::unique_ptr doc(ICUtils::api_result_to_doc(result)); auto *metadata_root = yyjson_doc_get_root(doc.get()); - auto load_table_result = rest_api_objects::LoadTableResult::FromJSON(metadata_root); - return load_table_result; + return rest_api_objects::LoadTableResult::FromJSON(metadata_root); } vector IRCAPI::GetTables(ClientContext &context, IRCatalog &catalog, diff --git a/src/common/api_utils.cpp b/src/common/api_utils.cpp index 535af527..23974238 100644 --- a/src/common/api_utils.cpp +++ b/src/common/api_utils.cpp @@ -100,4 +100,25 @@ unique_ptr APIUtils::GetRequest(ClientContext &context, const IRCE return http_util.Request(get_request); } +unique_ptr APIUtils::HeadRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, + const string &token) { + auto &db = DatabaseInstance::GetDatabase(context); + + HTTPHeaders headers(db); + headers.Insert("X-Iceberg-Access-Delegation", "vended-credentials"); + if (!token.empty()) { + headers.Insert("Authorization", StringUtil::Format("Bearer %s", token)); + } + + auto &http_util = HTTPUtil::Get(db); + unique_ptr params; + + string request_url = AddHttpHostIfMissing(endpoint_builder.GetURL()); + + params = http_util.InitializeParameters(context, request_url); + + HeadRequestInfo head_request(request_url, headers, *params); + return http_util.Request(head_request); +} + } // namespace duckdb diff --git a/src/include/api_utils.hpp b/src/include/api_utils.hpp index 2ecd0679..ade406dd 100644 --- a/src/include/api_utils.hpp +++ b/src/include/api_utils.hpp @@ -35,6 +35,8 @@ class APIUtils { public: static unique_ptr GetRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, const string &token = ""); + static unique_ptr HeadRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, + const string &token = ""); static unique_ptr DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, const string &token = ""); static unique_ptr PostRequest(ClientContext &context, const string &url, const string &post_data, diff --git a/src/include/aws.hpp b/src/include/aws.hpp index e24db3c6..7e7d3c6f 100644 --- a/src/include/aws.hpp +++ b/src/include/aws.hpp @@ -20,6 +20,7 @@ class AWSInput { public: unique_ptr GetRequest(ClientContext &context); + unique_ptr HeadRequest(ClientContext &context); unique_ptr DeleteRequest(ClientContext &context); unique_ptr PostRequest(ClientContext &context, string post_body); diff --git a/src/include/catalog_api.hpp b/src/include/catalog_api.hpp index adc5e94c..4e0af997 100644 --- a/src/include/catalog_api.hpp +++ b/src/include/catalog_api.hpp @@ -23,11 +23,14 @@ struct IRCAPISchema { class IRCAPI { public: static const string API_VERSION_1; - static vector ParseSchemaName(string &namespace_name); - static string GetSchemaName(const vector &items); - static string GetEncodedSchemaName(const vector &items); static vector GetTables(ClientContext &context, IRCatalog &catalog, const IRCSchemaEntry &schema); + static bool VerifySchemaExistence(ClientContext &context, IRCatalog &catalog, const string &schema); + static bool VerifyTableExistence(ClientContext &context, IRCatalog &catalog, const IRCSchemaEntry &schema, + const string &table); + static vector ParseSchemaName(const string &namespace_name); + static string GetSchemaName(const vector &items); + static string GetEncodedSchemaName(const vector &items); static rest_api_objects::LoadTableResult GetTable(ClientContext &context, IRCatalog &catalog, const IRCSchemaEntry &schema, const string &table_name); static vector GetSchemas(ClientContext &context, IRCatalog &catalog, const vector &parent); diff --git a/src/include/storage/authorization/none.hpp b/src/include/storage/authorization/none.hpp index e65d23f0..0c608af4 100644 --- a/src/include/storage/authorization/none.hpp +++ b/src/include/storage/authorization/none.hpp @@ -14,6 +14,7 @@ class NoneAuthorization : public IRCAuthorization { public: static unique_ptr FromAttachOptions(IcebergAttachOptions &input); unique_ptr GetRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; + unique_ptr HeadRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; unique_ptr DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; unique_ptr PostRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, const string &body) override; diff --git a/src/include/storage/authorization/oauth2.hpp b/src/include/storage/authorization/oauth2.hpp index 9baff0a1..89158b41 100644 --- a/src/include/storage/authorization/oauth2.hpp +++ b/src/include/storage/authorization/oauth2.hpp @@ -16,6 +16,7 @@ class OAuth2Authorization : public IRCAuthorization { public: static unique_ptr FromAttachOptions(ClientContext &context, IcebergAttachOptions &input); unique_ptr GetRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; + unique_ptr HeadRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; unique_ptr DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; unique_ptr PostRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, const string &body) override; diff --git a/src/include/storage/authorization/sigv4.hpp b/src/include/storage/authorization/sigv4.hpp index bbae9783..09474e6f 100644 --- a/src/include/storage/authorization/sigv4.hpp +++ b/src/include/storage/authorization/sigv4.hpp @@ -16,6 +16,7 @@ class SIGV4Authorization : public IRCAuthorization { public: static unique_ptr FromAttachOptions(IcebergAttachOptions &input); unique_ptr GetRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; + unique_ptr HeadRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; unique_ptr DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) override; unique_ptr PostRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, const string &body) override; diff --git a/src/include/storage/irc_authorization.hpp b/src/include/storage/irc_authorization.hpp index cac83473..335220db 100644 --- a/src/include/storage/irc_authorization.hpp +++ b/src/include/storage/irc_authorization.hpp @@ -40,6 +40,8 @@ struct IRCAuthorization { public: virtual unique_ptr GetRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) = 0; + virtual unique_ptr HeadRequest(ClientContext &context, + const IRCEndpointBuilder &endpoint_builder) = 0; virtual unique_ptr DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) = 0; virtual unique_ptr PostRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder, diff --git a/src/include/storage/irc_schema_entry.hpp b/src/include/storage/irc_schema_entry.hpp index dd65b279..71e536cd 100644 --- a/src/include/storage/irc_schema_entry.hpp +++ b/src/include/storage/irc_schema_entry.hpp @@ -4,6 +4,7 @@ #include "catalog_api.hpp" #include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp" #include "storage/irc_table_set.hpp" +#include "duckdb/common/enums/on_entry_not_found.hpp" namespace duckdb { class IRCTransaction; diff --git a/src/include/storage/irc_schema_set.hpp b/src/include/storage/irc_schema_set.hpp index ddb52688..dca8c65d 100644 --- a/src/include/storage/irc_schema_set.hpp +++ b/src/include/storage/irc_schema_set.hpp @@ -12,7 +12,7 @@ class IRCSchemaSet { public: void LoadEntries(ClientContext &context); - optional_ptr GetEntry(ClientContext &context, const string &name); + optional_ptr GetEntry(ClientContext &context, const string &name, OnEntryNotFound if_not_found); void Scan(ClientContext &context, const std::function &callback); protected: @@ -21,6 +21,8 @@ class IRCSchemaSet { public: Catalog &catalog; case_insensitive_map_t> entries; + //! Whether a listing has been done for the catalog + bool listed = false; private: mutex entry_lock; diff --git a/src/include/storage/irc_table_set.hpp b/src/include/storage/irc_table_set.hpp index 79a3029d..41735160 100644 --- a/src/include/storage/irc_table_set.hpp +++ b/src/include/storage/irc_table_set.hpp @@ -31,6 +31,8 @@ class ICTableSet { IRCSchemaEntry &schema; Catalog &catalog; case_insensitive_map_t entries; + //! Whether a listing is done for this transaction + bool listed = false; private: mutex entry_lock; diff --git a/src/storage/authorization/none.cpp b/src/storage/authorization/none.cpp index 7c32ac48..191a19c8 100644 --- a/src/storage/authorization/none.cpp +++ b/src/storage/authorization/none.cpp @@ -17,6 +17,11 @@ unique_ptr NoneAuthorization::GetRequest(ClientContext &context, return APIUtils::GetRequest(context, endpoint_builder, ""); } +unique_ptr NoneAuthorization::HeadRequest(ClientContext &context, + const IRCEndpointBuilder &endpoint_builder) { + return APIUtils::HeadRequest(context, endpoint_builder, ""); +} + unique_ptr NoneAuthorization::DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) { return APIUtils::DeleteRequest(context, endpoint_builder, ""); diff --git a/src/storage/authorization/oauth2.cpp b/src/storage/authorization/oauth2.cpp index b465d5f8..f7c5e1e8 100644 --- a/src/storage/authorization/oauth2.cpp +++ b/src/storage/authorization/oauth2.cpp @@ -103,6 +103,11 @@ unique_ptr OAuth2Authorization::GetRequest(ClientContext &context, return APIUtils::GetRequest(context, endpoint_builder, token); } +unique_ptr OAuth2Authorization::HeadRequest(ClientContext &context, + const IRCEndpointBuilder &endpoint_builder) { + return APIUtils::HeadRequest(context, endpoint_builder, token); +} + unique_ptr OAuth2Authorization::DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) { return APIUtils::DeleteRequest(context, endpoint_builder, token); diff --git a/src/storage/authorization/sigv4.cpp b/src/storage/authorization/sigv4.cpp index 0d6681a4..3e57f6f0 100644 --- a/src/storage/authorization/sigv4.cpp +++ b/src/storage/authorization/sigv4.cpp @@ -114,6 +114,12 @@ unique_ptr SIGV4Authorization::GetRequest(ClientContext &context, return aws_input.GetRequest(context); } +unique_ptr SIGV4Authorization::HeadRequest(ClientContext &context, + const IRCEndpointBuilder &endpoint_builder) { + AWSInput aws_input = CreateAWSInput(context, endpoint_builder); + return aws_input.HeadRequest(context); +} + unique_ptr SIGV4Authorization::DeleteRequest(ClientContext &context, const IRCEndpointBuilder &endpoint_builder) { AWSInput aws_input = CreateAWSInput(context, endpoint_builder); diff --git a/src/storage/irc_catalog.cpp b/src/storage/irc_catalog.cpp index 09f19a89..3029731f 100644 --- a/src/storage/irc_catalog.cpp +++ b/src/storage/irc_catalog.cpp @@ -57,7 +57,7 @@ optional_ptr IRCatalog::LookupSchema(CatalogTransaction tran auto &schemas = irc_transaction.GetSchemas(); auto &schema_name = schema_lookup.GetEntryName(); - auto entry = schemas.GetEntry(transaction.GetContext(), schema_name); + auto entry = schemas.GetEntry(transaction.GetContext(), schema_name, if_not_found); if (!entry && if_not_found != OnEntryNotFound::RETURN_NULL) { throw CatalogException(schema_lookup.GetErrorContext(), "Schema with name \"%s\" not found", schema_name); } @@ -318,41 +318,6 @@ void IRCatalog::GetConfig(ClientContext &context, IcebergEndpointType &endpoint_ } } -string IRCatalog::OptionalGetCachedValue(const string &url) { - std::lock_guard lock(metadata_cache_mutex); - auto value = metadata_cache.find(url); - if (value != metadata_cache.end()) { - auto now = system_clock::now(); - if (now < value->second->expires_at) { - return value->second->data; - } - } - return ""; -} - -bool IRCatalog::SetCachedValue(const string &url, const string &value, - const rest_api_objects::LoadTableResult &result) { - //! FIXME: shouldn't this also store the 'storage-credentials' ?? - if (!result.has_config) { - return false; - } - auto &credentials = result.config; - auto expires_at_it = credentials.find("s3.session-token-expires-at-ms"); - if (expires_at_it == credentials.end()) { - return false; - } - - auto &expires_at = expires_at_it->second; - auto epochMillis = std::stoll(expires_at); - auto expired_time = system_clock::time_point(milliseconds(epochMillis)); - auto val = make_uniq(value, expired_time); - { - std::lock_guard lock(metadata_cache_mutex); - metadata_cache[url] = std::move(val); - } - return true; -} - //===--------------------------------------------------------------------===// // Attach //===--------------------------------------------------------------------===// diff --git a/src/storage/irc_schema_set.cpp b/src/storage/irc_schema_set.cpp index af72d17c..f916e308 100644 --- a/src/storage/irc_schema_set.cpp +++ b/src/storage/irc_schema_set.cpp @@ -11,12 +11,28 @@ namespace duckdb { IRCSchemaSet::IRCSchemaSet(Catalog &catalog) : catalog(catalog) { } -optional_ptr IRCSchemaSet::GetEntry(ClientContext &context, const string &name) { - LoadEntries(context); +optional_ptr IRCSchemaSet::GetEntry(ClientContext &context, const string &name, + OnEntryNotFound if_not_found) { lock_guard l(entry_lock); + auto &ic_catalog = catalog.Cast(); + auto entry = entries.find(name); if (entry == entries.end()) { - return nullptr; + CreateSchemaInfo info; + if (!IRCAPI::VerifySchemaExistence(context, ic_catalog, name)) { + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + return nullptr; + } else { + throw CatalogException("Iceberg namespace by the name of '%s' does not exist", name); + } + } + info.schema = name; + info.internal = false; + auto schema_entry = make_uniq(catalog, info); + schema_entry->namespace_items = IRCAPI::ParseSchemaName(name); + CreateEntryInternal(context, std::move(schema_entry)); + entry = entries.find(name); + D_ASSERT(entry != entries.end()); } return entry->second.get(); } @@ -34,7 +50,7 @@ static string GetSchemaName(const vector &items) { } void IRCSchemaSet::LoadEntries(ClientContext &context) { - if (!entries.empty()) { + if (listed) { return; } @@ -48,6 +64,7 @@ void IRCSchemaSet::LoadEntries(ClientContext &context) { schema_entry->namespace_items = std::move(schema.items); CreateEntryInternal(context, std::move(schema_entry)); } + listed = true; } optional_ptr IRCSchemaSet::CreateEntryInternal(ClientContext &context, unique_ptr entry) { diff --git a/src/storage/irc_table_set.cpp b/src/storage/irc_table_set.cpp index e8a77f51..862a9a1b 100644 --- a/src/storage/irc_table_set.cpp +++ b/src/storage/irc_table_set.cpp @@ -29,7 +29,6 @@ ICTableSet::ICTableSet(IRCSchemaEntry &schema) : schema(schema), catalog(schema. void ICTableSet::FillEntry(ClientContext &context, IcebergTableInformation &table) { if (!table.schema_versions.empty()) { - //! Already filled return; } @@ -57,17 +56,20 @@ void ICTableSet::Scan(ClientContext &context, const std::function(); - // TODO: handle out-of-order columns using position property auto tables = IRCAPI::GetTables(context, ic_catalog, schema); for (auto &table : tables) { - entries.emplace(table.name, IcebergTableInformation(ic_catalog, schema, table.name)); + auto entry_it = entries.find(table.name); + if (entry_it == entries.end()) { + entries.emplace(table.name, IcebergTableInformation(ic_catalog, schema, table.name)); + } } + listed = true; } void ICTableSet::CreateNewEntry(ClientContext &context, IRCatalog &catalog, IRCSchemaEntry &schema, @@ -121,11 +123,17 @@ unique_ptr ICTableSet::GetTableInfo(ClientContext &context, IRCSche } optional_ptr ICTableSet::GetEntry(ClientContext &context, const EntryLookupInfo &lookup) { - LoadEntries(context); lock_guard l(entry_lock); - auto entry = entries.find(lookup.GetEntryName()); + auto &ic_catalog = catalog.Cast(); + + auto table_name = lookup.GetEntryName(); + auto entry = entries.find(table_name); if (entry == entries.end()) { - return nullptr; + if (!IRCAPI::VerifyTableExistence(context, ic_catalog, schema, table_name)) { + return nullptr; + } + auto it = entries.emplace(table_name, IcebergTableInformation(ic_catalog, schema, table_name)); + entry = it.first; } if (entry->second.transaction_data && entry->second.transaction_data->is_deleted) { return nullptr; diff --git a/test/sql/local/irc/iceberg_catalog_eager_refresh.test b/test/sql/local/irc/iceberg_catalog_eager_refresh.test index 43a9ad0c..f94ac8ce 100644 --- a/test/sql/local/irc/iceberg_catalog_eager_refresh.test +++ b/test/sql/local/irc/iceberg_catalog_eager_refresh.test @@ -58,8 +58,6 @@ select * from my_datalake.default.table_more_deletes order by all; query II SELECT request.url, response.reason FROM duckdb_logs_parsed('HTTP') WHERE request.type='GET' AND (request.url).starts_with('http://127.0.0.1:8181/v1/') order by timestamp ---- -http://127.0.0.1:8181/v1/namespaces OK -http://127.0.0.1:8181/v1/namespaces/default/tables OK http://127.0.0.1:8181/v1/namespaces/default/tables/table_unpartitioned OK http://127.0.0.1:8181/v1/namespaces/default/tables/table_more_deletes OK @@ -91,9 +89,5 @@ select * from my_datalake.default.table_more_deletes order by all; query II SELECT request.url, response.reason FROM duckdb_logs_parsed('HTTP') WHERE request.type='GET' AND (request.url).starts_with('http://127.0.0.1:8181/v1/') order by timestamp ---- -http://127.0.0.1:8181/v1/namespaces OK -http://127.0.0.1:8181/v1/namespaces/default/tables OK http://127.0.0.1:8181/v1/namespaces/default/tables/table_more_deletes OK -http://127.0.0.1:8181/v1/namespaces OK -http://127.0.0.1:8181/v1/namespaces/default/tables OK http://127.0.0.1:8181/v1/namespaces/default/tables/table_more_deletes OK diff --git a/test/sql/local/irc/iceberg_catalog_read.test b/test/sql/local/irc/iceberg_catalog_read.test index 929d70de..dc1d7dfe 100644 --- a/test/sql/local/irc/iceberg_catalog_read.test +++ b/test/sql/local/irc/iceberg_catalog_read.test @@ -88,11 +88,7 @@ select * from my_datalake.default.table_more_deletes order by all; query II SELECT request.url, response.reason FROM duckdb_logs_parsed('HTTP') WHERE request.type='GET' AND (request.url).starts_with('http://127.0.0.1:8181/v1/') order by timestamp ---- -http://127.0.0.1:8181/v1/namespaces OK -http://127.0.0.1:8181/v1/namespaces/default/tables OK http://127.0.0.1:8181/v1/namespaces/default/tables/table_unpartitioned OK -http://127.0.0.1:8181/v1/namespaces OK -http://127.0.0.1:8181/v1/namespaces/default/tables OK http://127.0.0.1:8181/v1/namespaces/default/tables/table_more_deletes OK query I diff --git a/test/sql/local/irc/test_minimal_head_requests.test b/test/sql/local/irc/test_minimal_head_requests.test index eff4496a..5114f8eb 100644 --- a/test/sql/local/irc/test_minimal_head_requests.test +++ b/test/sql/local/irc/test_minimal_head_requests.test @@ -54,11 +54,11 @@ select * from my_datalake.default.table_unpartitioned order by all; 2023-03-11 11 k 2023-03-12 12 l -# 0 head requests to all files +# 2 head requests to scan all files (1 for the schema, 1 for the table) query I select count(*) from duckdb_logs_parsed('HTTP') where request.type = 'HEAD'; ---- -0 +2 # only 13 get requests query I nosort get_count_1 @@ -85,11 +85,11 @@ select * from my_datalake.default.table_unpartitioned order by all; 2023-03-12 12 l -# after reading the same table, still no head requests +# after reading the same table, only 2 more head requests (because of new transactions) query I select count(*) from duckdb_logs_parsed('HTTP') where request.type = 'HEAD'; ---- -0 +4 # same amount of get calls query I nosort get_count_1 diff --git a/test/sql/local/irc/test_use.test b/test/sql/local/irc/test_use.test index f48e6eef..f5c3ae55 100644 --- a/test/sql/local/irc/test_use.test +++ b/test/sql/local/irc/test_use.test @@ -38,17 +38,17 @@ ATTACH '' AS my_datalake ( statement ok use my_datalake.default; -# need catalog and schema name for use. +# schema will default to 'main', which doesnt exist statement error use my_datalake; ---- -Catalog Error +Catalog Error: SET schema: No catalog + schema named "my_datalake" found. -# even after showing all tables. use statement needs catalog + schema. statement ok show all tables; +# 'main' still doesn't exist statement error use my_datalake; ---- -Catalog Error \ No newline at end of file +Catalog Error: SET schema: No catalog + schema named "my_datalake" found.