diff --git a/mkdocs/docs/cli.md b/mkdocs/docs/cli.md index 7160c2e0d0..c199248881 100644 --- a/mkdocs/docs/cli.md +++ b/mkdocs/docs/cli.md @@ -44,11 +44,12 @@ Options: Commands: create Operation to create a namespace. - describe Describe a namespace or a table. + describe Describe a namespace, a table, or a view. drop Operations to drop a namespace or table. files List all the files of the table. list List tables or namespaces. list-refs List all the refs in the provided table. + list-views List all views in a namespace. location Return the location of the table. properties Properties on tables/namespaces. rename Rename a table. @@ -254,3 +255,26 @@ To request purge for the underlying table files through the configured catalog, ➜ pyiceberg drop table nyc.taxis --purge Dropped table: nyc.taxis (purge requested) ``` + +For catalogs that support views, you can also list, describe, and drop views: + +```sh +➜ pyiceberg list-views nyc +nyc.taxi_trips + +➜ pyiceberg describe --entity view nyc.taxi_trips +View format version 1 +Metadata location s3://warehouse/nyc/taxi_trips/metadata/00001-b3a9c6e2-6c1f-4e47-9d4f-2f9a1d0e5c7b.metadata.json +View UUID fa6506c3-7681-40c8-86dc-e36561f83385 +Location s3://warehouse/nyc/taxi_trips +Current version 1 +Current schema Schema, id=1 + ├── 1: VendorID: optional long + └── 2: trip_distance: optional double +SQL SQL representations + └── spark: SELECT VendorID, trip_distance FROM nyc.taxis +Properties comment Taxi trip distances + +➜ pyiceberg drop view nyc.taxi_trips +Dropped view: nyc.taxi_trips +``` diff --git a/pyiceberg/cli/output.py b/pyiceberg/cli/output.py index 4a508d5343..cb8e247bf1 100644 --- a/pyiceberg/cli/output.py +++ b/pyiceberg/cli/output.py @@ -145,6 +145,7 @@ def describe_view(self, view: View) -> None: output_table = self._table output_table.add_row("View format version", str(metadata.format_version)) + output_table.add_row("Metadata location", view.metadata_location) output_table.add_row("View UUID", str(metadata.view_uuid)) output_table.add_row("Location", metadata.location) output_table.add_row("Current version", str(metadata.current_version_id)) diff --git a/tests/cli/test_console.py b/tests/cli/test_console.py index 2bf6651b7d..ebf1a5a90b 100644 --- a/tests/cli/test_console.py +++ b/tests/cli/test_console.py @@ -1209,7 +1209,11 @@ def test_warehouse_cli_option_forwarded_to_catalog(mocker: MockFixture) -> None: @pytest.fixture(name="catalog_with_view") def fixture_catalog_with_view(mocker: MockFixture, catalog: InMemoryCatalog) -> tuple[InMemoryCatalog, View]: - view = View(TEST_VIEW_IDENTIFIER, ViewMetadata.model_validate(TEST_VIEW_METADATA)) + view = View( + TEST_VIEW_IDENTIFIER, + ViewMetadata.model_validate(TEST_VIEW_METADATA), + metadata_location="s3://warehouse/default/my_view/metadata/metadata.json", + ) catalog.list_views = MagicMock(return_value=[TEST_VIEW_IDENTIFIER]) # type: ignore catalog.load_view = MagicMock(return_value=view) # type: ignore catalog.drop_view = MagicMock() # type: ignore @@ -1238,8 +1242,20 @@ def test_describe_view(catalog_with_view: tuple[InMemoryCatalog, View]) -> None: runner = CliRunner() result = runner.invoke(run, ["describe", "--entity=view", "default.my_view"]) assert result.exit_code == 0 - assert "b30125c8-7284-442c-9aea-15fee620737c" in result.output - assert "spark: SELECT * FROM my_table" in result.output + assert ( + "\n".join([line.rstrip() for line in result.output.split("\n")]) + == """View format version 1 +Metadata location s3://warehouse/default/my_view/metadata/metadata.json +View UUID b30125c8-7284-442c-9aea-15fee620737c +Location s3://warehouse/default/my_view +Current version 1 +Current schema Schema, id=1 + └── 1: x: required long +SQL SQL representations + └── spark: SELECT * FROM my_table +Properties +""" + ) def test_describe_view_does_not_exist(catalog: InMemoryCatalog) -> None: