SteNicholas commented on code in PR #447:
URL: https://github.com/apache/paimon-cpp/pull/447#discussion_r4361383239


##########
src/paimon/rest/rest_catalog.cpp:
##########
@@ -388,78 +390,110 @@ Result<std::shared_ptr<Schema>> 
RestCatalog::LoadTableSchema(const Identifier& i
         context.catalog_options = api_->GetMergedOptions();
         PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<SystemTable> system_table,
                                
GlobalSystemTableLoader::Load(identifier.GetObjectName(), context));
-        PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Schema> arrow_schema,
-                               system_table->ArrowSchema());
-        return std::make_shared<SystemTableSchema>(std::move(arrow_schema));
+        return system_table->LatestSchema();
     }
     PAIMON_ASSIGN_OR_RAISE(bool is_system_table, identifier.IsSystemTable());
     PAIMON_ASSIGN_OR_RAISE(std::optional<std::string> branch, 
identifier.GetBranchName());
     branch = NormalizeBranch(std::move(branch));
     PAIMON_ASSIGN_OR_RAISE(Identifier load_identifier, 
ToLoadIdentifier(identifier));
     if (is_system_table) {
-        PAIMON_ASSIGN_OR_RAISE(std::optional<std::string> system_table_name,
-                               identifier.GetSystemTableName());
-        if (!system_table_name || 
!SystemTableLoader::IsSupported(system_table_name.value())) {
-            return Status::NotExist(fmt::format("{} not exist", 
identifier.ToString()));
-        }
-        std::string data_table_path;
-        PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<TableSchema> latest_schema,
-                               LoadDataTableSchema(load_identifier, branch, 
&data_table_path,
-                                                   /*table_id=*/nullptr));
+        PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<SystemTable> system_table,
+                               LoadSystemTable(identifier, load_identifier, 
branch));
         if (table_path != nullptr) {
-            *table_path = data_table_path;
-        }
-        std::map<std::string, std::string> dynamic_options;
-        if (branch) {
-            dynamic_options[Options::BRANCH] = branch.value();
+            *table_path = system_table->GetRootPath();
         }
-        // The file system is only used to build the system table, whose 
schema does not
-        // read any file, so the catalog wide one is enough here. The 
credentials of the
-        // table are applied when its rows are read, through the file system 
of the read or
-        // scan context.
-        PAIMON_ASSIGN_OR_RAISE(
-            std::shared_ptr<SystemTable> system_table,
-            SystemTableLoader::Load(system_table_name.value(), fs_, 
data_table_path, latest_schema,
-                                    dynamic_options));
-        PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Schema> arrow_schema,
-                               system_table->ArrowSchema());
-        return std::make_shared<SystemTableSchema>(std::move(arrow_schema));
+        return system_table->LatestSchema();
     }
     PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<TableSchema> schema,
                            LoadDataTableSchema(load_identifier, branch, 
table_path, table_id));
     return checked_pointer_cast<Schema>(schema);
 }
 
-Result<std::shared_ptr<FormatTable>> RestCatalog::LoadFormatTable(
-    const Identifier& identifier) const {
-    // A system table is already refused by `Catalog::GetFormatTable()`, which 
every caller goes
-    // through, so this only has to load.
-    PAIMON_ASSIGN_OR_RAISE(std::optional<std::string> branch, 
identifier.GetBranchName());
-    branch = NormalizeBranch(std::move(branch));
-    PAIMON_ASSIGN_OR_RAISE(Identifier load_identifier, 
ToLoadIdentifier(identifier));
-    std::string location;
-    PAIMON_ASSIGN_OR_RAISE(
-        std::shared_ptr<TableSchema> schema,
-        LoadDataTableSchema(load_identifier, branch, &location, 
/*table_id=*/nullptr));
-    // A rest catalog holds the schema itself, so everything below the 
location is data.
-    return FormatTable::Create(fs_, location, identifier, 
checked_pointer_cast<DataSchema>(schema),
-                               /*location_carries_paimon_metadata=*/false,
-                               /*dynamic_options=*/{});
+Result<std::shared_ptr<SystemTable>> RestCatalog::LoadSystemTable(
+    const Identifier& identifier, const Identifier& load_identifier,
+    const std::optional<std::string>& branch) const {
+    PAIMON_ASSIGN_OR_RAISE(std::optional<std::string> system_table_name,
+                           identifier.GetSystemTableName());
+    if (!system_table_name || 
!SystemTableLoader::IsSupported(system_table_name.value())) {
+        return Status::NotExist(fmt::format("{} not exist", 
identifier.ToString()));
+    }
+    std::string data_table_path;
+    PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<TableSchema> latest_schema,
+                           LoadDataTableSchema(load_identifier, branch, 
&data_table_path,
+                                               /*table_id=*/nullptr));
+    std::map<std::string, std::string> dynamic_options;
+    if (branch) {
+        dynamic_options[Options::BRANCH] = branch.value();
+    }
+    // The system table reads the data table's own files - snapshots, 
manifests, data - so it is
+    // served by the file system that table's credentials open, which with 
data tokens is the
+    // only one that can: `GetTableFileSystem` folds the system identifier to 
the data table it
+    // belongs to and hands the catalog-wide file system out when no tokens 
are issued.
+    PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<FileSystem> table_file_system,
+                           GetTableFileSystem(identifier));
+    return SystemTableLoader::Load(system_table_name.value(), 
table_file_system, data_table_path,
+                                   latest_schema, dynamic_options);
 }
 
 Result<std::shared_ptr<Table>> RestCatalog::GetTable(const Identifier& 
identifier) const {
+    // The global system tables of the "sys" database expose the catalog 
itself rather than any
+    // table the server stands behind, so they are served locally - the way 
`LoadTableSchema`
+    // serves them their schema - and never reach the managed-table load 
below, whose schema
+    // cast a read-only system table schema would not survive.
+    if (CatalogUtils::IsSystemDatabase(identifier.GetDatabaseName())) {
+        PAIMON_ASSIGN_OR_RAISE(bool supported,
+                               
GlobalSystemTableLoader::IsSupported(identifier.GetObjectName(),
+                                                                    
api_->GetMergedOptions()));
+        if (!supported) {
+            return Status::NotExist(fmt::format("{} not exist", 
identifier.ToString()));
+        }
+        GlobalSystemTableContext context;
+        context.catalog = this;
+        context.fs = fs_;
+        context.warehouse = warehouse_;
+        context.catalog_options = api_->GetMergedOptions();
+        return GlobalSystemTableLoader::Load(identifier.GetObjectName(), 
context);

Review Comment:
   @lucasfang, preserve the catalog lifetime for global system tables. The 
returned system table stores `this` as a non-owning catalog pointer. After 
`GetTable` returns, destroying the catalog leaves `sys.tables`, 
`sys.partitions` and `sys.all_table_options` with a dangling pointer; their 
lazy `BuildRows` calls dereference it during `NextBatch`. Neither the table nor 
its reader retains the catalog (`InMemorySystemTableRead` retains only the 
table and memory pool). Please retain the required catalog state for the 
returned table's lifetime.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to