This is an automated email from the ASF dual-hosted git repository.
laskoviymishka 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 092822e5 feat(cli): add maintenance command wiring and stubs (#1073)
092822e5 is described below
commit 092822e5cb1d1dc3135a0f492876bbc2fb60f15a
Author: Tanmay Rauth <[email protected]>
AuthorDate: Tue May 12 00:42:16 2026 -0700
feat(cli): add maintenance command wiring and stubs (#1073)
Register all maintenance subcommands (snapshots, refs, partition-stats,
branch/tag create, expire-snapshots, clean-orphan-files, upgrade,
rollback, schema --show-defaults) with stub implementations.
Adds shared utilities: parseDuration, confirmAction, formatDurationMs.
Each command stub file will be replaced by its implementation PR.
---
cmd/iceberg/branch_tag.go | 39 ++++++
cmd/iceberg/clean_orphan_files.go | 34 +++++
cmd/iceberg/expire_snapshots.go | 34 +++++
cmd/iceberg/main.go | 68 +++++++---
cmd/iceberg/maintenance.go | 253 ++++++++++++++++++++++++++++++++++++++
cmd/iceberg/output.go | 9 ++
cmd/iceberg/partition_stats.go | 35 ++++++
cmd/iceberg/schema_defaults.go | 33 +++++
cmd/iceberg/snapshots.go | 42 +++++++
cmd/iceberg/upgrade_rollback.go | 41 ++++++
10 files changed, 573 insertions(+), 15 deletions(-)
diff --git a/cmd/iceberg/branch_tag.go b/cmd/iceberg/branch_tag.go
new file mode 100644
index 00000000..967b9bc4
--- /dev/null
+++ b/cmd/iceberg/branch_tag.go
@@ -0,0 +1,39 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go/catalog"
+)
+
+func runBranch(_ context.Context, output Output, _ catalog.Catalog, _
*BranchCmd) {
+ output.Error(errors.New("branch: not yet implemented"))
+ os.Exit(1)
+}
+
+func runTag(_ context.Context, output Output, _ catalog.Catalog, _ *TagCmd) {
+ output.Error(errors.New("tag: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) RefCreated(_ RefCreatedResult) {}
+func (jsonOutput) RefCreated(_ RefCreatedResult) {}
diff --git a/cmd/iceberg/clean_orphan_files.go
b/cmd/iceberg/clean_orphan_files.go
new file mode 100644
index 00000000..98297bb4
--- /dev/null
+++ b/cmd/iceberg/clean_orphan_files.go
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go/catalog"
+)
+
+func runCleanOrphanFiles(_ context.Context, output Output, _ catalog.Catalog,
_ *CleanOrphanFilesCmd) {
+ output.Error(errors.New("clean-orphan-files: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) CleanOrphanFilesResult(_ CleanOrphanFilesResult) {}
+func (jsonOutput) CleanOrphanFilesResult(_ CleanOrphanFilesResult) {}
diff --git a/cmd/iceberg/expire_snapshots.go b/cmd/iceberg/expire_snapshots.go
new file mode 100644
index 00000000..46a10d6e
--- /dev/null
+++ b/cmd/iceberg/expire_snapshots.go
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go/catalog"
+)
+
+func runExpireSnapshots(_ context.Context, output Output, _ catalog.Catalog, _
*ExpireSnapshotsCmd) {
+ output.Error(errors.New("expire-snapshots: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) ExpireSnapshotsResult(_ ExpireSnapshotsResult) {}
+func (jsonOutput) ExpireSnapshotsResult(_ ExpireSnapshotsResult) {}
diff --git a/cmd/iceberg/main.go b/cmd/iceberg/main.go
index ecc93f8c..fca148fe 100644
--- a/cmd/iceberg/main.go
+++ b/cmd/iceberg/main.go
@@ -55,7 +55,8 @@ type DescribeCmd struct {
}
type SchemaCmd struct {
- TableID string `arg:"positional,required" help:"full path to a table"`
+ TableID string `arg:"positional,required" help:"full path to a
table"`
+ ShowDefaults bool `arg:"--show-defaults" help:"show initial-default
and write-default values"`
}
type SpecCmd struct {
@@ -167,19 +168,28 @@ type CompactCmd struct {
// Top-level args
type Args struct {
- List *ListCmd `arg:"subcommand:list" help:"list tables or
namespaces"`
- Describe *DescribeCmd `arg:"subcommand:describe" help:"describe a
namespace or table"`
- Schema *SchemaCmd `arg:"subcommand:schema" help:"get the schema
of a table"`
- Spec *SpecCmd `arg:"subcommand:spec" help:"return the
partition spec of a table"`
- Uuid *UuidCmd `arg:"subcommand:uuid" help:"return the UUID
of a table"`
- Location *LocationCmd `arg:"subcommand:location" help:"return the
location of a table"`
- Create *CreateCmd `arg:"subcommand:create" help:"create a
namespace or table"`
- Drop *DropCmd `arg:"subcommand:drop" help:"drop a namespace
or table"`
- Files *FilesCmd `arg:"subcommand:files" help:"list all files
of a table"`
- Rename *RenameCmd `arg:"subcommand:rename" help:"rename a
table"`
- Properties *PropertiesCmd `arg:"subcommand:properties" help:"manage
properties on tables/namespaces"`
- Compact *CompactCmd `arg:"subcommand:compact" help:"analyze or
run bin-pack compaction"`
- Info *InfoCmd `arg:"subcommand:info" help:"show
single-screen table summary"`
+ List *ListCmd `arg:"subcommand:list" help:"list
tables or namespaces"`
+ Describe *DescribeCmd `arg:"subcommand:describe"
help:"describe a namespace or table"`
+ Schema *SchemaCmd `arg:"subcommand:schema" help:"get
the schema of a table"`
+ Spec *SpecCmd `arg:"subcommand:spec" help:"return
the partition spec of a table"`
+ Uuid *UuidCmd `arg:"subcommand:uuid" help:"return
the UUID of a table"`
+ Location *LocationCmd `arg:"subcommand:location"
help:"return the location of a table"`
+ Create *CreateCmd `arg:"subcommand:create" help:"create
a namespace or table"`
+ Drop *DropCmd `arg:"subcommand:drop" help:"drop a
namespace or table"`
+ Files *FilesCmd `arg:"subcommand:files" help:"list
all files of a table"`
+ Rename *RenameCmd `arg:"subcommand:rename" help:"rename
a table"`
+ Properties *PropertiesCmd `arg:"subcommand:properties"
help:"manage properties on tables/namespaces"`
+ Compact *CompactCmd `arg:"subcommand:compact"
help:"analyze or run bin-pack compaction"`
+ Info *InfoCmd `arg:"subcommand:info" help:"show
single-screen table summary"`
+ Snapshots *SnapshotsCmd `arg:"subcommand:snapshots"
help:"list table snapshots"`
+ Refs *RefsCmd `arg:"subcommand:refs" help:"list
snapshot refs"`
+ PartStats *PartitionStatsCmd `arg:"subcommand:partition-stats"
help:"list partition statistics files"`
+ Branch *BranchCmd `arg:"subcommand:branch" help:"manage
table branches"`
+ Tag *TagCmd `arg:"subcommand:tag" help:"manage
table tags"`
+ ExpireSnaps *ExpireSnapshotsCmd `arg:"subcommand:expire-snapshots"
help:"expire old snapshots"`
+ CleanOrphans *CleanOrphanFilesCmd `arg:"subcommand:clean-orphan-files"
help:"remove orphan files"`
+ Upgrade *UpgradeCmd `arg:"subcommand:upgrade"
help:"upgrade table format version"`
+ Rollback *RollbackCmd `arg:"subcommand:rollback" help:"roll
back to a previous snapshot"`
Catalog string `arg:"--catalog" default:"rest" help:"catalog type"`
CatalogName string `arg:"--catalog-name" default:"default"
help:"catalog name from config"`
@@ -243,6 +253,12 @@ func main() {
case args.Compact != nil && args.Compact.Analyze == nil &&
args.Compact.Run == nil:
_ = parser.WriteHelpForSubcommand(os.Stderr, "compact")
os.Exit(1)
+ case args.Branch != nil && args.Branch.Create == nil:
+ _ = parser.WriteHelpForSubcommand(os.Stderr, "branch")
+ os.Exit(1)
+ case args.Tag != nil && args.Tag.Create == nil:
+ _ = parser.WriteHelpForSubcommand(os.Stderr, "tag")
+ os.Exit(1)
}
var output Output
@@ -264,7 +280,11 @@ func main() {
runDescribe(ctx, output, cat, args.Describe)
case args.Schema != nil:
tbl := loadTable(ctx, output, cat, args.Schema.TableID)
- output.Schema(tbl.Schema())
+ if args.Schema.ShowDefaults {
+ runSchemaWithDefaults(output, tbl.Schema())
+ } else {
+ output.Schema(tbl.Schema())
+ }
case args.Spec != nil:
tbl := loadTable(ctx, output, cat, args.Spec.TableID)
output.Spec(tbl.Spec())
@@ -290,6 +310,24 @@ func main() {
case args.Info != nil:
tbl := loadTable(ctx, output, cat, args.Info.TableID)
output.Info(tbl)
+ case args.Snapshots != nil:
+ runSnapshots(ctx, output, cat, args.Snapshots)
+ case args.Refs != nil:
+ runRefs(ctx, output, cat, args.Refs)
+ case args.PartStats != nil:
+ runPartitionStats(ctx, output, cat, args.PartStats)
+ case args.Branch != nil:
+ runBranch(ctx, output, cat, args.Branch)
+ case args.Tag != nil:
+ runTag(ctx, output, cat, args.Tag)
+ case args.ExpireSnaps != nil:
+ runExpireSnapshots(ctx, output, cat, args.ExpireSnaps)
+ case args.CleanOrphans != nil:
+ runCleanOrphanFiles(ctx, output, cat, args.CleanOrphans)
+ case args.Upgrade != nil:
+ runUpgrade(ctx, output, cat, args.Upgrade)
+ case args.Rollback != nil:
+ runRollback(ctx, output, cat, args.Rollback)
}
}
diff --git a/cmd/iceberg/maintenance.go b/cmd/iceberg/maintenance.go
new file mode 100644
index 00000000..7a0f5e43
--- /dev/null
+++ b/cmd/iceberg/maintenance.go
@@ -0,0 +1,253 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/apache/iceberg-go"
+ "github.com/apache/iceberg-go/catalog"
+ "github.com/apache/iceberg-go/table"
+
+ "golang.org/x/term"
+)
+
+// Command structs
+
+type SnapshotsCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a table"`
+}
+
+type RefsCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a table"`
+ Type string `arg:"--type" help:"filter by ref type (branch or tag)"`
+}
+
+type PartitionStatsCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a
table"`
+ SnapshotID *int64 `arg:"--snapshot-id" help:"filter by snapshot ID"`
+ All bool `arg:"--all" help:"show partition statistics for all
snapshots"`
+}
+
+type ExpireSnapshotsCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a
table"`
+ OlderThan string `arg:"--older-than" help:"expire snapshots older than
duration (e.g. 7d, 168h)"`
+ RetainLast *int `arg:"--retain-last" help:"minimum number of
snapshots to retain"`
+ DryRun bool `arg:"--dry-run" help:"show what would be expired
without committing"`
+ Yes bool `arg:"--yes" help:"skip confirmation prompt"`
+}
+
+type CleanOrphanFilesCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a table"`
+ OlderThan string `arg:"--older-than" default:"72h" help:"delete files
older than duration (default 72h)"`
+ DryRun bool `arg:"--dry-run" help:"list orphan files without
deleting"`
+ Yes bool `arg:"--yes" help:"skip confirmation prompt"`
+ Location string `arg:"--location" help:"override location to scan for
orphan files"`
+}
+
+type UpgradeCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a
table"`
+ FormatVersion int `arg:"positional,required" help:"target format
version (e.g. 2, 3)"`
+ DryRun bool `arg:"--dry-run" help:"show what would change
without committing"`
+ Yes bool `arg:"--yes" help:"skip confirmation prompt"`
+}
+
+type RollbackCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a
table"`
+ SnapshotID int64 `arg:"--snapshot-id,required" help:"snapshot ID to
roll back to"`
+ Yes bool `arg:"--yes" help:"skip confirmation prompt"`
+}
+
+type BranchCreateCmd struct {
+ TableID string `arg:"positional,required" help:"full path to
a table"`
+ BranchName string `arg:"positional,required" help:"branch name"`
+ SnapshotID *int64 `arg:"--snapshot-id" help:"snapshot ID
(defaults to current snapshot)"`
+ MaxRefAge string `arg:"--max-ref-age" help:"max ref age
duration (e.g. 7d, 168h)"`
+ MaxSnapshotAge string `arg:"--max-snapshot-age" help:"max snapshot
age duration"`
+ MinSnapshotsToKeep *int `arg:"--min-snapshots-to-keep" help:"minimum
snapshots to keep"`
+}
+
+type BranchCmd struct {
+ Create *BranchCreateCmd `arg:"subcommand:create" help:"create a branch"`
+}
+
+type TagCreateCmd struct {
+ TableID string `arg:"positional,required" help:"full path to a
table"`
+ TagName string `arg:"positional,required" help:"tag name"`
+ SnapshotID *int64 `arg:"--snapshot-id" help:"snapshot ID (defaults to
current snapshot)"`
+ MaxRefAge string `arg:"--max-ref-age" help:"max ref age duration (e.g.
7d, 168h)"`
+}
+
+type TagCmd struct {
+ Create *TagCreateCmd `arg:"subcommand:create" help:"create a tag"`
+}
+
+// Result types
+
+type SnapshotEntry struct {
+ SnapshotID int64 `json:"snapshot_id"`
+ Timestamp string `json:"timestamp"`
+ ParentSnapshotID *int64 `json:"parent_snapshot_id"`
+ Operation string `json:"operation"`
+ AddedDataFiles string `json:"added_data_files"`
+ DeletedDataFiles string `json:"deleted_data_files"`
+}
+
+type RefEntry struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+ SnapshotID int64 `json:"snapshot_id"`
+ MaxRefAgeMs *int64 `json:"max_ref_age_ms"`
+ MaxSnapshotAgeMs *int64 `json:"max_snapshot_age_ms"`
+ MinSnapshotsToKeep *int `json:"min_snapshots_to_keep"`
+}
+
+type PartitionStatsEntry struct {
+ SnapshotID int64 `json:"snapshot_id"`
+ Path string `json:"path"`
+ SizeBytes int64 `json:"size_bytes"`
+}
+
+type SchemaFieldWithDefaults struct {
+ FieldID int `json:"field_id"`
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Required bool `json:"required"`
+ InitialDefault any `json:"initial_default"`
+ WriteDefault any `json:"write_default"`
+}
+
+type ExpireSnapshotsResult struct {
+ DryRun bool `json:"dry_run"`
+ Table string `json:"table"`
+ ExpiredSnapshotCount int `json:"expired_snapshot_count"`
+ ExpiredSnapshots []SnapshotEntry `json:"expired_snapshots"`
+}
+
+type CleanOrphanFilesResult struct {
+ DryRun bool `json:"dry_run"`
+ Table string `json:"table"`
+ OrphanFileCount int `json:"orphan_file_count"`
+ TotalSizeBytes int64 `json:"total_size_bytes"`
+ OrphanFiles []OrphanFileEntry `json:"orphan_files"`
+}
+
+type OrphanFileEntry struct {
+ Path string `json:"path"`
+ SizeBytes int64 `json:"size_bytes,omitempty"`
+}
+
+type UpgradeResult struct {
+ DryRun bool `json:"dry_run"`
+ Table string `json:"table"`
+ PreviousVersion int `json:"previous_version"`
+ TargetVersion int `json:"target_version"`
+ SpecURL string `json:"spec_url"`
+}
+
+type RollbackResult struct {
+ Table string `json:"table"`
+ PreviousSnapshotID *int64 `json:"previous_snapshot_id"`
+ RolledBackToSnapshotID int64 `json:"rolled_back_to_snapshot_id"`
+}
+
+type RefCreatedResult struct {
+ Table string `json:"table"`
+ RefName string `json:"ref_name"`
+ RefType string `json:"ref_type"`
+ SnapshotID int64 `json:"snapshot_id"`
+}
+
+// Shared helpers
+
+func parseDuration(s string) (time.Duration, error) {
+ s = strings.TrimSpace(s)
+ if s == "" {
+ return 0, errors.New("empty duration string")
+ }
+
+ if strings.HasSuffix(s, "d") {
+ daysStr := strings.TrimSuffix(s, "d")
+ days, err := strconv.ParseFloat(daysStr, 64)
+ if err != nil {
+ return 0, fmt.Errorf("invalid day duration %q: %w", s,
err)
+ }
+
+ return time.Duration(days * float64(24*time.Hour)), nil
+ }
+
+ d, err := time.ParseDuration(s)
+ if err != nil {
+ return 0, fmt.Errorf("invalid duration %q: %w", s, err)
+ }
+
+ return d, nil
+}
+
+func confirmAction(prompt string, skipConfirm bool) error {
+ if skipConfirm {
+ return nil
+ }
+
+ if !term.IsTerminal(int(os.Stdin.Fd())) {
+ return errors.New("stdin is not a terminal: use --yes to
confirm in non-interactive mode")
+ }
+
+ fmt.Fprintf(os.Stderr, "%s [y/N] ", prompt)
+
+ reader := bufio.NewReader(os.Stdin)
+ answer, err := reader.ReadString('\n')
+ if err != nil {
+ return fmt.Errorf("failed to read confirmation: %w", err)
+ }
+
+ answer = strings.TrimSpace(strings.ToLower(answer))
+ if answer != "y" && answer != "yes" {
+ return errors.New("aborted")
+ }
+
+ return nil
+}
+
+func formatDurationMs(ms *int64) string {
+ if ms == nil {
+ return "-"
+ }
+
+ d := time.Duration(*ms) * time.Millisecond
+ hours := int64(d.Hours())
+
+ if hours > 0 && d == time.Duration(hours)*time.Hour {
+ return fmt.Sprintf("%dh", hours)
+ }
+
+ return d.String()
+}
+
+// Ensure unused imports are satisfied for stub files.
+var (
+ _ = (*catalog.Catalog)(nil)
+ _ = (*table.Table)(nil)
+ _ = (*iceberg.Schema)(nil)
+)
diff --git a/cmd/iceberg/output.go b/cmd/iceberg/output.go
index 03ecf9f0..2e2a7114 100644
--- a/cmd/iceberg/output.go
+++ b/cmd/iceberg/output.go
@@ -40,6 +40,15 @@ type Output interface {
Files(tbl *table.Table, history bool)
DescribeProperties(iceberg.Properties)
Info(tbl *table.Table)
+ Snapshots(tbl *table.Table)
+ Refs(tbl *table.Table, filterType string)
+ PartitionStats(tbl *table.Table, snapshotID *int64, all bool)
+ SchemaWithDefaults(schema *iceberg.Schema)
+ ExpireSnapshotsResult(result ExpireSnapshotsResult)
+ CleanOrphanFilesResult(result CleanOrphanFilesResult)
+ UpgradeResult(result UpgradeResult)
+ RollbackResult(result RollbackResult)
+ RefCreated(result RefCreatedResult)
Text(string)
Schema(*iceberg.Schema)
Spec(iceberg.PartitionSpec)
diff --git a/cmd/iceberg/partition_stats.go b/cmd/iceberg/partition_stats.go
new file mode 100644
index 00000000..f4a30ae7
--- /dev/null
+++ b/cmd/iceberg/partition_stats.go
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go/catalog"
+ "github.com/apache/iceberg-go/table"
+)
+
+func runPartitionStats(_ context.Context, output Output, _ catalog.Catalog, _
*PartitionStatsCmd) {
+ output.Error(errors.New("partition-stats: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) PartitionStats(_ *table.Table, _ *int64, _ bool) {}
+func (jsonOutput) PartitionStats(_ *table.Table, _ *int64, _ bool) {}
diff --git a/cmd/iceberg/schema_defaults.go b/cmd/iceberg/schema_defaults.go
new file mode 100644
index 00000000..948ab8dc
--- /dev/null
+++ b/cmd/iceberg/schema_defaults.go
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go"
+)
+
+func runSchemaWithDefaults(output Output, _ *iceberg.Schema) {
+ output.Error(errors.New("schema --show-defaults: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) SchemaWithDefaults(_ *iceberg.Schema) {}
+func (jsonOutput) SchemaWithDefaults(_ *iceberg.Schema) {}
diff --git a/cmd/iceberg/snapshots.go b/cmd/iceberg/snapshots.go
new file mode 100644
index 00000000..d47ae656
--- /dev/null
+++ b/cmd/iceberg/snapshots.go
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go/catalog"
+ "github.com/apache/iceberg-go/table"
+)
+
+func runSnapshots(_ context.Context, output Output, _ catalog.Catalog, _
*SnapshotsCmd) {
+ output.Error(errors.New("snapshots: not yet implemented"))
+ os.Exit(1)
+}
+
+func runRefs(_ context.Context, output Output, _ catalog.Catalog, _ *RefsCmd) {
+ output.Error(errors.New("refs: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) Snapshots(_ *table.Table) {}
+func (jsonOutput) Snapshots(_ *table.Table) {}
+func (textOutput) Refs(_ *table.Table, _ string) {}
+func (jsonOutput) Refs(_ *table.Table, _ string) {}
diff --git a/cmd/iceberg/upgrade_rollback.go b/cmd/iceberg/upgrade_rollback.go
new file mode 100644
index 00000000..bfc7fc59
--- /dev/null
+++ b/cmd/iceberg/upgrade_rollback.go
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package main
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/apache/iceberg-go/catalog"
+)
+
+func runUpgrade(_ context.Context, output Output, _ catalog.Catalog, _
*UpgradeCmd) {
+ output.Error(errors.New("upgrade: not yet implemented"))
+ os.Exit(1)
+}
+
+func runRollback(_ context.Context, output Output, _ catalog.Catalog, _
*RollbackCmd) {
+ output.Error(errors.New("rollback: not yet implemented"))
+ os.Exit(1)
+}
+
+func (textOutput) UpgradeResult(_ UpgradeResult) {}
+func (jsonOutput) UpgradeResult(_ UpgradeResult) {}
+func (textOutput) RollbackResult(_ RollbackResult) {}
+func (jsonOutput) RollbackResult(_ RollbackResult) {}