This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 7939bd96 feat: load view (#640)
7939bd96 is described below

commit 7939bd96eda59c47739e8172dd27db25efe8fb42
Author: M Alvee <[email protected]>
AuthorDate: Tue Dec 9 23:36:20 2025 +0600

    feat: load view (#640)
    
    load view metadata
---
 catalog/rest/rest.go      |  30 +++++++++++++
 catalog/rest/rest_test.go | 112 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 138 insertions(+), 4 deletions(-)

diff --git a/catalog/rest/rest.go b/catalog/rest/rest.go
index c5ae8382..1633ffb7 100644
--- a/catalog/rest/rest.go
+++ b/catalog/rest/rest.go
@@ -1269,3 +1269,33 @@ func (r *Catalog) UpdateView(ctx context.Context, ident 
table.Identifier, requir
 
        return view.New(ident, ret.Metadata, ret.MetadataLoc), nil
 }
+
+// loadViewResponse contains the response from loading a view
+type loadViewResponse struct {
+       MetadataLoc string             `json:"metadata-location"`
+       RawMetadata json.RawMessage    `json:"metadata"`
+       Config      iceberg.Properties `json:"config"`
+}
+
+// LoadView loads a view from the catalog.
+func (r *Catalog) LoadView(ctx context.Context, identifier table.Identifier) 
(*view.View, error) {
+       ns, v, err := splitIdentForPath(identifier)
+       if err != nil {
+               return nil, err
+       }
+
+       rsp, err := doGet[loadViewResponse](ctx, r.baseURI, 
[]string{"namespaces", ns, "views", v},
+               r.cl, map[int]error{
+                       http.StatusNotFound: catalog.ErrNoSuchView,
+               })
+       if err != nil {
+               return nil, err
+       }
+
+       metadata, err := view.ParseMetadataBytes(rsp.RawMetadata)
+       if err != nil {
+               return nil, fmt.Errorf("failed to parse view metadata: %w", err)
+       }
+
+       return view.New(identifier, metadata, rsp.MetadataLoc), nil
+}
diff --git a/catalog/rest/rest_test.go b/catalog/rest/rest_test.go
index 0a842205..c515b360 100644
--- a/catalog/rest/rest_test.go
+++ b/catalog/rest/rest_test.go
@@ -1102,7 +1102,7 @@ func (r *RestCatalogSuite) TestLoadTable200() {
                        r.Equal(v, req.Header.Values(k))
                }
 
-               w.Write([]byte(`{                       
+               w.Write([]byte(`{
                        "metadata-location": 
"s3://warehouse/database/table/metadata/00001-5f2f8166-244c-4eae-ac36-384ecdec81fc.gz.metadata.json",
                        "metadata": {
                                "format-version": 1,
@@ -1387,14 +1387,14 @@ func (r *RestCatalogSuite) TestRegisterTable200() {
       }
     ],
     "partition-spec": [
-      
+
     ],
     "default-spec-id": 0,
     "partition-specs": [
       {
         "spec-id": 0,
         "fields": [
-          
+
         ]
       }
     ],
@@ -1404,7 +1404,7 @@ func (r *RestCatalogSuite) TestRegisterTable200() {
       {
         "order-id": 0,
         "fields": [
-          
+
         ]
       }
     ],
@@ -1872,6 +1872,110 @@ func (r *RestCatalogSuite) TestCheckViewExists404() {
        r.False(exists)
 }
 
+func (r *RestCatalogSuite) TestLoadView200() {
+       r.mux.HandleFunc("/v1/namespaces/fokko/views/myview", func(w 
http.ResponseWriter, req *http.Request) {
+               r.Require().Equal(http.MethodGet, req.Method)
+
+               for k, v := range TestHeaders {
+                       r.Equal(v, req.Header.Values(k))
+               }
+
+               w.Write([]byte(`{
+                       "metadata-location": 
"s3://bucket/warehouse/default.db/event_agg/metadata/00001.metadata.json",
+                       "metadata": {
+                               "view-uuid": 
"fa6506c3-7681-40c8-86dc-e36561f83385",
+                               "format-version": 1,
+                               "location": 
"s3://bucket/warehouse/default.db/event_agg",
+                               "current-version-id": 1,
+                               "properties": {
+                                       "comment": "Daily event counts"
+                               },
+                               "versions": [{
+                                       "version-id": 1,
+                                       "timestamp-ms": 1573518431292,
+                                       "schema-id": 1,
+                                       "default-catalog": "prod",
+                                       "default-namespace": ["default"],
+                                       "summary": {
+                                               "engine-name": "Spark",
+                                               "engine-version": "3.3.2"
+                                       },
+                                       "representations": [{
+                                               "type": "sql",
+                                               "sql": "SELECT COUNT(1), 
CAST(event_ts AS DATE) FROM events GROUP BY 2",
+                                               "dialect": "spark"
+                                       }]
+                               }],
+                               "schemas": [{
+                                       "schema-id": 1,
+                                       "type": "struct",
+                                       "fields": [
+                                               {"id": 1, "name": 
"event_count", "required": false, "type": "int"},
+                                               {"id": 2, "name": "event_date", 
"required": false, "type": "date"}
+                                       ]
+                               }],
+                               "version-log": [{
+                                       "timestamp-ms": 1573518431292,
+                                       "version-id": 1
+                               }]
+                       },
+                       "config": {}
+               }`))
+       })
+
+       cat, err := rest.NewCatalog(context.Background(), "rest", r.srv.URL, 
rest.WithOAuthToken(TestToken))
+       r.Require().NoError(err)
+
+       v, err := cat.LoadView(context.Background(), 
catalog.ToIdentifier("fokko", "myview"))
+       r.Require().NoError(err)
+
+       r.Equal(table.Identifier{"fokko", "myview"}, v.Identifier())
+       
r.Equal("s3://bucket/warehouse/default.db/event_agg/metadata/00001.metadata.json",
 v.MetadataLocation())
+
+       metadata := v.Metadata()
+       r.Equal(uuid.MustParse("fa6506c3-7681-40c8-86dc-e36561f83385"), 
metadata.ViewUUID())
+       r.Equal(1, metadata.FormatVersion())
+       r.Equal("s3://bucket/warehouse/default.db/event_agg", 
metadata.Location())
+       r.Equal("Daily event counts", metadata.Properties()["comment"])
+
+       currentVersion := metadata.CurrentVersion()
+       r.NotNil(currentVersion)
+       r.EqualValues(1, currentVersion.VersionID)
+       r.Equal(1, currentVersion.SchemaID)
+       r.EqualValues(1573518431292, currentVersion.TimestampMS)
+       r.Equal("Spark", currentVersion.Summary["engine-name"])
+       r.Len(currentVersion.Representations, 1)
+       r.Equal("sql", currentVersion.Representations[0].Type)
+       r.Equal("spark", currentVersion.Representations[0].Dialect)
+}
+
+func (r *RestCatalogSuite) TestLoadView404() {
+       r.mux.HandleFunc("/v1/namespaces/fokko/views/nonexistent", func(w 
http.ResponseWriter, req *http.Request) {
+               r.Require().Equal(http.MethodGet, req.Method)
+
+               for k, v := range TestHeaders {
+                       r.Equal(v, req.Header.Values(k))
+               }
+
+               w.WriteHeader(http.StatusNotFound)
+               json.NewEncoder(w).Encode(map[string]any{
+                       "error": map[string]any{
+                               "message": "View does not exist: 
fokko.nonexistent",
+                               "type":    "NoSuchViewException",
+                               "code":    404,
+                       },
+               })
+       })
+
+       cat, err := rest.NewCatalog(context.Background(), "rest", r.srv.URL, 
rest.WithOAuthToken(TestToken))
+       r.Require().NoError(err)
+
+       _, err = cat.LoadView(context.Background(), 
catalog.ToIdentifier("fokko", "nonexistent"))
+       r.Error(err)
+       r.ErrorIs(err, catalog.ErrNoSuchView)
+       r.ErrorContains(err, "View does not exist: fokko.nonexistent")
+}
+
 type RestTLSCatalogSuite struct {
        suite.Suite
 

Reply via email to