You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@paimon.apache.org by lz...@apache.org on 2026/03/09 12:12:17 UTC

(paimon) branch master updated: [python] Introduce select for CLI table read (#7377)

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

lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new c9cf264138 [python] Introduce select for CLI table read (#7377)
c9cf264138 is described below

commit c9cf264138d8f8d96d78475719743636ae316994
Author: Jingsong Lee <ji...@gmail.com>
AuthorDate: Mon Mar 9 20:12:11 2026 +0800

    [python] Introduce select for CLI table read (#7377)
    
    ```shell
    paimon table read mydb.users
    ```
    
    **Options:**
    
    - `--select, -s`: Select specific columns to read (comma-separated)
    - `--limit, -l`: Maximum number of results to display (default: 100)
    
    **Examples:**
    
    ```shell
    # Read with limit
    paimon table read mydb.users -l 50
    
    # Read specific columns
    paimon table read mydb.users -s id,name,age
    
    # Combine select and limit
    paimon table read mydb.users -s id,name -l 50
    ```
---
 docs/content/pypaimon/cli.md                   | 33 ++++++++++++----------
 paimon-python/pypaimon/cli/cli_table.py        | 22 +++++++++++++++
 paimon-python/pypaimon/tests/cli_table_test.py | 38 ++++++++++++++++++++++++++
 3 files changed, 79 insertions(+), 14 deletions(-)

diff --git a/docs/content/pypaimon/cli.md b/docs/content/pypaimon/cli.md
index 3519bb56cf..b29c1b39be 100644
--- a/docs/content/pypaimon/cli.md
+++ b/docs/content/pypaimon/cli.md
@@ -74,12 +74,30 @@ paimon [OPTIONS] COMMAND [ARGS]...
 
 ### Table Read
 
-Read data from a Paimon table and display it in a formatted table.
+Read data from a Paimon table and display it in a tabular format.
 
 ```shell
 paimon table read mydb.users
 ```
 
+**Options:**
+
+- `--select, -s`: Select specific columns to read (comma-separated)
+- `--limit, -l`: Maximum number of results to display (default: 100)
+
+**Examples:**
+
+```shell
+# Read with limit
+paimon table read mydb.users -l 50
+
+# Read specific columns
+paimon table read mydb.users -s id,name,age
+
+# Combine select and limit
+paimon table read mydb.users -s id,name -l 50
+```
+
 Output:
 ```
  id    name  age      city
@@ -90,19 +108,6 @@ Output:
   5     Eve   32  Hangzhou
 ```
 
-Use the `-l` or `--limit` option (default 100) to limit the number of rows displayed:
-
-```shell
-paimon table read mydb.users -l 2
-```
-
-Output:
-```
- id  name  age     city
-  1 Alice   25  Beijing
-  2   Bob   30 Shanghai
-```
-
 ### Table Get
 
 Get and display table schema information in JSON format. The output format is the same as the schema JSON format used
diff --git a/paimon-python/pypaimon/cli/cli_table.py b/paimon-python/pypaimon/cli/cli_table.py
index 565339ad6b..43e86488e4 100644
--- a/paimon-python/pypaimon/cli/cli_table.py
+++ b/paimon-python/pypaimon/cli/cli_table.py
@@ -63,6 +63,22 @@ def cmd_table_read(args):
     # Build read pipeline
     read_builder = table.new_read_builder()
     
+    # Apply projection (select columns) if specified
+    select_columns = args.select
+    if select_columns:
+        # Parse column names (comma-separated)
+        columns = [col.strip() for col in select_columns.split(',')]
+        
+        # Validate that all columns exist in the table schema
+        available_fields = set(field.name for field in table.table_schema.fields)
+        invalid_columns = [col for col in columns if col not in available_fields]
+        
+        if invalid_columns:
+            print(f"Error: Column(s) {invalid_columns} do not exist in table '{table_identifier}'.", file=sys.stderr)
+            sys.exit(1)
+        
+        read_builder = read_builder.with_projection(columns)
+
     # Apply limit if specified
     limit = args.limit
     if limit:
@@ -528,6 +544,12 @@ def add_table_subcommands(table_parser):
         'table',
         help='Table identifier in format: database.table'
     )
+    read_parser.add_argument(
+        '--select', '-s',
+        type=str,
+        default=None,
+        help='Select specific columns to read (comma-separated, e.g., "id,name,age")'
+    )
     read_parser.add_argument(
         '--limit', '-l',
         type=int,
diff --git a/paimon-python/pypaimon/tests/cli_table_test.py b/paimon-python/pypaimon/tests/cli_table_test.py
index fb92b8f43f..43469a6692 100644
--- a/paimon-python/pypaimon/tests/cli_table_test.py
+++ b/paimon-python/pypaimon/tests/cli_table_test.py
@@ -128,6 +128,44 @@ class CliTableTest(unittest.TestCase):
                 # Should have header + 2 data rows
                 self.assertLessEqual(len(lines), 4)  # header + 2 data rows + possible empty lines
 
+    def test_cli_table_read_with_select(self):
+        """Test table read with column selection via CLI."""
+        # Simulate CLI command: paimon table read test_db.users --select id,name
+        with patch('sys.argv',
+                   ['paimon', '-c', self.config_file,
+                    'table', 'read', 'test_db.users', '--select', 'id,name']):
+            with patch('sys.stdout', new_callable=StringIO) as mock_stdout:
+                try:
+                    main()
+                except SystemExit:
+                    pass
+                
+                output = mock_stdout.getvalue()
+                
+                # Verify output contains selected columns
+                self.assertIn('id', output.lower())
+                self.assertIn('name', output.lower())
+                # Verify selected data is present
+                self.assertIn('Alice', output)
+                self.assertIn('Bob', output)
+
+    def test_cli_table_read_with_invalid_select(self):
+        """Test table read with invalid column selection via CLI."""
+        # Simulate CLI command: paimon table read test_db.users --select invalid_column
+        with patch('sys.argv',
+                   ['paimon', '-c', self.config_file,
+                    'table', 'read', 'test_db.users', '--select', 'invalid_col1,invalid_col2']):
+            with patch('sys.stderr', new_callable=StringIO) as mock_stderr:
+                try:
+                    main()
+                except SystemExit:
+                    pass
+                
+                error_output = mock_stderr.getvalue()
+                
+                # Verify error message contains information about invalid column
+                self.assertIn("Column(s) ['invalid_col1', 'invalid_col2'] do not exist in table", error_output)
+
     def test_cli_with_custom_config_path(self):
         """Test CLI with custom configuration file path."""
         # Create a different config file