Skip to content

Commit 8b942d6

Browse files
authored
Allow to read only specific columns through CLI read command (#1787)
Allow to read only specific columns throug CLI read command
1 parent 8901b84 commit 8b942d6

2 files changed

Lines changed: 111 additions & 1 deletion

File tree

src/cli/src/Flow/CLI/Command/FileReadCommand.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Flow\CLI\Command;
66

7-
use function Flow\CLI\{option_bool, option_int, option_int_nullable};
7+
use function Flow\CLI\{option_bool, option_int, option_int_nullable, option_list_of_strings};
88
use function Flow\ETL\DSL\{df};
99
use Flow\CLI\Arguments\{FilePathArgument};
1010
use Flow\CLI\Command\Traits\{CSVOptions, ConfigOptions, ExcelOptions, JSONOptions, ParquetOptions, XMLOptions};
@@ -45,6 +45,7 @@ public function configure() : void
4545
->addOption('input-file-batch-size', null, InputOption::VALUE_REQUIRED, 'Number of rows that are going to be read and displayed in one batch, when set to -1 whole dataset will be displayed at once', self::DEFAULT_BATCH_SIZE)
4646
->addOption('input-file-limit', null, InputOption::VALUE_REQUIRED, 'Limit number of rows that are going to be used to infer file schema, when not set whole file is analyzed', null)
4747
->addOption('output-truncate', null, InputOption::VALUE_REQUIRED, 'Truncate output to given number of characters, when set to -1 output is not truncated at all', 20)
48+
->addOption('output-columns', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Columns to include in output, when not set all columns are displayed', [])
4849
->addOption('schema-auto-cast', null, InputOption::VALUE_OPTIONAL, 'When set Flow will try to automatically cast values to more precise data types, for example datetime strings will be casted to datetime type', false);
4950

5051
$this->addConfigOptions($this);
@@ -82,6 +83,12 @@ protected function execute(InputInterface $input, OutputInterface $output) : int
8283
$df->limit($limit);
8384
}
8485

86+
$outputColumns = option_list_of_strings('output-columns', $input);
87+
88+
if (\count($outputColumns)) {
89+
$df->select(...$outputColumns);
90+
}
91+
8592
$formatter = new AsciiTableFormatter();
8693

8794
$df->run(function (Rows $rows) use ($style, $formatter, $outputTruncate) : void {

src/cli/tests/Flow/CLI/Tests/Integration/FileReadCommandTest.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,109 @@ public function test_read_rows_text() : void
137137
);
138138
}
139139

140+
public function test_read_rows_with_output_columns_empty_maintains_all_columns() : void
141+
{
142+
$tester = new CommandTester(new FileReadCommand('read'));
143+
144+
$tester->execute([
145+
'input-file' => __DIR__ . '/Fixtures/orders.csv',
146+
'--input-file-limit' => 2,
147+
]);
148+
149+
$tester->assertCommandIsSuccessful();
150+
151+
// Should contain all original columns (order_id, created_at, updated_at, discount, address, notes, items)
152+
$output = $tester->getDisplay();
153+
self::assertStringContainsString('order_id', $output);
154+
self::assertStringContainsString('created_at', $output);
155+
self::assertStringContainsString('updated_at', $output);
156+
self::assertStringContainsString('discount', $output);
157+
self::assertStringContainsString('address', $output);
158+
self::assertStringContainsString('notes', $output);
159+
self::assertStringContainsString('items', $output);
160+
self::assertStringContainsString('2 rows', $output);
161+
}
162+
163+
public function test_read_rows_with_output_columns_multiple_columns() : void
164+
{
165+
$tester = new CommandTester(new FileReadCommand('read'));
166+
167+
$tester->execute([
168+
'input-file' => __DIR__ . '/Fixtures/orders.csv',
169+
'--input-file-limit' => 3,
170+
'--output-columns' => ['order_id', 'discount', 'created_at'],
171+
]);
172+
173+
$tester->assertCommandIsSuccessful();
174+
175+
self::assertStringContainsString(
176+
<<<'OUTPUT'
177+
+----------------------+----------+----------------------+
178+
| order_id | discount | created_at |
179+
+----------------------+----------+----------------------+
180+
| e13d7098-5a78-3389-9 | 12.45 | 2024-06-17T19:24:49+ |
181+
| 947df050-3abb-3f5a-9 | | 2024-02-23T19:18:53+ |
182+
| 6315f9e2-86bf-3321-a | 47.1 | 2024-04-02T11:30:25+ |
183+
+----------------------+----------+----------------------+
184+
3 rows
185+
OUTPUT,
186+
$tester->getDisplay()
187+
);
188+
}
189+
190+
public function test_read_rows_with_output_columns_nonexistent_column() : void
191+
{
192+
$tester = new CommandTester(new FileReadCommand('read'));
193+
194+
$tester->execute([
195+
'input-file' => __DIR__ . '/Fixtures/orders.csv',
196+
'--input-file-limit' => 2,
197+
'--output-columns' => ['nonexistent_column'],
198+
]);
199+
200+
$tester->assertCommandIsSuccessful();
201+
202+
self::assertStringContainsString(
203+
<<<'OUTPUT'
204+
+--------------------+
205+
| nonexistent_column |
206+
+--------------------+
207+
| |
208+
| |
209+
+--------------------+
210+
2 rows
211+
OUTPUT,
212+
$tester->getDisplay()
213+
);
214+
}
215+
216+
public function test_read_rows_with_output_columns_single_column() : void
217+
{
218+
$tester = new CommandTester(new FileReadCommand('read'));
219+
220+
$tester->execute([
221+
'input-file' => __DIR__ . '/Fixtures/orders.csv',
222+
'--input-file-limit' => 3,
223+
'--output-columns' => ['order_id'],
224+
]);
225+
226+
$tester->assertCommandIsSuccessful();
227+
228+
self::assertStringContainsString(
229+
<<<'OUTPUT'
230+
+----------------------+
231+
| order_id |
232+
+----------------------+
233+
| e13d7098-5a78-3389-9 |
234+
| 947df050-3abb-3f5a-9 |
235+
| 6315f9e2-86bf-3321-a |
236+
+----------------------+
237+
3 rows
238+
OUTPUT,
239+
$tester->getDisplay()
240+
);
241+
}
242+
140243
public function test_read_rows_xml() : void
141244
{
142245
$tester = new CommandTester(new FileReadCommand('read'));

0 commit comments

Comments
 (0)